mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 02:27:48 +00:00
Compare commits
161 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4f9c9d1b6 | |||
| aa10b682e4 | |||
| eafbe4ee69 | |||
| cf5912412d | |||
| 1f114b2acf | |||
| 94ebddbdfe | |||
| aa1ca27789 | |||
| 9999320cd0 | |||
| 74429b4a14 | |||
| bcb191c01e | |||
| ddb848816f | |||
| 889911d0a6 | |||
| a4dd38de81 | |||
| 486ee37a40 | |||
| 944176beef | |||
| c396418187 | |||
| 1b4ab772d2 | |||
| aca0fe0412 | |||
| af511c1118 | |||
| 5ba8766cbc | |||
| b792c10680 | |||
| 12d41ba0c1 | |||
| 020cca8c3c | |||
| 4cbd34d32f | |||
| 6426bf79b4 | |||
| aed8116b22 | |||
| f6c759ccbf | |||
| 4b389b90e8 | |||
| 4c3680635e | |||
| 0755145824 | |||
| eabd1ddce0 | |||
| 0e84235f9a | |||
| 894839484c | |||
| 1fadd0e772 | |||
| eba6e7a428 | |||
| f4a6e0373b | |||
| d274545e63 | |||
| f74d25c882 | |||
| 618c689246 | |||
| 9d29971755 | |||
| 451c57af92 | |||
| 59feac28b9 | |||
| c1f48fc79a | |||
| 3c07a36e95 | |||
| 98b3c27c76 | |||
| ddacdfacd5 | |||
| 2d477e069d | |||
| ed1a56785a | |||
| f496571747 | |||
| 17fed5980b | |||
| 2ff04f1a87 | |||
| f763865c5c | |||
| 52edf52245 | |||
| 8161b766d3 | |||
| 709349e24b | |||
| 5fd4878574 | |||
| a24dc8c543 | |||
| c3d514a751 | |||
| 5b7a2c73db | |||
| aaf6a36c55 | |||
| dc6e0e23b9 | |||
| 44b0c79eaf | |||
| 27e5baeb57 | |||
| a6a4f85e61 | |||
| 3386316b9f | |||
| 410bb9c103 | |||
| f176b3a480 | |||
| 9b1a3a2236 | |||
| b29edadf48 | |||
| d04332d688 | |||
| 547288529c | |||
| bd8de8719f | |||
| 2fd44ac341 | |||
| dc30aef687 | |||
| 29cadaa23b | |||
| a7c149f8dc | |||
| c2a04e1a45 | |||
| f748dc6fd8 | |||
| bfc21ad906 | |||
| 41726fab9d | |||
| 82f4fcf2a3 | |||
| 3a00f00f62 | |||
| a71f776203 | |||
| d2f60c02bb | |||
| 7ca53138bc | |||
| a9c0501826 | |||
| 60fb4b95fa | |||
| 323b62b405 | |||
| 40fb3466c1 | |||
| 2333ef2454 | |||
| 0ac7bf8c8b | |||
| 38a3ccee52 | |||
| 47115f0380 | |||
| 1f00425eb3 | |||
| 71245845c8 | |||
| d9f6f3b81f | |||
| b81a7c2bca | |||
| 0ec2f0818a | |||
| 4a6a82ae79 | |||
| b14ee51ff6 | |||
| 394116e998 | |||
| f902437848 | |||
| 86cc3b6c12 | |||
| 6bb6ea2432 | |||
| 3c590e36ad | |||
| 69a4dda8c8 | |||
| 8fbaffe56e | |||
| bfafef8df1 | |||
| 26ff622148 | |||
| 88a68eaf7e | |||
| 46a2a177c1 | |||
| b0ea05a853 | |||
| f3b79c412f | |||
| f4f3ad5051 | |||
| 0757ccc657 | |||
| 47282be619 | |||
| 9bdbe943ce | |||
| 180220a2e3 | |||
| 8ef4af45d7 | |||
| 9215aa7ece | |||
| b497c5da71 | |||
| bf4d2fef4a | |||
| c053b8fc8a | |||
| d364ac6024 | |||
| d78be5112b | |||
| b5233eea56 | |||
| 09a6612742 | |||
| 1778ad620f | |||
| 458b50bc07 | |||
| fca8784dc3 | |||
| a846ee2321 | |||
| df087b592f | |||
| eade931650 | |||
| a7649f5b42 | |||
| f0b953dec9 | |||
| bb8196653f | |||
| a1b44ddd58 | |||
| 48b0d7f434 | |||
| d8b6b257f4 | |||
| c98972a3e0 | |||
| b93759936c | |||
| d62dda8140 | |||
| ca36fba7e4 | |||
| 743bf45e00 | |||
| 9bc5d21185 | |||
| c8b56bd161 | |||
| fe20079300 | |||
| 068d7c1b44 | |||
| 42fed60e61 | |||
| 53c1ccaa42 | |||
| 72f667cac9 | |||
| 4fff472808 | |||
| cfd74c2954 | |||
| 9bcca974ba | |||
| a40586d092 | |||
| bc9708f51a | |||
| 8ef36ed939 | |||
| c7f62bae9b | |||
| 1b741bf2b7 | |||
| 266d70816f | |||
| 27cedf09e8 |
@@ -96,7 +96,7 @@ jobs:
|
|||||||
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
||||||
# least the smoke tests still pass.
|
# least the smoke tests still pass.
|
||||||
docker:
|
docker:
|
||||||
- image: golang:1.22-bullseye
|
- image: golang:1.23-bullseye
|
||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "15"
|
llvm: "15"
|
||||||
@@ -105,7 +105,7 @@ jobs:
|
|||||||
# This tests the latest supported LLVM version when linking against system
|
# This tests the latest supported LLVM version when linking against system
|
||||||
# libraries.
|
# libraries.
|
||||||
docker:
|
docker:
|
||||||
- image: golang:1.25-bullseye
|
- image: golang:1.26-bookworm
|
||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "20"
|
llvm: "20"
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
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@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Extract TinyGo version
|
- name: Extract TinyGo version
|
||||||
@@ -40,10 +40,10 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-20-${{ matrix.os }}-v1
|
key: llvm-source-20-${{ matrix.os }}-v1
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -68,7 +68,7 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore LLVM build cache
|
- name: Restore LLVM build cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-20-${{ matrix.os }}-v2
|
key: llvm-build-20-${{ matrix.os }}-v2
|
||||||
@@ -85,7 +85,7 @@ jobs:
|
|||||||
make llvm-build
|
make llvm-build
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save LLVM build cache
|
- name: Save LLVM build cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
||||||
@@ -101,16 +101,11 @@ jobs:
|
|||||||
- 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
|
run: cp -p build/release.tar.gz build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
# Note: this release artifact is double-zipped, see:
|
uses: actions/upload-artifact@v7
|
||||||
# https://github.com/actions/upload-artifact/issues/39
|
|
||||||
# We can essentially pick one of these:
|
|
||||||
# - have a double-zipped artifact when downloaded from the UI
|
|
||||||
# - have a very slow artifact upload
|
|
||||||
# We're doing the former here, to keep artifact uploads fast.
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: darwin-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}
|
name: darwin-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}
|
||||||
path: build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz
|
path: build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz
|
||||||
|
archive: false
|
||||||
- name: Smoke tests
|
- name: Smoke tests
|
||||||
run: make smoketest TINYGO=$(PWD)/build/tinygo
|
run: make smoketest TINYGO=$(PWD)/build/tinygo
|
||||||
test-macos-homebrew:
|
test-macos-homebrew:
|
||||||
@@ -121,7 +116,7 @@ jobs:
|
|||||||
version: [16, 17, 18, 19, 20]
|
version: [16, 17, 18, 19, 20]
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Homebrew
|
- name: Set up Homebrew
|
||||||
uses: Homebrew/actions/setup-homebrew@master
|
uses: Homebrew/actions/setup-homebrew@main
|
||||||
- name: Fix Python symlinks
|
- name: Fix Python symlinks
|
||||||
run: |
|
run: |
|
||||||
# Github runners have broken symlinks, so relink
|
# Github runners have broken symlinks, so relink
|
||||||
@@ -130,12 +125,13 @@ jobs:
|
|||||||
- name: Install LLVM
|
- name: Install LLVM
|
||||||
run: |
|
run: |
|
||||||
brew install llvm@${{ matrix.version }}
|
brew install llvm@${{ matrix.version }}
|
||||||
|
brew link llvm@${{ matrix.version }}
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Build TinyGo (LLVM ${{ matrix.version }})
|
- name: Build TinyGo (LLVM ${{ matrix.version }})
|
||||||
run: go install -tags=llvm${{ matrix.version }}
|
run: go install -tags=llvm${{ matrix.version }}
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ jobs:
|
|||||||
sudo rm -rf /usr/local/share/boost
|
sudo rm -rf /usr/local/share/boost
|
||||||
df -h
|
df -h
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v4
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v6
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
tinygo/tinygo-dev
|
tinygo/tinygo-dev
|
||||||
@@ -47,18 +47,18 @@ jobs:
|
|||||||
type=sha,format=long
|
type=sha,format=long
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
- name: Log in to Github Container Registry
|
- name: Log in to Github Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
+58
-48
@@ -18,12 +18,12 @@ jobs:
|
|||||||
# statically linked binary.
|
# statically linked binary.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: golang:1.25-alpine
|
image: golang:1.26-alpine
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.version.outputs.version }}
|
version: ${{ steps.version.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Install apk dependencies
|
- name: Install apk dependencies
|
||||||
# tar: needed for actions/cache@v4
|
# tar: needed for actions/cache@v5
|
||||||
# git+openssh: needed for checkout (I think?)
|
# git+openssh: needed for checkout (I think?)
|
||||||
# ruby: needed to install fpm
|
# ruby: needed to install fpm
|
||||||
run: apk add tar git openssh make g++ ruby-dev mold
|
run: apk add tar git openssh make g++ ruby-dev mold
|
||||||
@@ -31,24 +31,24 @@ jobs:
|
|||||||
# We're not on a multi-user machine, so this is safe.
|
# We're not on a multi-user machine, so this is safe.
|
||||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Extract TinyGo version
|
- name: Extract TinyGo version
|
||||||
id: version
|
id: version
|
||||||
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
|
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
|
||||||
- name: Cache Go
|
- name: Cache Go
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
with:
|
with:
|
||||||
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
|
key: go-cache-linux-alpine-v2-${{ hashFiles('go.mod') }}
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-20-linux-alpine-v1
|
key: llvm-source-20-linux-alpine-v2
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
@@ -59,7 +59,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -70,10 +70,10 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore LLVM build cache
|
- name: Restore LLVM build cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-20-linux-alpine-v1
|
key: llvm-build-20-linux-alpine-v2
|
||||||
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'
|
||||||
@@ -88,16 +88,16 @@ jobs:
|
|||||||
# Remove unnecessary object files (to reduce cache size).
|
# Remove unnecessary object files (to reduce cache size).
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save LLVM build cache
|
- name: Save LLVM build cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
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: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-alpine-v1
|
key: binaryen-linux-alpine-v2
|
||||||
path: build/wasm-opt
|
path: build/wasm-opt
|
||||||
- name: Build Binaryen
|
- name: Build Binaryen
|
||||||
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
||||||
@@ -118,26 +118,31 @@ jobs:
|
|||||||
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${{ steps.version.outputs.version }}.linux-amd64.tar.gz
|
||||||
cp -p build/release.deb /tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb
|
cp -p build/release.deb /tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb
|
||||||
- name: Publish release artifact
|
- name: "Publish release artifact: tarball"
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped-${{ steps.version.outputs.version }}
|
name: tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz
|
||||||
path: |
|
path: /tmp/tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz
|
||||||
/tmp/tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz
|
archive: false
|
||||||
/tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb
|
- name: "Publish release artifact: Debian package"
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: tinygo_${{ steps.version.outputs.version }}_amd64.deb
|
||||||
|
path: /tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb
|
||||||
|
archive: false
|
||||||
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
|
||||||
needs: build-linux
|
needs: build-linux
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
uses: bytecodealliance/actions/wasmtime/setup@v1
|
uses: bytecodealliance/actions/wasmtime/setup@v1
|
||||||
@@ -146,9 +151,9 @@ jobs:
|
|||||||
- name: Install wasm-tools
|
- name: Install wasm-tools
|
||||||
uses: bytecodealliance/actions/wasm-tools/setup@v1
|
uses: bytecodealliance/actions/wasm-tools/setup@v1
|
||||||
- name: Download release artifact
|
- name: Download release artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped-${{ needs.build-linux.outputs.version }}
|
name: tinygo${{ needs.build-linux.outputs.version }}.linux-amd64.tar.gz
|
||||||
- name: Extract release tarball
|
- name: Extract release tarball
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/lib
|
mkdir -p ~/lib
|
||||||
@@ -164,7 +169,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install apt dependencies
|
- name: Install apt dependencies
|
||||||
@@ -181,10 +186,10 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
@@ -194,7 +199,7 @@ jobs:
|
|||||||
- name: Setup `wasm-tools`
|
- name: Setup `wasm-tools`
|
||||||
uses: bytecodealliance/actions/wasm-tools/setup@v1
|
uses: bytecodealliance/actions/wasm-tools/setup@v1
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-20-linux-asserts-v1
|
key: llvm-source-20-linux-asserts-v1
|
||||||
@@ -208,7 +213,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -219,7 +224,7 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore LLVM build cache
|
- name: Restore LLVM build cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-20-linux-asserts-v1
|
key: llvm-build-20-linux-asserts-v1
|
||||||
@@ -235,13 +240,13 @@ jobs:
|
|||||||
# Remove unnecessary object files (to reduce cache size).
|
# Remove unnecessary object files (to reduce cache size).
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save LLVM build cache
|
- name: Save LLVM build cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
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: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-asserts-v1
|
key: binaryen-linux-asserts-v1
|
||||||
@@ -284,7 +289,7 @@ jobs:
|
|||||||
needs: build-linux
|
needs: build-linux
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
- name: Get TinyGo version
|
- name: Get TinyGo version
|
||||||
id: version
|
id: version
|
||||||
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
|
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
|
||||||
@@ -298,10 +303,10 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-20-linux-v1
|
key: llvm-source-20-linux-v1
|
||||||
@@ -315,7 +320,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -326,7 +331,7 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore LLVM build cache
|
- name: Restore LLVM build cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-20-linux-${{ matrix.goarch }}-v1
|
key: llvm-build-20-linux-${{ matrix.goarch }}-v1
|
||||||
@@ -344,13 +349,13 @@ jobs:
|
|||||||
# Remove unnecessary object files (to reduce cache size).
|
# Remove unnecessary object files (to reduce cache size).
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save LLVM build cache
|
- name: Save LLVM build cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
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: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-${{ matrix.goarch }}-v4
|
key: binaryen-linux-${{ matrix.goarch }}-v4
|
||||||
@@ -370,9 +375,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make CROSS=${{ matrix.toolchain }}
|
make CROSS=${{ matrix.toolchain }}
|
||||||
- name: Download amd64 release
|
- name: Download amd64 release
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped-${{ needs.build-linux.outputs.version }}
|
name: tinygo${{ needs.build-linux.outputs.version }}.linux-amd64.tar.gz
|
||||||
- name: Extract amd64 release
|
- name: Extract amd64 release
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build/release
|
mkdir -p build/release
|
||||||
@@ -384,12 +389,17 @@ 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${{ needs.build-linux.outputs.version }}.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_${{ needs.build-linux.outputs.version }}_${{ matrix.libc }}.deb
|
||||||
- name: Publish release artifact
|
- name: "Publish release artifact: tarball"
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: linux-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}
|
name: linux-${{ matrix.goarch }}-double-zipped-${{ needs.build-linux.outputs.version }}
|
||||||
path: |
|
path: /tmp/tinygo${{ needs.build-linux.outputs.version }}.linux-${{ matrix.goarch }}.tar.gz
|
||||||
/tmp/tinygo${{ steps.version.outputs.version }}.linux-${{ matrix.goarch }}.tar.gz
|
archive: false
|
||||||
/tmp/tinygo_${{ steps.version.outputs.version }}_${{ matrix.libc }}.deb
|
- name: "Publish release artifact: Debian package"
|
||||||
|
uses: actions/upload-artifact@v7
|
||||||
|
with:
|
||||||
|
name: linux-${{ matrix.goarch }}-double-zipped-${{ needs.build-linux.outputs.version }}
|
||||||
|
path: /tmp/tinygo_${{ needs.build-linux.outputs.version }}_${{ matrix.libc }}.deb
|
||||||
|
archive: false
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v4
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v6
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
tinygo/llvm-20
|
tinygo/llvm-20
|
||||||
@@ -46,13 +46,13 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
- name: Log in to Github Container Registry
|
- name: Log in to Github Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
target: tinygo-llvm-build
|
target: tinygo-llvm-build
|
||||||
context: .
|
context: .
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ jobs:
|
|||||||
# See: https://github.com/tinygo-org/tinygo/pull/4516#issuecomment-2416363668
|
# See: https://github.com/tinygo-org/tinygo/pull/4516#issuecomment-2416363668
|
||||||
run: sudo apt-get remove llvm-18
|
run: sudo apt-get remove llvm-18
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
- name: Pull musl, bdwgc
|
- name: Pull musl, bdwgc
|
||||||
run: |
|
run: |
|
||||||
git submodule update --init lib/musl lib/bdwgc
|
git submodule update --init lib/musl lib/bdwgc
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-20-linux-nix-v1
|
key: llvm-source-20-linux-nix-v1
|
||||||
@@ -36,13 +36,13 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
path: |
|
path: |
|
||||||
llvm-project/compiler-rt
|
llvm-project/compiler-rt
|
||||||
- uses: cachix/install-nix-action@v22
|
- uses: cachix/install-nix-action@v31
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
nix develop --ignore-environment --keep HOME --command bash -c "go install && ~/go/bin/tinygo version && ~/go/bin/tinygo build -o test ./testdata/cgo"
|
nix develop --ignore-environment --keep HOME --command bash -c "go install && ~/go/bin/tinygo version && ~/go/bin/tinygo build -o test ./testdata/cgo"
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "$HOME/go/bin" >> $GITHUB_PATH
|
echo "$HOME/go/bin" >> $GITHUB_PATH
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # fetch all history (no sparse checkout)
|
fetch-depth: 0 # fetch all history (no sparse checkout)
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install apt dependencies
|
- name: Install apt dependencies
|
||||||
run: ./.github/workflows/sizediff-install-pkgs.sh
|
run: ./.github/workflows/sizediff-install-pkgs.sh
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-20-sizediff-v1
|
key: llvm-source-20-sizediff-v1
|
||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Cache Go
|
- name: Cache Go
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
with:
|
with:
|
||||||
key: go-cache-linux-sizediff-v2-${{ hashFiles('go.mod') }}
|
key: go-cache-linux-sizediff-v2-${{ hashFiles('go.mod') }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -24,14 +24,13 @@ jobs:
|
|||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
- uses: MinoruSekine/setup-scoop@v4
|
- uses: MinoruSekine/setup-scoop@v4
|
||||||
with:
|
|
||||||
scoop_update: 'false'
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
scoop config use_external_7zip true
|
||||||
scoop install ninja binaryen
|
scoop install ninja binaryen
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Extract TinyGo version
|
- name: Extract TinyGo version
|
||||||
@@ -41,10 +40,10 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore cached LLVM source
|
- name: Restore cached LLVM source
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-20-windows-v1
|
key: llvm-source-20-windows-v1
|
||||||
@@ -58,7 +57,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save cached LLVM source
|
- name: Save cached LLVM source
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -69,7 +68,7 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore cached LLVM build
|
- name: Restore cached LLVM build
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v5
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-20-windows-v2
|
key: llvm-build-20-windows-v2
|
||||||
@@ -86,20 +85,21 @@ jobs:
|
|||||||
# Remove unnecessary object files (to reduce cache size).
|
# Remove unnecessary object files (to reduce cache size).
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save cached LLVM build
|
- name: Save cached LLVM build
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v5
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
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: Cache Go cache
|
- name: Cache Go cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
with:
|
with:
|
||||||
key: go-cache-windows-v1-${{ hashFiles('go.mod') }}
|
key: go-cache-windows-v2-${{ hashFiles('go.mod') }}
|
||||||
path: |
|
path: |
|
||||||
C:/Users/runneradmin/AppData/Local/go-build
|
C:/Users/runneradmin/AppData/Local/go-build
|
||||||
C:/Users/runneradmin/go/pkg/mod
|
C:/Users/runneradmin/go/pkg/mod
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
run: |
|
run: |
|
||||||
|
scoop config use_external_7zip true
|
||||||
scoop install wasmtime@29.0.1
|
scoop install wasmtime@29.0.1
|
||||||
- name: make gen-device
|
- name: make gen-device
|
||||||
run: make -j3 gen-device
|
run: make -j3 gen-device
|
||||||
@@ -114,16 +114,11 @@ jobs:
|
|||||||
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 tinygo${{ steps.version.outputs.version }}.windows-amd64.zip tinygo
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
# Note: this release artifact is double-zipped, see:
|
uses: actions/upload-artifact@v7
|
||||||
# https://github.com/actions/upload-artifact/issues/39
|
|
||||||
# We can essentially pick one of these:
|
|
||||||
# - have a dobule-zipped artifact when downloaded from the UI
|
|
||||||
# - have a very slow artifact upload
|
|
||||||
# We're doing the former here, to keep artifact uploads fast.
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped-${{ steps.version.outputs.version }}
|
name: tinygo${{ steps.version.outputs.version }}.windows-amd64.zip
|
||||||
path: build/release/tinygo${{ steps.version.outputs.version }}.windows-amd64.zip
|
path: build/release/tinygo${{ steps.version.outputs.version }}.windows-amd64.zip
|
||||||
|
archive: false
|
||||||
|
|
||||||
smoke-test-windows:
|
smoke-test-windows:
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
@@ -136,28 +131,24 @@ jobs:
|
|||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
- uses: MinoruSekine/setup-scoop@v4
|
- uses: MinoruSekine/setup-scoop@v4
|
||||||
with:
|
|
||||||
scoop_update: 'false'
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
scoop config use_external_7zip true
|
||||||
scoop install binaryen
|
scoop install binaryen
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
|
name: tinygo${{ needs.build-windows.outputs.version }}.windows-amd64.zip
|
||||||
path: build/
|
path: build/
|
||||||
- name: Unzip TinyGo build
|
# This build is already unzipped.
|
||||||
shell: bash
|
|
||||||
working-directory: build
|
|
||||||
run: 7z x tinygo*.windows-amd64.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
|
||||||
@@ -173,21 +164,18 @@ jobs:
|
|||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
|
name: tinygo${{ needs.build-windows.outputs.version }}.windows-amd64.zip
|
||||||
path: build/
|
path: build/
|
||||||
- name: Unzip TinyGo build
|
# This build is already unzipped.
|
||||||
shell: bash
|
|
||||||
working-directory: build
|
|
||||||
run: 7z x tinygo*.windows-amd64.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
|
||||||
|
|
||||||
@@ -202,27 +190,23 @@ jobs:
|
|||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
- uses: MinoruSekine/setup-scoop@v4
|
- uses: MinoruSekine/setup-scoop@v4
|
||||||
with:
|
|
||||||
scoop_update: 'false'
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
scoop install binaryen && scoop install wasmtime@29.0.1
|
scoop config use_external_7zip true
|
||||||
|
scoop install binaryen wasmtime@29.0.1
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v6
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v6
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.5'
|
go-version: '1.26.2'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
|
name: tinygo${{ needs.build-windows.outputs.version }}.windows-amd64.zip
|
||||||
path: build/
|
path: build/
|
||||||
- name: Unzip TinyGo build
|
# This build is already unzipped.
|
||||||
shell: bash
|
|
||||||
working-directory: build
|
|
||||||
run: 7z x tinygo*.windows-amd64.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
|
||||||
|
|||||||
+157
@@ -1,3 +1,160 @@
|
|||||||
|
0.41.1
|
||||||
|
---
|
||||||
|
* **machine**
|
||||||
|
- esp32c3: correct pin interrupt setup call that was overlooked from #5320
|
||||||
|
* **runtime**
|
||||||
|
- esp32s3: wait for TIMG0 update register to clear before reading timer registers
|
||||||
|
* **net**
|
||||||
|
- update net module to a version that is backwards compatible with Go 1.25.x to fix #5332
|
||||||
|
|
||||||
|
0.41.0
|
||||||
|
---
|
||||||
|
* **general**
|
||||||
|
- go.mod, compiler: bump minimum Go version to 1.23
|
||||||
|
- builder: support Go 1.26 now
|
||||||
|
- feat: add inheritable-only field to filter processor-level targets (#5270)
|
||||||
|
- feature: add esp32flash flash method for esp32s3/esp32c3/esp32/esp8266
|
||||||
|
- flashing: introduce flash method 'esp32jtag' for esp32c3/esp32s3 targets
|
||||||
|
- fashing: add "adb" flash method using Android Debug Bridge
|
||||||
|
- main: auto-use best available flashing options on esp32
|
||||||
|
- espflasher: update to espflasher 0.6.0
|
||||||
|
* **compiler**
|
||||||
|
- implement method-set based AssignableTo and Implements (#5304)
|
||||||
|
- simplify createObjectLayout
|
||||||
|
- implement copy directly
|
||||||
|
- fix min/max on floats by using intrinsics
|
||||||
|
- add element layout to sliceAppend
|
||||||
|
- add intrinsic for crypto/internal/constanttime.boolToUint8
|
||||||
|
- fix SyscallN handling for Windows on Go 1.26+
|
||||||
|
* **core**
|
||||||
|
- reflect: add TypeAssert
|
||||||
|
- reflect: fix TypeAssert for structs
|
||||||
|
- sync: add WaitGroup.Go
|
||||||
|
- os: add UserCacheDir and UserConfigDir
|
||||||
|
- os: implement Lchown function for changing file ownership (#5161)
|
||||||
|
- testing: add b.ReportMetric()
|
||||||
|
- errors: add errors package to passing list
|
||||||
|
- internal/gclayout: use correct lengths
|
||||||
|
- internal/abi: add EscapeNonString, EscapeToResultNonString
|
||||||
|
- internal, runtime: add internal fips bool
|
||||||
|
- internal/itoa: resurrect from Go stdlib
|
||||||
|
- internal/syscall/unix: implement GetRandom for WASI targets
|
||||||
|
- interp: make ptrtoint size mismatch a recoverable error
|
||||||
|
- loader: support "all:" prefix in //go:embed patterns
|
||||||
|
- loader, crypto/internal/entropy: fix 32 MiB RAM overflow on microcontrollers
|
||||||
|
- loader, unicode/utf8: fix hiBits overflow on 16-bit AVR targets
|
||||||
|
- builder: order embedded files deterministically
|
||||||
|
- builder: fix panic in findPackagePath when using -size short
|
||||||
|
- builder: fix SIGSEGV when stripping duplicate function definitions
|
||||||
|
- builder, runtime: fix duplicate symbol error with Go 1.26+ on Windows
|
||||||
|
- builder: use target-specific -march for RISC-V library compilation
|
||||||
|
- transform: modify output format from the -print-allocs flag to match the go coverage tool format
|
||||||
|
- cgo: allow for changes to 'short-enums' flag
|
||||||
|
- wasm: add more stubbed file operations
|
||||||
|
* **machine**
|
||||||
|
- esp32c3: implement BlockDevice for esp32c3 flash
|
||||||
|
- esp32c3: clear GPIO STATUS before dispatching pin callbacks
|
||||||
|
- esp32c3: implement USBDevice using interrupts
|
||||||
|
- esp32c3: add Enable stub for QEMU test target
|
||||||
|
- esp32c3: fix interrupt disable handling
|
||||||
|
- esp32c3: clear MCAUSE after handling interrupt
|
||||||
|
- esp32c3: map missing IRAM sections in linker script
|
||||||
|
- esp32c3: fix to use PROVIDE() for WiFi/BLE ROM function addresses to allow blob overrides
|
||||||
|
- esp32c3: add WiFi/BLE ROM linker support
|
||||||
|
- esp32c3: use TIMG0 alarm interrupt for sleepTicks instead of busy-waiting
|
||||||
|
- esp32s3: implement Pin.SetInterrupt for GPIO pin change interrupts
|
||||||
|
- esp32s3: use edge-triggered CPU interrupt for GPIO pin interrupts
|
||||||
|
- esp32s3: add interrupt support (#5244)
|
||||||
|
- esp32s3: switch USB implementation to use interrupts instead of polling
|
||||||
|
- esp32s3: replace inline ISR with full interrupt vector handler
|
||||||
|
- esp32s3: use TIMG0 alarm interrupt for sleepTicks
|
||||||
|
- esp32s3: improve exception handlers, add procPin/procUnpin, and linker wrap flags
|
||||||
|
- esp32s3: fix Xtensa register window spill using recursive call4 in task switching
|
||||||
|
- esp32s3: update linker script and boot assembly for multi-page flash XIP mapping
|
||||||
|
- esp32s3: add flash XIP boot assembly with cache/MMU init
|
||||||
|
- esp32s3: implement SPI (#5169)
|
||||||
|
- esp32s3: implement I2C interface (#5210)
|
||||||
|
- esp32s3: implement RNG based on onboard hardware random number generator
|
||||||
|
- esp32s3,esp32c3: add USB serial support
|
||||||
|
- esp32s3,esp32c3: add txStalled flag to skip USB serial spin when no host
|
||||||
|
- esp32s3,esp32c3: make USB Serial/JTAG writes non-blocking when FIFO is full
|
||||||
|
- esp32c3/esp32s3: refactor ADC implementation to reduce code duplication
|
||||||
|
- esp32s3,esp32c3: add ADC support (#5231)
|
||||||
|
- esp32s3,esp32c3: add PWM support (#5215)
|
||||||
|
- esp32c3/esp32s3: refactoring and corrections for SPI implementation
|
||||||
|
- esp32xx: add WASM simulator support for ESP32-C3/ESP32-S3 targets
|
||||||
|
- esp32: default SPI CS pin to NoPin when unset
|
||||||
|
- esp: fix tinygo_scanCurrentStack to spill register windows
|
||||||
|
- stm32: fix UART interrupt storm caused by uncleared overrun error
|
||||||
|
- stm32: fix PWM problem due to register shifting
|
||||||
|
- stm32: add STM32U585 target definition and runtime
|
||||||
|
- stm32: add STM32U5 GPIO, pin interrupts, and UART support
|
||||||
|
- stm32: add STM32U5 I2C support
|
||||||
|
- stm32: add STM32U5 SPI support
|
||||||
|
- stm32u585: implement ADC
|
||||||
|
- stm32g0b1: add support (#5150)
|
||||||
|
- stm32g0b1: add Watchdog + ADC support (#5158)
|
||||||
|
- stm32l0: add flash support
|
||||||
|
- stm32l0x1,l0x2: TIM: adapt to 32-bit register access
|
||||||
|
- stm32g0: sync with updated stm32 device files
|
||||||
|
- attiny85: add USI-based SPI support (#5181)
|
||||||
|
- attiny85: add PWM support (#5171)
|
||||||
|
- rp: add Close function to UART to allow for removing all system resources/power usage
|
||||||
|
- rp: use blockReset() and unresetBlockWait() helper functions for peripheral reset/unreset
|
||||||
|
- rp2: prevent PWM Period method overflow
|
||||||
|
- rp2: add per-byte timeout budget for I2C (#5189)
|
||||||
|
- feather-m0: export UART0 and pins
|
||||||
|
- usb/cdc: better ring buffer implementation (#5209)
|
||||||
|
- fix: replace ! with ~ for register mask
|
||||||
|
- atmega328p_simulator: add correct build tag for arduino_uno after renaming
|
||||||
|
* **net**
|
||||||
|
- update to Go 1.26.2 net package with UDP and JS improvements
|
||||||
|
* **runtime**
|
||||||
|
- implement fminimum/fmaximum
|
||||||
|
- make timeoffset atomic
|
||||||
|
- add MemStats.HeapObjects
|
||||||
|
- handle GODEBUG on wasip2 (#5312)
|
||||||
|
- fix Darwin syscall return value truncation and lost arguments
|
||||||
|
- add syscall.runtimeClearenv for Go 1.26
|
||||||
|
- split syscall functions for darwin changes for 1.26
|
||||||
|
- fix: init heap before random number seed on wasm platforms
|
||||||
|
* **targets**
|
||||||
|
- add esp32s3-supermini board target
|
||||||
|
- add support for Seeedstudio Xiao-RP2350 board
|
||||||
|
- add Shrike Lite board (#5170)
|
||||||
|
- rename arduino target to arduino-uno
|
||||||
|
- add pins/setup for Arduino UNO Q board QWIIC connector
|
||||||
|
- correct pin mapping for Arduino UNO Q STM32 MCU
|
||||||
|
- add stm32u585 openocd commands for flashing on Arduino UNO Q
|
||||||
|
- correct name/tag use for esp32s3-wroom1 board
|
||||||
|
- modify esp32, esp32s3, esp32c3, & esp8266 targets to use built-in esp32flash
|
||||||
|
- switch rp2040/rp2350 to default to tasks scheduler
|
||||||
|
- change default stack size for esp32c3 and esp32s3 to 8196
|
||||||
|
- swan: rename group build tag stm32l4x5 => stm32l4y5 to avoid clash with stm32 device name
|
||||||
|
- nucleo-f722ze: add build-tag stm32f722
|
||||||
|
- fix: set stm32u5x clock rate to default
|
||||||
|
- create generic targets for esp32 boards
|
||||||
|
* **libs**
|
||||||
|
- stm32-svd: update submodule
|
||||||
|
- update tools/gen-device-svd for recent changes to stm32-svd file structure (#5212)
|
||||||
|
* **build/test**
|
||||||
|
- build: use Golang 1.26 for all builds
|
||||||
|
- build: actually use the version of llvm we are supposed to be testing by using brew link command
|
||||||
|
- build: let scoop run updates to resolve binaryen install failures on Windows
|
||||||
|
- ci: don't double zip release artifacts
|
||||||
|
- test: increase default timeout from 1 to 2 minutes to prevent spurious CI fails
|
||||||
|
- testdata: fix flaky timers test by draining ticker channel after Stop
|
||||||
|
- testdata: more corpus entries (#5182)
|
||||||
|
- add soypat/lneto to corpus
|
||||||
|
- GNUmakefile: add context and expvar to stdlib tests
|
||||||
|
- GNUmakefile: add encoding/xml to stdlib tests on Linux
|
||||||
|
- main (test): skip mipsle test if the emulator is missing
|
||||||
|
- make: remove machine without board from smoketest
|
||||||
|
- stm32: add Arduino UNO Q to smoketests
|
||||||
|
- flake: bump to nixpkgs 25.11
|
||||||
|
- chore: update all github actions to latest versions
|
||||||
|
- fix: use external 7zip for scoop installs on Windows
|
||||||
|
|
||||||
0.40.1
|
0.40.1
|
||||||
---
|
---
|
||||||
* **machine**
|
* **machine**
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||||
FROM golang:1.25 AS tinygo-llvm
|
FROM golang:1.26 AS tinygo-llvm
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y apt-utils make cmake clang-17 ninja-build && \
|
apt-get install -y apt-utils make cmake clang-17 ninja-build && \
|
||||||
@@ -33,7 +33,7 @@ RUN cd /tinygo/ && \
|
|||||||
|
|
||||||
# tinygo-compiler copies the compiler build over to a base Go container (without
|
# tinygo-compiler copies the compiler build over to a base Go container (without
|
||||||
# all the build tools etc).
|
# all the build tools etc).
|
||||||
FROM golang:1.25 AS tinygo-compiler
|
FROM golang:1.26 AS tinygo-compiler
|
||||||
|
|
||||||
# Copy tinygo build.
|
# Copy tinygo build.
|
||||||
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
|
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
|
||||||
|
|||||||
+71
-8
@@ -289,13 +289,13 @@ WASM_TOOLS_MODULE=go.bytecodealliance.org
|
|||||||
.PHONY: wasi-syscall
|
.PHONY: wasi-syscall
|
||||||
wasi-syscall: wasi-cm
|
wasi-syscall: wasi-cm
|
||||||
rm -rf ./src/internal/wasi/*
|
rm -rf ./src/internal/wasi/*
|
||||||
go run -modfile ./internal/wasm-tools/go.mod $(WASM_TOOLS_MODULE)/cmd/wit-bindgen-go generate --versioned -o ./src/internal -p internal --cm internal/cm ./lib/wasi-cli/wit
|
go run $(WASM_TOOLS_MODULE)/cmd/wit-bindgen-go generate --versioned -o ./src/internal -p internal --cm internal/cm ./lib/wasi-cli/wit
|
||||||
|
|
||||||
# Copy package cm into src/internal/cm
|
# Copy package cm into src/internal/cm
|
||||||
.PHONY: wasi-cm
|
.PHONY: wasi-cm
|
||||||
wasi-cm:
|
wasi-cm:
|
||||||
rm -rf ./src/internal/cm/*
|
rm -rf ./src/internal/cm/*
|
||||||
rsync -rv --delete --exclude go.mod --exclude '*_test.go' --exclude '*_json.go' --exclude '*.md' --exclude LICENSE $(shell go list -modfile ./internal/wasm-tools/go.mod -m -f {{.Dir}} $(WASM_TOOLS_MODULE)/cm)/ ./src/internal/cm
|
rsync -rv --delete --exclude go.mod --exclude '*_test.go' --exclude '*_json.go' --exclude '*.md' --exclude LICENSE $(shell go list -m -f {{.Dir}} $(WASM_TOOLS_MODULE)/cm)/ ./src/internal/cm
|
||||||
|
|
||||||
# Check for Node.js used during WASM tests.
|
# Check for Node.js used during WASM tests.
|
||||||
MIN_NODEJS_VERSION=18
|
MIN_NODEJS_VERSION=18
|
||||||
@@ -339,14 +339,17 @@ TEST_PACKAGES_FAST = \
|
|||||||
embed/internal/embedtest \
|
embed/internal/embedtest \
|
||||||
encoding \
|
encoding \
|
||||||
encoding/ascii85 \
|
encoding/ascii85 \
|
||||||
|
errors \
|
||||||
encoding/asn1 \
|
encoding/asn1 \
|
||||||
encoding/base32 \
|
encoding/base32 \
|
||||||
encoding/base64 \
|
encoding/base64 \
|
||||||
encoding/csv \
|
encoding/csv \
|
||||||
encoding/hex \
|
encoding/hex \
|
||||||
|
expvar \
|
||||||
go/ast \
|
go/ast \
|
||||||
go/format \
|
go/format \
|
||||||
go/scanner \
|
go/scanner \
|
||||||
|
go/token \
|
||||||
go/version \
|
go/version \
|
||||||
hash \
|
hash \
|
||||||
hash/adler32 \
|
hash/adler32 \
|
||||||
@@ -359,6 +362,7 @@ TEST_PACKAGES_FAST = \
|
|||||||
math/cmplx \
|
math/cmplx \
|
||||||
net/http/internal/ascii \
|
net/http/internal/ascii \
|
||||||
net/mail \
|
net/mail \
|
||||||
|
net/url \
|
||||||
os \
|
os \
|
||||||
path \
|
path \
|
||||||
reflect \
|
reflect \
|
||||||
@@ -379,6 +383,7 @@ TEST_PACKAGES_FAST = \
|
|||||||
# crypto/des fails on wasi, needs panic()/recover()
|
# crypto/des fails on wasi, needs panic()/recover()
|
||||||
# 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
|
||||||
|
# encoding/xml takes a minute on linux and gives a stack overflow 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: fail on wasi; neds panic()/recover()
|
||||||
@@ -396,11 +401,13 @@ TEST_PACKAGES_FAST = \
|
|||||||
TEST_PACKAGES_LINUX := \
|
TEST_PACKAGES_LINUX := \
|
||||||
archive/zip \
|
archive/zip \
|
||||||
compress/flate \
|
compress/flate \
|
||||||
|
context \
|
||||||
crypto/aes \
|
crypto/aes \
|
||||||
crypto/des \
|
crypto/des \
|
||||||
crypto/hmac \
|
crypto/hmac \
|
||||||
debug/dwarf \
|
debug/dwarf \
|
||||||
debug/plan9obj \
|
debug/plan9obj \
|
||||||
|
encoding/xml \
|
||||||
image \
|
image \
|
||||||
io/ioutil \
|
io/ioutil \
|
||||||
mime \
|
mime \
|
||||||
@@ -437,6 +444,7 @@ TEST_PACKAGES_NONWASM = \
|
|||||||
crypto/ecdsa \
|
crypto/ecdsa \
|
||||||
debug/macho \
|
debug/macho \
|
||||||
embed/internal/embedtest \
|
embed/internal/embedtest \
|
||||||
|
expvar \
|
||||||
go/format \
|
go/format \
|
||||||
os \
|
os \
|
||||||
testing \
|
testing \
|
||||||
@@ -480,7 +488,7 @@ TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
|||||||
TEST_IOFS := false
|
TEST_IOFS := false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
TEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic'
|
TEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic|TestAsValidation'
|
||||||
TEST_ADDITIONAL_FLAGS ?=
|
TEST_ADDITIONAL_FLAGS ?=
|
||||||
|
|
||||||
# Test known-working standard library packages.
|
# Test known-working standard library packages.
|
||||||
@@ -626,7 +634,7 @@ smoketest: testchdir
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
# test simulated boards on play.tinygo.org
|
# test simulated boards on play.tinygo.org
|
||||||
ifneq ($(WASM), 0)
|
ifneq ($(WASM), 0)
|
||||||
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1
|
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=arduino_uno examples/blinky1
|
||||||
@$(MD5SUM) test.wasm
|
@$(MD5SUM) test.wasm
|
||||||
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=hifive1b examples/blinky1
|
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=hifive1b examples/blinky1
|
||||||
@$(MD5SUM) test.wasm
|
@$(MD5SUM) test.wasm
|
||||||
@@ -644,6 +652,8 @@ ifneq ($(WASM), 0)
|
|||||||
@$(MD5SUM) test.wasm
|
@$(MD5SUM) test.wasm
|
||||||
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=pico examples/blinky1
|
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=pico examples/blinky1
|
||||||
@$(MD5SUM) test.wasm
|
@$(MD5SUM) test.wasm
|
||||||
|
GOOS=js GOARCH=wasm $(TINYGO) build -size short -o test.wasm -tags=xiao_esp32s3 examples/blinky1
|
||||||
|
@$(MD5SUM) test.wasm
|
||||||
endif
|
endif
|
||||||
# test all targets/boards
|
# test all targets/boards
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
|
||||||
@@ -814,6 +824,10 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-tiny examples/echo
|
$(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-tiny examples/echo
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=vicharak_shrike-lite examples/echo
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=xiao-rp2350 examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
# test pwm
|
# test pwm
|
||||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
@@ -873,18 +887,24 @@ ifneq ($(STM32), 0)
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=stm32l0x1 examples/serial
|
$(TINYGO) build -size short -o test.hex -target=stm32l0x1 examples/serial
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=arduino-uno-q examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=arduino-uno-q examples/serial
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=arduino-uno-q examples/blinkm
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
endif
|
endif
|
||||||
$(TINYGO) build -size short -o test.hex -target=atmega328pb examples/blinkm
|
$(TINYGO) build -size short -o test.hex -target=atmega328pb examples/blinkm
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/machinetest
|
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/machinetest
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=arduino examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=arduino-uno examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=arduino-leonardo examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=arduino-leonardo examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=arduino examples/pwm
|
$(TINYGO) build -size short -o test.hex -target=arduino-uno examples/pwm
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=arduino -scheduler=tasks examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=arduino-uno -scheduler=tasks examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=arduino-mega1280 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=arduino-mega1280 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
@@ -896,13 +916,25 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=digispark examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=digispark examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=digispark examples/pwm
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=digispark examples/mcp3008
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=digispark -gc=leaking examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=digispark -gc=leaking examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
ifneq ($(XTENSA), 0)
|
ifneq ($(XTENSA), 0)
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32-generic examples/machinetest
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-generic examples/machinetest
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32s3-generic examples/machinetest
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp32-mini32 examples/blinky1
|
$(TINYGO) build -size short -o test.bin -target=esp32-mini32 examples/blinky1
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini examples/blinky1
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini examples/blinky1
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini examples/blinkm
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=nodemcu examples/blinky1
|
$(TINYGO) build -size short -o test.bin -target=nodemcu examples/blinky1
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target m5stack-core2 examples/machinetest
|
$(TINYGO) build -size short -o test.bin -target m5stack-core2 examples/machinetest
|
||||||
@@ -915,9 +947,39 @@ ifneq ($(XTENSA), 0)
|
|||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(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
|
||||||
|
# xiao-esp32s3
|
||||||
$(TINYGO) build -size short -o test.bin -target=xiao-esp32s3 examples/blinky1
|
$(TINYGO) build -size short -o test.bin -target=xiao-esp32s3 examples/blinky1
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=xiao-esp32s3 examples/blinkm
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=xiao-esp32s3 examples/mcp3008
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=xiao-esp32s3 examples/pwm
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=xiao-esp32s3 examples/adc
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
# esp32s3-supermini
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32s3-supermini examples/blinky1
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32s3-supermini examples/blinkm
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32s3-supermini examples/mcp3008
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32s3-supermini examples/adc
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
endif
|
endif
|
||||||
|
# esp32c3-supermini
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini examples/blinky1
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini examples/blinkm
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini examples/mcp3008
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini examples/pwm
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-supermini examples/adc
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp-c3-32s-kit examples/blinky1
|
$(TINYGO) build -size short -o test.bin -target=esp-c3-32s-kit examples/blinky1
|
||||||
@$(MD5SUM) test.bin
|
@$(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
|
||||||
@@ -930,6 +992,7 @@ endif
|
|||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/blinky1
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/blinky1
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
|
|
||||||
$(TINYGO) build -size short -o test.bin -target=makerfabs-esp32c3spi35 examples/machinetest
|
$(TINYGO) build -size short -o test.bin -target=makerfabs-esp32c3spi35 examples/machinetest
|
||||||
@$(MD5SUM) test.bin
|
@$(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
|
||||||
@@ -1123,7 +1186,7 @@ endif
|
|||||||
|
|
||||||
.PHONY: tools
|
.PHONY: tools
|
||||||
tools:
|
tools:
|
||||||
cd internal/tools && go generate -tags tools ./
|
go generate -tags tools ./
|
||||||
|
|
||||||
LINTDIRS=src/os/ src/reflect/
|
LINTDIRS=src/os/ src/reflect/
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
Copyright (c) 2018-2025 The TinyGo Authors. All rights reserved.
|
Copyright (c) 2018-2026 The TinyGo Authors. All rights reserved.
|
||||||
|
|
||||||
TinyGo includes portions of the Go standard library.
|
TinyGo includes portions of the Go standard library.
|
||||||
Copyright (c) 2009-2024 The Go Authors. All rights reserved.
|
Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
See https://github.com/golang/go/blob/master/LICENSE for license information.
|
||||||
|
|
||||||
TinyGo includes portions of LLVM, which is under the Apache License v2.0 with
|
TinyGo includes portions of LLVM, which is under the Apache License v2.0 with
|
||||||
LLVM Exceptions. See https://llvm.org/LICENSE.txt for license information.
|
LLVM Exceptions. See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ TinyGo is a Go compiler intended for use in small places such as microcontroller
|
|||||||
|
|
||||||
It reuses libraries used by the [Go language tools](https://golang.org/pkg/go/) alongside [LLVM](http://llvm.org) to provide an alternative way to compile programs written in the Go programming language.
|
It reuses libraries used by the [Go language tools](https://golang.org/pkg/go/) alongside [LLVM](http://llvm.org) to provide an alternative way to compile programs written in the Go programming language.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> You can help TinyGo with a financial contribution using OpenCollective. Please see https://opencollective.com/tinygo for more information. Thank you!
|
||||||
|
|
||||||
## Embedded
|
## Embedded
|
||||||
|
|
||||||
Here is an example program that blinks the built-in LED when run directly on any supported board with onboard LED:
|
Here is an example program that blinks the built-in LED when run directly on any supported board with onboard LED:
|
||||||
@@ -31,10 +34,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The above program can be compiled and run without modification on an Arduino Uno, an Adafruit ItsyBitsy M0, or any of the supported boards that have a built-in LED, just by setting the correct TinyGo compiler target. For example, this compiles and flashes an Arduino Uno:
|
The above program can be compiled and run without modification on an [Arduino Uno](https://tinygo.org/docs/reference/microcontrollers/boards/arduino-uno), an [Adafruit Circuit Playground Express](https://tinygo.org/docs/reference/microcontrollers/featured/circuitplay-express), a [Seeed Studio XIAO-ESP32S3](https://tinygo.org/docs/reference/microcontrollers/featured/xiao-esp32s3) or any of the many supported boards that have a built-in LED, just by setting the correct TinyGo compiler target. For example, this compiles and flashes an Arduino Uno:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
tinygo flash -target arduino examples/blinky1
|
tinygo flash -target arduino-uno examples/blinky1
|
||||||
```
|
```
|
||||||
|
|
||||||
## WebAssembly
|
## WebAssembly
|
||||||
@@ -63,7 +66,7 @@ tinygo build -buildmode=c-shared -o add.wasm -target=wasip1 add.go
|
|||||||
You can also use the same syntax as Go 1.24+:
|
You can also use the same syntax as Go 1.24+:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
GOARCH=wasip1 GOOS=wasm tinygo build -buildmode=c-shared -o add.wasm add.go
|
GOOS=wasip1 GOARCH=wasm tinygo build -buildmode=c-shared -o add.wasm add.go
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -74,7 +77,7 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
|
|||||||
|
|
||||||
### Embedded
|
### Embedded
|
||||||
|
|
||||||
You can compile TinyGo programs for over 94 different microcontroller boards.
|
You can compile TinyGo programs for over 150 different microcontroller boards.
|
||||||
|
|
||||||
For more information, please see https://tinygo.org/docs/reference/microcontrollers/
|
For more information, please see https://tinygo.org/docs/reference/microcontrollers/
|
||||||
|
|
||||||
@@ -139,7 +142,7 @@ Non-goals:
|
|||||||
|
|
||||||
## Why this project exists
|
## Why this project exists
|
||||||
|
|
||||||
> We never expected Go to be an embedded language and so its got serious problems...
|
> We never expected Go to be an embedded language, and so it’s got serious problems...
|
||||||
|
|
||||||
-- Rob Pike, [GopherCon 2014 Opening Keynote](https://www.youtube.com/watch?v=VoS7DsT1rdM&feature=youtu.be&t=2799)
|
-- Rob Pike, [GopherCon 2014 Opening Keynote](https://www.youtube.com/watch?v=VoS7DsT1rdM&feature=youtu.be&t=2799)
|
||||||
|
|
||||||
|
|||||||
+26
-4
@@ -19,6 +19,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -281,9 +282,13 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
allFiles[file.Name] = append(allFiles[file.Name], file)
|
allFiles[file.Name] = append(allFiles[file.Name], file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for name, files := range allFiles {
|
// Sort embedded files by name to maintain output determinism.
|
||||||
name := name
|
embedNames := make([]string, 0, len(allFiles))
|
||||||
files := files
|
for _, files := range allFiles {
|
||||||
|
embedNames = append(embedNames, files[0].Name)
|
||||||
|
}
|
||||||
|
slices.Sort(embedNames)
|
||||||
|
for _, name := range embedNames {
|
||||||
job := &compileJob{
|
job := &compileJob{
|
||||||
description: "make object file for " + name,
|
description: "make object file for " + name,
|
||||||
run: func(job *compileJob) error {
|
run: func(job *compileJob) error {
|
||||||
@@ -298,7 +303,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
sum := sha256.Sum256(data)
|
sum := sha256.Sum256(data)
|
||||||
hexSum := hex.EncodeToString(sum[:16])
|
hexSum := hex.EncodeToString(sum[:16])
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range allFiles[name] {
|
||||||
file.Size = uint64(len(data))
|
file.Size = uint64(len(data))
|
||||||
file.Hash = hexSum
|
file.Hash = hexSum
|
||||||
if file.NeedsData {
|
if file.NeedsData {
|
||||||
@@ -541,6 +546,23 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to load bitcode file: %w", err)
|
return fmt.Errorf("failed to load bitcode file: %w", err)
|
||||||
}
|
}
|
||||||
|
// Resolve duplicate function definitions before linking.
|
||||||
|
// This can happen when a newer Go version adds a function
|
||||||
|
// body in a standard library package that was previously
|
||||||
|
// just a declaration provided by //go:linkname from the
|
||||||
|
// runtime. In that case, keep the existing (runtime)
|
||||||
|
// definition by weakening the new one's linkage so the
|
||||||
|
// LLVM linker discards it in favor of the existing one.
|
||||||
|
for fn := pkgMod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
|
||||||
|
if fn.IsDeclaration() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
existing := mod.NamedFunction(fn.Name())
|
||||||
|
if existing.IsNil() || existing.IsDeclaration() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fn.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||||
|
}
|
||||||
err = llvm.LinkModules(mod, pkgMod)
|
err = llvm.LinkModules(mod, pkgMod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to link module: %w", err)
|
return fmt.Errorf("failed to link module: %w", err)
|
||||||
|
|||||||
+1
-1
@@ -107,7 +107,7 @@ struct AssemblerInvocation {
|
|||||||
EmitDwarfUnwindType EmitDwarfUnwind;
|
EmitDwarfUnwindType EmitDwarfUnwind;
|
||||||
|
|
||||||
// Whether to emit compact-unwind for non-canonical entries.
|
// Whether to emit compact-unwind for non-canonical entries.
|
||||||
// Note: maybe overriden by other constraints.
|
// Note: maybe overridden by other constraints.
|
||||||
LLVM_PREFERRED_TYPE(bool)
|
LLVM_PREFERRED_TYPE(bool)
|
||||||
unsigned EmitCompactUnwindNonCanonical : 1;
|
unsigned EmitCompactUnwindNonCanonical : 1;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
|||||||
|
|
||||||
// Version range supported by TinyGo.
|
// Version range supported by TinyGo.
|
||||||
const minorMin = 19
|
const minorMin = 19
|
||||||
const minorMax = 25
|
const minorMax = 26
|
||||||
|
|
||||||
// Check that we support this Go toolchain version.
|
// Check that we support this Go toolchain version.
|
||||||
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
|
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
|
||||||
|
|||||||
+16
-2
@@ -167,9 +167,9 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
// double.
|
// double.
|
||||||
args = append(args, "-mdouble=64")
|
args = append(args, "-mdouble=64")
|
||||||
case "riscv32":
|
case "riscv32":
|
||||||
args = append(args, "-march=rv32imac", "-fforce-enable-int128")
|
args = append(args, "-march="+riscvMarch(config, "rv32imac"), "-fforce-enable-int128")
|
||||||
case "riscv64":
|
case "riscv64":
|
||||||
args = append(args, "-march=rv64gc")
|
args = append(args, "-march="+riscvMarch(config, "rv64gc"))
|
||||||
case "mips":
|
case "mips":
|
||||||
args = append(args, "-fno-pic")
|
args = append(args, "-fno-pic")
|
||||||
}
|
}
|
||||||
@@ -298,3 +298,17 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
once.Do(unlock)
|
once.Do(unlock)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// riscvMarch returns the -march value for RISC-V library compilation.
|
||||||
|
// It extracts the value from the target's cflags if present, otherwise
|
||||||
|
// falls back to the provided default. This ensures libraries are compiled
|
||||||
|
// with the correct ISA extensions for each target (e.g. rv32imc for
|
||||||
|
// ESP32-C3 which lacks the atomic extension).
|
||||||
|
func riscvMarch(config *compileopts.Config, defaultMarch string) string {
|
||||||
|
for _, flag := range config.Target.CFlags {
|
||||||
|
if strings.HasPrefix(flag, "-march=") {
|
||||||
|
return flag[len("-march="):]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultMarch
|
||||||
|
}
|
||||||
|
|||||||
+5
-1
@@ -954,7 +954,11 @@ func findPackagePath(path string, packagePathMap map[string]string) (packagePath
|
|||||||
libPath := strings.TrimPrefix(path, filepath.Join(goenv.Get("TINYGOROOT"), "lib")+string(os.PathSeparator))
|
libPath := strings.TrimPrefix(path, filepath.Join(goenv.Get("TINYGOROOT"), "lib")+string(os.PathSeparator))
|
||||||
parts := strings.SplitN(libPath, string(os.PathSeparator), 2)
|
parts := strings.SplitN(libPath, string(os.PathSeparator), 2)
|
||||||
packagePath = "C " + parts[0]
|
packagePath = "C " + parts[0]
|
||||||
filename = parts[1]
|
if len(parts) > 1 {
|
||||||
|
filename = parts[1]
|
||||||
|
} else {
|
||||||
|
filename = parts[0]
|
||||||
|
}
|
||||||
} else if prefix := filepath.Join(goenv.Get("TINYGOROOT"), "llvm-project", "compiler-rt"); strings.HasPrefix(path, prefix) {
|
} else if prefix := filepath.Join(goenv.Get("TINYGOROOT"), "llvm-project", "compiler-rt"); strings.HasPrefix(path, prefix) {
|
||||||
packagePath = "C compiler-rt"
|
packagePath = "C compiler-rt"
|
||||||
filename = strings.TrimPrefix(path, prefix+string(os.PathSeparator))
|
filename = strings.TrimPrefix(path, prefix+string(os.PathSeparator))
|
||||||
|
|||||||
@@ -42,9 +42,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", 3668, 280, 0, 2244},
|
{"hifive1b", "examples/echo", 3680, 280, 0, 2252},
|
||||||
{"microbit", "examples/serial", 2694, 342, 8, 2248},
|
{"microbit", "examples/serial", 2694, 342, 8, 2248},
|
||||||
{"wioterminal", "examples/pininterrupt", 7187, 1489, 116, 6888},
|
{"wioterminal", "examples/pininterrupt", 7074, 1510, 120, 7248},
|
||||||
|
|
||||||
// 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
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ var validCompilerFlags = []*regexp.Regexp{
|
|||||||
re(`-f(no-)?(pic|PIC|pie|PIE)`),
|
re(`-f(no-)?(pic|PIC|pie|PIE)`),
|
||||||
re(`-f(no-)?plt`),
|
re(`-f(no-)?plt`),
|
||||||
re(`-f(no-)?rtti`),
|
re(`-f(no-)?rtti`),
|
||||||
|
re(`-f(no-)?short-enums`),
|
||||||
re(`-f(no-)?split-stack`),
|
re(`-f(no-)?split-stack`),
|
||||||
re(`-f(no-)?stack-(.+)`),
|
re(`-f(no-)?stack-(.+)`),
|
||||||
re(`-f(no-)?strict-aliasing`),
|
re(`-f(no-)?strict-aliasing`),
|
||||||
|
|||||||
@@ -536,7 +536,7 @@ func (c *Config) Programmer() (method, openocdInterface string) {
|
|||||||
case "":
|
case "":
|
||||||
// No configuration supplied.
|
// No configuration supplied.
|
||||||
return c.Target.FlashMethod, c.Target.OpenOCDInterface
|
return c.Target.FlashMethod, c.Target.OpenOCDInterface
|
||||||
case "openocd", "msd", "command":
|
case "openocd", "msd", "command", "adb":
|
||||||
// The -programmer flag only specifies the flash method.
|
// The -programmer flag only specifies the flash method.
|
||||||
return c.Options.Programmer, c.Target.OpenOCDInterface
|
return c.Options.Programmer, c.Target.OpenOCDInterface
|
||||||
case "bmp":
|
case "bmp":
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
// https://github.com/shepmaster/rust-arduino-blink-led-no-core-with-cargo/blob/master/blink/arduino.json
|
// https://github.com/shepmaster/rust-arduino-blink-led-no-core-with-cargo/blob/master/blink/arduino.json
|
||||||
type TargetSpec struct {
|
type TargetSpec struct {
|
||||||
Inherits []string `json:"inherits,omitempty"`
|
Inherits []string `json:"inherits,omitempty"`
|
||||||
|
InheritableOnly bool `json:"inheritable-only"` // this target is only meant to be inherited from, not used directly
|
||||||
Triple string `json:"llvm-target,omitempty"`
|
Triple string `json:"llvm-target,omitempty"`
|
||||||
CPU string `json:"cpu,omitempty"`
|
CPU string `json:"cpu,omitempty"`
|
||||||
ABI string `json:"target-abi,omitempty"` // roughly equivalent to -mabi= flag
|
ABI string `json:"target-abi,omitempty"` // roughly equivalent to -mabi= flag
|
||||||
@@ -63,6 +64,9 @@ type TargetSpec struct {
|
|||||||
OpenOCDCommands []string `json:"openocd-commands,omitempty"`
|
OpenOCDCommands []string `json:"openocd-commands,omitempty"`
|
||||||
OpenOCDVerify *bool `json:"openocd-verify,omitempty"` // enable verify when flashing with openocd
|
OpenOCDVerify *bool `json:"openocd-verify,omitempty"` // enable verify when flashing with openocd
|
||||||
JLinkDevice string `json:"jlink-device,omitempty"`
|
JLinkDevice string `json:"jlink-device,omitempty"`
|
||||||
|
ADBPreCommands []string `json:"adb-pre-commands,omitempty"`
|
||||||
|
ADBPushRemote string `json:"adb-push-remote,omitempty"`
|
||||||
|
ADBPostCommands []string `json:"adb-post-commands,omitempty"`
|
||||||
CodeModel string `json:"code-model,omitempty"`
|
CodeModel string `json:"code-model,omitempty"`
|
||||||
RelocationModel string `json:"relocation-model,omitempty"`
|
RelocationModel string `json:"relocation-model,omitempty"`
|
||||||
WITPackage string `json:"wit-package,omitempty"`
|
WITPackage string `json:"wit-package,omitempty"`
|
||||||
@@ -148,6 +152,11 @@ func (spec *TargetSpec) loadFromGivenStr(str string) error {
|
|||||||
|
|
||||||
// resolveInherits loads inherited targets, recursively.
|
// resolveInherits loads inherited targets, recursively.
|
||||||
func (spec *TargetSpec) resolveInherits() error {
|
func (spec *TargetSpec) resolveInherits() error {
|
||||||
|
// Save InheritableOnly before resolving, since it must not propagate
|
||||||
|
// from parent to child (a board target should not become inheritable-only
|
||||||
|
// just because its parent processor target is).
|
||||||
|
inheritableOnly := spec.InheritableOnly
|
||||||
|
|
||||||
// First create a new spec with all the inherited properties.
|
// First create a new spec with all the inherited properties.
|
||||||
newSpec := &TargetSpec{}
|
newSpec := &TargetSpec{}
|
||||||
for _, name := range spec.Inherits {
|
for _, name := range spec.Inherits {
|
||||||
@@ -173,6 +182,9 @@ func (spec *TargetSpec) resolveInherits() error {
|
|||||||
}
|
}
|
||||||
*spec = *newSpec
|
*spec = *newSpec
|
||||||
|
|
||||||
|
// Restore InheritableOnly from the original spec, not from parents.
|
||||||
|
spec.InheritableOnly = inheritableOnly
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,10 +251,17 @@ func GetTargetSpecs() (map[string]*TargetSpec, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
path := filepath.Join(dir, entry.Name())
|
path := filepath.Join(dir, entry.Name())
|
||||||
|
|
||||||
spec, err := LoadTarget(&Options{Target: path})
|
spec, err := LoadTarget(&Options{Target: path})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not list target: %w", err)
|
return nil, fmt.Errorf("could not list target: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if spec.InheritableOnly {
|
||||||
|
// Skip targets that are only meant to be inherited from, not used directly.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
|
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
|
||||||
// This doesn't look like a regular target file, but rather like
|
// This doesn't look like a regular target file, but rather like
|
||||||
// a parent target (such as targets/cortex-m.json).
|
// a parent target (such as targets/cortex-m.json).
|
||||||
|
|||||||
@@ -23,6 +23,37 @@ func TestLoadTarget(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetTargetSpecs_InheritableOnlyTargetsExcluded(t *testing.T) {
|
||||||
|
specs, err := GetTargetSpecs()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("GetTargetSpecs failed:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inheritable-only processor-level targets should not appear in the listing.
|
||||||
|
inheritableOnlyTargets := []string{"esp32", "esp32c3", "esp32s3", "esp8266", "rp2040", "rp2350", "rp2350b"}
|
||||||
|
for _, name := range inheritableOnlyTargets {
|
||||||
|
if _, ok := specs[name]; ok {
|
||||||
|
t.Errorf("inheritable-only target %q should not appear in GetTargetSpecs", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Board targets that inherit from inheritable-only targets should still appear.
|
||||||
|
boardTargets := []string{"esp32-coreboard-v2", "pico"}
|
||||||
|
for _, name := range boardTargets {
|
||||||
|
if _, ok := specs[name]; !ok {
|
||||||
|
t.Errorf("board target %q should appear in GetTargetSpecs", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadTarget_InheritableOnlyTargetStillLoadable(t *testing.T) {
|
||||||
|
// Inheritable-only targets should still be loadable directly (for building).
|
||||||
|
_, err := LoadTarget(&Options{Target: "esp32"})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("LoadTarget should still load inheritable-only target esp32: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestOverrideProperties(t *testing.T) {
|
func TestOverrideProperties(t *testing.T) {
|
||||||
baseAutoStackSize := true
|
baseAutoStackSize := true
|
||||||
base := &TargetSpec{
|
base := &TargetSpec{
|
||||||
|
|||||||
+101
-18
@@ -873,6 +873,10 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
|
|||||||
// with a LLVM intrinsic.
|
// with a LLVM intrinsic.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if ok := b.defineCryptoIntrinsic(); ok {
|
||||||
|
// Body of this function was replaced
|
||||||
|
continue
|
||||||
|
}
|
||||||
if member.Blocks == nil {
|
if member.Blocks == nil {
|
||||||
// Try to define this as an intrinsic function.
|
// Try to define this as an intrinsic function.
|
||||||
b.defineIntrinsicFunction()
|
b.defineIntrinsicFunction()
|
||||||
@@ -1599,7 +1603,8 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||||||
elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
|
elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
|
||||||
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
|
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
|
||||||
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
||||||
result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcBuf, elemsBuf, srcLen, srcCap, elemsLen, elemSize}, "append.new")
|
elemLayout := b.createObjectLayout(elemType, pos)
|
||||||
|
result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcBuf, elemsBuf, srcLen, srcCap, elemsLen, elemSize, elemLayout}, "append.new")
|
||||||
newPtr := b.CreateExtractValue(result, 0, "append.newPtr")
|
newPtr := b.CreateExtractValue(result, 0, "append.newPtr")
|
||||||
newLen := b.CreateExtractValue(result, 1, "append.newLen")
|
newLen := b.CreateExtractValue(result, 1, "append.newLen")
|
||||||
newCap := b.CreateExtractValue(result, 2, "append.newCap")
|
newCap := b.CreateExtractValue(result, 2, "append.newCap")
|
||||||
@@ -1681,13 +1686,41 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||||||
case "copy":
|
case "copy":
|
||||||
dst := argValues[0]
|
dst := argValues[0]
|
||||||
src := argValues[1]
|
src := argValues[1]
|
||||||
|
// Fetch the lengths.
|
||||||
dstLen := b.CreateExtractValue(dst, 1, "copy.dstLen")
|
dstLen := b.CreateExtractValue(dst, 1, "copy.dstLen")
|
||||||
srcLen := b.CreateExtractValue(src, 1, "copy.srcLen")
|
srcLen := b.CreateExtractValue(src, 1, "copy.srcLen")
|
||||||
dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray")
|
// Find the minimum of the lengths.
|
||||||
srcBuf := b.CreateExtractValue(src, 0, "copy.srcArray")
|
minFuncName := "llvm.umin.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
||||||
|
minFunc := b.mod.NamedFunction(minFuncName)
|
||||||
|
if minFunc.IsNil() {
|
||||||
|
fnType := llvm.FunctionType(b.uintptrType, []llvm.Type{b.uintptrType, b.uintptrType}, false)
|
||||||
|
minFunc = llvm.AddFunction(b.mod, minFuncName, fnType)
|
||||||
|
}
|
||||||
|
minLen := b.CreateCall(minFunc.GlobalValueType(), minFunc, []llvm.Value{dstLen, srcLen}, "copy.n")
|
||||||
|
// Multiply the length by the element size.
|
||||||
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
|
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
|
||||||
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
||||||
return b.createRuntimeCall("sliceCopy", []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil
|
// NOTE: This is also NSW when uintptr is int, but we can only choose one through the C API?
|
||||||
|
size := b.CreateNUWMul(minLen, elemSize, "copy.size")
|
||||||
|
// Fetch the pointers.
|
||||||
|
dstBuf := b.CreateExtractValue(dst, 0, "copy.dstPtr")
|
||||||
|
srcBuf := b.CreateExtractValue(src, 0, "copy.srcPtr")
|
||||||
|
// Create a memcpy.
|
||||||
|
call := b.createMemCopy("memmove", dstBuf, srcBuf, size)
|
||||||
|
align := b.targetData.ABITypeAlignment(elemType)
|
||||||
|
if align > 1 {
|
||||||
|
// Apply the type's alignment to the arguments.
|
||||||
|
// LLVM sometimes turns constant-length moves into loads and stores.
|
||||||
|
// It may use this alignment for the created loads and stores.
|
||||||
|
alignAttr := b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(align))
|
||||||
|
call.AddCallSiteAttribute(1, alignAttr)
|
||||||
|
call.AddCallSiteAttribute(2, alignAttr)
|
||||||
|
}
|
||||||
|
// Extend and return the copied length.
|
||||||
|
if b.targetData.TypeAllocSize(minLen.Type()) < b.targetData.TypeAllocSize(b.intType) {
|
||||||
|
minLen = b.CreateZExt(minLen, b.intType, "copy.n.zext")
|
||||||
|
}
|
||||||
|
return minLen, nil
|
||||||
case "delete":
|
case "delete":
|
||||||
m := argValues[0]
|
m := argValues[0]
|
||||||
key := argValues[1]
|
key := argValues[1]
|
||||||
@@ -1715,20 +1748,66 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||||||
return llvmLen, nil
|
return llvmLen, nil
|
||||||
case "min", "max":
|
case "min", "max":
|
||||||
// min and max builtins, added in Go 1.21.
|
// min and max builtins, added in Go 1.21.
|
||||||
// We can simply reuse the existing binop comparison code, which has all
|
// Find the corresponding intrinsic name.
|
||||||
// the edge cases figured out already.
|
ty := argTypes[0].Underlying().(*types.Basic)
|
||||||
tok := token.LSS
|
llvmType := b.getLLVMType(ty)
|
||||||
if callName == "max" {
|
info := ty.Info()
|
||||||
tok = token.GTR
|
var prefix, delimeter, typeName string
|
||||||
}
|
if info&types.IsInteger != 0 {
|
||||||
result := argValues[0]
|
// This is an integer value.
|
||||||
typ := argTypes[0]
|
// Use the LLVM int min/max intrinsics.
|
||||||
for _, arg := range argValues[1:] {
|
prefix = "llvm.s"
|
||||||
cmp, err := b.createBinOp(tok, typ, typ, result, arg, pos)
|
if info&types.IsUnsigned != 0 {
|
||||||
if err != nil {
|
prefix = "llvm.u"
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
result = b.CreateSelect(cmp, result, arg, "")
|
delimeter = ".i"
|
||||||
|
typeName = strconv.Itoa(llvmType.IntTypeWidth())
|
||||||
|
} else {
|
||||||
|
switch ty.Kind() {
|
||||||
|
case types.String:
|
||||||
|
// Strings do not have an equivalent intrinsic.
|
||||||
|
// Implement with compares and selects.
|
||||||
|
tok := token.LSS
|
||||||
|
if callName == "max" {
|
||||||
|
tok = token.GTR
|
||||||
|
}
|
||||||
|
result := argValues[0]
|
||||||
|
typ := argTypes[0]
|
||||||
|
for _, arg := range argValues[1:] {
|
||||||
|
cmp, err := b.createBinOp(tok, typ, typ, result, arg, pos)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
result = b.CreateSelect(cmp, result, arg, "")
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
case types.Float32:
|
||||||
|
typeName = "f32"
|
||||||
|
case types.Float64:
|
||||||
|
typeName = "f64"
|
||||||
|
default:
|
||||||
|
return llvm.Value{}, b.makeError(pos, "todo: min/max: unknown type")
|
||||||
|
}
|
||||||
|
// There are a few edge cases with floating point min/max:
|
||||||
|
// min(-0.0, +0.0) = -0.0
|
||||||
|
// min(NaN, number) = NaN
|
||||||
|
// The llvm.minimum.*/llvm.maximum.* intrinsics match this behavior.
|
||||||
|
// Neither Go nor LLVM defines the bit representation of resulting NaNs.
|
||||||
|
prefix = "llvm."
|
||||||
|
delimeter = "imum."
|
||||||
|
}
|
||||||
|
intrinsicName := prefix + callName + delimeter + typeName
|
||||||
|
// Find or create the intrinsic.
|
||||||
|
llvmFn := b.mod.NamedFunction(intrinsicName)
|
||||||
|
if llvmFn.IsNil() {
|
||||||
|
fnType := llvm.FunctionType(llvmType, []llvm.Type{llvmType, llvmType}, false)
|
||||||
|
llvmFn = llvm.AddFunction(b.mod, intrinsicName, fnType)
|
||||||
|
}
|
||||||
|
// Call the intrinsic repeatedly to merge the arguments.
|
||||||
|
callType := llvmFn.GlobalValueType()
|
||||||
|
result := argValues[0]
|
||||||
|
for _, arg := range argValues[1:] {
|
||||||
|
result = b.CreateCall(callType, llvmFn, []llvm.Value{result, arg}, "")
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
case "panic":
|
case "panic":
|
||||||
@@ -1901,10 +1980,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
return b.emitSV64Call(instr.Args, getPos(instr))
|
return b.emitSV64Call(instr.Args, getPos(instr))
|
||||||
case strings.HasPrefix(name, "(device/riscv.CSR)."):
|
case strings.HasPrefix(name, "(device/riscv.CSR)."):
|
||||||
return b.emitCSROperation(instr)
|
return b.emitCSROperation(instr)
|
||||||
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.Syscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscall"):
|
case (strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.Syscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscall")) && name != "syscall.SyscallN":
|
||||||
if b.GOOS != "darwin" {
|
if b.GOOS != "darwin" {
|
||||||
return b.createSyscall(instr)
|
return b.createSyscall(instr)
|
||||||
}
|
}
|
||||||
|
case name == "syscall.syscalln":
|
||||||
|
if b.GOOS == "windows" {
|
||||||
|
return b.createSyscalln(instr)
|
||||||
|
}
|
||||||
case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"):
|
case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"):
|
||||||
return b.createRawSyscallNoError(instr)
|
return b.createRawSyscallNoError(instr)
|
||||||
case name == "runtime.supportsRecover":
|
case name == "runtime.supportsRecover":
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ func typeHasPointers(t llvm.Type) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
case llvm.ArrayTypeKind:
|
case llvm.ArrayTypeKind:
|
||||||
|
if t.ArrayLength() == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if typeHasPointers(t.ElementType()) {
|
if typeHasPointers(t.ElementType()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
+153
-37
@@ -10,6 +10,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -17,6 +18,12 @@ import (
|
|||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// numMethodHasMethodSet is a flag in bit 15 of the numMethod field (uint16) in
|
||||||
|
// Named, Pointer, and Struct type descriptors. When set, an inline method set
|
||||||
|
// is present in the type descriptor. Must match the constant in
|
||||||
|
// src/internal/reflectlite/type.go.
|
||||||
|
const numMethodHasMethodSet = 0x8000
|
||||||
|
|
||||||
// Type kinds for basic types.
|
// Type kinds for basic types.
|
||||||
// They must match the constants for the Kind type in src/reflect/type.go.
|
// They must match the constants for the Kind type in src/reflect/type.go.
|
||||||
var basicTypes = [...]uint8{
|
var basicTypes = [...]uint8{
|
||||||
@@ -183,6 +190,16 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
typeFieldTypes := []*types.Var{
|
typeFieldTypes := []*types.Var{
|
||||||
types.NewVar(token.NoPos, nil, "kind", types.Typ[types.Int8]),
|
types.NewVar(token.NoPos, nil, "kind", types.Typ[types.Int8]),
|
||||||
}
|
}
|
||||||
|
// Compute the method set value for types that support methods.
|
||||||
|
var methods []*types.Func
|
||||||
|
for i := 0; i < ms.Len(); i++ {
|
||||||
|
methods = append(methods, ms.At(i).Obj().(*types.Func))
|
||||||
|
}
|
||||||
|
methodSetType := types.NewStruct([]*types.Var{
|
||||||
|
types.NewVar(token.NoPos, nil, "length", types.Typ[types.Uintptr]),
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", types.NewArray(types.Typ[types.UnsafePointer], int64(len(methods)))),
|
||||||
|
}, nil)
|
||||||
|
methodSetValue := c.getMethodSetValue(methods)
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
@@ -199,6 +216,13 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
||||||
types.NewVar(token.NoPos, nil, "underlying", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "underlying", types.Typ[types.UnsafePointer]),
|
||||||
types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]),
|
||||||
|
)
|
||||||
|
if len(methods) > 0 {
|
||||||
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", methodSetType),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], int64(len(pkgname)+1+len(name)+1))),
|
types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], int64(len(pkgname)+1+len(name)+1))),
|
||||||
)
|
)
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
@@ -218,6 +242,11 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
|
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
|
||||||
types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
|
||||||
)
|
)
|
||||||
|
if len(methods) > 0 {
|
||||||
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", methodSetType),
|
||||||
|
)
|
||||||
|
}
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
|
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
|
||||||
@@ -242,11 +271,16 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
types.NewVar(token.NoPos, nil, "numFields", types.Typ[types.Uint16]),
|
types.NewVar(token.NoPos, nil, "numFields", types.Typ[types.Uint16]),
|
||||||
types.NewVar(token.NoPos, nil, "fields", types.NewArray(c.getRuntimeType("structField"), int64(typ.NumFields()))),
|
types.NewVar(token.NoPos, nil, "fields", types.NewArray(c.getRuntimeType("structField"), int64(typ.NumFields()))),
|
||||||
)
|
)
|
||||||
|
if len(methods) > 0 {
|
||||||
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", methodSetType),
|
||||||
|
)
|
||||||
|
}
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
||||||
|
types.NewVar(token.NoPos, nil, "methods", methodSetType),
|
||||||
)
|
)
|
||||||
// TODO: methods
|
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
typeFieldTypes = append(typeFieldTypes,
|
typeFieldTypes = append(typeFieldTypes,
|
||||||
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
||||||
@@ -292,14 +326,24 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
pkgname = pkg.Name()
|
pkgname = pkg.Name()
|
||||||
}
|
}
|
||||||
pkgPathPtr := c.pkgPathPtr(pkgpath)
|
pkgPathPtr := c.pkgPathPtr(pkgpath)
|
||||||
typeFields = []llvm.Value{
|
namedNumMethods := uint64(numMethods)
|
||||||
llvm.ConstInt(c.ctx.Int16Type(), uint64(numMethods), false), // numMethods
|
if namedNumMethods&numMethodHasMethodSet != 0 {
|
||||||
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
panic("numMethods overflow: too many exported methods on named type " + name)
|
||||||
c.getTypeCode(typ.Underlying()), // underlying
|
|
||||||
pkgPathPtr, // pkgpath pointer
|
|
||||||
c.ctx.ConstString(pkgname+"."+name+"\x00", false), // name
|
|
||||||
}
|
}
|
||||||
metabyte |= 1 << 5 // "named" flag
|
if len(methods) > 0 {
|
||||||
|
namedNumMethods |= numMethodHasMethodSet
|
||||||
|
}
|
||||||
|
typeFields = []llvm.Value{
|
||||||
|
llvm.ConstInt(c.ctx.Int16Type(), namedNumMethods, false), // numMethods
|
||||||
|
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
||||||
|
c.getTypeCode(typ.Underlying()), // underlying
|
||||||
|
pkgPathPtr, // pkgpath pointer
|
||||||
|
}
|
||||||
|
if len(methods) > 0 {
|
||||||
|
typeFields = append(typeFields, methodSetValue) // methods
|
||||||
|
}
|
||||||
|
typeFields = append(typeFields, c.ctx.ConstString(pkgname+"."+name+"\x00", false)) // name
|
||||||
|
metabyte |= 1 << 5 // "named" flag
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
var dir reflectChanDir
|
var dir reflectChanDir
|
||||||
switch typ.Dir() {
|
switch typ.Dir() {
|
||||||
@@ -323,10 +367,20 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
c.getTypeCode(typ.Elem()), // elementType
|
c.getTypeCode(typ.Elem()), // elementType
|
||||||
}
|
}
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
|
ptrNumMethods := uint64(numMethods)
|
||||||
|
if ptrNumMethods&numMethodHasMethodSet != 0 {
|
||||||
|
panic("numMethods overflow: too many exported methods on pointer type")
|
||||||
|
}
|
||||||
|
if len(methods) > 0 {
|
||||||
|
ptrNumMethods |= numMethodHasMethodSet
|
||||||
|
}
|
||||||
typeFields = []llvm.Value{
|
typeFields = []llvm.Value{
|
||||||
llvm.ConstInt(c.ctx.Int16Type(), uint64(numMethods), false), // numMethods
|
llvm.ConstInt(c.ctx.Int16Type(), ptrNumMethods, false), // numMethods
|
||||||
c.getTypeCode(typ.Elem()),
|
c.getTypeCode(typ.Elem()),
|
||||||
}
|
}
|
||||||
|
if len(methods) > 0 {
|
||||||
|
typeFields = append(typeFields, methodSetValue)
|
||||||
|
}
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
typeFields = []llvm.Value{
|
typeFields = []llvm.Value{
|
||||||
llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods
|
llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods
|
||||||
@@ -353,9 +407,16 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
|
|
||||||
llvmStructType := c.getLLVMType(typ)
|
llvmStructType := c.getLLVMType(typ)
|
||||||
size := c.targetData.TypeStoreSize(llvmStructType)
|
size := c.targetData.TypeStoreSize(llvmStructType)
|
||||||
|
structNumMethods := uint64(numMethods)
|
||||||
|
if structNumMethods&numMethodHasMethodSet != 0 {
|
||||||
|
panic("numMethods overflow: too many exported methods on struct type")
|
||||||
|
}
|
||||||
|
if len(methods) > 0 {
|
||||||
|
structNumMethods |= numMethodHasMethodSet
|
||||||
|
}
|
||||||
typeFields = []llvm.Value{
|
typeFields = []llvm.Value{
|
||||||
llvm.ConstInt(c.ctx.Int16Type(), uint64(numMethods), false), // numMethods
|
llvm.ConstInt(c.ctx.Int16Type(), structNumMethods, false), // numMethods
|
||||||
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
||||||
pkgPathPtr,
|
pkgPathPtr,
|
||||||
llvm.ConstInt(c.ctx.Int32Type(), uint64(size), false), // size
|
llvm.ConstInt(c.ctx.Int32Type(), uint64(size), false), // size
|
||||||
llvm.ConstInt(c.ctx.Int16Type(), uint64(typ.NumFields()), false), // numFields
|
llvm.ConstInt(c.ctx.Int16Type(), uint64(typ.NumFields()), false), // numFields
|
||||||
@@ -407,9 +468,14 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
typeFields = append(typeFields, llvm.ConstArray(structFieldType, fields))
|
typeFields = append(typeFields, llvm.ConstArray(structFieldType, fields))
|
||||||
|
if len(methods) > 0 {
|
||||||
|
typeFields = append(typeFields, methodSetValue)
|
||||||
|
}
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}
|
typeFields = []llvm.Value{
|
||||||
// TODO: methods
|
c.getTypeCode(types.NewPointer(typ)),
|
||||||
|
methodSetValue,
|
||||||
|
}
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}
|
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}
|
||||||
// TODO: params, return values, etc
|
// TODO: params, return values, etc
|
||||||
@@ -696,17 +762,11 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
|
|||||||
// This type assertion always succeeds, so we can just set commaOk to true.
|
// This type assertion always succeeds, so we can just set commaOk to true.
|
||||||
commaOk = llvm.ConstInt(b.ctx.Int1Type(), 1, true)
|
commaOk = llvm.ConstInt(b.ctx.Int1Type(), 1, true)
|
||||||
} else {
|
} else {
|
||||||
// Type assert on interface type with methods.
|
// Type assert on an interface type with methods.
|
||||||
// This is a call to an interface type assert function.
|
// Create a call to a declared-but-not-defined function that will
|
||||||
// The interface lowering pass will define this function by filling it
|
// be lowered by the interface lowering pass into a type-ID
|
||||||
// with a type switch over all concrete types that implement this
|
// comparison chain.
|
||||||
// interface, and returning whether it's one of the matched types.
|
commaOk = b.createInterfaceTypeAssert(intf, actualTypeNum)
|
||||||
// This is very different from how interface asserts are implemented in
|
|
||||||
// the main Go compiler, where the runtime checks whether the type
|
|
||||||
// implements each method of the interface. See:
|
|
||||||
// https://research.swtch.com/interfaces
|
|
||||||
fn := b.getInterfaceImplementsFunc(expr.AssertedType)
|
|
||||||
commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, "")
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
name, _ := getTypeCodeName(expr.AssertedType)
|
name, _ := getTypeCodeName(expr.AssertedType)
|
||||||
@@ -783,20 +843,58 @@ func (c *compilerContext) getMethodsString(itf *types.Interface) string {
|
|||||||
return strings.Join(methods, "; ")
|
return strings.Join(methods, "; ")
|
||||||
}
|
}
|
||||||
|
|
||||||
// getInterfaceImplementsFunc returns a declared function that works as a type
|
// getMethodSetValue creates the method set struct value for a list of methods.
|
||||||
// switch. The interface lowering pass will define this function.
|
// The struct contains a length and a sorted array of method signature pointers.
|
||||||
func (c *compilerContext) getInterfaceImplementsFunc(assertedType types.Type) llvm.Value {
|
func (c *compilerContext) getMethodSetValue(methods []*types.Func) llvm.Value {
|
||||||
s, _ := getTypeCodeName(assertedType.Underlying())
|
// Create a sorted list of method signature global names.
|
||||||
fnName := s + ".$typeassert"
|
type methodRef struct {
|
||||||
llvmFn := c.mod.NamedFunction(fnName)
|
name string
|
||||||
if llvmFn.IsNil() {
|
value llvm.Value
|
||||||
llvmFnType := llvm.FunctionType(c.ctx.Int1Type(), []llvm.Type{c.dataPtrType}, false)
|
|
||||||
llvmFn = llvm.AddFunction(c.mod, fnName, llvmFnType)
|
|
||||||
c.addStandardDeclaredAttributes(llvmFn)
|
|
||||||
methods := c.getMethodsString(assertedType.Underlying().(*types.Interface))
|
|
||||||
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("tinygo-methods", methods))
|
|
||||||
}
|
}
|
||||||
return llvmFn
|
var refs []methodRef
|
||||||
|
for _, method := range methods {
|
||||||
|
name := method.Name()
|
||||||
|
if !token.IsExported(name) {
|
||||||
|
name = method.Pkg().Path() + "." + name
|
||||||
|
}
|
||||||
|
s, _ := getTypeCodeName(method.Type())
|
||||||
|
globalName := "reflect/types.signature:" + name + ":" + s
|
||||||
|
value := c.mod.NamedGlobal(globalName)
|
||||||
|
if value.IsNil() {
|
||||||
|
value = llvm.AddGlobal(c.mod, c.ctx.Int8Type(), globalName)
|
||||||
|
value.SetInitializer(llvm.ConstNull(c.ctx.Int8Type()))
|
||||||
|
value.SetGlobalConstant(true)
|
||||||
|
value.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||||
|
value.SetAlignment(1)
|
||||||
|
if c.Debug {
|
||||||
|
file := c.getDIFile("<Go type>")
|
||||||
|
diglobal := c.dibuilder.CreateGlobalVariableExpression(file, llvm.DIGlobalVariableExpression{
|
||||||
|
Name: globalName,
|
||||||
|
File: file,
|
||||||
|
Line: 1,
|
||||||
|
Type: c.getDIType(types.Typ[types.Uint8]),
|
||||||
|
LocalToUnit: false,
|
||||||
|
Expr: c.dibuilder.CreateExpression(nil),
|
||||||
|
AlignInBits: 8,
|
||||||
|
})
|
||||||
|
value.AddMetadata(0, diglobal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refs = append(refs, methodRef{globalName, value})
|
||||||
|
}
|
||||||
|
sort.Slice(refs, func(i, j int) bool {
|
||||||
|
return refs[i].name < refs[j].name
|
||||||
|
})
|
||||||
|
|
||||||
|
var values []llvm.Value
|
||||||
|
for _, ref := range refs {
|
||||||
|
values = append(values, ref.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.ctx.ConstStruct([]llvm.Value{
|
||||||
|
llvm.ConstInt(c.uintptrType, uint64(len(values)), false),
|
||||||
|
llvm.ConstArray(c.dataPtrType, values),
|
||||||
|
}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getInvokeFunction returns the thunk to call the given interface method. The
|
// getInvokeFunction returns the thunk to call the given interface method. The
|
||||||
@@ -823,6 +921,24 @@ func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon) llvm.Value {
|
|||||||
return llvmFn
|
return llvmFn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createInterfaceTypeAssert creates a call to a declared-but-not-defined
|
||||||
|
// $typeassert function for the given interface. This function will be defined
|
||||||
|
// by the interface lowering pass as a type-ID comparison chain, avoiding the
|
||||||
|
// need for runtime.typeImplementsMethodSet at compile time.
|
||||||
|
func (b *builder) createInterfaceTypeAssert(intf *types.Interface, actualType llvm.Value) llvm.Value {
|
||||||
|
s, _ := getTypeCodeName(intf)
|
||||||
|
fnName := s + ".$typeassert"
|
||||||
|
llvmFn := b.mod.NamedFunction(fnName)
|
||||||
|
if llvmFn.IsNil() {
|
||||||
|
llvmFnType := llvm.FunctionType(b.ctx.Int1Type(), []llvm.Type{b.dataPtrType}, false)
|
||||||
|
llvmFn = llvm.AddFunction(b.mod, fnName, llvmFnType)
|
||||||
|
b.addStandardDeclaredAttributes(llvmFn)
|
||||||
|
methods := b.getMethodsString(intf)
|
||||||
|
llvmFn.AddFunctionAttr(b.ctx.CreateStringAttribute("tinygo-methods", methods))
|
||||||
|
}
|
||||||
|
return b.CreateCall(llvmFn.GlobalValueType(), llvmFn, []llvm.Value{actualType}, "")
|
||||||
|
}
|
||||||
|
|
||||||
// getInterfaceInvokeWrapper returns a wrapper for the given method so it can be
|
// getInterfaceInvokeWrapper returns a wrapper for the given method so it can be
|
||||||
// invoked from an interface. The wrapper takes in a pointer to the underlying
|
// invoked from an interface. The wrapper takes in a pointer to the underlying
|
||||||
// value, dereferences or unpacks it if necessary, and calls the real method.
|
// value, dereferences or unpacks it if necessary, and calls the real method.
|
||||||
|
|||||||
+30
-8
@@ -50,19 +50,24 @@ func (b *builder) defineIntrinsicFunction() {
|
|||||||
// and will otherwise be lowered to regular libc memcpy/memmove calls.
|
// and will otherwise be lowered to regular libc memcpy/memmove calls.
|
||||||
func (b *builder) createMemoryCopyImpl() {
|
func (b *builder) createMemoryCopyImpl() {
|
||||||
b.createFunctionStart(true)
|
b.createFunctionStart(true)
|
||||||
fnName := "llvm." + b.fn.Name() + ".p0.p0.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
params := b.fn.Params[0:3]
|
||||||
|
b.createMemCopy(
|
||||||
|
b.fn.Name(),
|
||||||
|
b.getValue(params[0], getPos(b.fn)),
|
||||||
|
b.getValue(params[1], getPos(b.fn)),
|
||||||
|
b.getValue(params[2], getPos(b.fn)),
|
||||||
|
)
|
||||||
|
b.CreateRetVoid()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *builder) createMemCopy(kind string, dst, src, len llvm.Value) llvm.Value {
|
||||||
|
fnName := "llvm." + kind + ".p0.p0.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
||||||
llvmFn := b.mod.NamedFunction(fnName)
|
llvmFn := b.mod.NamedFunction(fnName)
|
||||||
if llvmFn.IsNil() {
|
if llvmFn.IsNil() {
|
||||||
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType, b.dataPtrType, b.uintptrType, b.ctx.Int1Type()}, false)
|
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType, b.dataPtrType, b.uintptrType, b.ctx.Int1Type()}, false)
|
||||||
llvmFn = llvm.AddFunction(b.mod, fnName, fnType)
|
llvmFn = llvm.AddFunction(b.mod, fnName, fnType)
|
||||||
}
|
}
|
||||||
var params []llvm.Value
|
return b.CreateCall(llvmFn.GlobalValueType(), llvmFn, []llvm.Value{dst, src, len, llvm.ConstInt(b.ctx.Int1Type(), 0, false)}, "")
|
||||||
for _, param := range b.fn.Params {
|
|
||||||
params = append(params, b.getValue(param, getPos(b.fn)))
|
|
||||||
}
|
|
||||||
params = append(params, llvm.ConstInt(b.ctx.Int1Type(), 0, false))
|
|
||||||
b.CreateCall(llvmFn.GlobalValueType(), llvmFn, params, "")
|
|
||||||
b.CreateRetVoid()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// createMemoryZeroImpl creates calls to llvm.memset.* to zero a block of
|
// createMemoryZeroImpl creates calls to llvm.memset.* to zero a block of
|
||||||
@@ -203,6 +208,23 @@ func (b *builder) defineMathOp() {
|
|||||||
b.CreateRet(result)
|
b.CreateRet(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *builder) defineCryptoIntrinsic() bool {
|
||||||
|
if b.fn.Pkg.Pkg.Path() != "crypto/internal/constanttime" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch b.fn.Name() {
|
||||||
|
case "boolToUint8":
|
||||||
|
b.createFunctionStart(true)
|
||||||
|
param := b.getValue(b.fn.Params[0], b.fn.Pos())
|
||||||
|
result := b.CreateZExt(param, b.ctx.Int8Type(), "")
|
||||||
|
b.CreateRet(result)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Implement most math/bits functions.
|
// Implement most math/bits functions.
|
||||||
//
|
//
|
||||||
// This implements all the functions that operate on bits. It does not yet
|
// This implements all the functions that operate on bits. It does not yet
|
||||||
|
|||||||
+90
-90
@@ -1,10 +1,10 @@
|
|||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"math/big"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
@@ -231,6 +231,12 @@ func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType l
|
|||||||
//
|
//
|
||||||
// For details on what's in this value, see src/runtime/gc_precise.go.
|
// For details on what's in this value, see src/runtime/gc_precise.go.
|
||||||
func (c *compilerContext) createObjectLayout(t llvm.Type, pos token.Pos) llvm.Value {
|
func (c *compilerContext) createObjectLayout(t llvm.Type, pos token.Pos) llvm.Value {
|
||||||
|
if !typeHasPointers(t) {
|
||||||
|
// There are no pointers in this type, so we can simplify the layout.
|
||||||
|
layout := (uint64(1) << 1) | 1
|
||||||
|
return llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, layout, false), c.dataPtrType)
|
||||||
|
}
|
||||||
|
|
||||||
// Use the element type for arrays. This works even for nested arrays.
|
// Use the element type for arrays. This works even for nested arrays.
|
||||||
for {
|
for {
|
||||||
kind := t.TypeKind()
|
kind := t.TypeKind()
|
||||||
@@ -248,54 +254,29 @@ func (c *compilerContext) createObjectLayout(t llvm.Type, pos token.Pos) llvm.Va
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a few checks to see whether we need to generate any object layout
|
// Create the pointer bitmap.
|
||||||
// information at all.
|
|
||||||
objectSizeBytes := c.targetData.TypeAllocSize(t)
|
objectSizeBytes := c.targetData.TypeAllocSize(t)
|
||||||
|
pointerAlignment := uint64(c.targetData.PrefTypeAlignment(c.dataPtrType))
|
||||||
|
bitmapLen := objectSizeBytes / pointerAlignment
|
||||||
|
bitmapBytes := (bitmapLen + 7) / 8
|
||||||
|
bitmap := make([]byte, bitmapBytes, max(bitmapBytes, 8))
|
||||||
|
c.buildPointerBitmap(bitmap, pointerAlignment, pos, t, 0)
|
||||||
|
|
||||||
|
// Try to encode the layout inline.
|
||||||
pointerSize := c.targetData.TypeAllocSize(c.dataPtrType)
|
pointerSize := c.targetData.TypeAllocSize(c.dataPtrType)
|
||||||
pointerAlignment := c.targetData.PrefTypeAlignment(c.dataPtrType)
|
|
||||||
if objectSizeBytes < pointerSize {
|
|
||||||
// Too small to contain a pointer.
|
|
||||||
layout := (uint64(1) << 1) | 1
|
|
||||||
return llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, layout, false), c.dataPtrType)
|
|
||||||
}
|
|
||||||
bitmap := c.getPointerBitmap(t, pos)
|
|
||||||
if bitmap.BitLen() == 0 {
|
|
||||||
// There are no pointers in this type, so we can simplify the layout.
|
|
||||||
// TODO: this can be done in many other cases, e.g. when allocating an
|
|
||||||
// array (like [4][]byte, which repeats a slice 4 times).
|
|
||||||
layout := (uint64(1) << 1) | 1
|
|
||||||
return llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, layout, false), c.dataPtrType)
|
|
||||||
}
|
|
||||||
if objectSizeBytes%uint64(pointerAlignment) != 0 {
|
|
||||||
// This shouldn't happen except for packed structs, which aren't
|
|
||||||
// currently used.
|
|
||||||
c.addError(pos, "internal error: unexpected object size for object with pointer field")
|
|
||||||
return llvm.ConstNull(c.dataPtrType)
|
|
||||||
}
|
|
||||||
objectSizeWords := objectSizeBytes / uint64(pointerAlignment)
|
|
||||||
|
|
||||||
pointerBits := pointerSize * 8
|
pointerBits := pointerSize * 8
|
||||||
var sizeFieldBits uint64
|
if bitmapLen < pointerBits {
|
||||||
switch pointerBits {
|
rawMask := binary.LittleEndian.Uint64(bitmap[0:8])
|
||||||
case 16:
|
layout := rawMask*pointerBits + bitmapLen
|
||||||
sizeFieldBits = 4
|
layout <<= 1
|
||||||
case 32:
|
layout |= 1
|
||||||
sizeFieldBits = 5
|
|
||||||
case 64:
|
|
||||||
sizeFieldBits = 6
|
|
||||||
default:
|
|
||||||
panic("unknown pointer size")
|
|
||||||
}
|
|
||||||
layoutFieldBits := pointerBits - 1 - sizeFieldBits
|
|
||||||
|
|
||||||
// Try to emit the value as an inline integer. This is possible in most
|
// Check if the layout fits.
|
||||||
// cases.
|
layout &= 1<<pointerBits - 1
|
||||||
if objectSizeWords < layoutFieldBits {
|
if (layout>>1)/pointerBits == rawMask {
|
||||||
// If it can be stored directly in the pointer value, do so.
|
// No set bits were shifted off.
|
||||||
// The runtime knows that if the least significant bit of the pointer is
|
return llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, layout, false), c.dataPtrType)
|
||||||
// set, the pointer contains the value itself.
|
}
|
||||||
layout := bitmap.Uint64()<<(sizeFieldBits+1) | (objectSizeWords << 1) | 1
|
|
||||||
return llvm.ConstIntToPtr(llvm.ConstInt(c.uintptrType, layout, false), c.dataPtrType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfortunately, the object layout is too big to fit in a pointer-sized
|
// Unfortunately, the object layout is too big to fit in a pointer-sized
|
||||||
@@ -303,25 +284,24 @@ func (c *compilerContext) createObjectLayout(t llvm.Type, pos token.Pos) llvm.Va
|
|||||||
|
|
||||||
// Try first whether the global already exists. All objects with a
|
// Try first whether the global already exists. All objects with a
|
||||||
// particular name have the same type, so this is possible.
|
// particular name have the same type, so this is possible.
|
||||||
globalName := "runtime/gc.layout:" + fmt.Sprintf("%d-%0*x", objectSizeWords, (objectSizeWords+15)/16, bitmap)
|
globalName := "runtime/gc.layout:" + fmt.Sprintf("%d-%0*x", bitmapLen, (bitmapLen+15)/16, bitmap)
|
||||||
global := c.mod.NamedGlobal(globalName)
|
global := c.mod.NamedGlobal(globalName)
|
||||||
if !global.IsNil() {
|
if !global.IsNil() {
|
||||||
return global
|
return global
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the global initializer.
|
// Create the global initializer.
|
||||||
bitmapBytes := make([]byte, int(objectSizeWords+7)/8)
|
bitmapByteValues := make([]llvm.Value, bitmapBytes)
|
||||||
bitmap.FillBytes(bitmapBytes)
|
i8 := c.ctx.Int8Type()
|
||||||
reverseBytes(bitmapBytes) // big-endian to little-endian
|
for i, b := range bitmap {
|
||||||
var bitmapByteValues []llvm.Value
|
bitmapByteValues[i] = llvm.ConstInt(i8, uint64(b), false)
|
||||||
for _, b := range bitmapBytes {
|
|
||||||
bitmapByteValues = append(bitmapByteValues, llvm.ConstInt(c.ctx.Int8Type(), uint64(b), false))
|
|
||||||
}
|
}
|
||||||
initializer := c.ctx.ConstStruct([]llvm.Value{
|
initializer := c.ctx.ConstStruct([]llvm.Value{
|
||||||
llvm.ConstInt(c.uintptrType, objectSizeWords, false),
|
llvm.ConstInt(c.uintptrType, bitmapLen, false),
|
||||||
llvm.ConstArray(c.ctx.Int8Type(), bitmapByteValues),
|
llvm.ConstArray(i8, bitmapByteValues),
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
|
// Create the actual global.
|
||||||
global = llvm.AddGlobal(c.mod, initializer.Type(), globalName)
|
global = llvm.AddGlobal(c.mod, initializer.Type(), globalName)
|
||||||
global.SetInitializer(initializer)
|
global.SetInitializer(initializer)
|
||||||
global.SetUnnamedAddr(true)
|
global.SetUnnamedAddr(true)
|
||||||
@@ -329,6 +309,7 @@ func (c *compilerContext) createObjectLayout(t llvm.Type, pos token.Pos) llvm.Va
|
|||||||
global.SetLinkage(llvm.LinkOnceODRLinkage)
|
global.SetLinkage(llvm.LinkOnceODRLinkage)
|
||||||
if c.targetData.PrefTypeAlignment(c.uintptrType) < 2 {
|
if c.targetData.PrefTypeAlignment(c.uintptrType) < 2 {
|
||||||
// AVR doesn't have alignment by default.
|
// AVR doesn't have alignment by default.
|
||||||
|
// The lowest bit must be unset to distinguish this from an inline layout.
|
||||||
global.SetAlignment(2)
|
global.SetAlignment(2)
|
||||||
}
|
}
|
||||||
if c.Debug && pos != token.NoPos {
|
if c.Debug && pos != token.NoPos {
|
||||||
@@ -360,52 +341,71 @@ func (c *compilerContext) createObjectLayout(t llvm.Type, pos token.Pos) llvm.Va
|
|||||||
return global
|
return global
|
||||||
}
|
}
|
||||||
|
|
||||||
// getPointerBitmap scans the given LLVM type for pointers and sets bits in a
|
// buildPointerBitmap scans the given LLVM type for pointers and sets bits in a
|
||||||
// bigint at the word offset that contains a pointer. This scan is recursive.
|
// bitmap at the word offset that contains a pointer. This scan is recursive.
|
||||||
func (c *compilerContext) getPointerBitmap(typ llvm.Type, pos token.Pos) *big.Int {
|
func (c *compilerContext) buildPointerBitmap(
|
||||||
alignment := c.targetData.PrefTypeAlignment(c.dataPtrType)
|
dst []byte,
|
||||||
switch typ.TypeKind() {
|
ptrAlign uint64,
|
||||||
|
pos token.Pos,
|
||||||
|
t llvm.Type,
|
||||||
|
offset uint64,
|
||||||
|
) {
|
||||||
|
switch t.TypeKind() {
|
||||||
case llvm.IntegerTypeKind, llvm.FloatTypeKind, llvm.DoubleTypeKind:
|
case llvm.IntegerTypeKind, llvm.FloatTypeKind, llvm.DoubleTypeKind:
|
||||||
return big.NewInt(0)
|
// These types do not contain pointers.
|
||||||
|
|
||||||
case llvm.PointerTypeKind:
|
case llvm.PointerTypeKind:
|
||||||
return big.NewInt(1)
|
// Set the corresponding position in the bitmap.
|
||||||
|
dst[offset/8] |= 1 << (offset % 8)
|
||||||
|
|
||||||
case llvm.StructTypeKind:
|
case llvm.StructTypeKind:
|
||||||
ptrs := big.NewInt(0)
|
// Recurse over struct elements.
|
||||||
for i, subtyp := range typ.StructElementTypes() {
|
for i, et := range t.StructElementTypes() {
|
||||||
subptrs := c.getPointerBitmap(subtyp, pos)
|
eo := c.targetData.ElementOffset(t, i)
|
||||||
if subptrs.BitLen() == 0 {
|
if eo%uint64(ptrAlign) != 0 {
|
||||||
|
if typeHasPointers(et) {
|
||||||
|
// This error will let the compilation fail, but by continuing
|
||||||
|
// the error can still easily be shown.
|
||||||
|
c.addError(pos, "internal error: allocated struct contains unaligned pointer")
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
offset := c.targetData.ElementOffset(typ, i)
|
c.buildPointerBitmap(
|
||||||
if offset%uint64(alignment) != 0 {
|
dst,
|
||||||
// This error will let the compilation fail, but by continuing
|
ptrAlign,
|
||||||
// the error can still easily be shown.
|
pos,
|
||||||
c.addError(pos, "internal error: allocated struct contains unaligned pointer")
|
et,
|
||||||
continue
|
offset+(eo/ptrAlign),
|
||||||
}
|
)
|
||||||
subptrs.Lsh(subptrs, uint(offset)/uint(alignment))
|
|
||||||
ptrs.Or(ptrs, subptrs)
|
|
||||||
}
|
}
|
||||||
return ptrs
|
|
||||||
case llvm.ArrayTypeKind:
|
case llvm.ArrayTypeKind:
|
||||||
subtyp := typ.ElementType()
|
// Recurse over array elements.
|
||||||
subptrs := c.getPointerBitmap(subtyp, pos)
|
len := t.ArrayLength()
|
||||||
ptrs := big.NewInt(0)
|
if len <= 0 {
|
||||||
if subptrs.BitLen() == 0 {
|
return
|
||||||
return ptrs
|
|
||||||
}
|
}
|
||||||
elementSize := c.targetData.TypeAllocSize(subtyp)
|
et := t.ElementType()
|
||||||
if elementSize%uint64(alignment) != 0 {
|
elementSize := c.targetData.TypeAllocSize(et)
|
||||||
// This error will let the compilation fail (but continues so that
|
if elementSize%ptrAlign != 0 {
|
||||||
// other errors can be shown).
|
if typeHasPointers(et) {
|
||||||
c.addError(pos, "internal error: allocated array contains unaligned pointer")
|
// This error will let the compilation fail (but continues so that
|
||||||
return ptrs
|
// other errors can be shown).
|
||||||
|
c.addError(pos, "internal error: allocated array contains unaligned pointer")
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
for i := 0; i < typ.ArrayLength(); i++ {
|
elementSize /= ptrAlign
|
||||||
ptrs.Lsh(ptrs, uint(elementSize)/uint(alignment))
|
for i := 0; i < len; i++ {
|
||||||
ptrs.Or(ptrs, subptrs)
|
c.buildPointerBitmap(
|
||||||
|
dst,
|
||||||
|
ptrAlign,
|
||||||
|
pos,
|
||||||
|
et,
|
||||||
|
offset+uint64(i)*elementSize,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return ptrs
|
|
||||||
default:
|
default:
|
||||||
// Should not happen.
|
// Should not happen.
|
||||||
panic("unknown LLVM type")
|
panic("unknown LLVM type")
|
||||||
|
|||||||
+1
-7
@@ -184,12 +184,6 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
|
|||||||
// be modified.
|
// be modified.
|
||||||
llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
llvmFn.AddAttributeAtIndex(2, 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))
|
||||||
case "runtime.sliceCopy":
|
|
||||||
// Copying a slice won't capture any of the parameters.
|
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("writeonly"), 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("nocapture"), 0))
|
|
||||||
case "runtime.stringFromBytes":
|
case "runtime.stringFromBytes":
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0))
|
||||||
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
|
llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0))
|
||||||
@@ -546,7 +540,7 @@ func (c *compilerContext) isValidWasmType(typ types.Type, site wasmSite) bool {
|
|||||||
}
|
}
|
||||||
for i := 0; i < typ.NumFields(); i++ {
|
for i := 0; i < typ.NumFields(); i++ {
|
||||||
ftyp := typ.Field(i).Type()
|
ftyp := typ.Field(i).Type()
|
||||||
if ftyp.String() == "structs.HostLayout" {
|
if types.Unalias(ftyp).String() == "structs.HostLayout" {
|
||||||
hasHostLayout = true
|
hasHostLayout = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -349,6 +349,130 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createSyscalln emits instructions for the syscall.syscalln function on
|
||||||
|
// Windows. This handles the variadic calling convention used in Go 1.26+:
|
||||||
|
//
|
||||||
|
// func syscalln(fn, n uintptr, args ...uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
//
|
||||||
|
// The function generates a switch on n to dispatch to the correct fixed-argument
|
||||||
|
// function pointer call with SetLastError(0)/GetLastError() wrapping.
|
||||||
|
func (b *builder) createSyscalln(call *ssa.CallCommon) (llvm.Value, error) {
|
||||||
|
const maxArgs = 18 // Windows syscalls support up to 18 args
|
||||||
|
|
||||||
|
isI386 := strings.HasPrefix(b.Triple, "i386-")
|
||||||
|
|
||||||
|
// Get the function pointer (call.Args[0]) and n (call.Args[1]).
|
||||||
|
fn := b.getValue(call.Args[0], getPos(call))
|
||||||
|
fnPtr := b.CreateIntToPtr(fn, b.dataPtrType, "")
|
||||||
|
n := b.getValue(call.Args[1], getPos(call))
|
||||||
|
|
||||||
|
// Get the variadic args slice (call.Args[2]).
|
||||||
|
// In SSA, the variadic slice is the third argument.
|
||||||
|
var argsPtr llvm.Value
|
||||||
|
if len(call.Args) > 2 {
|
||||||
|
argsSlice := b.getValue(call.Args[2], getPos(call))
|
||||||
|
argsPtr = b.CreateExtractValue(argsSlice, 0, "args.data")
|
||||||
|
} else {
|
||||||
|
argsPtr = llvm.ConstNull(b.dataPtrType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare SetLastError and GetLastError.
|
||||||
|
setLastError := b.mod.NamedFunction("SetLastError")
|
||||||
|
if setLastError.IsNil() {
|
||||||
|
llvmType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.ctx.Int32Type()}, false)
|
||||||
|
setLastError = llvm.AddFunction(b.mod, "SetLastError", llvmType)
|
||||||
|
if isI386 {
|
||||||
|
setLastError.SetFunctionCallConv(llvm.X86StdcallCallConv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getLastError := b.mod.NamedFunction("GetLastError")
|
||||||
|
if getLastError.IsNil() {
|
||||||
|
llvmType := llvm.FunctionType(b.ctx.Int32Type(), nil, false)
|
||||||
|
getLastError = llvm.AddFunction(b.mod, "GetLastError", llvmType)
|
||||||
|
if isI386 {
|
||||||
|
getLastError.SetFunctionCallConv(llvm.X86StdcallCallConv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retType := b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType, b.uintptrType}, false)
|
||||||
|
|
||||||
|
// Create the merge block where all cases converge.
|
||||||
|
mergeBB := b.insertBasicBlock("syscalln.merge")
|
||||||
|
|
||||||
|
// Create the default (panic) block.
|
||||||
|
panicBB := b.insertBasicBlock("syscalln.panic")
|
||||||
|
|
||||||
|
// Create the switch on n.
|
||||||
|
sw := b.CreateSwitch(n, panicBB, maxArgs+1)
|
||||||
|
|
||||||
|
// We'll collect blocks and values for the PHI node.
|
||||||
|
var incomingVals []llvm.Value
|
||||||
|
var incomingBlocks []llvm.BasicBlock
|
||||||
|
|
||||||
|
// Generate a case for each arg count 0..maxArgs.
|
||||||
|
for i := 0; i <= maxArgs; i++ {
|
||||||
|
caseBB := b.insertBasicBlock("syscalln.case" + strconv.Itoa(i))
|
||||||
|
sw.AddCase(llvm.ConstInt(b.uintptrType, uint64(i), false), caseBB)
|
||||||
|
b.SetInsertPointAtEnd(caseBB)
|
||||||
|
|
||||||
|
// Load args[0] through args[i-1] from the slice data pointer.
|
||||||
|
var params []llvm.Value
|
||||||
|
var paramTypes []llvm.Type
|
||||||
|
for j := 0; j < i; j++ {
|
||||||
|
gep := b.CreateInBoundsGEP(b.uintptrType, argsPtr, []llvm.Value{
|
||||||
|
llvm.ConstInt(b.ctx.Int32Type(), uint64(j), false),
|
||||||
|
}, "")
|
||||||
|
arg := b.CreateLoad(b.uintptrType, gep, "")
|
||||||
|
params = append(params, arg)
|
||||||
|
paramTypes = append(paramTypes, b.uintptrType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLastError(0)
|
||||||
|
setCall := b.CreateCall(setLastError.GlobalValueType(), setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, "")
|
||||||
|
var sp llvm.Value
|
||||||
|
if isI386 {
|
||||||
|
setCall.SetInstructionCallConv(llvm.X86StdcallCallConv)
|
||||||
|
sp = b.readStackPointer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call fn(args...)
|
||||||
|
fnType := llvm.FunctionType(b.uintptrType, paramTypes, false)
|
||||||
|
syscallResult := b.CreateCall(fnType, fnPtr, params, "")
|
||||||
|
if isI386 {
|
||||||
|
syscallResult.SetInstructionCallConv(llvm.X86StdcallCallConv)
|
||||||
|
b.writeStackPointer(sp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// err = GetLastError()
|
||||||
|
errResult := b.CreateCall(getLastError.GlobalValueType(), getLastError, nil, "err")
|
||||||
|
if isI386 {
|
||||||
|
errResult.SetInstructionCallConv(llvm.X86StdcallCallConv)
|
||||||
|
}
|
||||||
|
if b.uintptrType != b.ctx.Int32Type() {
|
||||||
|
errResult = b.CreateZExt(errResult, b.uintptrType, "err.uintptr")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build {r1, 0, err}
|
||||||
|
result := llvm.ConstNull(retType)
|
||||||
|
result = b.CreateInsertValue(result, syscallResult, 0, "")
|
||||||
|
result = b.CreateInsertValue(result, errResult, 2, "")
|
||||||
|
|
||||||
|
incomingVals = append(incomingVals, result)
|
||||||
|
incomingBlocks = append(incomingBlocks, b.Builder.GetInsertBlock())
|
||||||
|
b.CreateBr(mergeBB)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panic block for n > maxArgs.
|
||||||
|
b.SetInsertPointAtEnd(panicBB)
|
||||||
|
b.CreateUnreachable()
|
||||||
|
|
||||||
|
// Merge block: PHI node to select the result.
|
||||||
|
b.SetInsertPointAtEnd(mergeBB)
|
||||||
|
phi := b.CreatePHI(retType, "syscalln.result")
|
||||||
|
phi.AddIncoming(incomingVals, incomingBlocks)
|
||||||
|
return phi, nil
|
||||||
|
}
|
||||||
|
|
||||||
// createRawSyscallNoError emits instructions for the Linux-specific
|
// createRawSyscallNoError emits instructions for the Linux-specific
|
||||||
// syscall.rawSyscallNoError function.
|
// syscall.rawSyscallNoError function.
|
||||||
func (b *builder) createRawSyscallNoError(call *ssa.CallCommon) (llvm.Value, error) {
|
func (b *builder) createRawSyscallNoError(call *ssa.CallCommon) (llvm.Value, error) {
|
||||||
|
|||||||
Vendored
+8
@@ -24,6 +24,10 @@ var (
|
|||||||
x *byte
|
x *byte
|
||||||
y [61]uintptr
|
y [61]uintptr
|
||||||
}
|
}
|
||||||
|
struct5 *struct {
|
||||||
|
x *byte
|
||||||
|
y [30]uintptr
|
||||||
|
}
|
||||||
|
|
||||||
slice1 []byte
|
slice1 []byte
|
||||||
slice2 []*int
|
slice2 []*int
|
||||||
@@ -58,6 +62,10 @@ func newStruct() {
|
|||||||
x *byte
|
x *byte
|
||||||
y [61]uintptr
|
y [61]uintptr
|
||||||
})
|
})
|
||||||
|
struct5 = new(struct {
|
||||||
|
x *byte
|
||||||
|
y [30]uintptr
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFuncValue() *func() {
|
func newFuncValue() *func() {
|
||||||
|
|||||||
Vendored
+8
-4
@@ -16,11 +16,12 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
@main.struct2 = hidden global ptr null, align 4
|
@main.struct2 = hidden global ptr null, align 4
|
||||||
@main.struct3 = hidden global ptr null, align 4
|
@main.struct3 = hidden global ptr null, align 4
|
||||||
@main.struct4 = hidden global ptr null, align 4
|
@main.struct4 = hidden global ptr null, align 4
|
||||||
|
@main.struct5 = hidden global ptr null, align 4
|
||||||
@main.slice1 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
@main.slice1 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
||||||
@main.slice2 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
@main.slice2 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
||||||
@main.slice3 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
@main.slice3 = hidden global { ptr, i32, i32 } zeroinitializer, align 4
|
||||||
@"runtime/gc.layout:62-2000000000000001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00 " }
|
@"runtime/gc.layout:62-0100000000000020" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00 " }
|
||||||
@"runtime/gc.layout:62-0001" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00\00" }
|
@"runtime/gc.layout:62-0100000000000000" = linkonce_odr unnamed_addr constant { i32, [8 x i8] } { i32 62, [8 x i8] c"\01\00\00\00\00\00\00\00" }
|
||||||
@"reflect/types.type:basic:complex128" = linkonce_odr constant { i8, ptr } { i8 80, ptr @"reflect/types.type:pointer:basic:complex128" }, align 4
|
@"reflect/types.type:basic:complex128" = linkonce_odr constant { i8, ptr } { i8 80, ptr @"reflect/types.type:pointer:basic:complex128" }, align 4
|
||||||
@"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:complex128" }, align 4
|
@"reflect/types.type:pointer:basic:complex128" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:complex128" }, align 4
|
||||||
|
|
||||||
@@ -80,12 +81,15 @@ entry:
|
|||||||
%new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
%new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new1, ptr @main.struct2, align 4
|
store ptr %new1, ptr @main.struct2, align 4
|
||||||
%new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #3
|
%new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0100000000000020", ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new2, ptr @main.struct3, align 4
|
store ptr %new2, ptr @main.struct3, align 4
|
||||||
%new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #3
|
%new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0100000000000000", ptr undef) #3
|
||||||
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
store ptr %new3, ptr @main.struct4, align 4
|
store ptr %new3, ptr @main.struct4, align 4
|
||||||
|
%new4 = call align 4 dereferenceable(124) ptr @runtime.alloc(i32 124, ptr nonnull inttoptr (i32 127 to ptr), ptr undef) #3
|
||||||
|
call void @runtime.trackPointer(ptr nonnull %new4, ptr nonnull %stackalloc, ptr undef) #3
|
||||||
|
store ptr %new4, ptr @main.struct5, align 4
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+33
-27
@@ -22,6 +22,9 @@ entry:
|
|||||||
ret i32 %a
|
ret i32 %a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i32 @llvm.smin.i32(i32, i32) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.min2(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
define hidden i32 @main.min2(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
@@ -53,6 +56,9 @@ entry:
|
|||||||
ret i8 %0
|
ret i8 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i8 @llvm.umin.i8(i8, i8) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.minUnsigned(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
define hidden i32 @main.minUnsigned(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
@@ -60,22 +66,29 @@ entry:
|
|||||||
ret i32 %0
|
ret i32 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i32 @llvm.umin.i32(i32, i32) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden float @main.minFloat32(float %a, float %b, ptr %context) unnamed_addr #2 {
|
define hidden float @main.minFloat32(float %a, float %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp olt float %a, %b
|
%0 = call float @llvm.minimum.f32(float %a, float %b)
|
||||||
%1 = select i1 %0, float %a, float %b
|
ret float %0
|
||||||
ret float %1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare float @llvm.minimum.f32(float, float) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden double @main.minFloat64(double %a, double %b, ptr %context) unnamed_addr #2 {
|
define hidden double @main.minFloat64(double %a, double %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp olt double %a, %b
|
%0 = call double @llvm.minimum.f64(double %a, double %b)
|
||||||
%1 = select i1 %0, double %a, double %b
|
ret double %0
|
||||||
ret double %1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare double @llvm.minimum.f64(double, double) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._string @main.minString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {
|
define hidden %runtime._string @main.minString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
@@ -100,6 +113,9 @@ entry:
|
|||||||
ret i32 %0
|
ret i32 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i32 @llvm.smax.i32(i32, i32) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.maxUint(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
define hidden i32 @main.maxUint(i32 %a, i32 %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
@@ -107,14 +123,19 @@ entry:
|
|||||||
ret i32 %0
|
ret i32 %0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i32 @llvm.umax.i32(i32, i32) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden float @main.maxFloat32(float %a, float %b, ptr %context) unnamed_addr #2 {
|
define hidden float @main.maxFloat32(float %a, float %b, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%0 = fcmp ogt float %a, %b
|
%0 = call float @llvm.maximum.f32(float %a, float %b)
|
||||||
%1 = select i1 %0, float %a, float %b
|
ret float %0
|
||||||
ret float %1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare float @llvm.maximum.f32(float, float) #3
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden %runtime._string @main.maxString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {
|
define hidden %runtime._string @main.maxString(ptr readonly %a.data, i32 %a.len, ptr readonly %b.data, i32 %b.len, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
@@ -139,7 +160,7 @@ entry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
|
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
|
||||||
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #3
|
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #4
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
|
define hidden void @main.clearZeroSizedSlice(ptr %s.data, i32 %s.len, i32 %s.cap, ptr %context) unnamed_addr #2 {
|
||||||
@@ -156,24 +177,9 @@ entry:
|
|||||||
|
|
||||||
declare void @runtime.hashmapClear(ptr dereferenceable_or_null(40), ptr) #1
|
declare void @runtime.hashmapClear(ptr dereferenceable_or_null(40), ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
|
||||||
declare i32 @llvm.smin.i32(i32, i32) #4
|
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
|
||||||
declare i8 @llvm.umin.i8(i8, i8) #4
|
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
|
||||||
declare i32 @llvm.umin.i32(i32, i32) #4
|
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
|
||||||
declare i32 @llvm.smax.i32(i32, i32) #4
|
|
||||||
|
|
||||||
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
|
||||||
declare i32 @llvm.umax.i32(i32, i32) #4
|
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
||||||
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
||||||
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
||||||
attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) }
|
attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
|
||||||
attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
|
attributes #4 = { nocallback nofree nounwind willreturn memory(argmem: write) }
|
||||||
attributes #5 = { nounwind }
|
attributes #5 = { nounwind }
|
||||||
|
|||||||
+35
-28
@@ -17,8 +17,8 @@ entry:
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr undef) #9
|
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr undef) #11
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ declare void @main.regularFunction(i32, ptr) #2
|
|||||||
define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 {
|
define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 {
|
||||||
entry:
|
entry:
|
||||||
%unpack.int = ptrtoint ptr %0 to i32
|
%unpack.int = ptrtoint ptr %0 to i32
|
||||||
call void @main.regularFunction(i32 %unpack.int, ptr undef) #9
|
call void @main.regularFunction(i32 %unpack.int, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,8 +39,8 @@ declare void @"internal/task.start"(i32, ptr, i32, ptr) #2
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr undef) #9
|
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr undef) #11
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 %stacksize, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,18 +61,18 @@ entry:
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
|
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #11
|
||||||
store i32 3, ptr %n, align 4
|
store i32 3, ptr %n, align 4
|
||||||
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
|
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #11
|
||||||
store i32 5, ptr %0, align 4
|
store i32 5, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
store ptr %n, ptr %1, align 4
|
store ptr %n, ptr %1, align 4
|
||||||
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #9
|
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr undef) #11
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #11
|
||||||
%2 = load i32, ptr %n, align 4
|
%2 = load i32, ptr %n, align 4
|
||||||
call void @runtime.printlock(ptr undef) #9
|
call void @runtime.printlock(ptr undef) #11
|
||||||
call void @runtime.printint32(i32 %2, ptr undef) #9
|
call void @runtime.printint32(i32 %2, ptr undef) #11
|
||||||
call void @runtime.printunlock(ptr undef) #9
|
call void @runtime.printunlock(ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,14 +102,14 @@ declare void @runtime.printunlock(ptr) #2
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
|
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
|
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #11
|
||||||
store i32 5, ptr %0, align 4
|
store i32 5, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
store ptr %fn.context, ptr %1, align 4
|
store ptr %fn.context, ptr %1, align 4
|
||||||
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8
|
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8
|
||||||
store ptr %fn.funcptr, ptr %2, align 4
|
store ptr %fn.funcptr, ptr %2, align 4
|
||||||
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #9
|
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr undef) #11
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ entry:
|
|||||||
%3 = load ptr, ptr %2, align 4
|
%3 = load ptr, ptr %2, align 4
|
||||||
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
|
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
|
||||||
%5 = load ptr, ptr %4, align 4
|
%5 = load ptr, ptr %4, align 4
|
||||||
call void %5(i32 %1, ptr %3) #9
|
call void %5(i32 %1, ptr %3) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,16 +134,21 @@ entry:
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {
|
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9
|
%copy.n = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)
|
||||||
|
call void @llvm.memmove.p0.p0.i32(ptr align 1 %dst.data, ptr align 1 %src.data, i32 %copy.n, i1 false)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #2
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i32 @llvm.umin.i32(i32, i32) #7
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
|
||||||
|
declare void @llvm.memmove.p0.p0.i32(ptr nocapture writeonly, ptr nocapture readonly, i32, i1 immarg) #8
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
call void @runtime.chanClose(ptr %ch, ptr undef) #9
|
call void @runtime.chanClose(ptr %ch, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +157,7 @@ declare void @runtime.chanClose(ptr dereferenceable_or_null(36), ptr) #2
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
|
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 {
|
||||||
entry:
|
entry:
|
||||||
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
|
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #11
|
||||||
store ptr %itf.value, ptr %0, align 4
|
store ptr %itf.value, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
store ptr @"main$string", ptr %1, align 4
|
store ptr @"main$string", ptr %1, align 4
|
||||||
@@ -160,15 +165,15 @@ entry:
|
|||||||
store i32 4, ptr %2, align 4
|
store i32 4, ptr %2, align 4
|
||||||
%3 = getelementptr inbounds nuw i8, ptr %0, i32 12
|
%3 = getelementptr inbounds nuw i8, ptr %0, i32 12
|
||||||
store ptr %itf.typecode, ptr %3, align 4
|
store ptr %itf.typecode, ptr %3, align 4
|
||||||
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr undef) #9
|
%stacksize = call i32 @"internal/task.getGoroutineStackSize"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr undef) #11
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 %stacksize, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i32, ptr, ptr) #7
|
declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i32, ptr, ptr) #9
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #8 {
|
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #10 {
|
||||||
entry:
|
entry:
|
||||||
%1 = load ptr, ptr %0, align 4
|
%1 = load ptr, ptr %0, align 4
|
||||||
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
@@ -177,7 +182,7 @@ entry:
|
|||||||
%5 = load i32, ptr %4, align 4
|
%5 = load i32, ptr %4, align 4
|
||||||
%6 = getelementptr inbounds nuw i8, ptr %0, i32 12
|
%6 = getelementptr inbounds nuw i8, ptr %0, i32 12
|
||||||
%7 = load ptr, ptr %6, align 4
|
%7 = load ptr, ptr %6, align 4
|
||||||
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9
|
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +193,8 @@ attributes #3 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb
|
|||||||
attributes #4 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
|
attributes #4 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
|
||||||
attributes #5 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
|
attributes #5 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
|
||||||
attributes #6 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper" }
|
attributes #6 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper" }
|
||||||
attributes #7 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
|
attributes #7 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
|
||||||
attributes #8 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
|
attributes #8 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
|
||||||
attributes #9 = { nounwind }
|
attributes #9 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
|
||||||
|
attributes #10 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
|
||||||
|
attributes #11 = { nounwind }
|
||||||
|
|||||||
+41
-34
@@ -19,7 +19,7 @@ entry:
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +31,8 @@ declare void @runtime.deadlock(ptr) #1
|
|||||||
define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 {
|
define linkonce_odr void @"main.regularFunction$gowrapper"(ptr %0) unnamed_addr #3 {
|
||||||
entry:
|
entry:
|
||||||
%unpack.int = ptrtoint ptr %0 to i32
|
%unpack.int = ptrtoint ptr %0 to i32
|
||||||
call void @main.regularFunction(i32 %unpack.int, ptr undef) #9
|
call void @main.regularFunction(i32 %unpack.int, ptr undef) #11
|
||||||
call void @runtime.deadlock(ptr undef) #9
|
call void @runtime.deadlock(ptr undef) #11
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ declare void @"internal/task.start"(i32, ptr, i32, ptr) #1
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ define linkonce_odr void @"main.inlineFunctionGoroutine$1$gowrapper"(ptr %0) unn
|
|||||||
entry:
|
entry:
|
||||||
%unpack.int = ptrtoint ptr %0 to i32
|
%unpack.int = ptrtoint ptr %0 to i32
|
||||||
call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, ptr undef)
|
call void @"main.inlineFunctionGoroutine$1"(i32 %unpack.int, ptr undef)
|
||||||
call void @runtime.deadlock(ptr undef) #9
|
call void @runtime.deadlock(ptr undef) #11
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,21 +64,21 @@ entry:
|
|||||||
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9
|
%n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #11
|
||||||
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9
|
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #11
|
||||||
store i32 3, ptr %n, align 4
|
store i32 3, ptr %n, align 4
|
||||||
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9
|
call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #11
|
||||||
call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr nonnull %stackalloc, ptr undef) #9
|
call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr nonnull %stackalloc, ptr undef) #11
|
||||||
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9
|
%0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #11
|
||||||
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
|
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #11
|
||||||
store i32 5, ptr %0, align 4
|
store i32 5, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
store ptr %n, ptr %1, align 4
|
store ptr %n, ptr %1, align 4
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #11
|
||||||
%2 = load i32, ptr %n, align 4
|
%2 = load i32, ptr %n, align 4
|
||||||
call void @runtime.printlock(ptr undef) #9
|
call void @runtime.printlock(ptr undef) #11
|
||||||
call void @runtime.printint32(i32 %2, ptr undef) #9
|
call void @runtime.printint32(i32 %2, ptr undef) #11
|
||||||
call void @runtime.printunlock(ptr undef) #9
|
call void @runtime.printunlock(ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ entry:
|
|||||||
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
%3 = load ptr, ptr %2, align 4
|
%3 = load ptr, ptr %2, align 4
|
||||||
call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3)
|
call void @"main.closureFunctionGoroutine$1"(i32 %1, ptr %3)
|
||||||
call void @runtime.deadlock(ptr undef) #9
|
call void @runtime.deadlock(ptr undef) #11
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,14 +110,14 @@ declare void @runtime.printunlock(ptr) #1
|
|||||||
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #2 {
|
define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9
|
%0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #11
|
||||||
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
|
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #11
|
||||||
store i32 5, ptr %0, align 4
|
store i32 5, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
store ptr %fn.context, ptr %1, align 4
|
store ptr %fn.context, ptr %1, align 4
|
||||||
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8
|
%2 = getelementptr inbounds nuw i8, ptr %0, i32 8
|
||||||
store ptr %fn.funcptr, ptr %2, align 4
|
store ptr %fn.funcptr, ptr %2, align 4
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 65536, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 65536, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +129,8 @@ entry:
|
|||||||
%3 = load ptr, ptr %2, align 4
|
%3 = load ptr, ptr %2, align 4
|
||||||
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
|
%4 = getelementptr inbounds nuw i8, ptr %0, i32 8
|
||||||
%5 = load ptr, ptr %4, align 4
|
%5 = load ptr, ptr %4, align 4
|
||||||
call void %5(i32 %1, ptr %3) #9
|
call void %5(i32 %1, ptr %3) #11
|
||||||
call void @runtime.deadlock(ptr undef) #9
|
call void @runtime.deadlock(ptr undef) #11
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,16 +143,21 @@ entry:
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {
|
define hidden void @main.copyBuiltinGoroutine(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 1, ptr undef) #9
|
%copy.n = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)
|
||||||
|
call void @llvm.memmove.p0.p0.i32(ptr align 1 %dst.data, ptr align 1 %src.data, i32 %copy.n, i1 false)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #1
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i32 @llvm.umin.i32(i32, i32) #7
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
|
||||||
|
declare void @llvm.memmove.p0.p0.i32(ptr nocapture writeonly, ptr nocapture readonly, i32, i1 immarg) #8
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #2 {
|
define hidden void @main.closeBuiltinGoroutine(ptr dereferenceable_or_null(36) %ch, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @runtime.chanClose(ptr %ch, ptr undef) #9
|
call void @runtime.chanClose(ptr %ch, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +167,8 @@ declare void @runtime.chanClose(ptr dereferenceable_or_null(36), ptr) #1
|
|||||||
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
|
define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9
|
%0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #11
|
||||||
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9
|
call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #11
|
||||||
store ptr %itf.value, ptr %0, align 4
|
store ptr %itf.value, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%1 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
store ptr @"main$string", ptr %1, align 4
|
store ptr @"main$string", ptr %1, align 4
|
||||||
@@ -171,14 +176,14 @@ entry:
|
|||||||
store i32 4, ptr %2, align 4
|
store i32 4, ptr %2, align 4
|
||||||
%3 = getelementptr inbounds nuw i8, ptr %0, i32 12
|
%3 = getelementptr inbounds nuw i8, ptr %0, i32 12
|
||||||
store ptr %itf.typecode, ptr %3, align 4
|
store ptr %itf.typecode, ptr %3, align 4
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #11
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i32, ptr, ptr) #7
|
declare void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr, ptr, i32, ptr, ptr) #9
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #8 {
|
define linkonce_odr void @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper"(ptr %0) unnamed_addr #10 {
|
||||||
entry:
|
entry:
|
||||||
%1 = load ptr, ptr %0, align 4
|
%1 = load ptr, ptr %0, align 4
|
||||||
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
%2 = getelementptr inbounds nuw i8, ptr %0, i32 4
|
||||||
@@ -187,8 +192,8 @@ entry:
|
|||||||
%5 = load i32, ptr %4, align 4
|
%5 = load i32, ptr %4, align 4
|
||||||
%6 = getelementptr inbounds nuw i8, ptr %0, i32 12
|
%6 = getelementptr inbounds nuw i8, ptr %0, i32 12
|
||||||
%7 = load ptr, ptr %6, align 4
|
%7 = load ptr, ptr %6, align 4
|
||||||
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #9
|
call void @"interface:{Print:func:{basic:string}{}}.Print$invoke"(ptr %1, ptr %3, i32 %5, ptr %7, ptr undef) #11
|
||||||
call void @runtime.deadlock(ptr undef) #9
|
call void @runtime.deadlock(ptr undef) #11
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +204,8 @@ attributes #3 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+cal
|
|||||||
attributes #4 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
|
attributes #4 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.inlineFunctionGoroutine$1" }
|
||||||
attributes #5 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
|
attributes #5 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="main.closureFunctionGoroutine$1" }
|
||||||
attributes #6 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper" }
|
attributes #6 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper" }
|
||||||
attributes #7 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
|
attributes #7 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
|
||||||
attributes #8 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
|
attributes #8 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
|
||||||
attributes #9 = { nounwind }
|
attributes #9 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-invoke"="reflect/methods.Print(string)" "tinygo-methods"="reflect/methods.Print(string)" }
|
||||||
|
attributes #10 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" "tinygo-gowrapper"="interface:{Print:func:{basic:string}{}}.Print$invoke" }
|
||||||
|
attributes #11 = { nounwind }
|
||||||
|
|||||||
Vendored
+5
-3
@@ -9,12 +9,14 @@ target triple = "wasm32-unknown-wasi"
|
|||||||
@"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 -62, ptr @"reflect/types.type:pointer:basic:int" }, align 4
|
@"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 -62, ptr @"reflect/types.type:pointer:basic:int" }, align 4
|
||||||
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:int" }, align 4
|
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:basic:int" }, align 4
|
||||||
@"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:named:error" }, align 4
|
@"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:named:error" }, align 4
|
||||||
@"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, [7 x i8] } { i8 116, i16 1, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", [7 x i8] c".error\00" }, align 4
|
@"reflect/types.signature:Error:func:{}{basic:string}" = linkonce_odr constant i8 0, align 1
|
||||||
|
@"reflect/types.type:named:error" = linkonce_odr constant { i8, i16, ptr, ptr, ptr, { i32, [1 x ptr] }, [7 x i8] } { i8 116, i16 -32767, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", ptr @"reflect/types.type.pkgpath.empty", { i32, [1 x ptr] } { i32 1, [1 x ptr] [ptr @"reflect/types.signature:Error:func:{}{basic:string}"] }, [7 x i8] c".error\00" }, align 4
|
||||||
@"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
@"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
||||||
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 84, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }, align 4
|
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr, { i32, [1 x ptr] } } { i8 84, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}", { i32, [1 x ptr] } { i32 1, [1 x ptr] [ptr @"reflect/types.signature:Error:func:{}{basic:string}"] } }, align 4
|
||||||
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}" }, align 4
|
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}" }, align 4
|
||||||
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}" }, align 4
|
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, i16, ptr } { i8 -43, i16 0, ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}" }, align 4
|
||||||
@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 84, ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" }, align 4
|
@"reflect/types.signature:String:func:{}{basic:string}" = linkonce_odr constant i8 0, align 1
|
||||||
|
@"reflect/types.type:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr, { i32, [1 x ptr] } } { i8 84, ptr @"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}", { i32, [1 x ptr] } { i32 1, [1 x ptr] [ptr @"reflect/types.signature:String:func:{}{basic:string}"] } }, align 4
|
||||||
@"reflect/types.typeid:basic:int" = external constant i8
|
@"reflect/types.typeid:basic:int" = external constant i8
|
||||||
|
|
||||||
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
; Function Attrs: allockind("alloc,zeroed") allocsize(0)
|
||||||
|
|||||||
Vendored
+44
-36
@@ -38,7 +38,7 @@ lookup.next: ; preds = %entry
|
|||||||
ret i32 %1
|
ret i32 %1
|
||||||
|
|
||||||
lookup.throw: ; preds = %entry
|
lookup.throw: ; preds = %entry
|
||||||
call void @runtime.lookupPanic(ptr undef) #3
|
call void @runtime.lookupPanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,49 +48,55 @@ declare void @runtime.lookupPanic(ptr) #1
|
|||||||
define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
|
define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
%varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
|
||||||
call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
store i32 1, ptr %varargs, align 4
|
store i32 1, ptr %varargs, align 4
|
||||||
%0 = getelementptr inbounds nuw i8, ptr %varargs, i32 4
|
%0 = getelementptr inbounds nuw i8, ptr %varargs, i32 4
|
||||||
store i32 2, ptr %0, align 4
|
store i32 2, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds nuw i8, ptr %varargs, i32 8
|
%1 = getelementptr inbounds nuw i8, ptr %varargs, i32 8
|
||||||
store i32 3, ptr %1, align 4
|
store i32 3, ptr %1, align 4
|
||||||
%append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr undef) #3
|
%append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
|
||||||
%append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
|
%append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
|
||||||
%append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
|
%append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
|
||||||
%append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
|
%append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
|
||||||
%2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
|
%2 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
|
||||||
%3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1
|
%3 = insertvalue { ptr, i32, i32 } %2, i32 %append.newLen, 1
|
||||||
%4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2
|
%4 = insertvalue { ptr, i32, i32 } %3, i32 %append.newCap, 2
|
||||||
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %4
|
ret { ptr, i32, i32 } %4
|
||||||
}
|
}
|
||||||
|
|
||||||
declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr) #1
|
declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr, ptr) #1
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %added.data, i32 %added.len, i32 %added.cap, ptr %context) unnamed_addr #2 {
|
define hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %added.data, i32 %added.len, i32 %added.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr %added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr undef) #3
|
%append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr %added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
|
||||||
%append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
|
%append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
|
||||||
%append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
|
%append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
|
||||||
%append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
|
%append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
|
||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %append.newPtr, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %append.newLen, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %append.newCap, 2
|
||||||
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr %append.newPtr, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
}
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden i32 @main.sliceCopy(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {
|
define hidden i32 @main.sliceCopy(ptr %dst.data, i32 %dst.len, i32 %dst.cap, ptr %src.data, i32 %src.len, i32 %src.cap, ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%copy.n = call i32 @runtime.sliceCopy(ptr %dst.data, ptr %src.data, i32 %dst.len, i32 %src.len, i32 4, ptr undef) #3
|
%copy.n = call i32 @llvm.umin.i32(i32 %dst.len, i32 %src.len)
|
||||||
|
%copy.size = shl nuw i32 %copy.n, 2
|
||||||
|
call void @llvm.memmove.p0.p0.i32(ptr align 4 %dst.data, ptr align 4 %src.data, i32 %copy.size, i1 false)
|
||||||
ret i32 %copy.n
|
ret i32 %copy.n
|
||||||
}
|
}
|
||||||
|
|
||||||
declare i32 @runtime.sliceCopy(ptr nocapture writeonly, ptr nocapture readonly, i32, i32, i32, ptr) #1
|
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
|
||||||
|
declare i32 @llvm.umin.i32(i32, i32) #3
|
||||||
|
|
||||||
|
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
|
||||||
|
declare void @llvm.memmove.p0.p0.i32(ptr nocapture writeonly, ptr nocapture readonly, i32, i1 immarg) #4
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr #2 {
|
define hidden { ptr, i32, i32 } @main.makeByteSlice(i32 %len, ptr %context) unnamed_addr #2 {
|
||||||
@@ -100,15 +106,15 @@ entry:
|
|||||||
br i1 %slice.maxcap, label %slice.throw, label %slice.next
|
br i1 %slice.maxcap, label %slice.throw, label %slice.next
|
||||||
|
|
||||||
slice.next: ; preds = %entry
|
slice.next: ; preds = %entry
|
||||||
%makeslice.buf = call align 1 ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
%makeslice.buf = call align 1 ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
|
||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
|
|
||||||
slice.throw: ; preds = %entry
|
slice.throw: ; preds = %entry
|
||||||
call void @runtime.slicePanic(ptr undef) #3
|
call void @runtime.slicePanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,15 +129,15 @@ entry:
|
|||||||
|
|
||||||
slice.next: ; preds = %entry
|
slice.next: ; preds = %entry
|
||||||
%makeslice.cap = shl nuw i32 %len, 1
|
%makeslice.cap = shl nuw i32 %len, 1
|
||||||
%makeslice.buf = call align 2 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
%makeslice.buf = call align 2 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
|
||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
|
|
||||||
slice.throw: ; preds = %entry
|
slice.throw: ; preds = %entry
|
||||||
call void @runtime.slicePanic(ptr undef) #3
|
call void @runtime.slicePanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,15 +150,15 @@ entry:
|
|||||||
|
|
||||||
slice.next: ; preds = %entry
|
slice.next: ; preds = %entry
|
||||||
%makeslice.cap = mul i32 %len, 3
|
%makeslice.cap = mul i32 %len, 3
|
||||||
%makeslice.buf = call align 1 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
%makeslice.buf = call align 1 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
|
||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
|
|
||||||
slice.throw: ; preds = %entry
|
slice.throw: ; preds = %entry
|
||||||
call void @runtime.slicePanic(ptr undef) #3
|
call void @runtime.slicePanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,15 +171,15 @@ entry:
|
|||||||
|
|
||||||
slice.next: ; preds = %entry
|
slice.next: ; preds = %entry
|
||||||
%makeslice.cap = shl nuw i32 %len, 2
|
%makeslice.cap = shl nuw i32 %len, 2
|
||||||
%makeslice.buf = call align 4 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
%makeslice.buf = call align 4 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
|
||||||
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
%0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0
|
||||||
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
%1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1
|
||||||
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
%2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %makeslice.buf, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %2
|
ret { ptr, i32, i32 } %2
|
||||||
|
|
||||||
slice.throw: ; preds = %entry
|
slice.throw: ; preds = %entry
|
||||||
call void @runtime.slicePanic(ptr undef) #3
|
call void @runtime.slicePanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +188,7 @@ define hidden ptr @main.Add32(ptr %p, i32 %len, ptr %context) unnamed_addr #2 {
|
|||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = getelementptr i8, ptr %p, i32 %len
|
%0 = getelementptr i8, ptr %p, i32 %len
|
||||||
call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret ptr %0
|
ret ptr %0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +198,7 @@ entry:
|
|||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%0 = trunc i64 %len to i32
|
%0 = trunc i64 %len to i32
|
||||||
%1 = getelementptr i8, ptr %p, i32 %0
|
%1 = getelementptr i8, ptr %p, i32 %0
|
||||||
call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret ptr %1
|
ret ptr %1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +212,7 @@ slicetoarray.next: ; preds = %entry
|
|||||||
ret ptr %s.data
|
ret ptr %s.data
|
||||||
|
|
||||||
slicetoarray.throw: ; preds = %entry
|
slicetoarray.throw: ; preds = %entry
|
||||||
call void @runtime.sliceToArrayPointerPanic(ptr undef) #3
|
call void @runtime.sliceToArrayPointerPanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,8 +222,8 @@ declare void @runtime.sliceToArrayPointerPanic(ptr) #1
|
|||||||
define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #2 {
|
define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%stackalloc = alloca i8, align 1
|
||||||
%makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3
|
%makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #5
|
||||||
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
|
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
|
||||||
|
|
||||||
slicetoarray.next: ; preds = %entry
|
slicetoarray.next: ; preds = %entry
|
||||||
@@ -242,11 +248,11 @@ unsafe.Slice.next: ; preds = %entry
|
|||||||
%5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
%5 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
||||||
%6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1
|
%6 = insertvalue { ptr, i32, i32 } %5, i32 %len, 1
|
||||||
%7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2
|
%7 = insertvalue { ptr, i32, i32 } %6, i32 %len, 2
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %7
|
ret { ptr, i32, i32 } %7
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
call void @runtime.unsafeSlicePanic(ptr undef) #3
|
call void @runtime.unsafeSlicePanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,11 +272,11 @@ unsafe.Slice.next: ; preds = %entry
|
|||||||
%4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
%4 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
||||||
%5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1
|
%5 = insertvalue { ptr, i32, i32 } %4, i32 %3, 1
|
||||||
%6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2
|
%6 = insertvalue { ptr, i32, i32 } %5, i32 %3, 2
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %6
|
ret { ptr, i32, i32 } %6
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
call void @runtime.unsafeSlicePanic(ptr undef) #3
|
call void @runtime.unsafeSlicePanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,11 +296,11 @@ unsafe.Slice.next: ; preds = %entry
|
|||||||
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
||||||
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
|
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
|
||||||
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
|
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %8
|
ret { ptr, i32, i32 } %8
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
call void @runtime.unsafeSlicePanic(ptr undef) #3
|
call void @runtime.unsafeSlicePanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,15 +320,17 @@ unsafe.Slice.next: ; preds = %entry
|
|||||||
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
%6 = insertvalue { ptr, i32, i32 } undef, ptr %ptr, 0
|
||||||
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
|
%7 = insertvalue { ptr, i32, i32 } %6, i32 %5, 1
|
||||||
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
|
%8 = insertvalue { ptr, i32, i32 } %7, i32 %5, 2
|
||||||
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #3
|
call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #5
|
||||||
ret { ptr, i32, i32 } %8
|
ret { ptr, i32, i32 } %8
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
call void @runtime.unsafeSlicePanic(ptr undef) #3
|
call void @runtime.unsafeSlicePanic(ptr undef) #5
|
||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
attributes #0 = { allockind("alloc,zeroed") allocsize(0) "alloc-family"="runtime.alloc" "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
||||||
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
attributes #1 = { "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
||||||
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+bulk-memory-opt,+call-indirect-overlong,+mutable-globals,+nontrapping-fptoint,+sign-ext,-multivalue,-reference-types" }
|
||||||
attributes #3 = { nounwind }
|
attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
|
||||||
|
attributes #4 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
|
||||||
|
attributes #5 = { nounwind }
|
||||||
|
|||||||
Generated
+4
-4
@@ -20,16 +20,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1747953325,
|
"lastModified": 1770136044,
|
||||||
"narHash": "sha256-y2ZtlIlNTuVJUZCqzZAhIw5rrKP4DOSklev6c8PyCkQ=",
|
"narHash": "sha256-tlFqNG/uzz2++aAmn4v8J0vAkV3z7XngeIIB3rM3650=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "55d1f923c480dadce40f5231feb472e81b0bab48",
|
"rev": "e576e3c9cf9bad747afcddd9e34f51d18c855b4e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"id": "nixpkgs",
|
||||||
"ref": "nixos-25.05",
|
"ref": "nixos-25.11",
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -34,7 +34,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-25.05";
|
nixpkgs.url = "nixpkgs/nixos-25.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 }:
|
||||||
|
|||||||
@@ -1,29 +1,53 @@
|
|||||||
module github.com/tinygo-org/tinygo
|
module github.com/tinygo-org/tinygo
|
||||||
|
|
||||||
go 1.22.0
|
go 1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139
|
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139
|
||||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
|
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
|
||||||
github.com/gofrs/flock v0.8.1
|
github.com/gofrs/flock v0.8.1
|
||||||
|
github.com/golangci/misspell v0.6.0
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
||||||
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf
|
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf
|
||||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
||||||
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/mgechev/revive v1.3.9
|
||||||
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
|
github.com/tetratelabs/wazero v1.9.0
|
||||||
go.bug.st/serial v1.6.0
|
go.bug.st/serial v1.6.4
|
||||||
|
go.bytecodealliance.org v0.6.2
|
||||||
|
go.bytecodealliance.org/cm v0.2.2
|
||||||
golang.org/x/net v0.35.0
|
golang.org/x/net v0.35.0
|
||||||
golang.org/x/sys v0.30.0
|
golang.org/x/sys v0.30.0
|
||||||
golang.org/x/tools v0.30.0
|
golang.org/x/tools v0.30.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
|
tinygo.org/x/espflasher v0.6.0
|
||||||
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74
|
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
|
github.com/chavacava/garif v0.1.0 // indirect
|
||||||
|
github.com/coreos/go-semver v0.3.1 // indirect
|
||||||
github.com/creack/goselect v0.1.2 // indirect
|
github.com/creack/goselect v0.1.2 // indirect
|
||||||
|
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||||
|
github.com/fatih/color v1.17.0 // indirect
|
||||||
|
github.com/fatih/structtag v1.2.0 // indirect
|
||||||
|
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/stretchr/testify v1.8.4 // indirect
|
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||||
|
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/regclient/regclient v0.8.2 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
|
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||||
|
github.com/urfave/cli/v3 v3.0.0-beta1 // indirect
|
||||||
|
golang.org/x/mod v0.23.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.22.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,17 +1,36 @@
|
|||||||
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139 h1:2O/WuAt8J5id3khcAtVB90czG80m+v0sfkLE07GrCVg=
|
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139 h1:2O/WuAt8J5id3khcAtVB90czG80m+v0sfkLE07GrCVg=
|
||||||
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=
|
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=
|
||||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI=
|
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI=
|
||||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||||
|
github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=
|
||||||
|
github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=
|
||||||
|
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||||
|
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||||
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.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/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||||
|
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||||
|
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||||
|
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||||
|
github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
|
||||||
|
github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
||||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
||||||
|
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||||
|
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=
|
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=
|
||||||
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=
|
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=
|
||||||
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
|
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
|
||||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
|
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
@@ -23,18 +42,57 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
|
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
|
||||||
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
|
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
|
||||||
|
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 h1:zpIH83+oKzcpryru8ceC6BxnoG8TBrhgAvRg8obzup0=
|
||||||
|
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
|
||||||
|
github.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A=
|
||||||
|
github.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/olareg/olareg v0.1.1 h1:Ui7q93zjcoF+U9U71sgqgZWByDoZOpqHitUXEu2xV+g=
|
||||||
|
github.com/olareg/olareg v0.1.1/go.mod h1:w8NP4SWrHHtxsFaUiv1lnCnYPm4sN1seCd2h7FK/dc0=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 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.8.2 h1:23BQ3jWgKYHHIXUhp/S9laVJDHDoOQaQCzXMJ4undVE=
|
||||||
|
github.com/regclient/regclient v0.8.2/go.mod h1:uGyetv0o6VLyRDjtfeBqp/QBwRLJ3Hcn07/+8QbhNcM=
|
||||||
|
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/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/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||||
|
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.4/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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
|
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
|
||||||
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
|
||||||
|
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-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=
|
||||||
|
github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
|
||||||
|
go.bug.st/serial v1.6.4 h1:7FmqNPgVp3pu2Jz5PoPtbZ9jJO5gnEnZIvnI1lzve8A=
|
||||||
|
go.bug.st/serial v1.6.4/go.mod h1:nofMJxTeNVny/m6+KaafC6vJGj3miwQZ6vW4BZUGJPI=
|
||||||
|
go.bytecodealliance.org v0.6.2 h1:Jy4u5DVmSkXgsnwojBhJ+AD/YsJsR3VzVnxF0xRCqTQ=
|
||||||
|
go.bytecodealliance.org v0.6.2/go.mod h1:gqjTJm0y9NSksG4py/lSjIQ/SNuIlOQ+hCIEPQwtJgA=
|
||||||
|
go.bytecodealliance.org/cm v0.2.2 h1:M9iHS6qs884mbQbIjtLX1OifgyPG9DuMs2iwz8G4WQA=
|
||||||
|
go.bytecodealliance.org/cm v0.2.2/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI=
|
||||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
@@ -44,6 +102,7 @@ golang.org/x/sync v0.11.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=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
@@ -56,7 +115,10 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
|
|||||||
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.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.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=
|
||||||
|
tinygo.org/x/espflasher v0.6.0 h1:CHbGMHAIWq1tB8FKd/QwBpNFw1jvHHxpmvZiF+QOYUo=
|
||||||
|
tinygo.org/x/espflasher v0.6.0/go.mod h1:tr5u08HoE67WD5zxJesCiiVF/R1b6Akz3yXwh5zah8U=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74 h1:ovavgTdIBWCH8YWlcfq9gkpoyT1+IxMKSn+Df27QwE8=
|
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74 h1:ovavgTdIBWCH8YWlcfq9gkpoyT1+IxMKSn+Df27QwE8=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
// 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.40.1"
|
const version = "0.41.1"
|
||||||
|
|
||||||
// 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).
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
// TODO: remove this (by merging it into the top-level go.mod)
|
|
||||||
// once the top level go.mod specifies a go new enough to make our version of misspell happy.
|
|
||||||
|
|
||||||
module tools
|
|
||||||
|
|
||||||
go 1.21
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/golangci/misspell v0.6.0
|
|
||||||
github.com/mgechev/revive v1.3.9
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
|
||||||
github.com/chavacava/garif v0.1.0 // indirect
|
|
||||||
github.com/fatih/color v1.17.0 // indirect
|
|
||||||
github.com/fatih/structtag v1.2.0 // indirect
|
|
||||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
||||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
|
||||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 // indirect
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
|
||||||
github.com/spf13/afero v1.11.0 // indirect
|
|
||||||
golang.org/x/sys v0.22.0 // indirect
|
|
||||||
golang.org/x/text v0.14.0 // indirect
|
|
||||||
golang.org/x/tools v0.23.0 // indirect
|
|
||||||
)
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
|
||||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
|
||||||
github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc=
|
|
||||||
github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
|
||||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
|
||||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
|
||||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
|
||||||
github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
|
|
||||||
github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
|
|
||||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
|
||||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
|
||||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 h1:zpIH83+oKzcpryru8ceC6BxnoG8TBrhgAvRg8obzup0=
|
|
||||||
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
|
|
||||||
github.com/mgechev/revive v1.3.9 h1:18Y3R4a2USSBF+QZKFQwVkBROUda7uoBlkEuBD+YD1A=
|
|
||||||
github.com/mgechev/revive v1.3.9/go.mod h1:+uxEIr5UH0TjXWHTno3xh4u7eg6jDpXKzQccA9UGhHU=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
|
||||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
|
||||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
|
||||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
|
||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|
||||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
|
||||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# wasm-tools directory
|
|
||||||
|
|
||||||
This directory has a separate `go.mod` file because the `wasm-tools-go` module requires Go 1.22, while TinyGo itself supports Go 1.19.
|
|
||||||
|
|
||||||
When the minimum Go version for TinyGo is 1.22, this directory can be folded into `internal/tools` and the `go.mod` and `go.sum` files deleted.
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
module github.com/tinygo-org/tinygo/internal/wasm-tools
|
|
||||||
|
|
||||||
go 1.23.0
|
|
||||||
|
|
||||||
require (
|
|
||||||
go.bytecodealliance.org v0.6.2
|
|
||||||
go.bytecodealliance.org/cm v0.2.2
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/coreos/go-semver v0.3.1 // indirect
|
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
|
||||||
github.com/regclient/regclient v0.8.2 // indirect
|
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
|
||||||
github.com/tetratelabs/wazero v1.9.0 // indirect
|
|
||||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
|
||||||
github.com/urfave/cli/v3 v3.0.0-beta1 // indirect
|
|
||||||
golang.org/x/mod v0.24.0 // indirect
|
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
|
||||||
)
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
|
||||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
|
||||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
|
||||||
github.com/olareg/olareg v0.1.1 h1:Ui7q93zjcoF+U9U71sgqgZWByDoZOpqHitUXEu2xV+g=
|
|
||||||
github.com/olareg/olareg v0.1.1/go.mod h1:w8NP4SWrHHtxsFaUiv1lnCnYPm4sN1seCd2h7FK/dc0=
|
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/regclient/regclient v0.8.2 h1:23BQ3jWgKYHHIXUhp/S9laVJDHDoOQaQCzXMJ4undVE=
|
|
||||||
github.com/regclient/regclient v0.8.2/go.mod h1:uGyetv0o6VLyRDjtfeBqp/QBwRLJ3Hcn07/+8QbhNcM=
|
|
||||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
|
||||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
||||||
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
|
|
||||||
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
|
|
||||||
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-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=
|
|
||||||
github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
|
|
||||||
go.bytecodealliance.org v0.6.2 h1:Jy4u5DVmSkXgsnwojBhJ+AD/YsJsR3VzVnxF0xRCqTQ=
|
|
||||||
go.bytecodealliance.org v0.6.2/go.mod h1:gqjTJm0y9NSksG4py/lSjIQ/SNuIlOQ+hCIEPQwtJgA=
|
|
||||||
go.bytecodealliance.org/cm v0.2.2 h1:M9iHS6qs884mbQbIjtLX1OifgyPG9DuMs2iwz8G4WQA=
|
|
||||||
go.bytecodealliance.org/cm v0.2.2/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI=
|
|
||||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
|
||||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
|
||||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
//go:build tools
|
|
||||||
|
|
||||||
// Install tools specified in go.mod.
|
|
||||||
// See https://marcofranssen.nl/manage-go-tools-via-go-modules for idiom.
|
|
||||||
package tools
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "go.bytecodealliance.org/cm"
|
|
||||||
_ "go.bytecodealliance.org/cmd/wit-bindgen-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:generate go install go.bytecodealliance.org/cmd/wit-bindgen-go
|
|
||||||
+1
-1
@@ -29,7 +29,7 @@ var errInvalidPtrToIntSize = errors.New("interp: ptrtoint integer size does not
|
|||||||
func isRecoverableError(err error) bool {
|
func isRecoverableError(err error) bool {
|
||||||
return err == errIntegerAsPointer || err == errUnsupportedInst ||
|
return err == errIntegerAsPointer || err == errUnsupportedInst ||
|
||||||
err == errUnsupportedRuntimeInst || err == errMapAlreadyCreated ||
|
err == errUnsupportedRuntimeInst || err == errMapAlreadyCreated ||
|
||||||
err == errLoopUnrolled
|
err == errLoopUnrolled || err == errInvalidPtrToIntSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorLine is one line in a traceback. The position may be missing.
|
// ErrorLine is one line in a traceback. The position may be missing.
|
||||||
|
|||||||
+2
-11
@@ -2,7 +2,6 @@ package interp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -11,25 +10,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestInterp(t *testing.T) {
|
func TestInterp(t *testing.T) {
|
||||||
llvmVersion, err := strconv.Atoi(strings.Split(llvm.Version, ".")[0])
|
|
||||||
if err != nil {
|
|
||||||
// Note: this should never happen and if it does, it will always happen
|
|
||||||
// for a particular build because llvm.Version is a constant.
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for _, name := range []string{
|
for _, name := range []string{
|
||||||
"basic",
|
"basic",
|
||||||
"phi",
|
"phi",
|
||||||
"slice-copy",
|
|
||||||
"consteval",
|
"consteval",
|
||||||
|
"intrinsics",
|
||||||
|
"copy",
|
||||||
"interface",
|
"interface",
|
||||||
"revert",
|
"revert",
|
||||||
"alloc",
|
"alloc",
|
||||||
} {
|
} {
|
||||||
name := name // make local to this closure
|
name := name // make local to this closure
|
||||||
if name == "slice-copy" && llvmVersion < 14 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runTest(t, "testdata/"+name)
|
runTest(t, "testdata/"+name)
|
||||||
|
|||||||
+22
-109
@@ -312,33 +312,28 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
fmt.Fprintln(os.Stderr, indent+"runtime.alloc:", size, "->", ptr)
|
fmt.Fprintln(os.Stderr, indent+"runtime.alloc:", size, "->", ptr)
|
||||||
}
|
}
|
||||||
locals[inst.localIndex] = ptr
|
locals[inst.localIndex] = ptr
|
||||||
case callFn.name == "runtime.sliceCopy":
|
case strings.HasPrefix(callFn.name, "llvm.umin."):
|
||||||
// sliceCopy implements the built-in copy function for slices.
|
locals[inst.localIndex] = makeLiteralInt(min(operands[1].Uint(r), operands[2].Uint(r)), inst.llvmInst.Type().IntTypeWidth())
|
||||||
// It is implemented here so that it can be used even if the
|
case strings.HasPrefix(callFn.name, "llvm.smin."):
|
||||||
// runtime implementation is not available. Doing it this way
|
locals[inst.localIndex] = makeLiteralInt(uint64(min(operands[1].Int(r), operands[2].Int(r))), inst.llvmInst.Type().IntTypeWidth())
|
||||||
// may also be faster.
|
case strings.HasPrefix(callFn.name, "llvm.umax."):
|
||||||
// Code:
|
locals[inst.localIndex] = makeLiteralInt(max(operands[1].Uint(r), operands[2].Uint(r)), inst.llvmInst.Type().IntTypeWidth())
|
||||||
// func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) int {
|
case strings.HasPrefix(callFn.name, "llvm.smax."):
|
||||||
// n := srcLen
|
locals[inst.localIndex] = makeLiteralInt(uint64(max(operands[1].Int(r), operands[2].Int(r))), inst.llvmInst.Type().IntTypeWidth())
|
||||||
// if n > dstLen {
|
case strings.HasPrefix(callFn.name, "llvm.memcpy.p0") || strings.HasPrefix(callFn.name, "llvm.memmove.p0"):
|
||||||
// n = dstLen
|
// Copy a block of memory from one pointer to another.
|
||||||
// }
|
if operands[4].Uint(r) != 0 {
|
||||||
// memmove(dst, src, n*elemSize)
|
// This is a volatile copy/move.
|
||||||
// return int(n)
|
err := r.runAtRuntime(fn, inst, locals, &mem, indent)
|
||||||
// }
|
if err != nil {
|
||||||
dstLen := operands[3].Uint(r)
|
return nil, mem, err
|
||||||
srcLen := operands[4].Uint(r)
|
}
|
||||||
elemSize := operands[5].Uint(r)
|
continue
|
||||||
n := srcLen
|
|
||||||
if n > dstLen {
|
|
||||||
n = dstLen
|
|
||||||
}
|
}
|
||||||
if r.debug {
|
nBytes := operands[3].Uint(r)
|
||||||
fmt.Fprintln(os.Stderr, indent+"copy:", operands[1], operands[2], n)
|
if nBytes != 0 {
|
||||||
}
|
|
||||||
if n != 0 {
|
|
||||||
// Only try to copy bytes when there are any bytes to copy.
|
// Only try to copy bytes when there are any bytes to copy.
|
||||||
// This is not just an optimization. If one of the slices
|
// This is not just an optimization. If one of the pointers
|
||||||
// (or both) are nil, the asPointer method call will fail
|
// (or both) are nil, the asPointer method call will fail
|
||||||
// even though copying a nil slice is allowed.
|
// even though copying a nil slice is allowed.
|
||||||
dst, err := operands[1].asPointer(r)
|
dst, err := operands[1].asPointer(r)
|
||||||
@@ -363,11 +358,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nBytes := uint32(n * elemSize)
|
|
||||||
srcObj := mem.get(src.index())
|
srcObj := mem.get(src.index())
|
||||||
dstObj := mem.getWritable(dst.index())
|
dstObj := mem.getWritable(dst.index())
|
||||||
if srcObj.buffer == nil || dstObj.buffer == nil {
|
if srcObj.buffer == nil || dstObj.buffer == nil {
|
||||||
// If the buffer is nil, it means the slice is external.
|
// If the buffer is nil, it means the memory is external.
|
||||||
// This can happen for example when copying data out of
|
// This can happen for example when copying data out of
|
||||||
// a //go:embed slice, which is not available at interp
|
// a //go:embed slice, which is not available at interp
|
||||||
// time.
|
// time.
|
||||||
@@ -380,33 +374,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
}
|
}
|
||||||
dstBuf := dstObj.buffer.asRawValue(r)
|
dstBuf := dstObj.buffer.asRawValue(r)
|
||||||
srcBuf := srcObj.buffer.asRawValue(r)
|
srcBuf := srcObj.buffer.asRawValue(r)
|
||||||
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
copy(dstBuf.buf[dst.offset():][:nBytes], srcBuf.buf[src.offset():][:nBytes])
|
||||||
dstObj.buffer = dstBuf
|
dstObj.buffer = dstBuf
|
||||||
mem.put(dst.index(), dstObj)
|
mem.put(dst.index(), dstObj)
|
||||||
}
|
}
|
||||||
locals[inst.localIndex] = makeLiteralInt(n, inst.llvmInst.Type().IntTypeWidth())
|
|
||||||
case strings.HasPrefix(callFn.name, "llvm.memcpy.p0") || strings.HasPrefix(callFn.name, "llvm.memmove.p0"):
|
|
||||||
// Copy a block of memory from one pointer to another.
|
|
||||||
dst, err := operands[1].asPointer(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, r.errorAt(inst, err)
|
|
||||||
}
|
|
||||||
src, err := operands[2].asPointer(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, r.errorAt(inst, err)
|
|
||||||
}
|
|
||||||
nBytes := uint32(operands[3].Uint(r))
|
|
||||||
dstObj := mem.getWritable(dst.index())
|
|
||||||
dstBuf := dstObj.buffer.asRawValue(r)
|
|
||||||
if mem.get(src.index()).buffer == nil {
|
|
||||||
// Looks like the source buffer is not defined.
|
|
||||||
// This can happen with //extern or //go:embed.
|
|
||||||
return nil, mem, r.errorAt(inst, errUnsupportedRuntimeInst)
|
|
||||||
}
|
|
||||||
srcBuf := mem.get(src.index()).buffer.asRawValue(r)
|
|
||||||
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
|
||||||
dstObj.buffer = dstBuf
|
|
||||||
mem.put(dst.index(), dstObj)
|
|
||||||
case callFn.name == "runtime.typeAssert":
|
case callFn.name == "runtime.typeAssert":
|
||||||
// This function must be implemented manually as it is normally
|
// This function must be implemented manually as it is normally
|
||||||
// implemented by the interface lowering pass.
|
// implemented by the interface lowering pass.
|
||||||
@@ -442,64 +413,6 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
// Special function that will trigger an error.
|
// Special function that will trigger an error.
|
||||||
// This is used to test error reporting.
|
// This is used to test error reporting.
|
||||||
return nil, mem, r.errorAt(inst, errors.New("test error"))
|
return nil, mem, r.errorAt(inst, errors.New("test error"))
|
||||||
case strings.HasSuffix(callFn.name, ".$typeassert"):
|
|
||||||
if r.debug {
|
|
||||||
fmt.Fprintln(os.Stderr, indent+"interface assert:", operands[1:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load various values for the interface implements check below.
|
|
||||||
typecodePtr, err := operands[1].asPointer(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, r.errorAt(inst, err)
|
|
||||||
}
|
|
||||||
// typecodePtr always point to the numMethod field in the type
|
|
||||||
// description struct. The methodSet, when present, comes right
|
|
||||||
// before the numMethod field (the compiler doesn't generate
|
|
||||||
// method sets for concrete types without methods).
|
|
||||||
// Considering that the compiler doesn't emit interface type
|
|
||||||
// asserts for interfaces with no methods (as the always succeed)
|
|
||||||
// then if the offset is zero, this assert must always fail.
|
|
||||||
if typecodePtr.offset() == 0 {
|
|
||||||
locals[inst.localIndex] = literalValue{uint8(0)}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
typecodePtrOffset, err := typecodePtr.addOffset(-int64(r.pointerSize))
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, r.errorAt(inst, err)
|
|
||||||
}
|
|
||||||
methodSetPtr, err := mem.load(typecodePtrOffset, r.pointerSize).asPointer(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, r.errorAt(inst, err)
|
|
||||||
}
|
|
||||||
methodSet := mem.get(methodSetPtr.index()).llvmGlobal.Initializer()
|
|
||||||
numMethods := int(r.builder.CreateExtractValue(methodSet, 0, "").ZExtValue())
|
|
||||||
llvmFn := inst.llvmInst.CalledValue()
|
|
||||||
methodSetAttr := llvmFn.GetStringAttributeAtIndex(-1, "tinygo-methods")
|
|
||||||
methodSetString := methodSetAttr.GetStringValue()
|
|
||||||
|
|
||||||
// Make a set of all the methods on the concrete type, for
|
|
||||||
// easier checking in the next step.
|
|
||||||
concreteTypeMethods := map[string]struct{}{}
|
|
||||||
for i := 0; i < numMethods; i++ {
|
|
||||||
methodInfo := r.builder.CreateExtractValue(methodSet, 1, "")
|
|
||||||
name := r.builder.CreateExtractValue(methodInfo, i, "").Name()
|
|
||||||
concreteTypeMethods[name] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether all interface methods are also in the list
|
|
||||||
// of defined methods calculated above. This is the interface
|
|
||||||
// assert itself.
|
|
||||||
assertOk := uint8(1) // i1 true
|
|
||||||
for _, name := range strings.Split(methodSetString, "; ") {
|
|
||||||
if _, ok := concreteTypeMethods[name]; !ok {
|
|
||||||
// There is a method on the interface that is not
|
|
||||||
// implemented by the type. The assertion will fail.
|
|
||||||
assertOk = 0 // i1 false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If assertOk is still 1, the assertion succeeded.
|
|
||||||
locals[inst.localIndex] = literalValue{assertOk}
|
|
||||||
case strings.HasSuffix(callFn.name, "$invoke"):
|
case strings.HasSuffix(callFn.name, "$invoke"):
|
||||||
// This thunk is the interface method dispatcher: it is called
|
// This thunk is the interface method dispatcher: it is called
|
||||||
// with all regular parameters and a type code. It will then
|
// with all regular parameters and a type code. It will then
|
||||||
|
|||||||
Vendored
+68
@@ -0,0 +1,68 @@
|
|||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64--linux"
|
||||||
|
|
||||||
|
@string = internal unnamed_addr constant [3 x i8] c"foo"
|
||||||
|
@moveDst = global [3 x i8] zeroinitializer
|
||||||
|
@copyDst = global [3 x i8] zeroinitializer
|
||||||
|
|
||||||
|
@externalSrc = external global [2 x i8]
|
||||||
|
@moveExternalDst = global [2 x i8] zeroinitializer
|
||||||
|
|
||||||
|
@moveEscapedSrc = global [4 x i8] c"abcd"
|
||||||
|
@moveEscapedDst = global [4 x i8] zeroinitializer
|
||||||
|
|
||||||
|
@volatileSrc = global [2 x i8] c"xy"
|
||||||
|
@volatileDst = global [2 x i8] zeroinitializer
|
||||||
|
|
||||||
|
declare void @use(ptr)
|
||||||
|
|
||||||
|
define void @runtime.initAll() {
|
||||||
|
call void @main.init()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @main.init() {
|
||||||
|
call void @testMove()
|
||||||
|
call void @testCopy()
|
||||||
|
call void @testMoveExternal()
|
||||||
|
call void @testMoveEscaped()
|
||||||
|
call void @testVolatileCopy()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Test a simple memmove between globals.
|
||||||
|
define internal void @testMove() {
|
||||||
|
call void @llvm.memmove.p0.p0.i64(ptr @moveDst, ptr @string, i64 3, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Test a simple memcpy between globals.
|
||||||
|
define internal void @testCopy() {
|
||||||
|
call void @llvm.memcpy.p0.p0.i64(ptr @copyDst, ptr @string, i64 3, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Test a memmove from an external global.
|
||||||
|
; This should be run at runtime.
|
||||||
|
define internal void @testMoveExternal() {
|
||||||
|
call void @llvm.memmove.p0.p0.i64(ptr @moveExternalDst, ptr @externalSrc, i64 2, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Test a memmove from an escaped (and potentially modified) source buffer.
|
||||||
|
define internal void @testMoveEscaped() {
|
||||||
|
call void @use(ptr @moveEscapedSrc)
|
||||||
|
call void @llvm.memmove.p0.p0.i64(ptr @moveEscapedDst, ptr @moveEscapedSrc, i64 4, i1 false)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; Test a volatile memcpy.
|
||||||
|
; This should always be run at runtime.
|
||||||
|
define internal void @testVolatileCopy() {
|
||||||
|
call void @llvm.memcpy.p0.p0.i64(ptr @volatileDst, ptr @volatileSrc, i64 2, i1 true)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memmove.p0.p0.i64(ptr, ptr, i64, i1)
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
|
||||||
Vendored
+27
@@ -0,0 +1,27 @@
|
|||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64--linux"
|
||||||
|
|
||||||
|
@moveDst = local_unnamed_addr global [3 x i8] c"foo"
|
||||||
|
@copyDst = local_unnamed_addr global [3 x i8] c"foo"
|
||||||
|
@externalSrc = external local_unnamed_addr global [2 x i8]
|
||||||
|
@moveExternalDst = local_unnamed_addr global [2 x i8] zeroinitializer
|
||||||
|
@moveEscapedSrc = global [4 x i8] c"abcd"
|
||||||
|
@moveEscapedDst = local_unnamed_addr global [4 x i8] zeroinitializer
|
||||||
|
@volatileSrc = global [2 x i8] c"xy"
|
||||||
|
@volatileDst = global [2 x i8] zeroinitializer
|
||||||
|
|
||||||
|
declare void @use(ptr) local_unnamed_addr
|
||||||
|
|
||||||
|
define void @runtime.initAll() local_unnamed_addr {
|
||||||
|
call void @llvm.memmove.p0.p0.i64(ptr @moveExternalDst, ptr @externalSrc, i64 2, i1 false)
|
||||||
|
call void @use(ptr @moveEscapedSrc)
|
||||||
|
call void @llvm.memmove.p0.p0.i64(ptr @moveEscapedDst, ptr @moveEscapedSrc, i64 4, i1 false)
|
||||||
|
call void @llvm.memcpy.p0.p0.i64(ptr @volatileDst, ptr @volatileSrc, i64 2, i1 true)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg) #0
|
||||||
|
|
||||||
|
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0
|
||||||
|
|
||||||
|
attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
|
||||||
Vendored
+52
@@ -0,0 +1,52 @@
|
|||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64--linux"
|
||||||
|
|
||||||
|
@uminResult = global i32 0
|
||||||
|
@sminResult = global i32 0
|
||||||
|
@umaxResult = global i32 0
|
||||||
|
@smaxResult = global i32 0
|
||||||
|
|
||||||
|
define void @runtime.initAll() {
|
||||||
|
call void @main.init()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @main.init() {
|
||||||
|
call void @testUMin()
|
||||||
|
call void @testSMin()
|
||||||
|
call void @testUMax()
|
||||||
|
call void @testSMax()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @testUMin() {
|
||||||
|
%umin = call i32 @llvm.umin.i32(i32 12, i32 -1)
|
||||||
|
store i32 %umin, ptr @uminResult
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @llvm.umin.i32(i32, i32)
|
||||||
|
|
||||||
|
define internal void @testSMin() {
|
||||||
|
%smin = call i32 @llvm.smin.i32(i32 12, i32 -1)
|
||||||
|
store i32 %smin, ptr @sminResult
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @llvm.smin.i32(i32, i32)
|
||||||
|
|
||||||
|
define internal void @testUMax() {
|
||||||
|
%umax = call i32 @llvm.umax.i32(i32 12, i32 -1)
|
||||||
|
store i32 %umax, ptr @umaxResult
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @llvm.umax.i32(i32, i32)
|
||||||
|
|
||||||
|
define internal void @testSMax() {
|
||||||
|
%smax = call i32 @llvm.smax.i32(i32 12, i32 -1)
|
||||||
|
store i32 %smax, ptr @smaxResult
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @llvm.smax.i32(i32, i32)
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64--linux"
|
||||||
|
|
||||||
|
@uminResult = local_unnamed_addr global i32 12
|
||||||
|
@sminResult = local_unnamed_addr global i32 -1
|
||||||
|
@umaxResult = local_unnamed_addr global i32 -1
|
||||||
|
@smaxResult = local_unnamed_addr global i32 12
|
||||||
|
|
||||||
|
define void @runtime.initAll() local_unnamed_addr {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
Vendored
-124
@@ -1,124 +0,0 @@
|
|||||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
||||||
target triple = "x86_64--linux"
|
|
||||||
|
|
||||||
@main.uint8SliceSrc.buf = internal global [2 x i8] c"\03d"
|
|
||||||
@main.uint8SliceSrc = internal unnamed_addr global { ptr, i64, i64 } { ptr @main.uint8SliceSrc.buf, i64 2, i64 2 }
|
|
||||||
@main.uint8SliceDst = internal unnamed_addr global { ptr, i64, i64 } zeroinitializer
|
|
||||||
@main.int16SliceSrc.buf = internal global [3 x i16] [i16 5, i16 123, i16 1024]
|
|
||||||
@main.int16SliceSrc = internal unnamed_addr global { ptr, i64, i64 } { ptr @main.int16SliceSrc.buf, i64 3, i64 3 }
|
|
||||||
@main.int16SliceDst = internal unnamed_addr global { ptr, i64, i64 } zeroinitializer
|
|
||||||
@main.sliceSrcUntaint.buf = internal global [2 x i8] c"ab"
|
|
||||||
@main.sliceDstUntaint.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceSrcTaint.buf = internal global [2 x i8] c"cd"
|
|
||||||
@main.sliceDstTaint.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceSrcExternal1.buf = external global [2 x i8]
|
|
||||||
@main.sliceDstExternal1.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceSrcExternal2.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceDstExternal2.buf = external global [2 x i8]
|
|
||||||
|
|
||||||
declare i64 @runtime.sliceCopy(ptr %dst, ptr %src, i64 %dstLen, i64 %srcLen, i64 %elemSize) unnamed_addr
|
|
||||||
|
|
||||||
declare ptr @runtime.alloc(i64, ptr) unnamed_addr
|
|
||||||
|
|
||||||
declare void @runtime.printuint8(i8)
|
|
||||||
|
|
||||||
declare void @runtime.printint16(i16)
|
|
||||||
|
|
||||||
declare void @use(ptr)
|
|
||||||
|
|
||||||
define void @runtime.initAll() unnamed_addr {
|
|
||||||
entry:
|
|
||||||
call void @main.init()
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @main() unnamed_addr {
|
|
||||||
entry:
|
|
||||||
; print(uintSliceSrc[0])
|
|
||||||
%uint8SliceSrc.buf = load ptr, ptr @main.uint8SliceSrc
|
|
||||||
%uint8SliceSrc.val = load i8, ptr %uint8SliceSrc.buf
|
|
||||||
call void @runtime.printuint8(i8 %uint8SliceSrc.val)
|
|
||||||
|
|
||||||
; print(uintSliceDst[0])
|
|
||||||
%uint8SliceDst.buf = load ptr, ptr @main.uint8SliceDst
|
|
||||||
%uint8SliceDst.val = load i8, ptr %uint8SliceDst.buf
|
|
||||||
call void @runtime.printuint8(i8 %uint8SliceDst.val)
|
|
||||||
|
|
||||||
; print(int16SliceSrc[0])
|
|
||||||
%int16SliceSrc.buf = load ptr, ptr @main.int16SliceSrc
|
|
||||||
%int16SliceSrc.val = load i16, ptr %int16SliceSrc.buf
|
|
||||||
call void @runtime.printint16(i16 %int16SliceSrc.val)
|
|
||||||
|
|
||||||
; print(int16SliceDst[0])
|
|
||||||
%int16SliceDst.buf = load ptr, ptr @main.int16SliceDst
|
|
||||||
%int16SliceDst.val = load i16, ptr %int16SliceDst.buf
|
|
||||||
call void @runtime.printint16(i16 %int16SliceDst.val)
|
|
||||||
|
|
||||||
; print(sliceDstUntaint[0])
|
|
||||||
%sliceDstUntaint.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstUntaint.buf, i32 0)
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstUntaint.val)
|
|
||||||
|
|
||||||
; print(sliceDstTaint[0])
|
|
||||||
%sliceDstTaint.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstTaint.buf, i32 0)
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstTaint.val)
|
|
||||||
|
|
||||||
; print(sliceDstExternal1[0])
|
|
||||||
%sliceDstExternal1.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstExternal1.buf, i32 0)
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstExternal1.val)
|
|
||||||
|
|
||||||
; print(sliceDstExternal2[0])
|
|
||||||
%sliceDstExternal2.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstExternal2.buf, i32 0)
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstExternal2.val)
|
|
||||||
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define internal void @main.init() unnamed_addr {
|
|
||||||
entry:
|
|
||||||
; equivalent of:
|
|
||||||
; uint8SliceDst = make([]uint8, len(uint8SliceSrc))
|
|
||||||
%uint8SliceSrc = load { ptr, i64, i64 }, ptr @main.uint8SliceSrc
|
|
||||||
%uint8SliceSrc.len = extractvalue { ptr, i64, i64 } %uint8SliceSrc, 1
|
|
||||||
%uint8SliceDst.buf = call ptr @runtime.alloc(i64 %uint8SliceSrc.len, ptr null)
|
|
||||||
%0 = insertvalue { ptr, i64, i64 } undef, ptr %uint8SliceDst.buf, 0
|
|
||||||
%1 = insertvalue { ptr, i64, i64 } %0, i64 %uint8SliceSrc.len, 1
|
|
||||||
%2 = insertvalue { ptr, i64, i64 } %1, i64 %uint8SliceSrc.len, 2
|
|
||||||
store { ptr, i64, i64 } %2, ptr @main.uint8SliceDst
|
|
||||||
|
|
||||||
; equivalent of:
|
|
||||||
; copy(uint8SliceDst, uint8SliceSrc)
|
|
||||||
%uint8SliceSrc.buf = extractvalue { ptr, i64, i64 } %uint8SliceSrc, 0
|
|
||||||
%copy.n = call i64 @runtime.sliceCopy(ptr %uint8SliceDst.buf, ptr %uint8SliceSrc.buf, i64 %uint8SliceSrc.len, i64 %uint8SliceSrc.len, i64 1)
|
|
||||||
|
|
||||||
; equivalent of:
|
|
||||||
; int16SliceDst = make([]int16, len(int16SliceSrc))
|
|
||||||
%int16SliceSrc = load { ptr, i64, i64 }, ptr @main.int16SliceSrc
|
|
||||||
%int16SliceSrc.len = extractvalue { ptr, i64, i64 } %int16SliceSrc, 1
|
|
||||||
%int16SliceSrc.len.bytes = mul i64 %int16SliceSrc.len, 2
|
|
||||||
%int16SliceDst.buf = call ptr @runtime.alloc(i64 %int16SliceSrc.len.bytes, ptr null)
|
|
||||||
%3 = insertvalue { ptr, i64, i64 } undef, ptr %int16SliceDst.buf, 0
|
|
||||||
%4 = insertvalue { ptr, i64, i64 } %3, i64 %int16SliceSrc.len, 1
|
|
||||||
%5 = insertvalue { ptr, i64, i64 } %4, i64 %int16SliceSrc.len, 2
|
|
||||||
store { ptr, i64, i64 } %5, ptr @main.int16SliceDst
|
|
||||||
|
|
||||||
; equivalent of:
|
|
||||||
; copy(int16SliceDst, int16SliceSrc)
|
|
||||||
%int16SliceSrc.buf = extractvalue { ptr, i64, i64 } %int16SliceSrc, 0
|
|
||||||
%copy.n2 = call i64 @runtime.sliceCopy(ptr %int16SliceDst.buf, ptr %int16SliceSrc.buf, i64 %int16SliceSrc.len, i64 %int16SliceSrc.len, i64 2)
|
|
||||||
|
|
||||||
; Copy slice that has a known value.
|
|
||||||
%copy.n3 = call i64 @runtime.sliceCopy(ptr @main.sliceDstUntaint.buf, ptr @main.sliceSrcUntaint.buf, i64 2, i64 2, i64 1)
|
|
||||||
|
|
||||||
; Copy slice that might have been modified by the external @use call.
|
|
||||||
; This is a fix for https://github.com/tinygo-org/tinygo/issues/3890.
|
|
||||||
call void @use(ptr @main.sliceSrcTaint.buf)
|
|
||||||
%copy.n4 = call i64 @runtime.sliceCopy(ptr @main.sliceDstTaint.buf, ptr @main.sliceSrcTaint.buf, i64 2, i64 2, i64 1)
|
|
||||||
|
|
||||||
; Test that copying from or into external buffers works correctly.
|
|
||||||
; These copy operations must be done at runtime.
|
|
||||||
; https://github.com/tinygo-org/tinygo/issues/4895
|
|
||||||
%copy.n5 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal1.buf, ptr @main.sliceSrcExternal1.buf, i64 2, i64 2, i64 1)
|
|
||||||
%copy.n6 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal2.buf, ptr @main.sliceSrcExternal2.buf, i64 2, i64 2, i64 1)
|
|
||||||
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
Vendored
-42
@@ -1,42 +0,0 @@
|
|||||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
||||||
target triple = "x86_64--linux"
|
|
||||||
|
|
||||||
@main.sliceSrcTaint.buf = internal global [2 x i8] c"cd"
|
|
||||||
@main.sliceDstTaint.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceSrcExternal1.buf = external global [2 x i8]
|
|
||||||
@main.sliceDstExternal1.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceSrcExternal2.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceDstExternal2.buf = external global [2 x i8]
|
|
||||||
|
|
||||||
declare i64 @runtime.sliceCopy(ptr, ptr, i64, i64, i64) unnamed_addr
|
|
||||||
|
|
||||||
declare void @runtime.printuint8(i8) local_unnamed_addr
|
|
||||||
|
|
||||||
declare void @runtime.printint16(i16) local_unnamed_addr
|
|
||||||
|
|
||||||
declare void @use(ptr) local_unnamed_addr
|
|
||||||
|
|
||||||
define void @runtime.initAll() unnamed_addr {
|
|
||||||
entry:
|
|
||||||
call void @use(ptr @main.sliceSrcTaint.buf)
|
|
||||||
%copy.n4 = call i64 @runtime.sliceCopy(ptr @main.sliceDstTaint.buf, ptr @main.sliceSrcTaint.buf, i64 2, i64 2, i64 1)
|
|
||||||
%copy.n5 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal1.buf, ptr @main.sliceSrcExternal1.buf, i64 2, i64 2, i64 1)
|
|
||||||
%copy.n6 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal2.buf, ptr @main.sliceSrcExternal2.buf, i64 2, i64 2, i64 1)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @main() unnamed_addr {
|
|
||||||
entry:
|
|
||||||
call void @runtime.printuint8(i8 3)
|
|
||||||
call void @runtime.printuint8(i8 3)
|
|
||||||
call void @runtime.printint16(i16 5)
|
|
||||||
call void @runtime.printint16(i16 5)
|
|
||||||
call void @runtime.printuint8(i8 97)
|
|
||||||
%sliceDstTaint.val = load i8, ptr @main.sliceDstTaint.buf, align 1
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstTaint.val)
|
|
||||||
%sliceDstExternal1.val = load i8, ptr @main.sliceDstExternal1.buf, align 1
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstExternal1.val)
|
|
||||||
%sliceDstExternal2.val = load i8, ptr @main.sliceDstExternal2.buf, align 1
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstExternal2.val)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
+1
-1
Submodule lib/stm32-svd updated: e6db8e32d5...bfed180b63
@@ -245,6 +245,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
|||||||
"internal/cm/": false,
|
"internal/cm/": false,
|
||||||
"internal/futex/": false,
|
"internal/futex/": false,
|
||||||
"internal/fuzz/": false,
|
"internal/fuzz/": false,
|
||||||
|
"internal/itoa": false,
|
||||||
"internal/reflectlite/": false,
|
"internal/reflectlite/": false,
|
||||||
"internal/gclayout": false,
|
"internal/gclayout": false,
|
||||||
"internal/task/": false,
|
"internal/task/": false,
|
||||||
@@ -267,11 +268,31 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
|||||||
paths["crypto/internal/boring/sig/"] = false
|
paths["crypto/internal/boring/sig/"] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if goMinor >= 26 {
|
||||||
|
// Go 1.26 added a CPU jitter entropy source for FIPS 140-3 that
|
||||||
|
// allocates a 32 MiB global buffer (ScratchBuffer [1<<25]byte).
|
||||||
|
// This is fine on systems with virtual memory, but causes RAM
|
||||||
|
// overflow on microcontrollers. Replace with a zero-size stub
|
||||||
|
// since TinyGo targets never use FIPS jitter entropy.
|
||||||
|
paths["crypto/internal/entropy/"] = true
|
||||||
|
paths["crypto/internal/entropy/v1.0.0/"] = false
|
||||||
|
}
|
||||||
|
|
||||||
if needsSyscallPackage {
|
if needsSyscallPackage {
|
||||||
paths["syscall/"] = true // include syscall/js
|
paths["syscall/"] = true // include syscall/js
|
||||||
paths["internal/syscall/"] = true
|
paths["internal/syscall/"] = true
|
||||||
paths["internal/syscall/unix/"] = false
|
paths["internal/syscall/unix/"] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if goMinor >= 26 {
|
||||||
|
// Go 1.26 added SWAR optimizations to unicode/utf8 that use
|
||||||
|
// constants assuming at least 32-bit uintptr. TinyGo supports
|
||||||
|
// 16-bit targets (AVR) where these constants overflow, so we
|
||||||
|
// provide a patched version.
|
||||||
|
paths["unicode/"] = true
|
||||||
|
paths["unicode/utf8/"] = false
|
||||||
|
}
|
||||||
|
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+55
-41
@@ -549,7 +549,7 @@ func (p *Package) extractEmbedLines(addError func(error)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look for //go:embed comments.
|
// Look for //go:embed comments.
|
||||||
var allPatterns []string
|
var allPatterns []embedPattern
|
||||||
for _, comment := range doc.List {
|
for _, comment := range doc.List {
|
||||||
if comment.Text != "//go:embed" && !strings.HasPrefix(comment.Text, "//go:embed ") {
|
if comment.Text != "//go:embed" && !strings.HasPrefix(comment.Text, "//go:embed ") {
|
||||||
continue
|
continue
|
||||||
@@ -577,21 +577,7 @@ func (p *Package) extractEmbedLines(addError func(error)) {
|
|||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, pattern := range patterns {
|
allPatterns = append(allPatterns, patterns...)
|
||||||
// Check that the pattern is well-formed.
|
|
||||||
// It must be valid: the Go toolchain has already
|
|
||||||
// checked for invalid patterns. But let's check
|
|
||||||
// anyway to be sure.
|
|
||||||
if _, err := path.Match(pattern, ""); err != nil {
|
|
||||||
addError(types.Error{
|
|
||||||
Fset: p.program.fset,
|
|
||||||
Pos: comment.Pos(),
|
|
||||||
Msg: "invalid pattern syntax",
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
allPatterns = append(allPatterns, pattern)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(allPatterns) != 0 {
|
if len(allPatterns) != 0 {
|
||||||
@@ -624,8 +610,8 @@ func (p *Package) extractEmbedLines(addError func(error)) {
|
|||||||
// Match all //go:embed patterns against the embed files
|
// Match all //go:embed patterns against the embed files
|
||||||
// provided by `go list`.
|
// provided by `go list`.
|
||||||
for _, name := range p.EmbedFiles {
|
for _, name := range p.EmbedFiles {
|
||||||
for _, pattern := range allPatterns {
|
for _, ep := range allPatterns {
|
||||||
if matchPattern(pattern, name) {
|
if ep.Match(name) {
|
||||||
p.EmbedGlobals[globalName] = append(p.EmbedGlobals[globalName], &EmbedFile{
|
p.EmbedGlobals[globalName] = append(p.EmbedGlobals[globalName], &EmbedFile{
|
||||||
Name: name,
|
Name: name,
|
||||||
NeedsData: byteSlice,
|
NeedsData: byteSlice,
|
||||||
@@ -641,13 +627,37 @@ func (p *Package) extractEmbedLines(addError func(error)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// matchPattern returns true if (and only if) the given pattern would match the
|
// embedPattern represents a valid //go:embed pattern.
|
||||||
// filename. The pattern could also match a parent directory of name, in which
|
// See: https://pkg.go.dev/embed#hdr-Directives
|
||||||
// case hidden files do not match.
|
type embedPattern struct {
|
||||||
func matchPattern(pattern, name string) bool {
|
pattern string // glob pattern without "all:" prefix
|
||||||
|
includeHidden bool // true if "all:" prefix was present
|
||||||
|
}
|
||||||
|
|
||||||
|
// newEmbedPattern parses and validates a //go:embed pattern.
|
||||||
|
// The "all:" prefix (if present) is stripped and reflected in includeHidden.
|
||||||
|
// Returns an error if the pattern syntax is invalid.
|
||||||
|
func newEmbedPattern(s string) (embedPattern, error) {
|
||||||
|
ep := embedPattern{pattern: s}
|
||||||
|
if strings.HasPrefix(s, "all:") {
|
||||||
|
ep.pattern = s[4:]
|
||||||
|
ep.includeHidden = true
|
||||||
|
}
|
||||||
|
if _, err := path.Match(ep.pattern, ""); err != nil {
|
||||||
|
return embedPattern{}, err
|
||||||
|
}
|
||||||
|
return ep, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match returns true if (and only if) the pattern matches the given filename.
|
||||||
|
// The pattern could also match a parent directory of name, in which case hidden
|
||||||
|
// files do not match (unless includeHidden is true).
|
||||||
|
func (ep embedPattern) Match(name string) bool {
|
||||||
|
pattern := ep.pattern
|
||||||
|
includeHidden := ep.includeHidden
|
||||||
|
|
||||||
// Match this file.
|
// Match this file.
|
||||||
matched, _ := path.Match(pattern, name)
|
if matched, _ := path.Match(pattern, name); matched {
|
||||||
if matched {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,17 +671,20 @@ func matchPattern(pattern, name string) bool {
|
|||||||
dir = path.Clean(dir)
|
dir = path.Clean(dir)
|
||||||
if matched, _ := path.Match(pattern, dir); matched {
|
if matched, _ := path.Match(pattern, dir); matched {
|
||||||
// Pattern matches the directory.
|
// Pattern matches the directory.
|
||||||
suffix := name[len(dir):]
|
if !includeHidden {
|
||||||
if strings.Contains(suffix, "/_") || strings.Contains(suffix, "/.") {
|
suffix := name[len(dir):]
|
||||||
// Pattern matches a hidden file.
|
if strings.Contains(suffix, "/_") || strings.Contains(suffix, "/.") {
|
||||||
// Hidden files are included when listed directly as a
|
// Pattern matches a hidden file.
|
||||||
// pattern, but not when they are part of a directory tree.
|
// Hidden files are included when listed directly as a
|
||||||
// Source:
|
// pattern, or when the "all:" prefix is used, but not
|
||||||
// > If a pattern names a directory, all files in the
|
// when they are part of a directory tree without "all:".
|
||||||
// > subtree rooted at that directory are embedded
|
// Source:
|
||||||
// > (recursively), except that files with names beginning
|
// > If a pattern names a directory, all files in the
|
||||||
// > with ‘.’ or ‘_’ are excluded.
|
// > subtree rooted at that directory are embedded
|
||||||
return false
|
// > (recursively), except that files with names beginning
|
||||||
|
// > with ‘.’ or ‘_’ are excluded.
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -680,11 +693,12 @@ func matchPattern(pattern, name string) bool {
|
|||||||
|
|
||||||
// parseGoEmbed is like strings.Fields but for a //go:embed line. It parses
|
// parseGoEmbed is like strings.Fields but for a //go:embed line. It parses
|
||||||
// regular fields and quoted fields (that may contain spaces).
|
// regular fields and quoted fields (that may contain spaces).
|
||||||
func (p *Package) parseGoEmbed(args string, pos token.Pos) (patterns []string, err error) {
|
func (p *Package) parseGoEmbed(args string, pos token.Pos) (patterns []embedPattern, err error) {
|
||||||
args = strings.TrimSpace(args)
|
args = strings.TrimSpace(args)
|
||||||
initialLen := len(args)
|
initialLen := len(args)
|
||||||
for args != "" {
|
for args != "" {
|
||||||
patternPos := pos + token.Pos(initialLen-len(args))
|
patternPos := pos + token.Pos(initialLen-len(args))
|
||||||
|
var pattern string
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case '`', '"', '\\':
|
case '`', '"', '\\':
|
||||||
// Parse the next pattern using the Go scanner.
|
// Parse the next pattern using the Go scanner.
|
||||||
@@ -703,8 +717,7 @@ func (p *Package) parseGoEmbed(args string, pos token.Pos) (patterns []string, e
|
|||||||
Msg: "invalid quoted string in //go:embed",
|
Msg: "invalid quoted string in //go:embed",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pattern := constant.StringVal(constant.MakeFromLiteral(lit, tok, 0))
|
pattern = constant.StringVal(constant.MakeFromLiteral(lit, tok, 0))
|
||||||
patterns = append(patterns, pattern)
|
|
||||||
args = strings.TrimLeftFunc(args[len(lit):], unicode.IsSpace)
|
args = strings.TrimLeftFunc(args[len(lit):], unicode.IsSpace)
|
||||||
default:
|
default:
|
||||||
// The value is just a regular value.
|
// The value is just a regular value.
|
||||||
@@ -713,17 +726,18 @@ func (p *Package) parseGoEmbed(args string, pos token.Pos) (patterns []string, e
|
|||||||
if index < 0 {
|
if index < 0 {
|
||||||
index = len(args)
|
index = len(args)
|
||||||
}
|
}
|
||||||
pattern := args[:index]
|
pattern = args[:index]
|
||||||
patterns = append(patterns, pattern)
|
|
||||||
args = strings.TrimLeftFunc(args[len(pattern):], unicode.IsSpace)
|
args = strings.TrimLeftFunc(args[len(pattern):], unicode.IsSpace)
|
||||||
}
|
}
|
||||||
if _, err := path.Match(patterns[len(patterns)-1], ""); err != nil {
|
ep, err := newEmbedPattern(pattern)
|
||||||
|
if err != nil {
|
||||||
return nil, types.Error{
|
return nil, types.Error{
|
||||||
Fset: p.program.fset,
|
Fset: p.program.fset,
|
||||||
Pos: patternPos,
|
Pos: patternPos,
|
||||||
Msg: "invalid pattern syntax",
|
Msg: "invalid pattern syntax",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
patterns = append(patterns, ep)
|
||||||
}
|
}
|
||||||
return patterns, nil
|
return patterns, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,15 @@ import (
|
|||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
"github.com/tinygo-org/tinygo/loader"
|
"github.com/tinygo-org/tinygo/loader"
|
||||||
"golang.org/x/tools/go/buildutil"
|
"golang.org/x/tools/go/buildutil"
|
||||||
|
"tinygo.org/x/espflasher/pkg/espflasher"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
|
|
||||||
"go.bug.st/serial"
|
"go.bug.st/serial"
|
||||||
"go.bug.st/serial/enumerator"
|
"go.bug.st/serial/enumerator"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errInheritableOnly = errors.New("target is inheritable-only, which means it cannot be used directly for building or flashing")
|
||||||
|
|
||||||
// commandError is an error type to wrap os/exec.Command errors. This provides
|
// commandError is an error type to wrap os/exec.Command errors. This provides
|
||||||
// some more information regarding what went wrong while running a command.
|
// some more information regarding what went wrong while running a command.
|
||||||
type commandError struct {
|
type commandError struct {
|
||||||
@@ -139,6 +142,10 @@ func printCommand(cmd string, args ...string) {
|
|||||||
|
|
||||||
// Build compiles and links the given package and writes it to outpath.
|
// Build compiles and links the given package and writes it to outpath.
|
||||||
func Build(pkgName, outpath string, config *compileopts.Config) error {
|
func Build(pkgName, outpath string, config *compileopts.Config) error {
|
||||||
|
if config.Target != nil && config.Target.InheritableOnly {
|
||||||
|
return errInheritableOnly
|
||||||
|
}
|
||||||
|
|
||||||
// Create a temporary directory for intermediary files.
|
// Create a temporary directory for intermediary files.
|
||||||
tmpdir, err := os.MkdirTemp("", "tinygo")
|
tmpdir, err := os.MkdirTemp("", "tinygo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -356,6 +363,10 @@ func Flash(pkgName, port, outpath string, options *compileopts.Options) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Target != nil && config.Target.InheritableOnly {
|
||||||
|
return errInheritableOnly
|
||||||
|
}
|
||||||
|
|
||||||
// determine the type of file to compile
|
// determine the type of file to compile
|
||||||
var fileExt string
|
var fileExt string
|
||||||
|
|
||||||
@@ -385,6 +396,10 @@ func Flash(pkgName, port, outpath string, options *compileopts.Options) error {
|
|||||||
fileExt = ".hex"
|
fileExt = ".hex"
|
||||||
case "bmp":
|
case "bmp":
|
||||||
fileExt = ".elf"
|
fileExt = ".elf"
|
||||||
|
case "adb":
|
||||||
|
fileExt = ".hex"
|
||||||
|
case "esp32flash", "esp32jtag":
|
||||||
|
fileExt = ".bin"
|
||||||
case "native":
|
case "native":
|
||||||
return errors.New("unknown flash method \"native\" - did you miss a -target flag?")
|
return errors.New("unknown flash method \"native\" - did you miss a -target flag?")
|
||||||
default:
|
default:
|
||||||
@@ -519,6 +534,56 @@ func Flash(pkgName, port, outpath string, options *compileopts.Options) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to flash", result.Binary, err}
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
}
|
}
|
||||||
|
case "adb":
|
||||||
|
// Run pre-flash adb shell commands.
|
||||||
|
for _, preCmd := range config.Target.ADBPreCommands {
|
||||||
|
cmd := executeCommand(config.Options, "adb", "shell", preCmd)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return &commandError{"failed to run adb pre-command", preCmd, err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the binary to the device.
|
||||||
|
if config.Target.ADBPushRemote == "" {
|
||||||
|
return errors.New("invalid target file: flash-method was set to \"adb\" but no adb-push-remote was set")
|
||||||
|
}
|
||||||
|
cmd := executeCommand(config.Options, "adb", "push", result.Binary, config.Target.ADBPushRemote)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return &commandError{"adb push failed to " + config.Target.ADBPushRemote, result.Binary, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run post-flash adb shell commands.
|
||||||
|
for _, postCmd := range config.Target.ADBPostCommands {
|
||||||
|
postCmd = strings.ReplaceAll(postCmd, "{remote}", config.Target.ADBPushRemote)
|
||||||
|
cmd := executeCommand(config.Options, "adb", "shell", postCmd)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return &commandError{"failed to run adb post-command", postCmd, err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "esp32flash":
|
||||||
|
port, err := getDefaultPort(port, config.Target.SerialPort)
|
||||||
|
if err != nil {
|
||||||
|
return &commandError{"failed to find port", port, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := flashBinUsingEsp32(port, classicReset, result.Binary, config.Options); err != nil {
|
||||||
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
|
}
|
||||||
|
case "esp32jtag":
|
||||||
|
port, err := getDefaultPort(port, config.Target.SerialPort)
|
||||||
|
if err != nil {
|
||||||
|
return &commandError{"failed to find port", port, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := flashBinUsingEsp32(port, jtagReset, result.Binary, config.Options); err != nil {
|
||||||
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
||||||
}
|
}
|
||||||
@@ -765,6 +830,10 @@ func Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Target != nil && config.Target.InheritableOnly {
|
||||||
|
return errInheritableOnly
|
||||||
|
}
|
||||||
|
|
||||||
_, err = buildAndRun(pkgName, config, os.Stdout, cmdArgs, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
_, err = buildAndRun(pkgName, config, os.Stdout, cmdArgs, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
})
|
})
|
||||||
@@ -1019,6 +1088,68 @@ func flashHexUsingMSD(volumes []string, tmppath string, options *compileopts.Opt
|
|||||||
return errors.New("unable to locate any volume: [" + strings.Join(volumes, ",") + "]")
|
return errors.New("unable to locate any volume: [" + strings.Join(volumes, ",") + "]")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultReset = "default"
|
||||||
|
classicReset = "classic"
|
||||||
|
jtagReset = "jtag"
|
||||||
|
)
|
||||||
|
|
||||||
|
func flashBinUsingEsp32(port, resetMode, tmppath string, options *compileopts.Options) error {
|
||||||
|
opts := espflasher.DefaultOptions()
|
||||||
|
opts.Compress = true
|
||||||
|
opts.Logger = &espflasher.StdoutLogger{W: os.Stdout}
|
||||||
|
if options.BaudRate != 0 {
|
||||||
|
opts.FlashBaudRate = options.BaudRate
|
||||||
|
}
|
||||||
|
|
||||||
|
if resetMode == jtagReset {
|
||||||
|
opts.ResetMode = espflasher.ResetUSBJTAG
|
||||||
|
}
|
||||||
|
|
||||||
|
flasher, err := espflasher.New(port, opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer flasher.Close()
|
||||||
|
|
||||||
|
chipName := flasher.ChipName()
|
||||||
|
offset := uint32(0x0)
|
||||||
|
if chipName == "ESP32" {
|
||||||
|
offset = 0x1000
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the firmware binary
|
||||||
|
data, err := os.ReadFile(tmppath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := flasher.EraseFlash(); err != nil {
|
||||||
|
return fmt.Errorf("erase failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
progress := func(current, total int) {
|
||||||
|
pct := float64(current) / float64(total) * 100
|
||||||
|
bar := int(pct / 2)
|
||||||
|
fmt.Printf("\r[%-50s] %6.1f%%", strings.Repeat("#", bar)+strings.Repeat(".", 50-bar), pct)
|
||||||
|
if current >= total {
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flash with progress reporting
|
||||||
|
err = flasher.FlashImage(data, offset, progress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// Reset the device to run the new firmware
|
||||||
|
flasher.Reset()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type mountPoint struct {
|
type mountPoint struct {
|
||||||
name string
|
name string
|
||||||
path string
|
path string
|
||||||
|
|||||||
+5
-1
@@ -107,6 +107,9 @@ func TestBuild(t *testing.T) {
|
|||||||
if minor >= 23 {
|
if minor >= 23 {
|
||||||
tests = append(tests, "go1.23/")
|
tests = append(tests, "go1.23/")
|
||||||
}
|
}
|
||||||
|
if minor >= 24 {
|
||||||
|
tests = append(tests, "typealias.go")
|
||||||
|
}
|
||||||
|
|
||||||
if *testTarget != "" {
|
if *testTarget != "" {
|
||||||
// This makes it possible to run one specific test (instead of all),
|
// This makes it possible to run one specific test (instead of all),
|
||||||
@@ -222,6 +225,7 @@ func TestBuild(t *testing.T) {
|
|||||||
// to be sure.
|
// to be sure.
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
options := optionsFromOSARCH("linux/mipsle/softfloat", sema)
|
options := optionsFromOSARCH("linux/mipsle/softfloat", sema)
|
||||||
|
emuCheck(t, options)
|
||||||
runTest("cgo/", options, t, nil, nil)
|
runTest("cgo/", options, t, nil, nil)
|
||||||
})
|
})
|
||||||
} else if runtime.GOOS == "windows" {
|
} else if runtime.GOOS == "windows" {
|
||||||
@@ -450,7 +454,7 @@ 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{}
|
||||||
_, err = buildAndRun(pkgName, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
_, err = buildAndRun(pkgName, config, stdout, cmdArgs, environmentVars, 2*time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Stripped-down version of the entropy package for TinyGo.
|
||||||
|
//
|
||||||
|
// The upstream Go 1.26 package allocates a [1<<25]byte (32 MiB) global buffer
|
||||||
|
// for CPU jitter-based SP 800-90B entropy collection. This is fine on systems
|
||||||
|
// with virtual memory where BSS pages are lazily backed, but it causes a fatal
|
||||||
|
// "RAM overflowed" error on microcontrollers and other memory-constrained
|
||||||
|
// targets.
|
||||||
|
//
|
||||||
|
// Because FIPS 140-3 jitter entropy is never used on TinyGo targets (the DRBG
|
||||||
|
// falls through to sysrand.Read when fips140.Enabled is false), this overlay
|
||||||
|
// replaces the 32 MiB buffer with a zero-size type.
|
||||||
|
package entropy
|
||||||
|
|
||||||
|
// Version returns the version of the entropy source.
|
||||||
|
func Version() string {
|
||||||
|
return "v1.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScratchBuffer is a large buffer in upstream Go (32 MiB). TinyGo replaces it
|
||||||
|
// with a zero-size type since the CPU jitter entropy source is not used.
|
||||||
|
type ScratchBuffer [0]byte
|
||||||
|
|
||||||
|
// Seed returns a 384-bit seed with full entropy.
|
||||||
|
// On TinyGo targets this is never called because FIPS mode is not enabled.
|
||||||
|
func Seed(memory *ScratchBuffer) ([48]byte, error) {
|
||||||
|
panic("entropy: CPU jitter entropy source is not supported on TinyGo targets")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Samples collects entropy samples. Not supported on TinyGo targets.
|
||||||
|
func Samples(samples []uint8, memory *ScratchBuffer) error {
|
||||||
|
panic("entropy: CPU jitter entropy source is not supported on TinyGo targets")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SHA384 computes SHA-384 over 1024 bytes. Not supported on TinyGo targets.
|
||||||
|
func SHA384(p *[1024]byte) [48]byte {
|
||||||
|
panic("entropy: CPU jitter entropy source is not supported on TinyGo targets")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestingOnlySHA384 computes SHA-384 over arbitrary bytes. Not supported on TinyGo targets.
|
||||||
|
func TestingOnlySHA384(p []byte) [48]byte {
|
||||||
|
panic("entropy: CPU jitter entropy source is not supported on TinyGo targets")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepetitionCountTest implements the repetition count test from SP 800-90B.
|
||||||
|
func RepetitionCountTest(samples []uint8) error {
|
||||||
|
panic("entropy: CPU jitter entropy source is not supported on TinyGo targets")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdaptiveProportionTest implements the adaptive proportion test from SP 800-90B.
|
||||||
|
func AdaptiveProportionTest(samples []uint8) error {
|
||||||
|
panic("entropy: CPU jitter entropy source is not supported on TinyGo targets")
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || tkey || (tinygo.riscv32 && virt)
|
//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3 || esp32s3 || tkey || (tinygo.riscv32 && virt)
|
||||||
|
|
||||||
// If you update the above build constraint, you'll probably also need to update
|
// If you update the above build constraint, you'll probably also need to update
|
||||||
// src/runtime/rand_hwrng.go.
|
// src/runtime/rand_hwrng.go.
|
||||||
|
|||||||
@@ -0,0 +1,397 @@
|
|||||||
|
// Startup code for the ESP32-S3 (Xtensa LX7, windowed ABI).
|
||||||
|
//
|
||||||
|
// The ROM bootloader loads IRAM/DRAM segments into SRAM but does NOT
|
||||||
|
// configure flash cache/MMU. We must:
|
||||||
|
// 1. Set up the windowed-ABI register file and stack pointer.
|
||||||
|
// 2. Set VECBASE and clear PS.EXCM (needed for callx4 window overflows).
|
||||||
|
// 3. Disable watchdog timers.
|
||||||
|
// 4. Configure the flash cache and MMU so IROM/DROM are accessible.
|
||||||
|
// 5. Jump to runtime.main (in IROM).
|
||||||
|
//
|
||||||
|
// Cache/MMU init sequence (from NuttX esp_loader.c / ESP-IDF bootloader / esp-hal):
|
||||||
|
// Phase A — configure cache modes:
|
||||||
|
// a. rom_config_instruction_cache_mode(16KB, 8-way, 32B)
|
||||||
|
// b. rom_Cache_Suspend_DCache()
|
||||||
|
// c. rom_config_data_cache_mode(32KB, 8-way, 32B)
|
||||||
|
// d. Cache_Resume_DCache(0)
|
||||||
|
// Phase B — map flash pages:
|
||||||
|
// e. Disable caches
|
||||||
|
// f. Cache_MMU_Init() — reset all MMU entries to invalid
|
||||||
|
// g. Cache_Set_IDROM_MMU_Size() — set IROM/DROM entry split
|
||||||
|
// h. Write MMU entries mapping flash page 0 for IROM and DROM
|
||||||
|
// i. Clear bus-shut bits
|
||||||
|
// j. Enable caches + isync
|
||||||
|
|
||||||
|
#define PS_WOE 0x00040000
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Boot entry point — placed in IRAM by the linker.
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
.section .text.call_start_cpu0
|
||||||
|
.literal_position
|
||||||
|
.align 4
|
||||||
|
.Lstack_top_addr:
|
||||||
|
.long _stack_top
|
||||||
|
.Lmain_addr:
|
||||||
|
.long main
|
||||||
|
.Lvector_table_addr:
|
||||||
|
.long _vector_table
|
||||||
|
// WDT register addresses
|
||||||
|
.Lwdt_key:
|
||||||
|
.long 0x50D83AA1
|
||||||
|
.Lrtc_wdt_protect:
|
||||||
|
.long 0x600080B0
|
||||||
|
.Lrtc_wdt_config0:
|
||||||
|
.long 0x60008098
|
||||||
|
.Ltimg0_wdt_protect:
|
||||||
|
.long 0x6001F064
|
||||||
|
.Ltimg0_wdt_config0:
|
||||||
|
.long 0x6001F048
|
||||||
|
.Ltimg1_wdt_protect:
|
||||||
|
.long 0x60020064
|
||||||
|
.Ltimg1_wdt_config0:
|
||||||
|
.long 0x60020048
|
||||||
|
.Lswd_protect:
|
||||||
|
.long 0x600080B8
|
||||||
|
.Lswd_key:
|
||||||
|
.long 0x8F1D312A
|
||||||
|
.Lswd_conf:
|
||||||
|
.long 0x600080B4
|
||||||
|
.Lswd_disable:
|
||||||
|
.long 0x40000000
|
||||||
|
// ROM function addresses (from ESP-IDF esp32s3.rom.ld)
|
||||||
|
.Lrom_config_icache:
|
||||||
|
.long 0x40001a1c
|
||||||
|
.Lrom_config_dcache:
|
||||||
|
.long 0x40001a28
|
||||||
|
.Lrom_suspend_dcache:
|
||||||
|
.long 0x400018b4
|
||||||
|
.LCache_Resume_DCache:
|
||||||
|
.long 0x400018c0
|
||||||
|
.LCache_Disable_ICache:
|
||||||
|
.long 0x4000186c
|
||||||
|
.LCache_Disable_DCache:
|
||||||
|
.long 0x40001884
|
||||||
|
.LCache_MMU_Init:
|
||||||
|
.long 0x40001998
|
||||||
|
.LCache_Set_IDROM_MMU_Size:
|
||||||
|
.long 0x40001914
|
||||||
|
.LCache_Enable_ICache:
|
||||||
|
.long 0x40001878
|
||||||
|
.LCache_Enable_DCache:
|
||||||
|
.long 0x40001890
|
||||||
|
// Cache/MMU register addresses
|
||||||
|
.Lmmu_table_base:
|
||||||
|
.long 0x600C5000
|
||||||
|
.Licache_ctrl1_reg:
|
||||||
|
.long 0x600C4064
|
||||||
|
.Ldcache_ctrl1_reg:
|
||||||
|
.long 0x600C4004
|
||||||
|
// End-of-section symbols for multi-page MMU mapping.
|
||||||
|
.Lirom_end:
|
||||||
|
.long _irom_end
|
||||||
|
.Ldrom_end:
|
||||||
|
.long _drom_end
|
||||||
|
.Lirom_base:
|
||||||
|
.long 0x42000000
|
||||||
|
.Ldrom_base:
|
||||||
|
.long 0x3C000000
|
||||||
|
|
||||||
|
.global call_start_cpu0
|
||||||
|
call_start_cpu0:
|
||||||
|
|
||||||
|
// ---- 1. Windowed-ABI register file setup ----
|
||||||
|
|
||||||
|
// Disable WOE so we can safely manipulate WINDOWSTART.
|
||||||
|
rsr.ps a2
|
||||||
|
movi a3, ~(PS_WOE)
|
||||||
|
and a2, a2, a3
|
||||||
|
wsr.ps a2
|
||||||
|
rsync
|
||||||
|
|
||||||
|
// Set WINDOWSTART to 1 << WINDOWBASE (mark only current window as valid).
|
||||||
|
rsr.windowbase a2
|
||||||
|
ssl a2
|
||||||
|
movi a2, 1
|
||||||
|
sll a2, a2
|
||||||
|
wsr.windowstart a2
|
||||||
|
rsync
|
||||||
|
|
||||||
|
// Load stack pointer.
|
||||||
|
l32r a1, .Lstack_top_addr
|
||||||
|
|
||||||
|
// Re-enable WOE.
|
||||||
|
rsr.ps a2
|
||||||
|
movi a3, PS_WOE
|
||||||
|
or a2, a2, a3
|
||||||
|
wsr.ps a2
|
||||||
|
rsync
|
||||||
|
|
||||||
|
// Enable FPU (coprocessor 0).
|
||||||
|
movi a2, 1
|
||||||
|
wsr.cpenable a2
|
||||||
|
rsync
|
||||||
|
|
||||||
|
// ---- 2. Disable all watchdog timers (IMMEDIATELY, before any delay) ----
|
||||||
|
l32r a3, .Lwdt_key
|
||||||
|
movi a4, 0
|
||||||
|
|
||||||
|
// RTC WDT
|
||||||
|
l32r a2, .Lrtc_wdt_protect
|
||||||
|
memw
|
||||||
|
s32i a3, a2, 0
|
||||||
|
l32r a5, .Lrtc_wdt_config0
|
||||||
|
memw
|
||||||
|
s32i a4, a5, 0
|
||||||
|
memw
|
||||||
|
s32i a4, a2, 0
|
||||||
|
|
||||||
|
// TIMG0 WDT
|
||||||
|
l32r a2, .Ltimg0_wdt_protect
|
||||||
|
memw
|
||||||
|
s32i a3, a2, 0
|
||||||
|
l32r a5, .Ltimg0_wdt_config0
|
||||||
|
memw
|
||||||
|
s32i a4, a5, 0
|
||||||
|
memw
|
||||||
|
s32i a4, a2, 0
|
||||||
|
|
||||||
|
// TIMG1 WDT
|
||||||
|
l32r a2, .Ltimg1_wdt_protect
|
||||||
|
memw
|
||||||
|
s32i a3, a2, 0
|
||||||
|
l32r a5, .Ltimg1_wdt_config0
|
||||||
|
memw
|
||||||
|
s32i a4, a5, 0
|
||||||
|
memw
|
||||||
|
s32i a4, a2, 0
|
||||||
|
|
||||||
|
// Super WDT
|
||||||
|
l32r a2, .Lswd_protect
|
||||||
|
l32r a3, .Lswd_key
|
||||||
|
memw
|
||||||
|
s32i a3, a2, 0
|
||||||
|
l32r a5, .Lswd_conf
|
||||||
|
l32r a6, .Lswd_disable
|
||||||
|
memw
|
||||||
|
s32i a6, a5, 0
|
||||||
|
memw
|
||||||
|
s32i a4, a2, 0
|
||||||
|
|
||||||
|
// ---- 3. Set VECBASE and clear PS.EXCM ----
|
||||||
|
// VECBASE must be set before any callx4 so that window overflow
|
||||||
|
// exceptions (triggered by register window rotation) route to our
|
||||||
|
// handlers in IRAM, not the ROM's default vectors.
|
||||||
|
l32r a8, .Lvector_table_addr
|
||||||
|
wsr.vecbase a8
|
||||||
|
rsync
|
||||||
|
|
||||||
|
// Clear PS.EXCM (bit 4) and PS.INTLEVEL (bits 0-3).
|
||||||
|
// The ROM bootloader may leave EXCM=1; with EXCM set any callx4
|
||||||
|
// window overflow would become a double exception.
|
||||||
|
// Set PS.UM (bit 5) so level-1 exceptions route to User vector.
|
||||||
|
rsr.ps a2
|
||||||
|
movi a3, ~0x1F
|
||||||
|
and a2, a2, a3
|
||||||
|
movi a3, 0x20
|
||||||
|
or a2, a2, a3
|
||||||
|
wsr.ps a2
|
||||||
|
rsync
|
||||||
|
|
||||||
|
// ---- 4. Configure flash cache and MMU ----
|
||||||
|
//
|
||||||
|
// ROM function calls use callx4 (windowed ABI):
|
||||||
|
// a4 = target address (overwritten with return addr by call mechanism)
|
||||||
|
// a5 = stack pointer for callee (becomes callee's a1 via entry)
|
||||||
|
// a6 = first argument (becomes callee's a2)
|
||||||
|
// a7 = second argument (becomes callee's a3)
|
||||||
|
// a8 = third argument (becomes callee's a4)
|
||||||
|
// Registers a0-a3 are preserved across callx4; a4-a11 may be clobbered.
|
||||||
|
|
||||||
|
// Phase A: Configure cache modes (required for cache hardware to function).
|
||||||
|
// Without this, the cache doesn't know its size/associativity/line-size
|
||||||
|
// and cannot service flash accesses.
|
||||||
|
|
||||||
|
// 4a. Configure ICache mode: 16KB, 8-way, 32-byte line
|
||||||
|
movi a6, 0x4000 // cache_size = 16KB
|
||||||
|
movi a7, 8 // ways = 8
|
||||||
|
movi a8, 32 // line_size = 32
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .Lrom_config_icache
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// 4b. Suspend DCache before configuring it
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .Lrom_suspend_dcache
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// 4c. Configure DCache mode: 32KB, 8-way, 32-byte line
|
||||||
|
movi a6, 0x8000 // cache_size = 32KB
|
||||||
|
movi a7, 8 // ways = 8
|
||||||
|
movi a8, 32 // line_size = 32
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .Lrom_config_dcache
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// 4d. Resume DCache
|
||||||
|
movi a6, 0
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .LCache_Resume_DCache
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// Phase B: Map flash pages into MMU.
|
||||||
|
|
||||||
|
// 4e. Disable ICache
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .LCache_Disable_ICache
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// 4f. Disable DCache
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .LCache_Disable_DCache
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// 4g. Initialize MMU (resets all 512 entries to invalid = 0x4000)
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .LCache_MMU_Init
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// 4h. Set IDROM MMU size: even 256/256 split.
|
||||||
|
// Each entry is 4 bytes, so 256 entries = 0x400 bytes per region.
|
||||||
|
movi a6, 0x400 // irom_mmu_size (256 entries × 4 bytes)
|
||||||
|
movi a7, 0x400 // drom_mmu_size (256 entries × 4 bytes)
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .LCache_Set_IDROM_MMU_Size
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// 4i. Map flash pages for IROM and DROM using identity mapping.
|
||||||
|
// MMU table at 0x600C5000: entries 0-255 = ICache, 256-511 = DCache.
|
||||||
|
// Entry value N = flash page N (SOC_MMU_VALID = 0 on S3).
|
||||||
|
// Each 64KB page needs one 4-byte entry.
|
||||||
|
//
|
||||||
|
// IROM: map pages 0..N where N = (_irom_end - 0x42000000) >> 16
|
||||||
|
// DROM: map pages 0..M where M = (_drom_end - 0x3C000000) >> 16
|
||||||
|
|
||||||
|
l32r a8, .Lmmu_table_base // a8 = 0x600C5000
|
||||||
|
|
||||||
|
// --- IROM pages ---
|
||||||
|
l32r a2, .Lirom_end // a2 = _irom_end (VMA in 0x42xxxxxx)
|
||||||
|
l32r a3, .Lirom_base // a3 = 0x42000000
|
||||||
|
sub a2, a2, a3 // a2 = byte offset past IROM base
|
||||||
|
srli a2, a2, 16 // a2 = last page index
|
||||||
|
addi a2, a2, 1 // a2 = number of pages to map
|
||||||
|
movi a9, 0 // a9 = page counter (and entry value)
|
||||||
|
mov a10, a8 // a10 = current MMU entry pointer
|
||||||
|
.Lirom_loop:
|
||||||
|
s32i a9, a10, 0
|
||||||
|
addi a9, a9, 1
|
||||||
|
addi a10, a10, 4
|
||||||
|
blt a9, a2, .Lirom_loop
|
||||||
|
|
||||||
|
// --- DROM pages ---
|
||||||
|
l32r a2, .Ldrom_end // a2 = _drom_end (VMA in 0x3Cxxxxxx)
|
||||||
|
l32r a3, .Ldrom_base // a3 = 0x3C000000
|
||||||
|
sub a2, a2, a3 // a2 = byte offset past DROM base
|
||||||
|
srli a2, a2, 16 // a2 = last page index
|
||||||
|
addi a2, a2, 1 // a2 = number of pages to map
|
||||||
|
movi a9, 0 // a9 = page counter (and entry value)
|
||||||
|
addmi a10, a8, 0x400 // a10 = 0x600C5400 (DCache entry 256)
|
||||||
|
.Ldrom_loop:
|
||||||
|
s32i a9, a10, 0
|
||||||
|
addi a9, a9, 1
|
||||||
|
addi a10, a10, 4
|
||||||
|
blt a9, a2, .Ldrom_loop
|
||||||
|
memw
|
||||||
|
|
||||||
|
// 4j. Clear bus-shut bits so core 0 can access ICache and DCache buses.
|
||||||
|
l32r a8, .Licache_ctrl1_reg // 0x600C4064
|
||||||
|
movi a9, 0
|
||||||
|
s32i a9, a8, 0 // Clear all ICACHE_CTRL1 shut bits
|
||||||
|
l32r a8, .Ldcache_ctrl1_reg // 0x600C4004
|
||||||
|
s32i a9, a8, 0 // Clear all DCACHE_CTRL1 shut bits
|
||||||
|
memw
|
||||||
|
|
||||||
|
// 4k. Enable ICache (arg: autoload = 0)
|
||||||
|
movi a6, 0
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .LCache_Enable_ICache
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// 4l. Enable DCache (arg: autoload = 0)
|
||||||
|
movi a6, 0
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .LCache_Enable_DCache
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// Flush instruction pipeline so new cache/MMU config takes effect.
|
||||||
|
isync
|
||||||
|
|
||||||
|
// ---- 5. Jump to main (in IROM) ----
|
||||||
|
// Re-clear PS.EXCM in case ROM calls changed processor state.
|
||||||
|
rsr.ps a2
|
||||||
|
movi a3, ~0x1F
|
||||||
|
and a2, a2, a3
|
||||||
|
movi a3, 0x20
|
||||||
|
or a2, a2, a3
|
||||||
|
wsr.ps a2
|
||||||
|
rsync
|
||||||
|
|
||||||
|
mov a5, a1
|
||||||
|
l32r a4, .Lmain_addr
|
||||||
|
callx4 a4
|
||||||
|
|
||||||
|
// If main returns, loop forever.
|
||||||
|
1: j 1b
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// tinygo_scanCurrentStack — Spill all Xtensa register windows to the
|
||||||
|
// stack, then call tinygo_scanstack(sp) so the conservative GC can
|
||||||
|
// discover live heap pointers that are currently in physical registers.
|
||||||
|
//
|
||||||
|
// On RISC-V / ARM the equivalent function pushes callee-saved registers
|
||||||
|
// before the call. On Xtensa windowed ABI the same effect is achieved
|
||||||
|
// by forcing hardware window-overflow for every occupied pane: each
|
||||||
|
// overflow saves the four registers in that pane to the stack frame
|
||||||
|
// pointed to by the pane's a1 (sp). After all panes are flushed, a
|
||||||
|
// scan from the current sp to stackTop covers every live value.
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
.section .text.tinygo_scanCurrentStack
|
||||||
|
|
||||||
|
.global tinygo_scanCurrentStack
|
||||||
|
tinygo_scanCurrentStack:
|
||||||
|
entry a1, 48
|
||||||
|
|
||||||
|
// Disable interrupts while flushing register windows.
|
||||||
|
rsr a4, PS
|
||||||
|
s32i a4, a1, 0 // save PS for later restore
|
||||||
|
rsil a4, 3 // XCHAL_EXCM_LEVEL
|
||||||
|
|
||||||
|
// Flush all register windows using recursive call4.
|
||||||
|
// For NAREG=64 (16 panes), 15 recursive levels cover all panes
|
||||||
|
// except the current one (which is kept active).
|
||||||
|
movi a6, 15
|
||||||
|
call4 .Lscan_spill
|
||||||
|
|
||||||
|
// Restore interrupts.
|
||||||
|
l32i a4, a1, 0
|
||||||
|
wsr.ps a4
|
||||||
|
rsync
|
||||||
|
|
||||||
|
// Pass current sp to tinygo_scanstack.
|
||||||
|
// call4 maps caller's a5→callee's a1 (stack ptr for callee's entry)
|
||||||
|
// and caller's a6→callee's a2 (first argument = sp).
|
||||||
|
mov a5, a1 // callee's a1 = valid stack pointer
|
||||||
|
mov a6, a1 // callee's a2 = sp argument
|
||||||
|
call4 tinygo_scanstack
|
||||||
|
|
||||||
|
retw
|
||||||
|
|
||||||
|
.balign 4
|
||||||
|
.Lscan_spill:
|
||||||
|
entry a1, 16
|
||||||
|
beqz a2, .Lscan_spill_done
|
||||||
|
addi a2, a2, -1
|
||||||
|
mov a6, a2
|
||||||
|
call4 .Lscan_spill
|
||||||
|
.Lscan_spill_done:
|
||||||
|
retw
|
||||||
@@ -75,6 +75,10 @@ handleInterruptASM:
|
|||||||
SFREG f30,(30 + 16)*REGSIZE(sp)
|
SFREG f30,(30 + 16)*REGSIZE(sp)
|
||||||
SFREG f31,(31 + 16)*REGSIZE(sp)
|
SFREG f31,(31 + 16)*REGSIZE(sp)
|
||||||
#endif
|
#endif
|
||||||
|
// Save ra to a global so handleException can print the caller of the NULL
|
||||||
|
// function pointer.
|
||||||
|
la t0, tinygo_saved_ra
|
||||||
|
SREG ra, 0(t0)
|
||||||
call handleInterrupt
|
call handleInterrupt
|
||||||
#ifdef __riscv_flen
|
#ifdef __riscv_flen
|
||||||
LFREG f0, (31 + 16)*REGSIZE(sp)
|
LFREG f0, (31 + 16)*REGSIZE(sp)
|
||||||
@@ -128,3 +132,10 @@ handleInterruptASM:
|
|||||||
LREG ra, 0*REGSIZE(sp)
|
LREG ra, 0*REGSIZE(sp)
|
||||||
addi sp, sp, NREG*REGSIZE
|
addi sp, sp, NREG*REGSIZE
|
||||||
mret
|
mret
|
||||||
|
|
||||||
|
.section .bss.tinygo_saved_ra
|
||||||
|
.global tinygo_saved_ra
|
||||||
|
.type tinygo_saved_ra,@object
|
||||||
|
.align 2
|
||||||
|
tinygo_saved_ra:
|
||||||
|
.space REGSIZE
|
||||||
|
|||||||
+2
-12
@@ -5,25 +5,15 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This example assumes that an analog sensor such as a rotary dial is connected to pin ADC0.
|
|
||||||
// When the dial is turned past the midway point, the built-in LED will light up.
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
machine.InitADC()
|
machine.InitADC()
|
||||||
|
|
||||||
led := machine.LED
|
|
||||||
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
||||||
|
|
||||||
sensor := machine.ADC{machine.ADC2}
|
sensor := machine.ADC{machine.ADC2}
|
||||||
sensor.Configure(machine.ADCConfig{})
|
sensor.Configure(machine.ADCConfig{})
|
||||||
|
|
||||||
for {
|
for {
|
||||||
val := sensor.Get()
|
val := sensor.Get()
|
||||||
if val < 0x8000 {
|
println(val)
|
||||||
led.Low()
|
time.Sleep(time.Millisecond * 500)
|
||||||
} else {
|
|
||||||
led.High()
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 100)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build arduino
|
//go:build arduino_uno
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//go:build xiao_esp32s3
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "machine"
|
||||||
|
|
||||||
|
const (
|
||||||
|
button = machine.D1
|
||||||
|
buttonMode = machine.PinInputPullup
|
||||||
|
buttonPinChange = machine.PinFalling
|
||||||
|
)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//go:build arduino_uno_q
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "machine"
|
||||||
|
|
||||||
|
var (
|
||||||
|
pwm = &machine.TIM3
|
||||||
|
pinA = machine.D3 // PB0 = TIM3_CH3
|
||||||
|
pinB = machine.D6 // PB1 = TIM3_CH4
|
||||||
|
)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build arduino
|
//go:build arduino_uno
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
//go:build digispark
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "machine"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Use Timer1 for PWM (recommended for ATtiny85)
|
||||||
|
pwm = machine.Timer1
|
||||||
|
pinA = machine.P1 // PB1, Timer1 channel A (LED pin)
|
||||||
|
pinB = machine.P4 // PB4, Timer1 channel B
|
||||||
|
)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//go:build esp32c3_supermini
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "machine"
|
||||||
|
|
||||||
|
var (
|
||||||
|
pwm = machine.PWM0
|
||||||
|
pinA = machine.GPIO5
|
||||||
|
pinB = machine.GPIO6
|
||||||
|
)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//go:build pico2 || pico_plus2
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "machine"
|
||||||
|
|
||||||
|
var (
|
||||||
|
pwm = machine.PWM0 // Pin 25 (LED on pico2) corresponds to PWM0.
|
||||||
|
//pinA = machine.LED
|
||||||
|
pinA = machine.GPIO16
|
||||||
|
)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//go:build xiao_esp32s3
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "machine"
|
||||||
|
|
||||||
|
var (
|
||||||
|
pwm = machine.PWM0
|
||||||
|
pinA = machine.D0
|
||||||
|
pinB = machine.D1
|
||||||
|
)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
time.Sleep(2 * time.Second) // connect via serial
|
||||||
|
buf1 := makeBuffer('|', 600)
|
||||||
|
buf2 := makeBuffer('/', 600)
|
||||||
|
println("start")
|
||||||
|
serialWrite(buf1)
|
||||||
|
serialWrite(buf2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeBuffer(sep byte, size int) []byte {
|
||||||
|
buf := make([]byte, size)
|
||||||
|
for i := 0; i < size-5; i += 5 {
|
||||||
|
buf[i] = sep
|
||||||
|
strconv.AppendInt(buf[i+1:i+1:i+5], int64(i), 10)
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func serialWrite(b []byte) {
|
||||||
|
machine.Serial.Write(b)
|
||||||
|
}
|
||||||
@@ -15,3 +15,35 @@ func Escape[T any](x T) T {
|
|||||||
// as-is.
|
// as-is.
|
||||||
panic("internal/abi.Escape: unreachable (implemented in the compiler)")
|
panic("internal/abi.Escape: unreachable (implemented in the compiler)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EscapeNonString forces v to be on the heap, if v contains a
|
||||||
|
// non-string pointer.
|
||||||
|
//
|
||||||
|
// This is used in hash/maphash.Comparable. We cannot hash pointers
|
||||||
|
// to local variables on stack, as their addresses might change on
|
||||||
|
// stack growth. Strings are okay as the hash depends on only the
|
||||||
|
// content, not the pointer.
|
||||||
|
//
|
||||||
|
// This is essentially
|
||||||
|
//
|
||||||
|
// if hasNonStringPointers(T) { Escape(v) }
|
||||||
|
//
|
||||||
|
// Implemented as a compiler intrinsic.
|
||||||
|
func EscapeNonString[T any](v T) { panic("intrinsic") }
|
||||||
|
|
||||||
|
// EscapeToResultNonString models a data flow edge from v to the result,
|
||||||
|
// if v contains a non-string pointer. If v contains only string pointers,
|
||||||
|
// it returns a copy of v, but is not modeled as a data flow edge
|
||||||
|
// from the escape analysis's perspective.
|
||||||
|
//
|
||||||
|
// This is used in unique.clone, to model the data flow edge on the
|
||||||
|
// value with strings excluded, because strings are cloned (by
|
||||||
|
// content).
|
||||||
|
//
|
||||||
|
// TODO: probably we should define this as a intrinsic and EscapeNonString
|
||||||
|
// could just be "heap = EscapeToResultNonString(v)". This way we can model
|
||||||
|
// an edge to the result but not necessarily heap.
|
||||||
|
func EscapeToResultNonString[T any](v T) T {
|
||||||
|
EscapeNonString(v)
|
||||||
|
return *(*T)(NoEscape(unsafe.Pointer(&v)))
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ const (
|
|||||||
// 64-bit int => bits = 6
|
// 64-bit int => bits = 6
|
||||||
sizeBits = 4 + unsafe.Sizeof(uintptr(0))/4
|
sizeBits = 4 + unsafe.Sizeof(uintptr(0))/4
|
||||||
|
|
||||||
|
ptrAlign = unsafe.Alignof(uintptr(0))
|
||||||
|
|
||||||
sizeShift = sizeBits + 1
|
sizeShift = sizeBits + 1
|
||||||
|
|
||||||
NoPtrs = Layout(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
NoPtrs = Layout((0 << sizeShift) | (1 << 1) | 1)
|
||||||
Pointer = Layout(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
Pointer = Layout((1 << sizeShift) | ((unsafe.Sizeof(unsafe.Pointer(nil)) / ptrAlign) << 1) | 1)
|
||||||
String = Layout(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
|
String = Layout((1 << sizeShift) | ((unsafe.Sizeof("") / ptrAlign) << 1) | 1)
|
||||||
Slice = Layout(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
|
Slice = Layout((1 << sizeShift) | ((unsafe.Sizeof([]byte{}) / ptrAlign) << 1) | 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l Layout) AsPtr() unsafe.Pointer { return unsafe.Pointer(l) }
|
func (l Layout) AsPtr() unsafe.Pointer { return unsafe.Pointer(l) }
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Simple conversions to avoid depending on strconv.
|
||||||
|
|
||||||
|
package itoa
|
||||||
|
|
||||||
|
// Itoa converts val to a decimal string.
|
||||||
|
func Itoa(val int) string {
|
||||||
|
if val < 0 {
|
||||||
|
return "-" + Uitoa(uint(-val))
|
||||||
|
}
|
||||||
|
return Uitoa(uint(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uitoa converts val to a decimal string.
|
||||||
|
func Uitoa(val uint) string {
|
||||||
|
if val == 0 { // avoid string allocation
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
var buf [20]byte // big enough for 64bit value base 10
|
||||||
|
i := len(buf) - 1
|
||||||
|
for val >= 10 {
|
||||||
|
q := val / 10
|
||||||
|
buf[i] = byte('0' + val - q*10)
|
||||||
|
i--
|
||||||
|
val = q
|
||||||
|
}
|
||||||
|
// val < 10
|
||||||
|
buf[i] = byte('0' + val)
|
||||||
|
return string(buf[i:])
|
||||||
|
}
|
||||||
|
|
||||||
|
const hex = "0123456789abcdef"
|
||||||
|
|
||||||
|
// Uitox converts val (a uint) to a hexadecimal string.
|
||||||
|
func Uitox(val uint) string {
|
||||||
|
if val == 0 { // avoid string allocation
|
||||||
|
return "0x0"
|
||||||
|
}
|
||||||
|
var buf [20]byte // big enough for 64bit value base 16 + 0x
|
||||||
|
i := len(buf) - 1
|
||||||
|
for val >= 16 {
|
||||||
|
q := val / 16
|
||||||
|
buf[i] = hex[val%16]
|
||||||
|
i--
|
||||||
|
val = q
|
||||||
|
}
|
||||||
|
// val < 16
|
||||||
|
buf[i] = hex[val%16]
|
||||||
|
i--
|
||||||
|
buf[i] = 'x'
|
||||||
|
i--
|
||||||
|
buf[i] = '0'
|
||||||
|
return string(buf[i:])
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package itoa_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"internal/itoa"
|
||||||
|
"math"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
minInt64 int64 = math.MinInt64
|
||||||
|
maxInt64 int64 = math.MaxInt64
|
||||||
|
maxUint64 uint64 = math.MaxUint64
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestItoa(t *testing.T) {
|
||||||
|
tests := []int{int(minInt64), math.MinInt32, -999, -100, -1, 0, 1, 100, 999, math.MaxInt32, int(maxInt64)}
|
||||||
|
for _, tt := range tests {
|
||||||
|
got := itoa.Itoa(tt)
|
||||||
|
want := fmt.Sprint(tt)
|
||||||
|
if want != got {
|
||||||
|
t.Fatalf("Itoa(%d) = %s, want %s", tt, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUitoa(t *testing.T) {
|
||||||
|
tests := []uint{0, 1, 100, 999, math.MaxUint32, uint(maxUint64)}
|
||||||
|
for _, tt := range tests {
|
||||||
|
got := itoa.Uitoa(tt)
|
||||||
|
want := fmt.Sprint(tt)
|
||||||
|
if want != got {
|
||||||
|
t.Fatalf("Uitoa(%d) = %s, want %s", tt, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUitox(t *testing.T) {
|
||||||
|
tests := []uint{0, 1, 15, 100, 999, math.MaxUint32, uint(maxUint64)}
|
||||||
|
for _, tt := range tests {
|
||||||
|
got := itoa.Uitox(tt)
|
||||||
|
want := fmt.Sprintf("%#x", tt)
|
||||||
|
if want != got {
|
||||||
|
t.Fatalf("Uitox(%x) = %s, want %s", tt, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -157,6 +157,10 @@ const (
|
|||||||
flagIsBinary = 128 // flag that is set if this type uses the hashmap binary algorithm
|
flagIsBinary = 128 // flag that is set if this type uses the hashmap binary algorithm
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Flag in the numMethod field (uint16) of Pointer and Struct type descriptors,
|
||||||
|
// indicating that an inline method set is present in the type descriptor.
|
||||||
|
const numMethodHasMethodSet = 0x8000
|
||||||
|
|
||||||
// The base type struct. All type structs start with this.
|
// The base type struct. All type structs start with this.
|
||||||
type RawType struct {
|
type RawType struct {
|
||||||
meta uint8 // metadata byte, contains kind and flags (see constants above)
|
meta uint8 // metadata byte, contains kind and flags (see constants above)
|
||||||
@@ -171,16 +175,22 @@ type elemType struct {
|
|||||||
elem *RawType
|
elem *RawType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ptrType is the type descriptor for pointer types.
|
||||||
|
// The numMethod field stores the number of exported methods in the lower bits,
|
||||||
|
// with bit 15 (numMethodHasMethodSet) indicating whether the methods field is
|
||||||
|
// present. When the flag is clear, the methods field does not exist in the
|
||||||
|
// actual type descriptor and must not be accessed.
|
||||||
type ptrType struct {
|
type ptrType struct {
|
||||||
RawType
|
RawType
|
||||||
numMethod uint16
|
numMethod uint16
|
||||||
elem *RawType
|
elem *RawType
|
||||||
|
methods methodSet // only present when numMethod & numMethodHasMethodSet != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type interfaceType struct {
|
type interfaceType struct {
|
||||||
RawType
|
RawType
|
||||||
ptrTo *RawType
|
ptrTo *RawType
|
||||||
// TODO: methods
|
methods methodSet
|
||||||
}
|
}
|
||||||
|
|
||||||
type arrayType struct {
|
type arrayType struct {
|
||||||
@@ -200,13 +210,19 @@ type mapType struct {
|
|||||||
key *RawType
|
key *RawType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// namedType is the type descriptor for named types. The numMethod field uses
|
||||||
|
// bit 15 (numMethodHasMethodSet) to indicate whether an inline method set is
|
||||||
|
// present after pkg. When the flag is set, a methodSet follows at
|
||||||
|
// unsafe.Sizeof(namedType{}), and the name string follows after the method
|
||||||
|
// set's entries. When clear, the name string starts directly at that offset.
|
||||||
type namedType struct {
|
type namedType struct {
|
||||||
RawType
|
RawType
|
||||||
numMethod uint16
|
numMethod uint16
|
||||||
ptrTo *RawType
|
ptrTo *RawType
|
||||||
elem *RawType
|
elem *RawType
|
||||||
pkg *byte
|
pkg *byte
|
||||||
name [1]byte
|
// if numMethod & numMethodHasMethodSet != 0: methodSet follows here
|
||||||
|
// name (null-terminated "pkg.Name\0") follows after the method set (or directly here)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type for struct types. The numField value is intentionally put before ptrTo
|
// Type for struct types. The numField value is intentionally put before ptrTo
|
||||||
@@ -216,6 +232,10 @@ type namedType struct {
|
|||||||
// The fields array isn't necessarily 1 structField long, instead it is as long
|
// The fields array isn't necessarily 1 structField long, instead it is as long
|
||||||
// as numFields. The array is given a length of 1 to satisfy the Go type
|
// as numFields. The array is given a length of 1 to satisfy the Go type
|
||||||
// checker.
|
// checker.
|
||||||
|
// The numMethod field stores the number of exported methods in the lower bits,
|
||||||
|
// with bit 15 (numMethodHasMethodSet) indicating whether an inline method set
|
||||||
|
// follows the fields array. When the flag is clear, no method set is present
|
||||||
|
// and the type descriptor ends after the last structField entry.
|
||||||
type structType struct {
|
type structType struct {
|
||||||
RawType
|
RawType
|
||||||
numMethod uint16
|
numMethod uint16
|
||||||
@@ -224,6 +244,7 @@ type structType struct {
|
|||||||
size uint32
|
size uint32
|
||||||
numField uint16
|
numField uint16
|
||||||
fields [1]structField // the remaining fields are all of type structField
|
fields [1]structField // the remaining fields are all of type structField
|
||||||
|
// methods methodSet follows after fields, only when numMethod & numMethodHasMethodSet != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type structField struct {
|
type structField struct {
|
||||||
@@ -231,6 +252,12 @@ type structField struct {
|
|||||||
data unsafe.Pointer // various bits of information, packed in a byte array
|
data unsafe.Pointer // various bits of information, packed in a byte array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method set, as emitted by the compiler.
|
||||||
|
type methodSet struct {
|
||||||
|
length uintptr
|
||||||
|
methods [0]unsafe.Pointer // variable number of method signature pointers
|
||||||
|
}
|
||||||
|
|
||||||
// Equivalent to (go/types.Type).Underlying(): if this is a named type return
|
// Equivalent to (go/types.Type).Underlying(): if this is a named type return
|
||||||
// the underlying type, else just return the type itself.
|
// the underlying type, else just return the type itself.
|
||||||
func (t *RawType) underlying() *RawType {
|
func (t *RawType) underlying() *RawType {
|
||||||
@@ -733,21 +760,38 @@ func (t *RawType) FieldAlign() int {
|
|||||||
// AssignableTo returns whether a value of type t can be assigned to a variable
|
// AssignableTo returns whether a value of type t can be assigned to a variable
|
||||||
// of type u.
|
// of type u.
|
||||||
func (t *RawType) AssignableTo(u Type) bool {
|
func (t *RawType) AssignableTo(u Type) bool {
|
||||||
if t == u.(*RawType) {
|
u_raw := u.(*RawType)
|
||||||
return true
|
if t == u_raw {
|
||||||
}
|
|
||||||
|
|
||||||
if t.underlying() == u.(*RawType).underlying() && (!t.isNamed() || !u.(*RawType).isNamed()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Kind() == Interface && u.NumMethod() == 0 {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.Kind() == Interface {
|
if u.Kind() == Interface {
|
||||||
panic("reflect: unimplemented: AssignableTo with interface")
|
// T is an interface type and x implements T.
|
||||||
|
u_itf := (*interfaceType)(unsafe.Pointer(u_raw.underlying()))
|
||||||
|
return typeImplementsMethodSet(unsafe.Pointer(t), unsafe.Pointer(&u_itf.methods))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_named := t.isNamed()
|
||||||
|
u_named := u_raw.isNamed()
|
||||||
|
if t_named && u_named {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t.underlying() == u_raw.underlying() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Kind() == Chan && u_raw.Kind() == Chan {
|
||||||
|
t_chan := (*elemType)(unsafe.Pointer(t.underlying()))
|
||||||
|
u_chan := (*elemType)(unsafe.Pointer(u_raw.underlying()))
|
||||||
|
if t_chan.elem != u_chan.elem {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t_chan.ChanDir() != BothDir {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,7 +799,85 @@ func (t *RawType) Implements(u Type) bool {
|
|||||||
if u.Kind() != Interface {
|
if u.Kind() != Interface {
|
||||||
panic("reflect: non-interface type passed to Type.Implements")
|
panic("reflect: non-interface type passed to Type.Implements")
|
||||||
}
|
}
|
||||||
return t.AssignableTo(u)
|
u_itf := (*interfaceType)(unsafe.Pointer(u.(*RawType).underlying()))
|
||||||
|
return typeImplementsMethodSet(unsafe.Pointer(t), unsafe.Pointer(&u_itf.methods))
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeImplementsMethodSet checks whether the concrete type (identified by its
|
||||||
|
// typecode pointer) implements the given method set. Both the concrete type's
|
||||||
|
// method set and the asserted method set are sorted arrays of method signature
|
||||||
|
// pointers, so comparison is O(n+m).
|
||||||
|
//
|
||||||
|
//go:linkname typeImplementsMethodSet runtime.typeImplementsMethodSet
|
||||||
|
func typeImplementsMethodSet(concreteType, assertedMethodSet unsafe.Pointer) bool {
|
||||||
|
if concreteType == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const ptrSize = unsafe.Sizeof((*byte)(nil))
|
||||||
|
itfNumMethod := *(*uintptr)(assertedMethodSet)
|
||||||
|
if itfNumMethod == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull the method set out of the concrete type.
|
||||||
|
var methods *methodSet
|
||||||
|
metaByte := *(*uint8)(concreteType)
|
||||||
|
if metaByte&flagNamed != 0 {
|
||||||
|
ct := (*namedType)(concreteType)
|
||||||
|
if ct.numMethod&numMethodHasMethodSet == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
methods = (*methodSet)(unsafe.Add(unsafe.Pointer(ct), unsafe.Sizeof(*ct)))
|
||||||
|
} else if metaByte&kindMask == uint8(Interface) {
|
||||||
|
ct := (*interfaceType)(concreteType)
|
||||||
|
methods = &ct.methods
|
||||||
|
} else if metaByte&kindMask == uint8(Pointer) {
|
||||||
|
ct := (*ptrType)(concreteType)
|
||||||
|
if ct.numMethod&numMethodHasMethodSet == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
methods = &ct.methods
|
||||||
|
} else if metaByte&kindMask == uint8(Struct) {
|
||||||
|
ct := (*structType)(concreteType)
|
||||||
|
if ct.numMethod&numMethodHasMethodSet == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// For struct types, the method set follows after the variable-length
|
||||||
|
// fields array. We need to compute its offset dynamically.
|
||||||
|
fieldSize := unsafe.Sizeof(structField{})
|
||||||
|
methodsPtr := unsafe.Add(unsafe.Pointer(&ct.fields[0]), uintptr(ct.numField)*fieldSize)
|
||||||
|
methods = (*methodSet)(methodsPtr)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
concreteTypePtr := unsafe.Pointer(&methods.methods)
|
||||||
|
concreteTypeEnd := unsafe.Add(concreteTypePtr, uintptr(methods.length)*ptrSize)
|
||||||
|
|
||||||
|
// Iterate over each method in the interface method set, and check whether
|
||||||
|
// the method exists in the method set of the concrete type.
|
||||||
|
// Both method sets are sorted, so we can use a linear scan.
|
||||||
|
assertedTypePtr := unsafe.Add(assertedMethodSet, ptrSize)
|
||||||
|
assertedTypeEnd := unsafe.Add(assertedTypePtr, itfNumMethod*ptrSize)
|
||||||
|
for assertedTypePtr != assertedTypeEnd {
|
||||||
|
assertedMethod := *(*unsafe.Pointer)(assertedTypePtr)
|
||||||
|
|
||||||
|
for {
|
||||||
|
if concreteTypePtr == concreteTypeEnd {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
concreteMethod := *(*unsafe.Pointer)(concreteTypePtr)
|
||||||
|
concreteTypePtr = unsafe.Add(concreteTypePtr, ptrSize)
|
||||||
|
if concreteMethod == assertedMethod {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertedTypePtr = unsafe.Add(assertedTypePtr, ptrSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparable returns whether values of this type can be compared to each other.
|
// Comparable returns whether values of this type can be compared to each other.
|
||||||
@@ -782,14 +904,14 @@ func (t *RawType) ChanDir() ChanDir {
|
|||||||
func (t *RawType) NumMethod() int {
|
func (t *RawType) NumMethod() int {
|
||||||
|
|
||||||
if t.isNamed() {
|
if t.isNamed() {
|
||||||
return int((*namedType)(unsafe.Pointer(t)).numMethod)
|
return int((*namedType)(unsafe.Pointer(t)).numMethod & ^uint16(numMethodHasMethodSet))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case Pointer:
|
case Pointer:
|
||||||
return int((*ptrType)(unsafe.Pointer(t)).numMethod)
|
return int((*ptrType)(unsafe.Pointer(t)).numMethod & ^uint16(numMethodHasMethodSet))
|
||||||
case Struct:
|
case Struct:
|
||||||
return int((*structType)(unsafe.Pointer(t)).numMethod)
|
return int((*structType)(unsafe.Pointer(t)).numMethod & ^uint16(numMethodHasMethodSet))
|
||||||
case Interface:
|
case Interface:
|
||||||
//FIXME: Use len(methods)
|
//FIXME: Use len(methods)
|
||||||
return (*interfaceType)(unsafe.Pointer(t)).ptrTo.NumMethod()
|
return (*interfaceType)(unsafe.Pointer(t)).ptrTo.NumMethod()
|
||||||
@@ -816,7 +938,14 @@ func readStringZ(data unsafe.Pointer) string {
|
|||||||
|
|
||||||
func (t *RawType) name() string {
|
func (t *RawType) name() string {
|
||||||
ntype := (*namedType)(unsafe.Pointer(t))
|
ntype := (*namedType)(unsafe.Pointer(t))
|
||||||
return readStringZ(unsafe.Pointer(&ntype.name[0]))
|
// The name follows after the fixed fields (and optionally the method set).
|
||||||
|
ptr := unsafe.Add(unsafe.Pointer(ntype), unsafe.Sizeof(*ntype))
|
||||||
|
if ntype.numMethod&numMethodHasMethodSet != 0 {
|
||||||
|
ms := (*methodSet)(ptr)
|
||||||
|
// Skip past the length field and the method pointer entries.
|
||||||
|
ptr = unsafe.Add(ptr, unsafe.Sizeof(uintptr(0))+uintptr(ms.length)*unsafe.Sizeof(unsafe.Pointer(nil)))
|
||||||
|
}
|
||||||
|
return readStringZ(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *RawType) Name() string {
|
func (t *RawType) Name() string {
|
||||||
|
|||||||
@@ -86,6 +86,64 @@ func (v Value) Interface() interface{} {
|
|||||||
return valueInterfaceUnsafe(v)
|
return valueInterfaceUnsafe(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TypeAssert[T any](v Value) (T, bool) {
|
||||||
|
if v.typecode == nil {
|
||||||
|
panic("reflect.TypeAssert: zero Value")
|
||||||
|
}
|
||||||
|
if !v.isExported() {
|
||||||
|
// Do not allow access to unexported values via TypeAssert,
|
||||||
|
// because they might be pointers that should not be
|
||||||
|
// writable or methods or function that should not be callable.
|
||||||
|
panic("reflect.TypeAssert: cannot return value obtained from unexported field or method")
|
||||||
|
}
|
||||||
|
|
||||||
|
typ := TypeFor[T]()
|
||||||
|
|
||||||
|
// If v is an interface, return the element inside the interface.
|
||||||
|
//
|
||||||
|
// T is a concrete type and v is an interface. For example:
|
||||||
|
//
|
||||||
|
// var v any = int(1)
|
||||||
|
// val := ValueOf(&v).Elem()
|
||||||
|
// TypeAssert[int](val) == val.Interface().(int)
|
||||||
|
//
|
||||||
|
// T is a interface and v is a non-nil interface value. For example:
|
||||||
|
//
|
||||||
|
// var v any = &someError{}
|
||||||
|
// val := ValueOf(&v).Elem()
|
||||||
|
// TypeAssert[error](val) == val.Interface().(error)
|
||||||
|
//
|
||||||
|
// T is a interface and v is a nil interface value. For example:
|
||||||
|
//
|
||||||
|
// var v error = nil
|
||||||
|
// val := ValueOf(&v).Elem()
|
||||||
|
// TypeAssert[error](val) == val.Interface().(error)
|
||||||
|
if v.Kind() == Interface {
|
||||||
|
val, ok := valueInterfaceUnsafe(v).(T)
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// If T is an interface and v is a concrete type. For example:
|
||||||
|
//
|
||||||
|
// TypeAssert[any](ValueOf(1)) == ValueOf(1).Interface().(any)
|
||||||
|
// TypeAssert[error](ValueOf(&someError{})) == ValueOf(&someError{}).Interface().(error)
|
||||||
|
if typ.Kind() == Interface {
|
||||||
|
val, ok := valueInterfaceUnsafe(v).(T)
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both v and T must be concrete types.
|
||||||
|
// The only way for an type-assertion to match is if the types are equal.
|
||||||
|
if typ != v.typecode {
|
||||||
|
var zero T
|
||||||
|
return zero, false
|
||||||
|
}
|
||||||
|
if !v.isIndirect() && v.typecode.Size() <= unsafe.Sizeof(uintptr(0)) {
|
||||||
|
return *(*T)(unsafe.Pointer(&v.value)), true
|
||||||
|
}
|
||||||
|
return *(*T)(v.value), true
|
||||||
|
}
|
||||||
|
|
||||||
// valueInterfaceUnsafe is used by the runtime to hash map keys. It should not
|
// valueInterfaceUnsafe is used by the runtime to hash map keys. It should not
|
||||||
// be subject to the isExported check.
|
// be subject to the isExported check.
|
||||||
func valueInterfaceUnsafe(v Value) interface{} {
|
func valueInterfaceUnsafe(v Value) interface{} {
|
||||||
@@ -1738,6 +1796,9 @@ func (e *ValueError) Error() string {
|
|||||||
//go:linkname memcpy runtime.memcpy
|
//go:linkname memcpy runtime.memcpy
|
||||||
func memcpy(dst, src unsafe.Pointer, size uintptr)
|
func memcpy(dst, src unsafe.Pointer, size uintptr)
|
||||||
|
|
||||||
|
//go:linkname memmove runtime.memmove
|
||||||
|
func memmove(dst, src unsafe.Pointer, size uintptr)
|
||||||
|
|
||||||
//go:linkname memzero runtime.memzero
|
//go:linkname memzero runtime.memzero
|
||||||
func memzero(ptr unsafe.Pointer, size uintptr)
|
func memzero(ptr unsafe.Pointer, size uintptr)
|
||||||
|
|
||||||
@@ -1745,10 +1806,7 @@ func memzero(ptr unsafe.Pointer, size uintptr)
|
|||||||
func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
|
func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname sliceAppend runtime.sliceAppend
|
//go:linkname sliceAppend runtime.sliceAppend
|
||||||
func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr)
|
func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr, layout unsafe.Pointer) (unsafe.Pointer, uintptr, uintptr)
|
||||||
|
|
||||||
//go:linkname sliceCopy runtime.sliceCopy
|
|
||||||
func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) int
|
|
||||||
|
|
||||||
// Copy copies the contents of src into dst until either
|
// Copy copies the contents of src into dst until either
|
||||||
// dst has been filled or src has been exhausted.
|
// dst has been filled or src has been exhausted.
|
||||||
@@ -1779,7 +1837,10 @@ func Copy(dst, src Value) int {
|
|||||||
dst.checkRO()
|
dst.checkRO()
|
||||||
}
|
}
|
||||||
|
|
||||||
return sliceCopy(dstbuf, srcbuf, dstlen, srclen, dst.typecode.elem().Size())
|
minLen := min(dstlen, srclen)
|
||||||
|
elemSize := dst.typecode.elem().Size()
|
||||||
|
memmove(dstbuf, srcbuf, minLen*elemSize)
|
||||||
|
return int(minLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buflen(v Value) (unsafe.Pointer, uintptr) {
|
func buflen(v Value) (unsafe.Pointer, uintptr) {
|
||||||
@@ -1810,7 +1871,7 @@ func buflen(v Value) (unsafe.Pointer, uintptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname sliceGrow runtime.sliceGrow
|
//go:linkname sliceGrow runtime.sliceGrow
|
||||||
func sliceGrow(buf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr)
|
func sliceGrow(buf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr, layout unsafe.Pointer) (unsafe.Pointer, uintptr, uintptr)
|
||||||
|
|
||||||
// extend slice to hold n new elements
|
// extend slice to hold n new elements
|
||||||
func extendSlice(v Value, n int) sliceHeader {
|
func extendSlice(v Value, n int) sliceHeader {
|
||||||
@@ -1823,7 +1884,10 @@ func extendSlice(v Value, n int) sliceHeader {
|
|||||||
old = *(*sliceHeader)(v.value)
|
old = *(*sliceHeader)(v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
nbuf, nlen, ncap := sliceGrow(old.data, old.len, old.cap, old.len+uintptr(n), v.typecode.elem().Size())
|
elem := v.typecode.elem()
|
||||||
|
elemSize := elem.Size()
|
||||||
|
elemLayout := elem.gcLayout()
|
||||||
|
nbuf, nlen, ncap := sliceGrow(old.data, old.len, old.cap, old.len+uintptr(n), elemSize, elemLayout)
|
||||||
|
|
||||||
return sliceHeader{
|
return sliceHeader{
|
||||||
data: nbuf,
|
data: nbuf,
|
||||||
@@ -1862,8 +1926,10 @@ func AppendSlice(s, t Value) Value {
|
|||||||
}
|
}
|
||||||
sSlice := (*sliceHeader)(s.value)
|
sSlice := (*sliceHeader)(s.value)
|
||||||
tSlice := (*sliceHeader)(t.value)
|
tSlice := (*sliceHeader)(t.value)
|
||||||
elemSize := s.typecode.elem().Size()
|
elem := s.typecode.elem()
|
||||||
ptr, len, cap := sliceAppend(sSlice.data, tSlice.data, sSlice.len, sSlice.cap, tSlice.len, elemSize)
|
elemSize := elem.Size()
|
||||||
|
elemLayout := elem.gcLayout()
|
||||||
|
ptr, len, cap := sliceAppend(sSlice.data, tSlice.data, sSlice.len, sSlice.cap, tSlice.len, elemSize, elemLayout)
|
||||||
result := &sliceHeader{
|
result := &sliceHeader{
|
||||||
data: ptr,
|
data: ptr,
|
||||||
len: len,
|
len: len,
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
//go:build !tinygo.wasm
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
type GetRandomFlag uintptr
|
type GetRandomFlag uintptr
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -8,5 +12,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
|
func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
|
||||||
panic("todo: unix.GetRandom")
|
// Not supported on most TinyGo targets.
|
||||||
|
// On real Linux the sysrand package will fall back to /dev/urandom.
|
||||||
|
return 0, syscall.ENOSYS
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//go:build tinygo.wasm
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type GetRandomFlag uintptr
|
||||||
|
|
||||||
|
const (
|
||||||
|
GRND_NONBLOCK GetRandomFlag = 0x0001
|
||||||
|
GRND_RANDOM GetRandomFlag = 0x0002
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
|
||||||
|
if len(p) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
libc_arc4random_buf(unsafe.Pointer(&p[0]), uint(len(p)))
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// void arc4random_buf(void *buf, size_t buflen);
|
||||||
|
//
|
||||||
|
//export arc4random_buf
|
||||||
|
func libc_arc4random_buf(buf unsafe.Pointer, buflen uint)
|
||||||
@@ -22,7 +22,8 @@ type Task struct {
|
|||||||
state state
|
state state
|
||||||
|
|
||||||
// This is needed for some crypto packages.
|
// This is needed for some crypto packages.
|
||||||
FipsIndicator uint8
|
FipsIndicator uint8
|
||||||
|
FipsOnlyBypass bool
|
||||||
|
|
||||||
// State of the goroutine: running, paused, or must-resume-next-pause.
|
// State of the goroutine: running, paused, or must-resume-next-pause.
|
||||||
// This extra field doesn't increase memory usage on 32-bit CPUs and above,
|
// This extra field doesn't increase memory usage on 32-bit CPUs and above,
|
||||||
|
|||||||
@@ -46,26 +46,40 @@ tinygo_swapTask:
|
|||||||
// arbitrary register while registers are flushed.
|
// arbitrary register while registers are flushed.
|
||||||
rsil a4, 3 // XCHAL_EXCM_LEVEL
|
rsil a4, 3 // XCHAL_EXCM_LEVEL
|
||||||
|
|
||||||
// Flush all unsaved registers to the stack.
|
// Save the old PS (in a4) to the stack because call4 clobbers a4-a7.
|
||||||
// This trick has been borrowed from the Zephyr project:
|
s32i a4, sp, 4
|
||||||
// https://github.com/zephyrproject-rtos/zephyr/blob/d79b003758/arch/xtensa/include/xtensa-asm2-s.h#L17
|
|
||||||
and a12, a12, a12
|
// Flush all register windows to the stack using recursive call4.
|
||||||
rotw 3
|
//
|
||||||
and a12, a12, a12
|
// The previous ROTW-based approach (borrowed from Zephyr) does NOT
|
||||||
rotw 3
|
// actually trigger window overflow exceptions on Xtensa LX7 — ROTW
|
||||||
and a12, a12, a12
|
// simply modifies WindowBase without saving any registers to the stack.
|
||||||
rotw 3
|
// This leaves stale window data in the physical register file after a
|
||||||
and a12, a12, a12
|
// goroutine switch, corrupting the overflow save chain when the new
|
||||||
rotw 3
|
// goroutine's deeper calls trigger overflow of old goroutine windows.
|
||||||
and a12, a12, a12
|
//
|
||||||
rotw 4
|
// Instead, we recursively call a small function via call4. Each call4 +
|
||||||
|
// entry triggers the hardware window-overflow mechanism for any occupied
|
||||||
|
// pane being reused, correctly saving registers to the stack.
|
||||||
|
// For NAREG=64 (16 panes), 15 recursive levels cover all panes except
|
||||||
|
// the current one (tinygo_swapTask), which must stay active.
|
||||||
|
movi a6, 15
|
||||||
|
call4 .Lspill_windows
|
||||||
|
|
||||||
|
// After the recursive spill returns, the physical register file still
|
||||||
|
// has WindowStart bits set for the spill helper frames.
|
||||||
|
// We will clear WindowStart completely (to 0) right before the retw.n
|
||||||
|
// below, after the stack switch is done. This prevents stale overflow
|
||||||
|
// when the new goroutine's calls rotate back into these panes.
|
||||||
|
|
||||||
// Restore interrupts.
|
// Restore interrupts.
|
||||||
|
l32i a4, sp, 4 // reload saved PS
|
||||||
wsr.ps a4
|
wsr.ps a4
|
||||||
|
rsync
|
||||||
|
|
||||||
// At this point, the following is true:
|
// At this point, the following is true:
|
||||||
// WindowStart == 1 << WindowBase
|
// WindowStart == 1 << WindowBase
|
||||||
// Therefore, we don't need to do this manually.
|
// All other windows have been properly flushed to their stacks.
|
||||||
// It also means that the stack pointer can now be safely modified.
|
// It also means that the stack pointer can now be safely modified.
|
||||||
|
|
||||||
// Save a0, which stores the return address and the parent register window
|
// Save a0, which stores the return address and the parent register window
|
||||||
@@ -83,6 +97,30 @@ tinygo_swapTask:
|
|||||||
// register also stores the parent register window.
|
// register also stores the parent register window.
|
||||||
l32i.n a0, sp, 0
|
l32i.n a0, sp, 0
|
||||||
|
|
||||||
|
// Clear ALL WindowStart bits. With all windows spilled to the stack,
|
||||||
|
// we must ensure no stale WS bits remain: the retw.n below will trigger
|
||||||
|
// underflow4 to load the new goroutine's registers from the new stack
|
||||||
|
// (which sets the appropriate WS bit via rfwu). Any stale WS bits
|
||||||
|
// (from spill helpers or the old goroutine) would cause spurious
|
||||||
|
// overflows of garbage register values into memory.
|
||||||
|
movi a5, 0
|
||||||
|
wsr a5, WINDOWSTART
|
||||||
|
rsync
|
||||||
|
|
||||||
// Return into the new stack. This instruction will trigger a window
|
// Return into the new stack. This instruction will trigger a window
|
||||||
// underflow, reloading the saved registers from the stack.
|
// underflow, reloading the saved registers from the stack.
|
||||||
retw.n
|
retw.n
|
||||||
|
|
||||||
|
// Recursive helper for flushing all register windows.
|
||||||
|
// Parameter: a2 = remaining recursion depth (passed via caller's a6).
|
||||||
|
// Each call4 + entry triggers the hardware overflow mechanism for any
|
||||||
|
// occupied pane at the new WindowBase position.
|
||||||
|
.balign 4
|
||||||
|
.Lspill_windows:
|
||||||
|
entry a1, 16
|
||||||
|
beqz a2, .Lspill_done
|
||||||
|
addi a2, a2, -1
|
||||||
|
mov a6, a2
|
||||||
|
call4 .Lspill_windows
|
||||||
|
.Lspill_done:
|
||||||
|
retw.n
|
||||||
|
|||||||
@@ -74,3 +74,8 @@ func (s *state) pause() {
|
|||||||
func SystemStack() uintptr {
|
func SystemStack() uintptr {
|
||||||
return systemStack
|
return systemStack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export tinygo_task_current
|
||||||
|
func tinygo_task_current() unsafe.Pointer {
|
||||||
|
return unsafe.Pointer(Current())
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,3 +71,8 @@ func (s *state) pause() {
|
|||||||
func SystemStack() uintptr {
|
func SystemStack() uintptr {
|
||||||
return *runtime_systemStackPtr()
|
return *runtime_systemStackPtr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export tinygo_task_current
|
||||||
|
func tinygo_task_current() unsafe.Pointer {
|
||||||
|
return unsafe.Pointer(Current())
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
//go:build amken_trio
|
||||||
|
|
||||||
|
// RabbitPNP Toolhead Board
|
||||||
|
// MCU: STM32G0B1CBTx (LQFP48, 128KB Flash, 144KB RAM)
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/stm32"
|
||||||
|
"runtime/interrupt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Vacuum sensors (PWM input via TIM2)
|
||||||
|
const (
|
||||||
|
VAC1 = PA0 // TIM2_CH1
|
||||||
|
VAC2 = PA1 // TIM2_CH2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Motor 1 pins (stepper driver)
|
||||||
|
const (
|
||||||
|
M1_CS = PC7
|
||||||
|
M1_DIR = PB13 // REFL
|
||||||
|
M1_STEP = PB14 // REFR
|
||||||
|
M1_ENN = PA10 // Enable (active low)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Motor 2 pins (stepper driver)
|
||||||
|
const (
|
||||||
|
M2_CS = PA9
|
||||||
|
M2_DIR = PB12 // REFL
|
||||||
|
M2_STEP = PB11 // REFR
|
||||||
|
M2_ENN = PC6 // Enable (active low)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Motor 3 pins (stepper driver)
|
||||||
|
const (
|
||||||
|
M3_CS = PB15
|
||||||
|
M3_DIR = PB2 // REFL
|
||||||
|
M3_STEP = PB1 // REFR
|
||||||
|
M3_ENN = PA8 // Enable (active low)
|
||||||
|
)
|
||||||
|
|
||||||
|
// LED
|
||||||
|
const (
|
||||||
|
LED = LED1
|
||||||
|
LED_BUILTIN = LED1
|
||||||
|
LED1 = PB7
|
||||||
|
)
|
||||||
|
|
||||||
|
// Solenoid and Neopixel (PWM via TIM4)
|
||||||
|
const (
|
||||||
|
SOLENOID = PB8 // TIM4_CH3
|
||||||
|
NEOPIXEL = PB9 // TIM4_CH4
|
||||||
|
)
|
||||||
|
|
||||||
|
// Endstops
|
||||||
|
const (
|
||||||
|
ENDSTOP_IN1 = PC13
|
||||||
|
ENDSTOP_IN2 = PC14
|
||||||
|
)
|
||||||
|
|
||||||
|
// Magnetic sensor
|
||||||
|
const (
|
||||||
|
MAG1 = PB3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Accelerometer chip select (LIS2D on SPI2)
|
||||||
|
const (
|
||||||
|
LIS2D_CS = PB5
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI1 pins (motor drivers)
|
||||||
|
const (
|
||||||
|
SPI1_SCK_PIN = PA5
|
||||||
|
SPI1_SDO_PIN = PA2 // MOSI
|
||||||
|
SPI1_SDI_PIN = PA6 // MISO
|
||||||
|
SPI0_SCK_PIN = SPI1_SCK_PIN
|
||||||
|
SPI0_SDO_PIN = SPI1_SDO_PIN
|
||||||
|
SPI0_SDI_PIN = SPI1_SDI_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI2 pins (accelerometer)
|
||||||
|
const (
|
||||||
|
SPI2_SCK_PIN = PB10
|
||||||
|
SPI2_SDO_PIN = PA4 // MOSI
|
||||||
|
SPI2_SDI_PIN = PA3 // MISO
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C2 pins
|
||||||
|
const (
|
||||||
|
I2C2_SCL_PIN = PA7
|
||||||
|
I2C2_SDA_PIN = PB4
|
||||||
|
I2C0_SCL_PIN = I2C2_SCL_PIN
|
||||||
|
I2C0_SDA_PIN = I2C2_SDA_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
// FDCAN1 pins
|
||||||
|
const (
|
||||||
|
CAN_RX = PD0
|
||||||
|
CAN_TX = PD1
|
||||||
|
)
|
||||||
|
|
||||||
|
// USB pins
|
||||||
|
const (
|
||||||
|
USB_DM = PA11
|
||||||
|
USB_DP = PA12
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART pins (not directly connected but required by machine package)
|
||||||
|
const (
|
||||||
|
UART_TX_PIN = NoPin
|
||||||
|
UART_RX_PIN = NoPin
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// SPI1 for motor drivers
|
||||||
|
SPI1 = &SPI{
|
||||||
|
Bus: stm32.SPI1,
|
||||||
|
AltFuncSelector: AF0_SYSTEM,
|
||||||
|
}
|
||||||
|
SPI0 = SPI1
|
||||||
|
|
||||||
|
// SPI2 for accelerometer
|
||||||
|
SPI2 = &SPI{
|
||||||
|
Bus: stm32.SPI2,
|
||||||
|
AltFuncSelector: AF1_TIM1_TIM2_TIM3_LPTIM1,
|
||||||
|
}
|
||||||
|
|
||||||
|
// I2C2
|
||||||
|
I2C2 = &I2C{
|
||||||
|
Bus: stm32.I2C2,
|
||||||
|
AltFuncSelector: AF6_SPI2_USART3_USART4_I2C1,
|
||||||
|
}
|
||||||
|
I2C0 = I2C2
|
||||||
|
|
||||||
|
// FDCAN1 on PD0 (RX) / PD1 (TX) with onboard transceiver
|
||||||
|
CAN1 = &_CAN1
|
||||||
|
_CAN1 = FDCAN{
|
||||||
|
Bus: stm32.FDCAN1,
|
||||||
|
TxAltFuncSelect: AF3_FDCAN1_FDCAN2,
|
||||||
|
RxAltFuncSelect: AF3_FDCAN1_FDCAN2,
|
||||||
|
instance: 0,
|
||||||
|
}
|
||||||
|
// Alias for convenience
|
||||||
|
CAN0 = CAN1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Suppress unused import warning for interrupt package
|
||||||
|
var _ = interrupt.New
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// No UART configured on this board - uses USB or CAN for communication
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build arduino
|
//go:build arduino_uno
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
//go:build arduino_uno_q
|
||||||
|
|
||||||
|
// Arduino UNO Q board with STM32U585 processor.
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/stm32"
|
||||||
|
"runtime/interrupt"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Arduino Pins
|
||||||
|
A0 = PA4
|
||||||
|
A1 = PA5
|
||||||
|
A2 = PA6
|
||||||
|
A3 = PA7
|
||||||
|
A4 = PC1
|
||||||
|
A5 = PC0
|
||||||
|
|
||||||
|
// ADC pin aliases
|
||||||
|
ADC0 = A0
|
||||||
|
ADC1 = A1
|
||||||
|
ADC2 = A2
|
||||||
|
ADC3 = A3
|
||||||
|
ADC4 = A4
|
||||||
|
ADC5 = A5
|
||||||
|
|
||||||
|
D0 = PB7 // USART1 RX, PWM TIM4_CH2
|
||||||
|
D1 = PB6 // USART1 TX, PWM TIM4_CH1
|
||||||
|
D2 = PB3 // PWM TIM2_CH2
|
||||||
|
D3 = PB0 // PWM TIM3_CH3
|
||||||
|
D4 = PA12
|
||||||
|
D5 = PA11 // PWM TIM1_CH4
|
||||||
|
D6 = PB1 // PWM TIM3_CH4
|
||||||
|
D7 = PB2
|
||||||
|
D8 = PB4 // PWM TIM3_CH1
|
||||||
|
D9 = PB8 // PWM TIM4_CH3 / TIM16_CH1
|
||||||
|
D10 = PB9 // PWM TIM4_CH4 / TIM17_CH1
|
||||||
|
D11 = PB15 // PWM TIM15_CH2
|
||||||
|
D12 = PB14 // PWM TIM15_CH1
|
||||||
|
D13 = PB13
|
||||||
|
D18 = PC1
|
||||||
|
D19 = PC0
|
||||||
|
D20 = PB10 // I2C2 SCL, PWM TIM2_CH3
|
||||||
|
D21 = PB11 // I2C2 SDA, PWM TIM2_CH4
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LED = LED3_R
|
||||||
|
LED3_R = PH10
|
||||||
|
LED3_G = PH11
|
||||||
|
LED3_B = PH12
|
||||||
|
LED4_R = PH13
|
||||||
|
LED4_G = PH14
|
||||||
|
LED4_B = PH15
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Default UART pins (LPUART1 active via ST-LINK virtual COM port)
|
||||||
|
UART_TX_PIN = PG7
|
||||||
|
UART_RX_PIN = PG8
|
||||||
|
|
||||||
|
// USART1 pins (Arduino header D1/D0)
|
||||||
|
UART1_TX_PIN = D1
|
||||||
|
UART1_RX_PIN = D0
|
||||||
|
|
||||||
|
// LPUART1 pins (active via ST-LINK virtual COM port)
|
||||||
|
UART2_TX_PIN = PG7
|
||||||
|
UART2_RX_PIN = PG8
|
||||||
|
|
||||||
|
// I2C pins, also connected to I2C2
|
||||||
|
I2C0_SCL_PIN = D20
|
||||||
|
I2C0_SDA_PIN = D21
|
||||||
|
// QWIIC connector pins, also connected to I2C4
|
||||||
|
I2C1_SCL_PIN = PD12
|
||||||
|
I2C1_SDA_PIN = PD13
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
SPI1_SCK_PIN = PA5
|
||||||
|
SPI1_SDI_PIN = PA6
|
||||||
|
SPI1_SDO_PIN = PA7
|
||||||
|
SPI0_SCK_PIN = SPI1_SCK_PIN
|
||||||
|
SPI0_SDI_PIN = SPI1_SDI_PIN
|
||||||
|
SPI0_SDO_PIN = SPI1_SDO_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// USART1 on PB6/PB7 (Arduino header D1/D0).
|
||||||
|
UART1 = &_UART1
|
||||||
|
_UART1 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: stm32.USART1,
|
||||||
|
TxAltFuncSelector: AF7_USART1_2_3,
|
||||||
|
RxAltFuncSelector: AF7_USART1_2_3,
|
||||||
|
}
|
||||||
|
|
||||||
|
// LPUART1 on PG7/PG8 (active via ST-LINK virtual COM port).
|
||||||
|
UART2 = &_UART2
|
||||||
|
_UART2 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: (*stm32.USART_Type)(unsafe.Pointer(stm32.LPUART1)),
|
||||||
|
TxAltFuncSelector: AF8_UART4_5_LPUART1_SDMMC1,
|
||||||
|
RxAltFuncSelector: AF8_UART4_5_LPUART1_SDMMC1,
|
||||||
|
}
|
||||||
|
DefaultUART = UART2
|
||||||
|
|
||||||
|
// I2C2 is documented, alias to I2C0 as well
|
||||||
|
I2C2 = &I2C{
|
||||||
|
Bus: stm32.I2C2,
|
||||||
|
AltFuncSelector: AF4_I2C1_2_3_4,
|
||||||
|
}
|
||||||
|
I2C0 = I2C2
|
||||||
|
|
||||||
|
// I2C4 is is connected to the QWIIC connector, alias to I2C1 as well
|
||||||
|
I2C4 = &I2C{
|
||||||
|
Bus: stm32.I2C4,
|
||||||
|
AltFuncSelector: AF4_I2C1_2_3_4,
|
||||||
|
}
|
||||||
|
I2C1 = I2C4
|
||||||
|
|
||||||
|
// SPI1 is documented, alias to SPI0 as well
|
||||||
|
SPI1 = &SPI{
|
||||||
|
Bus: stm32.SPI1,
|
||||||
|
AltFuncSelector: AF5_SPI1_2_3_OCTOSPI1_OCTOSPI2,
|
||||||
|
}
|
||||||
|
SPI0 = SPI1
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
UART1.Interrupt = interrupt.New(stm32.IRQ_USART1, _UART1.handleInterrupt)
|
||||||
|
UART2.Interrupt = interrupt.New(stm32.IRQ_LPUART1, _UART2.handleInterrupt)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build (avr && atmega328p) || arduino || arduino_nano
|
//go:build (avr && atmega328p) || arduino_uno || arduino_nano
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,26 @@
|
|||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
// Digispark is a tiny ATtiny85-based board with 6 I/O pins.
|
||||||
|
//
|
||||||
|
// PWM is available on the following pins:
|
||||||
|
// - P0 (PB0): Timer0 channel A
|
||||||
|
// - P1 (PB1): Timer0 channel B or Timer1 channel A (LED pin)
|
||||||
|
// - P4 (PB4): Timer1 channel B
|
||||||
|
//
|
||||||
|
// Timer1 is recommended for PWM as it provides more flexible frequency control.
|
||||||
|
|
||||||
// Return the current CPU frequency in hertz.
|
// Return the current CPU frequency in hertz.
|
||||||
func CPUFrequency() uint32 {
|
func CPUFrequency() uint32 {
|
||||||
return 16000000
|
return 16000000
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
P0 Pin = PB0
|
P0 Pin = PB0 // PWM available (Timer0 OC0A)
|
||||||
P1 Pin = PB1
|
P1 Pin = PB1 // PWM available (Timer0 OC0B or Timer1 OC1A)
|
||||||
P2 Pin = PB2
|
P2 Pin = PB2
|
||||||
P3 Pin = PB3
|
P3 Pin = PB3
|
||||||
P4 Pin = PB4
|
P4 Pin = PB4 // PWM available (Timer1 OC1B)
|
||||||
P5 Pin = PB5
|
P5 Pin = PB5
|
||||||
|
|
||||||
LED = P1
|
LED = P1
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
//go:build esp32_generic
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// I2C pins
|
||||||
|
const (
|
||||||
|
SDA_PIN = NoPin
|
||||||
|
SCL_PIN = NoPin
|
||||||
|
)
|
||||||
@@ -30,9 +30,6 @@ const (
|
|||||||
|
|
||||||
// ADC pins
|
// ADC pins
|
||||||
const (
|
const (
|
||||||
ADC0 Pin = ADC1_0
|
|
||||||
ADC1 Pin = ADC2_0
|
|
||||||
|
|
||||||
ADC1_0 Pin = IO0
|
ADC1_0 Pin = IO0
|
||||||
ADC1_1 Pin = IO1
|
ADC1_1 Pin = IO1
|
||||||
ADC1_2 Pin = IO2
|
ADC1_2 Pin = IO2
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
//go:build esp32c3_generic
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
const (
|
||||||
|
SDA_PIN = NoPin
|
||||||
|
SCL_PIN = NoPin
|
||||||
|
)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
//go:build esp32c3_supermini
|
//go:build esp32c3_supermini
|
||||||
|
|
||||||
// This file contains the pin mappings for the ESP32 supermini boards.
|
// This file contains the pin mappings for the ESP32C3 supermini board.
|
||||||
//
|
//
|
||||||
// - https://web.archive.org/web/20240805232453/https://dl.artronshop.co.th/ESP32-C3%20SuperMini%20datasheet.pdf
|
// - https://web.archive.org/web/20240805232453/https://dl.artronshop.co.th/ESP32-C3%20SuperMini%20datasheet.pdf
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
//go:build esp32s3_generic
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCL_PIN = NoPin
|
||||||
|
SDA_PIN = NoPin
|
||||||
|
|
||||||
|
SPI1_SCK_PIN = NoPin // SCK
|
||||||
|
SPI1_MOSI_PIN = NoPin // SDO (MOSI)
|
||||||
|
SPI1_MISO_PIN = NoPin // SDI (MISO)
|
||||||
|
SPI1_CS_PIN = NoPin // CS
|
||||||
|
|
||||||
|
SPI2_SCK_PIN = NoPin // SCK
|
||||||
|
SPI2_MOSI_PIN = NoPin // SDO (MOSI)
|
||||||
|
SPI2_MISO_PIN = NoPin // SDI (MISO)
|
||||||
|
SPI2_CS_PIN = NoPin // CS
|
||||||
|
)
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
//go:build esp32s3_supermini
|
||||||
|
|
||||||
|
// This file contains the pin mappings for the ESP32S3 supermini board.
|
||||||
|
//
|
||||||
|
// - https://www.nologo.tech/product/esp32/esp32s3/esp32s3supermini/esp32S3SuperMini.html
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Digital Pins
|
||||||
|
const (
|
||||||
|
IO1 = GPIO1
|
||||||
|
IO2 = GPIO2
|
||||||
|
IO3 = GPIO3
|
||||||
|
IO4 = GPIO4
|
||||||
|
IO5 = GPIO5
|
||||||
|
IO6 = GPIO6
|
||||||
|
IO7 = GPIO7
|
||||||
|
IO8 = GPIO8
|
||||||
|
IO9 = GPIO9
|
||||||
|
IO10 = GPIO10
|
||||||
|
IO11 = GPIO11
|
||||||
|
IO12 = GPIO12
|
||||||
|
IO13 = GPIO13
|
||||||
|
IO14 = GPIO14
|
||||||
|
IO15 = GPIO15
|
||||||
|
IO16 = GPIO16
|
||||||
|
IO17 = GPIO17
|
||||||
|
IO18 = GPIO18
|
||||||
|
IO21 = GPIO21
|
||||||
|
IO33 = GPIO33
|
||||||
|
IO34 = GPIO34
|
||||||
|
IO35 = GPIO35
|
||||||
|
IO36 = GPIO36
|
||||||
|
IO37 = GPIO37
|
||||||
|
IO38 = GPIO38
|
||||||
|
IO39 = GPIO39
|
||||||
|
IO40 = GPIO40
|
||||||
|
IO41 = GPIO41
|
||||||
|
IO42 = GPIO42
|
||||||
|
IO43 = GPIO43
|
||||||
|
IO44 = GPIO44
|
||||||
|
IO45 = GPIO45
|
||||||
|
IO46 = GPIO46
|
||||||
|
IO47 = GPIO47
|
||||||
|
IO48 = GPIO48
|
||||||
|
)
|
||||||
|
|
||||||
|
// Built-in LED
|
||||||
|
const LED = GPIO48
|
||||||
|
|
||||||
|
// Analog pins
|
||||||
|
const (
|
||||||
|
A1 = GPIO1
|
||||||
|
A2 = GPIO2
|
||||||
|
A3 = GPIO3
|
||||||
|
A4 = GPIO4
|
||||||
|
A5 = GPIO5
|
||||||
|
A6 = GPIO6
|
||||||
|
A7 = GPIO7
|
||||||
|
A8 = GPIO8
|
||||||
|
A9 = GPIO9
|
||||||
|
A10 = GPIO10
|
||||||
|
A11 = GPIO11
|
||||||
|
A12 = GPIO12
|
||||||
|
A13 = GPIO13
|
||||||
|
A14 = GPIO14
|
||||||
|
A15 = GPIO15
|
||||||
|
A16 = GPIO16
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C pins
|
||||||
|
const (
|
||||||
|
SDA_PIN = GPIO8
|
||||||
|
SCL_PIN = GPIO9
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
const (
|
||||||
|
SPI1_SCK_PIN = GPIO4
|
||||||
|
SPI1_MISO_PIN = GPIO5
|
||||||
|
SPI1_MOSI_PIN = GPIO6
|
||||||
|
SPI1_CS_PIN = GPIO7
|
||||||
|
|
||||||
|
SPI2_SCK_PIN = NoPin
|
||||||
|
SPI2_MOSI_PIN = NoPin
|
||||||
|
SPI2_MISO_PIN = NoPin
|
||||||
|
SPI2_CS_PIN = NoPin
|
||||||
|
)
|
||||||
@@ -43,6 +43,15 @@ const (
|
|||||||
USBCDC_DP_PIN = PA25
|
USBCDC_DP_PIN = PA25
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// UART0 pins
|
||||||
|
const (
|
||||||
|
UART0_TX_PIN = D1
|
||||||
|
UART0_RX_PIN = D0
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART0 on the Feather M0.
|
||||||
|
var UART0 = &sercomUSART0
|
||||||
|
|
||||||
// UART1 pins
|
// UART1 pins
|
||||||
const (
|
const (
|
||||||
UART_TX_PIN = D10
|
UART_TX_PIN = D10
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user