mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 02:27:48 +00:00
Compare commits
111 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| df8add7b60 | |||
| fca2de21b1 | |||
| 107b1c2906 | |||
| 2409bbef69 | |||
| 8b078a9e8f | |||
| 9e24441978 | |||
| 1e6c14b3e4 | |||
| 25f6be1488 | |||
| 9a9106a297 | |||
| a68f7e4ce3 | |||
| 70b3ece6ec | |||
| 86ea216e7d | |||
| 5a92c35536 | |||
| 7513fa2c96 | |||
| bc946f346d | |||
| 6e6666519c | |||
| cecae8084c | |||
| 9720ccacbb | |||
| a5aa777c7b | |||
| aca1ad187d | |||
| 5a41ed6329 | |||
| 91e9c84d85 | |||
| 4af530f238 | |||
| d3863f337d | |||
| 5551ec7a1e | |||
| 91104b2f27 | |||
| 80f38e8449 | |||
| 22893c5180 | |||
| 9e4e182615 | |||
| 5f96d2b784 | |||
| bd1d93b705 | |||
| 03d1c44265 | |||
| dc0346d968 | |||
| dadae95448 | |||
| f5fc2fc072 | |||
| 4ba76a5df9 | |||
| ea1e08f53f | |||
| bba0dc9575 | |||
| 617c7586fe | |||
| 7366d5e185 | |||
| 96e3ecd949 | |||
| 8bbfb1ee68 | |||
| 07cdcc61f7 | |||
| 4ca9b34133 | |||
| d5e4b16911 | |||
| fd05254683 | |||
| c579e7e509 | |||
| d463528a72 | |||
| 49b0086f8f | |||
| d7814ff50b | |||
| 02160aa8d8 | |||
| c199dd03c7 | |||
| 472aecf07a | |||
| 09350e5719 | |||
| 623dd6a815 | |||
| e09bd5abb3 | |||
| e955aa1941 | |||
| edaf13f951 | |||
| 5f6cf665f5 | |||
| c6db89ff05 | |||
| 61d651c947 | |||
| 227a55d891 | |||
| b485e8bfbd | |||
| 9e8739bb47 | |||
| 20a7a6fd54 | |||
| 4695da83b7 | |||
| f094e895c5 | |||
| 55573c6729 | |||
| b8a6a1f62b | |||
| ef912a132d | |||
| fb603a471c | |||
| f439514703 | |||
| 303410d3fc | |||
| aa13b5d83b | |||
| 12d63d9642 | |||
| 24b45555bd | |||
| 80c17c0f32 | |||
| f6e6aca8d9 | |||
| c4d99e5297 | |||
| 697e8c725b | |||
| a87e5cdbf0 | |||
| b56baa7aad | |||
| ee94f92ede | |||
| 0b77e92c50 | |||
| a4ee98e0e1 | |||
| d0808c93f6 | |||
| a0407be7b7 | |||
| e70dfa4dd6 | |||
| f34a0d44ca | |||
| df52b500bf | |||
| c2f437e0b7 | |||
| 2365c7cfec | |||
| a5d28bdcca | |||
| f12ddfe164 | |||
| f9ba99344a | |||
| 1784bcd728 | |||
| a2704f1435 | |||
| edbbca5614 | |||
| 13f21477b1 | |||
| 9d73e6cfe4 | |||
| 9e7667ffae | |||
| b86467f9c5 | |||
| 13a16afc2a | |||
| a107b4d459 | |||
| 5c176f80d5 | |||
| c4392d9472 | |||
| b6d6efde07 | |||
| 8b67282f91 | |||
| c7a23183e8 | |||
| f936125658 | |||
| 3cfaceeb16 |
+4
-13
@@ -112,26 +112,17 @@ commands:
|
|||||||
- /go/pkg/mod
|
- /go/pkg/mod
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-llvm13-go116:
|
test-llvm14-go118:
|
||||||
docker:
|
docker:
|
||||||
- image: golang:1.16-buster
|
- image: golang:1.18-buster
|
||||||
steps:
|
|
||||||
- test-linux:
|
|
||||||
llvm: "13"
|
|
||||||
test-llvm14-go119:
|
|
||||||
docker:
|
|
||||||
- image: golang:1.19beta1-buster
|
|
||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "14"
|
llvm: "14"
|
||||||
fmt-check: false
|
resource_class: large
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
test-all:
|
test-all:
|
||||||
jobs:
|
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.
|
||||||
- test-llvm13-go116
|
- test-llvm14-go118
|
||||||
# This tests a beta version of Go. It should be removed once regular
|
|
||||||
# release builds are built using this version.
|
|
||||||
- test-llvm14-go119
|
|
||||||
|
|||||||
@@ -16,10 +16,6 @@ jobs:
|
|||||||
name: build-macos
|
name: build-macos
|
||||||
runs-on: macos-11
|
runs-on: macos-11
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: '1.18.1'
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -35,8 +31,13 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '1.19'
|
||||||
|
cache: true
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-14-macos-v1
|
key: llvm-source-14-macos-v1
|
||||||
@@ -50,7 +51,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 LLVM build
|
- name: Cache LLVM build
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-14-macos-v1
|
key: llvm-build-14-macos-v1
|
||||||
@@ -68,7 +69,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: Cache wasi-libc sysroot
|
- name: Cache wasi-libc sysroot
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-v4
|
key: wasi-libc-sysroot-v4
|
||||||
@@ -100,3 +101,22 @@ jobs:
|
|||||||
- name: Smoke tests
|
- name: Smoke tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0
|
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0
|
||||||
|
test-macos-homebrew:
|
||||||
|
name: homebrew-install
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- name: Install LLVM
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@14
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '1.19'
|
||||||
|
cache: true
|
||||||
|
- name: Build TinyGo
|
||||||
|
run: go install
|
||||||
|
- name: Check binary
|
||||||
|
run: tinygo version
|
||||||
|
|||||||
+35
-52
@@ -18,14 +18,13 @@ jobs:
|
|||||||
# statically linked binary.
|
# statically linked binary.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: alpine:3.16
|
image: golang:1.19-alpine
|
||||||
steps:
|
steps:
|
||||||
- name: Install apk dependencies
|
- name: Install apk dependencies
|
||||||
# tar: needed for actions/cache@v2
|
# tar: needed for actions/cache@v3
|
||||||
# git+openssh: needed for checkout (I think?)
|
# git+openssh: needed for checkout (I think?)
|
||||||
# gcompat: needed for go binary
|
|
||||||
# ruby: needed to install fpm
|
# ruby: needed to install fpm
|
||||||
run: apk add tar git openssh gcompat make g++ ruby
|
run: apk add tar git openssh make g++ ruby
|
||||||
- name: Work around CVE-2022-24765
|
- name: Work around CVE-2022-24765
|
||||||
# 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"
|
||||||
@@ -33,19 +32,15 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install Go
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: '1.18.1'
|
|
||||||
- name: Cache Go
|
- name: Cache Go
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
|
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-14-linux-alpine-v1
|
key: llvm-source-14-linux-alpine-v1
|
||||||
@@ -59,7 +54,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 LLVM build
|
- name: Cache LLVM build
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-14-linux-alpine-v1
|
key: llvm-build-14-linux-alpine-v1
|
||||||
@@ -77,7 +72,7 @@ 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: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-alpine-v1
|
key: binaryen-linux-alpine-v1
|
||||||
@@ -88,7 +83,7 @@ jobs:
|
|||||||
apk add cmake samurai python3
|
apk add cmake samurai python3
|
||||||
make binaryen STATIC=1
|
make binaryen STATIC=1
|
||||||
- name: Cache wasi-libc
|
- name: Cache wasi-libc
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-linux-alpine-v1
|
key: wasi-libc-sysroot-linux-alpine-v1
|
||||||
@@ -98,6 +93,7 @@ jobs:
|
|||||||
run: make wasi-libc
|
run: make wasi-libc
|
||||||
- name: Install fpm
|
- name: Install fpm
|
||||||
run: |
|
run: |
|
||||||
|
gem install --version 4.0.7 public_suffix
|
||||||
gem install --version 2.7.6 dotenv
|
gem install --version 2.7.6 dotenv
|
||||||
gem install --no-document fpm
|
gem install --no-document fpm
|
||||||
- name: Build TinyGo release
|
- name: Build TinyGo release
|
||||||
@@ -120,9 +116,10 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
|
cache: true
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
run: |
|
run: |
|
||||||
curl https://wasmtime.dev/install.sh -sSf | bash
|
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||||
@@ -172,9 +169,10 @@ jobs:
|
|||||||
simavr \
|
simavr \
|
||||||
ninja-build
|
ninja-build
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
|
cache: true
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
@@ -183,15 +181,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
curl https://wasmtime.dev/install.sh -sSf | bash
|
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||||
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
|
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
|
||||||
- name: Cache Go
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
key: go-cache-linux-asserts-v1-${{ hashFiles('go.mod') }}
|
|
||||||
path: |
|
|
||||||
~/.cache/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-14-linux-asserts-v2
|
key: llvm-source-14-linux-asserts-v2
|
||||||
@@ -205,7 +196,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 LLVM build
|
- name: Cache LLVM build
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-14-linux-asserts-v1
|
key: llvm-build-14-linux-asserts-v1
|
||||||
@@ -221,7 +212,7 @@ 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: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-asserts-v1
|
key: binaryen-linux-asserts-v1
|
||||||
@@ -230,7 +221,7 @@ jobs:
|
|||||||
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
||||||
run: make binaryen
|
run: make binaryen
|
||||||
- name: Cache wasi-libc
|
- name: Cache wasi-libc
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-linux-asserts-v5
|
key: wasi-libc-sysroot-linux-asserts-v5
|
||||||
@@ -245,6 +236,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make ASSERT=1
|
make ASSERT=1
|
||||||
echo "$(pwd)/build" >> $GITHUB_PATH
|
echo "$(pwd)/build" >> $GITHUB_PATH
|
||||||
|
- name: Test machine package
|
||||||
|
run: make check-machine
|
||||||
- name: Test stdlib packages
|
- name: Test stdlib packages
|
||||||
run: make tinygo-test
|
run: make tinygo-test
|
||||||
- name: Install Xtensa toolchain
|
- name: Install Xtensa toolchain
|
||||||
@@ -278,18 +271,12 @@ jobs:
|
|||||||
g++-arm-linux-gnueabihf \
|
g++-arm-linux-gnueabihf \
|
||||||
libc6-dev-armhf-cross
|
libc6-dev-armhf-cross
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
- name: Cache Go
|
cache: true
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
key: go-cache-linux-arm-v2-${{ hashFiles('go.mod') }}
|
|
||||||
path: |
|
|
||||||
~/.cache/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-14-linux-v2
|
key: llvm-source-14-linux-v2
|
||||||
@@ -303,7 +290,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 LLVM build
|
- name: Cache LLVM build
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-14-linux-arm-v1
|
key: llvm-build-14-linux-arm-v1
|
||||||
@@ -321,7 +308,7 @@ 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: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-arm-v1
|
key: binaryen-linux-arm-v1
|
||||||
@@ -334,6 +321,7 @@ jobs:
|
|||||||
make CROSS=arm-linux-gnueabihf binaryen
|
make CROSS=arm-linux-gnueabihf binaryen
|
||||||
- name: Install fpm
|
- name: Install fpm
|
||||||
run: |
|
run: |
|
||||||
|
sudo gem install --version 4.0.7 public_suffix
|
||||||
sudo gem install --version 2.7.6 dotenv
|
sudo gem install --version 2.7.6 dotenv
|
||||||
sudo gem install --no-document fpm
|
sudo gem install --no-document fpm
|
||||||
- name: Build TinyGo binary
|
- name: Build TinyGo binary
|
||||||
@@ -383,18 +371,12 @@ jobs:
|
|||||||
libc6-dev-arm64-cross \
|
libc6-dev-arm64-cross \
|
||||||
ninja-build
|
ninja-build
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.18.1'
|
go-version: '1.19'
|
||||||
- name: Cache Go
|
cache: true
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
key: go-cache-linux-arm64-v2-${{ hashFiles('go.mod') }}
|
|
||||||
path: |
|
|
||||||
~/.cache/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-14-linux-v1
|
key: llvm-source-14-linux-v1
|
||||||
@@ -408,7 +390,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 LLVM build
|
- name: Cache LLVM build
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-14-linux-arm64-v1
|
key: llvm-build-14-linux-arm64-v1
|
||||||
@@ -424,7 +406,7 @@ 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: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-arm64-v1
|
key: binaryen-linux-arm64-v1
|
||||||
@@ -436,6 +418,7 @@ jobs:
|
|||||||
make CROSS=aarch64-linux-gnu binaryen
|
make CROSS=aarch64-linux-gnu binaryen
|
||||||
- name: Install fpm
|
- name: Install fpm
|
||||||
run: |
|
run: |
|
||||||
|
sudo gem install --version 4.0.7 public_suffix
|
||||||
sudo gem install --version 2.7.6 dotenv
|
sudo gem install --version 2.7.6 dotenv
|
||||||
sudo gem install --no-document fpm
|
sudo gem install --no-document fpm
|
||||||
- name: Build TinyGo binary
|
- name: Build TinyGo binary
|
||||||
|
|||||||
@@ -15,10 +15,6 @@ jobs:
|
|||||||
build-windows:
|
build-windows:
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: '1.18.1'
|
|
||||||
- uses: brechtm/setup-scoop@v2
|
- uses: brechtm/setup-scoop@v2
|
||||||
with:
|
with:
|
||||||
scoop_update: 'false'
|
scoop_update: 'false'
|
||||||
@@ -30,15 +26,13 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Cache Go
|
- name: Install Go
|
||||||
uses: actions/cache@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
key: go-cache-windows-v1-${{ hashFiles('go.mod') }}
|
go-version: '1.19'
|
||||||
path: |
|
cache: true
|
||||||
~/AppData/Local/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
- name: Cache LLVM source
|
- name: Cache LLVM source
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-14-windows-v2
|
key: llvm-source-14-windows-v2
|
||||||
@@ -52,7 +46,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 LLVM build
|
- name: Cache LLVM build
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-14-windows-v2
|
key: llvm-build-14-windows-v2
|
||||||
@@ -69,7 +63,7 @@ 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: Cache wasi-libc sysroot
|
- name: Cache wasi-libc sysroot
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-v4
|
key: wasi-libc-sysroot-v4
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ tarball. If you want to help with development of TinyGo itself, you should follo
|
|||||||
LLVM, Clang and LLD are quite light on dependencies, requiring only standard
|
LLVM, Clang and LLD are quite light on dependencies, requiring only standard
|
||||||
build tools to be built. Go is of course necessary to build TinyGo itself.
|
build tools to be built. Go is of course necessary to build TinyGo itself.
|
||||||
|
|
||||||
* Go (1.16+)
|
* Go (1.18+)
|
||||||
* Standard build tools (gcc/clang)
|
* Standard build tools (gcc/clang)
|
||||||
* git
|
* git
|
||||||
* CMake
|
* CMake
|
||||||
|
|||||||
+1
-1
@@ -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.18 AS tinygo-llvm
|
FROM golang:1.19 AS tinygo-llvm
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
||||||
|
|||||||
@@ -267,6 +267,18 @@ tinygo:
|
|||||||
test: wasi-libc
|
test: wasi-libc
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags "byollvm osusergo" ./builder ./cgo ./compileopts ./compiler ./interp ./transform .
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags "byollvm osusergo" ./builder ./cgo ./compileopts ./compiler ./interp ./transform .
|
||||||
|
|
||||||
|
# Check whether the machine package matches the documentation.
|
||||||
|
# TODO: improve `tinygo targets` so it doesn't return these invalid targets.
|
||||||
|
CHECK_MACHINE_EXCULDE = \
|
||||||
|
cortex-m-qemu \
|
||||||
|
particle-3rd-gen \
|
||||||
|
riscv-qemu \
|
||||||
|
riscv64-qemu \
|
||||||
|
rp2040 \
|
||||||
|
$(nil)
|
||||||
|
check-machine:
|
||||||
|
$(GO) run ./tools/machinecheck $(filter-out $(CHECK_MACHINE_EXCULDE),$(shell $(TINYGO) targets))
|
||||||
|
|
||||||
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
|
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
|
||||||
TEST_PACKAGES_SLOW = \
|
TEST_PACKAGES_SLOW = \
|
||||||
compress/bzip2 \
|
compress/bzip2 \
|
||||||
@@ -280,7 +292,6 @@ TEST_PACKAGES_FAST = \
|
|||||||
container/list \
|
container/list \
|
||||||
container/ring \
|
container/ring \
|
||||||
crypto/des \
|
crypto/des \
|
||||||
crypto/elliptic/internal/fiat \
|
|
||||||
crypto/internal/subtle \
|
crypto/internal/subtle \
|
||||||
crypto/md5 \
|
crypto/md5 \
|
||||||
crypto/rc4 \
|
crypto/rc4 \
|
||||||
@@ -317,13 +328,24 @@ TEST_PACKAGES_FAST = \
|
|||||||
unicode \
|
unicode \
|
||||||
unicode/utf16 \
|
unicode/utf16 \
|
||||||
unicode/utf8 \
|
unicode/utf8 \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
|
# Assume this will go away before Go2, so only check minor version.
|
||||||
|
ifeq ($(filter $(shell $(GO) env GOVERSION | cut -f 2 -d.), 16 17 18), )
|
||||||
|
TEST_PACKAGES_FAST += crypto/internal/nistec/fiat
|
||||||
|
else
|
||||||
|
TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat
|
||||||
|
endif
|
||||||
|
|
||||||
# archive/zip requires os.ReadAt, which is not yet supported on windows
|
# archive/zip requires os.ReadAt, which is not yet supported on windows
|
||||||
|
# compress/flate appears to hang on wasi
|
||||||
|
# compress/lzw appears to hang on wasi
|
||||||
|
# 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
|
||||||
# io/fs 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
|
||||||
|
# strconv requires recover() which is not yet supported on wasi
|
||||||
|
# text/template/parse requires recover(), which is not yet supported on wasi
|
||||||
# testing/fstest requires os.ReadDir, which is not yet supported on windows or wasi
|
# testing/fstest requires os.ReadDir, which is not yet supported on windows or wasi
|
||||||
# compress/flate fails windows go 1.18, https://github.com/tinygo-org/tinygo/issues/2762
|
|
||||||
# compress/lzw fails windows go 1.18 wasi, https://github.com/tinygo-org/tinygo/issues/2762
|
|
||||||
|
|
||||||
# Additional standard library packages that pass tests on individual platforms
|
# Additional standard library packages that pass tests on individual platforms
|
||||||
TEST_PACKAGES_LINUX := \
|
TEST_PACKAGES_LINUX := \
|
||||||
@@ -333,7 +355,6 @@ TEST_PACKAGES_LINUX := \
|
|||||||
crypto/hmac \
|
crypto/hmac \
|
||||||
debug/dwarf \
|
debug/dwarf \
|
||||||
debug/plan9obj \
|
debug/plan9obj \
|
||||||
io/fs \
|
|
||||||
io/ioutil \
|
io/ioutil \
|
||||||
strconv \
|
strconv \
|
||||||
testing/fstest \
|
testing/fstest \
|
||||||
@@ -342,7 +363,12 @@ TEST_PACKAGES_LINUX := \
|
|||||||
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
|
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
|
||||||
|
|
||||||
TEST_PACKAGES_WINDOWS := \
|
TEST_PACKAGES_WINDOWS := \
|
||||||
compress/lzw
|
compress/flate \
|
||||||
|
compress/lzw \
|
||||||
|
crypto/hmac \
|
||||||
|
strconv \
|
||||||
|
text/template/parse \
|
||||||
|
$(nil)
|
||||||
|
|
||||||
# Report platforms on which each standard library package is known to pass tests
|
# Report platforms on which each standard library package is known to pass tests
|
||||||
jointmp := $(shell echo /tmp/join.$$$$)
|
jointmp := $(shell echo /tmp/join.$$$$)
|
||||||
@@ -357,12 +383,15 @@ report-stdlib-tests-pass:
|
|||||||
# Standard library packages that pass tests quickly on the current platform
|
# Standard library packages that pass tests quickly on the current platform
|
||||||
ifeq ($(shell uname),Darwin)
|
ifeq ($(shell uname),Darwin)
|
||||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
||||||
|
TEST_IOFS := true
|
||||||
endif
|
endif
|
||||||
ifeq ($(shell uname),Linux)
|
ifeq ($(shell uname),Linux)
|
||||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
||||||
|
TEST_IOFS := true
|
||||||
endif
|
endif
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
||||||
|
TEST_IOFS := false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Test known-working standard library packages.
|
# Test known-working standard library packages.
|
||||||
@@ -370,6 +399,12 @@ endif
|
|||||||
.PHONY: tinygo-test
|
.PHONY: tinygo-test
|
||||||
tinygo-test:
|
tinygo-test:
|
||||||
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||||
|
@# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also
|
||||||
|
@# requires a large stack-size. Hence, io/fs is only run conditionally.
|
||||||
|
@# For more details, see the comments on issue #3143.
|
||||||
|
ifeq ($(TEST_IOFS),true)
|
||||||
|
$(TINYGO) test -stack-size=6MB io/fs
|
||||||
|
endif
|
||||||
tinygo-test-fast:
|
tinygo-test-fast:
|
||||||
$(TINYGO) test $(TEST_PACKAGES_HOST)
|
$(TINYGO) test $(TEST_PACKAGES_HOST)
|
||||||
tinygo-bench:
|
tinygo-bench:
|
||||||
@@ -379,9 +414,9 @@ tinygo-bench-fast:
|
|||||||
|
|
||||||
# Same thing, except for wasi rather than the current platform.
|
# Same thing, except for wasi rather than the current platform.
|
||||||
tinygo-test-wasi:
|
tinygo-test-wasi:
|
||||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
||||||
tinygo-test-wasi-fast:
|
tinygo-test-wasi-fast:
|
||||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST)
|
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
|
||||||
tinygo-bench-wasi:
|
tinygo-bench-wasi:
|
||||||
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
||||||
tinygo-bench-wasi-fast:
|
tinygo-bench-wasi-fast:
|
||||||
@@ -403,6 +438,7 @@ tinygo-baremetal:
|
|||||||
.PHONY: smoketest
|
.PHONY: smoketest
|
||||||
smoketest:
|
smoketest:
|
||||||
$(TINYGO) version
|
$(TINYGO) version
|
||||||
|
$(TINYGO) targets > /dev/null
|
||||||
# regression test for #2892
|
# regression test for #2892
|
||||||
cd tests/testing/recurse && ($(TINYGO) test ./... > recurse.log && cat recurse.log && test $$(wc -l < recurse.log) = 2 && rm recurse.log)
|
cd tests/testing/recurse && ($(TINYGO) test ./... > recurse.log && cat recurse.log && test $$(wc -l < recurse.log) = 2 && rm recurse.log)
|
||||||
# compile-only platform-independent examples
|
# compile-only platform-independent examples
|
||||||
@@ -512,6 +548,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=feather-m4 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=feather-m4 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=matrixportal-m4 examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=pybadge examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pybadge examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=metro-m4-airlift examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=metro-m4-airlift examples/blinky1
|
||||||
@@ -578,16 +616,22 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=qtpy-rp2040 examples/echo
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=macropad-rp2040 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=macropad-rp2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=badger2040 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=badger2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=tufty2040 examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=thingplus-rp2040 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=thingplus-rp2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=xiao-rp2040 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=xiao-rp2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/temp
|
||||||
|
@$(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
|
||||||
@@ -668,14 +712,16 @@ ifneq ($(XTENSA), 0)
|
|||||||
$(TINYGO) build -size short -o test.bin -target mch2022 examples/serial
|
$(TINYGO) build -size short -o test.bin -target mch2022 examples/serial
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
endif
|
endif
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
|
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/serial
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
|
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
|
$(TINYGO) build -size short -o test.bin -target=xiao-esp32c3 examples/serial
|
||||||
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=hifive1-qemu examples/serial
|
|
||||||
@$(MD5SUM) test.hex
|
|
||||||
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
ifneq ($(WASM), 0)
|
ifneq ($(WASM), 0)
|
||||||
@@ -748,6 +794,7 @@ endif
|
|||||||
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src
|
||||||
|
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src
|
||||||
@@ -766,6 +813,7 @@ endif
|
|||||||
@cp -rp lib/picolibc/newlib/libc/string build/release/tinygo/lib/picolibc/newlib/libc
|
@cp -rp lib/picolibc/newlib/libc/string build/release/tinygo/lib/picolibc/newlib/libc
|
||||||
@cp -rp lib/picolibc/newlib/libc/tinystdio build/release/tinygo/lib/picolibc/newlib/libc
|
@cp -rp lib/picolibc/newlib/libc/tinystdio build/release/tinygo/lib/picolibc/newlib/libc
|
||||||
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
|
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
|
||||||
|
@cp -rp lib/picolibc/newlib/libm/math build/release/tinygo/lib/picolibc/newlib/libm
|
||||||
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
||||||
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
|
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
|
||||||
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
|
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
|
|||||||
|
|
||||||
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
|
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
|
||||||
|
|
||||||
The following 88 microcontroller boards are currently supported:
|
The following 91 microcontroller boards are currently supported:
|
||||||
|
|
||||||
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
||||||
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
||||||
@@ -66,7 +66,9 @@ The following 88 microcontroller boards are currently supported:
|
|||||||
* [Adafruit PyGamer](https://www.adafruit.com/product/4242)
|
* [Adafruit PyGamer](https://www.adafruit.com/product/4242)
|
||||||
* [Adafruit PyPortal](https://www.adafruit.com/product/4116)
|
* [Adafruit PyPortal](https://www.adafruit.com/product/4116)
|
||||||
* [Adafruit QT Py](https://www.adafruit.com/product/4600)
|
* [Adafruit QT Py](https://www.adafruit.com/product/4600)
|
||||||
|
* [Adafruit QT Py RP2040](https://www.adafruit.com/product/4900)
|
||||||
* [Adafruit Trinket M0](https://www.adafruit.com/product/3500)
|
* [Adafruit Trinket M0](https://www.adafruit.com/product/3500)
|
||||||
|
* [Adafruit Trinkey QT2040](https://adafruit.com/product/5056)
|
||||||
* [Arduino Mega 1280](https://www.arduino.cc/en/Main/arduinoBoardMega/)
|
* [Arduino Mega 1280](https://www.arduino.cc/en/Main/arduinoBoardMega/)
|
||||||
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
|
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
|
||||||
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
|
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
|
||||||
@@ -108,6 +110,7 @@ The following 88 microcontroller boards are currently supported:
|
|||||||
* [Particle Xenon](https://docs.particle.io/datasheets/discontinued/xenon-datasheet/)
|
* [Particle Xenon](https://docs.particle.io/datasheets/discontinued/xenon-datasheet/)
|
||||||
* [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/)
|
* [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/)
|
||||||
* [Pimoroni Badger2040](https://shop.pimoroni.com/products/badger-2040)
|
* [Pimoroni Badger2040](https://shop.pimoroni.com/products/badger-2040)
|
||||||
|
* [Pimoroni Tufty2040](https://shop.pimoroni.com/products/tufty-2040)
|
||||||
* [PineTime DevKit](https://www.pine64.org/pinetime/)
|
* [PineTime DevKit](https://www.pine64.org/pinetime/)
|
||||||
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
||||||
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
|
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
|
||||||
@@ -117,11 +120,12 @@ The following 88 microcontroller boards are currently supported:
|
|||||||
* [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199)
|
* [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199)
|
||||||
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
||||||
* [Seeed XIAO BLE](https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html)
|
* [Seeed XIAO BLE](https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html)
|
||||||
|
* [Seeed XIAO ESP32C3](https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html)
|
||||||
* [Seeed XIAO RP2040](https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html)
|
* [Seeed XIAO RP2040](https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html)
|
||||||
* [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html)
|
* [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html)
|
||||||
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
|
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
|
||||||
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
||||||
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1)
|
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1-rev-b)
|
||||||
* [Sparkfun Thing Plus RP2040](https://www.sparkfun.com/products/17745)
|
* [Sparkfun Thing Plus RP2040](https://www.sparkfun.com/products/17745)
|
||||||
* [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
|
* [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
|
||||||
* [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
|
* [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ import (
|
|||||||
// makeArchive creates an arcive for static linking from a list of object files
|
// makeArchive creates an arcive for static linking from a list of object files
|
||||||
// given as a parameter. It is equivalent to the following command:
|
// given as a parameter. It is equivalent to the following command:
|
||||||
//
|
//
|
||||||
// ar -rcs <archivePath> <objs...>
|
// ar -rcs <archivePath> <objs...>
|
||||||
func makeArchive(arfile *os.File, objs []string) error {
|
func makeArchive(arfile *os.File, objs []string) error {
|
||||||
// Open the archive file.
|
// Open the archive file.
|
||||||
arwriter := ar.NewWriter(arfile)
|
arwriter := ar.NewWriter(arfile)
|
||||||
|
|||||||
+16
-16
@@ -14,7 +14,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io/ioutil"
|
"io/fs"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -103,7 +103,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a temporary directory for intermediary files.
|
// Create a temporary directory for intermediary files.
|
||||||
dir, err := ioutil.TempDir("", "tinygo")
|
dir, err := os.MkdirTemp("", "tinygo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
libcDependencies = append(libcDependencies, libcJob)
|
libcDependencies = append(libcDependencies, libcJob)
|
||||||
case "wasi-libc":
|
case "wasi-libc":
|
||||||
path := filepath.Join(root, "lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a")
|
path := filepath.Join(root, "lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a")
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
if _, err := os.Stat(path); errors.Is(err, fs.ErrNotExist) {
|
||||||
return errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?")
|
return errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?")
|
||||||
}
|
}
|
||||||
libcDependencies = append(libcDependencies, dummyCompileJob(path))
|
libcDependencies = append(libcDependencies, dummyCompileJob(path))
|
||||||
@@ -178,7 +178,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
|
|
||||||
Scheduler: config.Scheduler(),
|
Scheduler: config.Scheduler(),
|
||||||
AutomaticStackSize: config.AutomaticStackSize(),
|
AutomaticStackSize: config.AutomaticStackSize(),
|
||||||
DefaultStackSize: config.Target.DefaultStackSize,
|
DefaultStackSize: config.StackSize(),
|
||||||
NeedsStackObjects: config.NeedsStackObjects(),
|
NeedsStackObjects: config.NeedsStackObjects(),
|
||||||
Debug: true,
|
Debug: true,
|
||||||
}
|
}
|
||||||
@@ -370,7 +370,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
// Packages are compiled independently anyway.
|
// Packages are compiled independently anyway.
|
||||||
for _, cgoHeader := range pkg.CGoHeaders {
|
for _, cgoHeader := range pkg.CGoHeaders {
|
||||||
// Store the header text in a temporary file.
|
// Store the header text in a temporary file.
|
||||||
f, err := ioutil.TempFile(dir, "cgosnippet-*.c")
|
f, err := os.CreateTemp(dir, "cgosnippet-*.c")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -431,7 +431,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
if pkgInit.IsNil() {
|
if pkgInit.IsNil() {
|
||||||
panic("init not found for " + pkg.Pkg.Path())
|
panic("init not found for " + pkg.Pkg.Path())
|
||||||
}
|
}
|
||||||
err := interp.RunFunc(pkgInit, config.DumpSSA())
|
err := interp.RunFunc(pkgInit, config.Options.InterpTimeout, config.DumpSSA())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -445,7 +445,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
// Write to a temporary path that is renamed to the destination
|
// Write to a temporary path that is renamed to the destination
|
||||||
// file to avoid race conditions with other TinyGo invocatiosn
|
// file to avoid race conditions with other TinyGo invocatiosn
|
||||||
// that might also be compiling this package at the same time.
|
// that might also be compiling this package at the same time.
|
||||||
f, err := ioutil.TempFile(filepath.Dir(job.result), filepath.Base(job.result))
|
f, err := os.CreateTemp(filepath.Dir(job.result), filepath.Base(job.result))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -589,7 +589,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer llvmBuf.Dispose()
|
defer llvmBuf.Dispose()
|
||||||
return ioutil.WriteFile(outpath, llvmBuf.Bytes(), 0666)
|
return os.WriteFile(outpath, llvmBuf.Bytes(), 0666)
|
||||||
case ".bc":
|
case ".bc":
|
||||||
var buf llvm.MemoryBuffer
|
var buf llvm.MemoryBuffer
|
||||||
if config.UseThinLTO() {
|
if config.UseThinLTO() {
|
||||||
@@ -598,10 +598,10 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
buf = llvm.WriteBitcodeToMemoryBuffer(mod)
|
buf = llvm.WriteBitcodeToMemoryBuffer(mod)
|
||||||
}
|
}
|
||||||
defer buf.Dispose()
|
defer buf.Dispose()
|
||||||
return ioutil.WriteFile(outpath, buf.Bytes(), 0666)
|
return os.WriteFile(outpath, buf.Bytes(), 0666)
|
||||||
case ".ll":
|
case ".ll":
|
||||||
data := []byte(mod.String())
|
data := []byte(mod.String())
|
||||||
return ioutil.WriteFile(outpath, data, 0666)
|
return os.WriteFile(outpath, data, 0666)
|
||||||
default:
|
default:
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
@@ -629,7 +629,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer llvmBuf.Dispose()
|
defer llvmBuf.Dispose()
|
||||||
return ioutil.WriteFile(objfile, llvmBuf.Bytes(), 0666)
|
return os.WriteFile(objfile, llvmBuf.Bytes(), 0666)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1055,7 +1055,7 @@ func createEmbedObjectFile(data, hexSum, sourceFile, sourceDir, tmpdir string, c
|
|||||||
// needed to convert a program to its final form. Some transformations are not
|
// needed to convert a program to its final form. Some transformations are not
|
||||||
// optional and must be run as the compiler expects them to run.
|
// optional and must be run as the compiler expects them to run.
|
||||||
func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
||||||
err := interp.Run(mod, config.DumpSSA())
|
err := interp.Run(mod, config.Options.InterpTimeout, config.DumpSSA())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1367,10 +1367,10 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
|
|||||||
//
|
//
|
||||||
// It might print something like the following:
|
// It might print something like the following:
|
||||||
//
|
//
|
||||||
// function stack usage (in bytes)
|
// function stack usage (in bytes)
|
||||||
// Reset_Handler 316
|
// Reset_Handler 316
|
||||||
// examples/blinky2.led1 92
|
// examples/blinky2.led1 92
|
||||||
// runtime.run$1 300
|
// runtime.run$1 300
|
||||||
func printStacks(calculatedStacks []string, stackSizes map[string]functionStackSize) {
|
func printStacks(calculatedStacks []string, stackSizes map[string]functionStackSize) {
|
||||||
// Print the sizes of all stacks.
|
// Print the sizes of all stacks.
|
||||||
fmt.Printf("%-32s %s\n", "function", "stack usage (in bytes)")
|
fmt.Printf("%-32s %s\n", "function", "stack usage (in bytes)")
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package builder
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -90,7 +89,7 @@ func testClangAttributes(t *testing.T, options *compileopts.Options) {
|
|||||||
|
|
||||||
// Create a very simple C input file.
|
// Create a very simple C input file.
|
||||||
srcpath := filepath.Join(testDir, "test.c")
|
srcpath := filepath.Join(testDir, "test.c")
|
||||||
err = ioutil.WriteFile(srcpath, []byte("int add(int a, int b) { return a + b; }"), 0o666)
|
err = os.WriteFile(srcpath, []byte("int add(int a, int b) { return a + b; }"), 0o666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not write target file %s: %s", srcpath, err)
|
t.Fatalf("could not write target file %s: %s", srcpath, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ func ReadBuildID() ([]byte, error) {
|
|||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux", "freebsd":
|
case "linux", "freebsd", "android":
|
||||||
// Read the GNU build id section. (Not sure about FreeBSD though...)
|
// Read the GNU build id section. (Not sure about FreeBSD though...)
|
||||||
file, err := elf.NewFile(f)
|
file, err := elf.NewFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+37
-36
@@ -10,7 +10,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -33,29 +33,29 @@ import (
|
|||||||
// Because of this complexity, every file has in fact two cached build outputs:
|
// Because of this complexity, every file has in fact two cached build outputs:
|
||||||
// the file itself, and the list of dependencies. Its operation is as follows:
|
// the file itself, and the list of dependencies. Its operation is as follows:
|
||||||
//
|
//
|
||||||
// depfile = hash(path, compiler, cflags, ...)
|
// depfile = hash(path, compiler, cflags, ...)
|
||||||
// if depfile exists:
|
// if depfile exists:
|
||||||
// outfile = hash of all files and depfile name
|
// outfile = hash of all files and depfile name
|
||||||
// if outfile exists:
|
// if outfile exists:
|
||||||
// # cache hit
|
// # cache hit
|
||||||
// return outfile
|
// return outfile
|
||||||
// # cache miss
|
// # cache miss
|
||||||
// tmpfile = compile file
|
// tmpfile = compile file
|
||||||
// read dependencies (side effect of compile)
|
// read dependencies (side effect of compile)
|
||||||
// write depfile
|
// write depfile
|
||||||
// outfile = hash of all files and depfile name
|
// outfile = hash of all files and depfile name
|
||||||
// rename tmpfile to outfile
|
// rename tmpfile to outfile
|
||||||
//
|
//
|
||||||
// There are a few edge cases that are not handled:
|
// There are a few edge cases that are not handled:
|
||||||
// - If a file is added to an include path, that file may be included instead of
|
// - If a file is added to an include path, that file may be included instead of
|
||||||
// some other file. This would be fixed by also including lookup failures in the
|
// some other file. This would be fixed by also including lookup failures in the
|
||||||
// dependencies file, but I'm not aware of a compiler which does that.
|
// dependencies file, but I'm not aware of a compiler which does that.
|
||||||
// - The Makefile syntax that compilers output has issues, see readDepFile for
|
// - The Makefile syntax that compilers output has issues, see readDepFile for
|
||||||
// details.
|
// details.
|
||||||
// - A header file may be changed to add/remove an include. This invalidates the
|
// - A header file may be changed to add/remove an include. This invalidates the
|
||||||
// depfile but without invalidating its name. For this reason, the depfile is
|
// depfile but without invalidating its name. For this reason, the depfile is
|
||||||
// written on each new compilation (even when it seems unnecessary). However, it
|
// written on each new compilation (even when it seems unnecessary). However, it
|
||||||
// could in rare cases lead to a stale file fetched from the cache.
|
// could in rare cases lead to a stale file fetched from the cache.
|
||||||
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool, printCommands func(string, ...string)) (string, error) {
|
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool, printCommands func(string, ...string)) (string, error) {
|
||||||
// Hash input file.
|
// Hash input file.
|
||||||
fileHash, err := hashFile(abspath)
|
fileHash, err := hashFile(abspath)
|
||||||
@@ -93,7 +93,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
|||||||
// Load dependencies file, if possible.
|
// Load dependencies file, if possible.
|
||||||
depfileName := "dep-" + depfileNameHash + ".json"
|
depfileName := "dep-" + depfileNameHash + ".json"
|
||||||
depfileCachePath := filepath.Join(goenv.Get("GOCACHE"), depfileName)
|
depfileCachePath := filepath.Join(goenv.Get("GOCACHE"), depfileName)
|
||||||
depfileBuf, err := ioutil.ReadFile(depfileCachePath)
|
depfileBuf, err := os.ReadFile(depfileCachePath)
|
||||||
var dependencies []string // sorted list of dependency paths
|
var dependencies []string // sorted list of dependency paths
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// There is a dependency file, that's great!
|
// There is a dependency file, that's great!
|
||||||
@@ -108,21 +108,21 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
if _, err := os.Stat(outpath); err == nil {
|
if _, err := os.Stat(outpath); err == nil {
|
||||||
return outpath, nil
|
return outpath, nil
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !errors.Is(err, fs.ErrNotExist) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !errors.Is(err, fs.ErrNotExist) {
|
||||||
// expected either nil or IsNotExist
|
// expected either nil or IsNotExist
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
objTmpFile, err := ioutil.TempFile(goenv.Get("GOCACHE"), "tmp-*"+ext)
|
objTmpFile, err := os.CreateTemp(goenv.Get("GOCACHE"), "tmp-*"+ext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
objTmpFile.Close()
|
objTmpFile.Close()
|
||||||
depTmpFile, err := ioutil.TempFile(tmpdir, "dep-*.d")
|
depTmpFile, err := os.CreateTemp(tmpdir, "dep-*.d")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
|||||||
sort.Strings(dependencySlice)
|
sort.Strings(dependencySlice)
|
||||||
|
|
||||||
// Write dependencies file.
|
// Write dependencies file.
|
||||||
f, err := ioutil.TempFile(filepath.Dir(depfileCachePath), depfileName)
|
f, err := os.CreateTemp(filepath.Dir(depfileCachePath), depfileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -252,13 +252,14 @@ func hashFile(path string) (string, error) {
|
|||||||
// file is assumed to have a single target named deps.
|
// file is assumed to have a single target named deps.
|
||||||
//
|
//
|
||||||
// There are roughly three make syntax variants:
|
// There are roughly three make syntax variants:
|
||||||
// - BSD make, which doesn't support any escaping. This means that many special
|
// - BSD make, which doesn't support any escaping. This means that many special
|
||||||
// characters are not supported in file names.
|
// characters are not supported in file names.
|
||||||
// - GNU make, which supports escaping using a backslash but when it fails to
|
// - GNU make, which supports escaping using a backslash but when it fails to
|
||||||
// find a file it tries to fall back with the literal path name (to match BSD
|
// find a file it tries to fall back with the literal path name (to match BSD
|
||||||
// make).
|
// make).
|
||||||
// - NMake (Visual Studio) and Jom, which simply quote the string if there are
|
// - NMake (Visual Studio) and Jom, which simply quote the string if there are
|
||||||
// any weird characters.
|
// any weird characters.
|
||||||
|
//
|
||||||
// Clang supports two variants: a format that's a compromise between BSD and GNU
|
// Clang supports two variants: a format that's a compromise between BSD and GNU
|
||||||
// make (and is buggy to match GCC which is equally buggy), and NMake/Jom, which
|
// make (and is buggy to match GCC which is equally buggy), and NMake/Jom, which
|
||||||
// is at least somewhat sane. This last format isn't perfect either: it does not
|
// is at least somewhat sane. This last format isn't perfect either: it does not
|
||||||
@@ -266,7 +267,7 @@ func hashFile(path string) (string, error) {
|
|||||||
// allowed on Windows, but of course can be used on POSIX like systems. Still,
|
// allowed on Windows, but of course can be used on POSIX like systems. Still,
|
||||||
// it's the most sane of any of the formats so readDepFile will use that format.
|
// it's the most sane of any of the formats so readDepFile will use that format.
|
||||||
func readDepFile(filename string) ([]string, error) {
|
func readDepFile(filename string) ([]string, error) {
|
||||||
buf, err := ioutil.ReadFile(filename)
|
buf, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -33,8 +33,8 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
|
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
|
||||||
}
|
}
|
||||||
if major != 1 || minor < 16 || minor > 19 {
|
if major != 1 || minor < 18 || minor > 19 {
|
||||||
return nil, fmt.Errorf("requires go version 1.16 through 1.19, got go%d.%d", major, minor)
|
return nil, fmt.Errorf("requires go version 1.18 through 1.19, got go%d.%d", major, minor)
|
||||||
}
|
}
|
||||||
|
|
||||||
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
||||||
|
|||||||
+4
-2
@@ -1,6 +1,8 @@
|
|||||||
package builder
|
package builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -17,13 +19,13 @@ import (
|
|||||||
func getClangHeaderPath(TINYGOROOT string) string {
|
func getClangHeaderPath(TINYGOROOT string) string {
|
||||||
// Check whether we're running from the source directory.
|
// Check whether we're running from the source directory.
|
||||||
path := filepath.Join(TINYGOROOT, "llvm-project", "clang", "lib", "Headers")
|
path := filepath.Join(TINYGOROOT, "llvm-project", "clang", "lib", "Headers")
|
||||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
if _, err := os.Stat(path); !errors.Is(err, fs.ErrNotExist) {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether we're running from the installation directory.
|
// Check whether we're running from the installation directory.
|
||||||
path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
|
path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
|
||||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
if _, err := os.Stat(path); !errors.Is(err, fs.ErrNotExist) {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -13,7 +13,7 @@ import (
|
|||||||
"debug/elf"
|
"debug/elf"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -189,5 +189,5 @@ func makeESPFirmareImage(infile, outfile, format string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the image to the output file.
|
// Write the image to the output file.
|
||||||
return ioutil.WriteFile(outfile, outf.Bytes(), 0666)
|
return os.WriteFile(outfile, outf.Bytes(), 0666)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-7
@@ -1,7 +1,8 @@
|
|||||||
package builder
|
package builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"errors"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -94,7 +95,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
target := config.Triple()
|
target := config.Triple()
|
||||||
if l.makeHeaders != nil {
|
if l.makeHeaders != nil {
|
||||||
if _, err = os.Stat(headerPath); err != nil {
|
if _, err = os.Stat(headerPath); err != nil {
|
||||||
temporaryHeaderPath, err := ioutil.TempDir(outdir, "include.tmp*")
|
temporaryHeaderPath, err := os.MkdirTemp(outdir, "include.tmp*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -110,10 +111,10 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
err = os.Rename(temporaryHeaderPath, headerPath)
|
err = os.Rename(temporaryHeaderPath, headerPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch {
|
switch {
|
||||||
case os.IsExist(err):
|
case errors.Is(err, fs.ErrExist):
|
||||||
// Another invocation of TinyGo also seems to have already created the headers.
|
// Another invocation of TinyGo also seems to have already created the headers.
|
||||||
|
|
||||||
case runtime.GOOS == "windows" && os.IsPermission(err):
|
case runtime.GOOS == "windows" && errors.Is(err, fs.ErrPermission):
|
||||||
// On Windows, a rename with a destination directory that already
|
// On Windows, a rename with a destination directory that already
|
||||||
// exists does not result in an IsExist error, but rather in an
|
// exists does not result in an IsExist error, but rather in an
|
||||||
// access denied error. To be sure, check for this case by checking
|
// access denied error. To be sure, check for this case by checking
|
||||||
@@ -155,7 +156,11 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
|
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
|
||||||
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
if strings.Split(target, "-")[2] == "linux" {
|
||||||
|
args = append(args, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||||
|
} else {
|
||||||
|
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(target, "avr") {
|
if strings.HasPrefix(target, "avr") {
|
||||||
// AVR defaults to C float and double both being 32-bit. This deviates
|
// AVR defaults to C float and double both being 32-bit. This deviates
|
||||||
@@ -189,7 +194,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
defer once.Do(unlock)
|
defer once.Do(unlock)
|
||||||
|
|
||||||
// Create an archive of all object files.
|
// Create an archive of all object files.
|
||||||
f, err := ioutil.TempFile(outdir, "libc.a.tmp*")
|
f, err := os.CreateTemp(outdir, "libc.a.tmp*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -250,7 +255,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
run: func(*compileJob) error {
|
run: func(*compileJob) error {
|
||||||
var compileArgs []string
|
var compileArgs []string
|
||||||
compileArgs = append(compileArgs, args...)
|
compileArgs = append(compileArgs, args...)
|
||||||
tmpfile, err := ioutil.TempFile(outdir, "crt1.o.tmp*")
|
tmpfile, err := os.CreateTemp(outdir, "crt1.o.tmp*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func makeMinGWExtraLibs(tmpdir string) []*compileJob {
|
|||||||
// .in files need to be preprocessed by a preprocessor (-E)
|
// .in files need to be preprocessed by a preprocessor (-E)
|
||||||
// first.
|
// first.
|
||||||
defpath = outpath + ".def"
|
defpath = outpath + ".def"
|
||||||
err := runCCompiler("-E", "-x", "c", "-Wp,-w", "-P", "-DDEF_X64", "-o", defpath, inpath, "-I"+goenv.Get("TINYGOROOT")+"/lib/mingw-w64/mingw-w64-crt/def-include/")
|
err := runCCompiler("-E", "-x", "c", "-Wp,-w", "-P", "-DDEF_X64", "-DDATA", "-o", defpath, inpath, "-I"+goenv.Get("TINYGOROOT")+"/lib/mingw-w64/mingw-w64-crt/def-include/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -3,7 +3,6 @@ package builder
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -35,7 +34,7 @@ var Musl = Library{
|
|||||||
filepath.Join(muslDir, "include", "alltypes.h.in"),
|
filepath.Join(muslDir, "include", "alltypes.h.in"),
|
||||||
}
|
}
|
||||||
for _, infile := range infiles {
|
for _, infile := range infiles {
|
||||||
data, err := ioutil.ReadFile(infile)
|
data, err := os.ReadFile(infile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -63,7 +62,7 @@ var Musl = Library{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadFile(filepath.Join(muslDir, "arch", arch, "bits", "syscall.h.in"))
|
data, err := os.ReadFile(filepath.Join(muslDir, "arch", arch, "bits", "syscall.h.in"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -90,6 +89,7 @@ var Musl = Library{
|
|||||||
"-Wno-shift-op-parentheses",
|
"-Wno-shift-op-parentheses",
|
||||||
"-Wno-ignored-attributes",
|
"-Wno-ignored-attributes",
|
||||||
"-Wno-string-plus-int",
|
"-Wno-string-plus-int",
|
||||||
|
"-Wno-ignored-pragmas",
|
||||||
"-Qunused-arguments",
|
"-Qunused-arguments",
|
||||||
// Select include dirs. Don't include standard library includes
|
// Select include dirs. Don't include standard library includes
|
||||||
// (that would introduce host dependencies and other complications),
|
// (that would introduce host dependencies and other complications),
|
||||||
@@ -118,6 +118,7 @@ var Musl = Library{
|
|||||||
"legacy/*.c",
|
"legacy/*.c",
|
||||||
"malloc/*.c",
|
"malloc/*.c",
|
||||||
"mman/*.c",
|
"mman/*.c",
|
||||||
|
"math/*.c",
|
||||||
"signal/*.c",
|
"signal/*.c",
|
||||||
"stdio/*.c",
|
"stdio/*.c",
|
||||||
"string/*.c",
|
"string/*.c",
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ package builder
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
@@ -18,7 +18,7 @@ func makeDFUFirmwareImage(options *compileopts.Options, infile, outfile string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(cmdLine[0], cmdLine[1:]...)
|
cmd := exec.Command(cmdLine[0], cmdLine[1:]...)
|
||||||
cmd.Stdout = ioutil.Discard
|
cmd.Stdout = io.Discard
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not run nrfutil pkg generate: %w", err)
|
return fmt.Errorf("could not run nrfutil pkg generate: %w", err)
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ package builder
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ func extractROM(path string) (uint64, []byte, error) {
|
|||||||
// Pad the difference
|
// Pad the difference
|
||||||
rom = append(rom, make([]byte, diff)...)
|
rom = append(rom, make([]byte, diff)...)
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadAll(prog.Open())
|
data, err := io.ReadAll(prog.Open())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, objcopyError{"failed to extract segment from ELF file: " + path, err}
|
return 0, nil, objcopyError{"failed to extract segment from ELF file: " + path, err}
|
||||||
}
|
}
|
||||||
|
|||||||
+380
-204
@@ -19,7 +19,7 @@ var Picolibc = Library{
|
|||||||
return f.Close()
|
return f.Close()
|
||||||
},
|
},
|
||||||
cflags: func(target, headerPath string) []string {
|
cflags: func(target, headerPath string) []string {
|
||||||
picolibcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc")
|
newlibDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib")
|
||||||
return []string{
|
return []string{
|
||||||
"-Werror",
|
"-Werror",
|
||||||
"-Wall",
|
"-Wall",
|
||||||
@@ -27,219 +27,395 @@ var Picolibc = Library{
|
|||||||
"-D_COMPILING_NEWLIB",
|
"-D_COMPILING_NEWLIB",
|
||||||
"-DHAVE_ALIAS_ATTRIBUTE",
|
"-DHAVE_ALIAS_ATTRIBUTE",
|
||||||
"-DTINY_STDIO",
|
"-DTINY_STDIO",
|
||||||
|
"-D_IEEE_LIBM",
|
||||||
|
"-D__OBSOLETE_MATH_FLOAT=1", // use old math code that doesn't expect a FPU
|
||||||
|
"-D__OBSOLETE_MATH_DOUBLE=0",
|
||||||
"-nostdlibinc",
|
"-nostdlibinc",
|
||||||
"-isystem", picolibcDir + "/include",
|
"-isystem", newlibDir + "/libc/include",
|
||||||
"-I" + picolibcDir + "/tinystdio",
|
"-I" + newlibDir + "/libc/tinystdio",
|
||||||
|
"-I" + newlibDir + "/libm/common",
|
||||||
"-I" + headerPath,
|
"-I" + headerPath,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc") },
|
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib") },
|
||||||
librarySources: func(target string) []string {
|
librarySources: func(target string) []string {
|
||||||
return picolibcSources
|
return picolibcSources
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var picolibcSources = []string{
|
var picolibcSources = []string{
|
||||||
"../../../picolibc-stdio.c",
|
"../../picolibc-stdio.c",
|
||||||
|
|
||||||
"tinystdio/asprintf.c",
|
"libc/tinystdio/asprintf.c",
|
||||||
"tinystdio/atod_engine.c",
|
"libc/tinystdio/atod_engine.c",
|
||||||
"tinystdio/atod_ryu.c",
|
"libc/tinystdio/atod_ryu.c",
|
||||||
"tinystdio/atof_engine.c",
|
"libc/tinystdio/atof_engine.c",
|
||||||
"tinystdio/atof_ryu.c",
|
"libc/tinystdio/atof_ryu.c",
|
||||||
//"tinystdio/atold_engine.c", // have_long_double and not long_double_equals_double
|
//"libc/tinystdio/atold_engine.c", // have_long_double and not long_double_equals_double
|
||||||
"tinystdio/clearerr.c",
|
"libc/tinystdio/clearerr.c",
|
||||||
"tinystdio/compare_exchange.c",
|
"libc/tinystdio/compare_exchange.c",
|
||||||
"tinystdio/dtoa_data.c",
|
"libc/tinystdio/dtoa_data.c",
|
||||||
"tinystdio/dtoa_engine.c",
|
"libc/tinystdio/dtoa_engine.c",
|
||||||
"tinystdio/dtoa_ryu.c",
|
"libc/tinystdio/dtoa_ryu.c",
|
||||||
"tinystdio/ecvtbuf.c",
|
"libc/tinystdio/ecvtbuf.c",
|
||||||
"tinystdio/ecvt.c",
|
"libc/tinystdio/ecvt.c",
|
||||||
"tinystdio/ecvt_data.c",
|
"libc/tinystdio/ecvt_data.c",
|
||||||
"tinystdio/ecvtfbuf.c",
|
"libc/tinystdio/ecvtfbuf.c",
|
||||||
"tinystdio/ecvtf.c",
|
"libc/tinystdio/ecvtf.c",
|
||||||
"tinystdio/ecvtf_data.c",
|
"libc/tinystdio/ecvtf_data.c",
|
||||||
"tinystdio/exchange.c",
|
"libc/tinystdio/exchange.c",
|
||||||
//"tinystdio/fclose.c", // posix-io
|
//"libc/tinystdio/fclose.c", // posix-io
|
||||||
"tinystdio/fcvtbuf.c",
|
"libc/tinystdio/fcvtbuf.c",
|
||||||
"tinystdio/fcvt.c",
|
"libc/tinystdio/fcvt.c",
|
||||||
"tinystdio/fcvtfbuf.c",
|
"libc/tinystdio/fcvtfbuf.c",
|
||||||
"tinystdio/fcvtf.c",
|
"libc/tinystdio/fcvtf.c",
|
||||||
"tinystdio/fdevopen.c",
|
"libc/tinystdio/fdevopen.c",
|
||||||
//"tinystdio/fdopen.c", // posix-io
|
//"libc/tinystdio/fdopen.c", // posix-io
|
||||||
"tinystdio/feof.c",
|
"libc/tinystdio/feof.c",
|
||||||
"tinystdio/ferror.c",
|
"libc/tinystdio/ferror.c",
|
||||||
"tinystdio/fflush.c",
|
"libc/tinystdio/fflush.c",
|
||||||
"tinystdio/fgetc.c",
|
"libc/tinystdio/fgetc.c",
|
||||||
"tinystdio/fgets.c",
|
"libc/tinystdio/fgets.c",
|
||||||
"tinystdio/fileno.c",
|
"libc/tinystdio/fileno.c",
|
||||||
"tinystdio/filestrget.c",
|
"libc/tinystdio/filestrget.c",
|
||||||
"tinystdio/filestrputalloc.c",
|
"libc/tinystdio/filestrputalloc.c",
|
||||||
"tinystdio/filestrput.c",
|
"libc/tinystdio/filestrput.c",
|
||||||
//"tinystdio/fopen.c", // posix-io
|
//"libc/tinystdio/fopen.c", // posix-io
|
||||||
"tinystdio/fprintf.c",
|
"libc/tinystdio/fprintf.c",
|
||||||
"tinystdio/fputc.c",
|
"libc/tinystdio/fputc.c",
|
||||||
"tinystdio/fputs.c",
|
"libc/tinystdio/fputs.c",
|
||||||
"tinystdio/fread.c",
|
"libc/tinystdio/fread.c",
|
||||||
"tinystdio/fscanf.c",
|
"libc/tinystdio/fscanf.c",
|
||||||
"tinystdio/fseek.c",
|
"libc/tinystdio/fseek.c",
|
||||||
"tinystdio/ftell.c",
|
"libc/tinystdio/ftell.c",
|
||||||
"tinystdio/ftoa_data.c",
|
"libc/tinystdio/ftoa_data.c",
|
||||||
"tinystdio/ftoa_engine.c",
|
"libc/tinystdio/ftoa_engine.c",
|
||||||
"tinystdio/ftoa_ryu.c",
|
"libc/tinystdio/ftoa_ryu.c",
|
||||||
"tinystdio/fwrite.c",
|
"libc/tinystdio/fwrite.c",
|
||||||
"tinystdio/gcvtbuf.c",
|
"libc/tinystdio/gcvtbuf.c",
|
||||||
"tinystdio/gcvt.c",
|
"libc/tinystdio/gcvt.c",
|
||||||
"tinystdio/gcvtfbuf.c",
|
"libc/tinystdio/gcvtfbuf.c",
|
||||||
"tinystdio/gcvtf.c",
|
"libc/tinystdio/gcvtf.c",
|
||||||
"tinystdio/getchar.c",
|
"libc/tinystdio/getchar.c",
|
||||||
"tinystdio/gets.c",
|
"libc/tinystdio/gets.c",
|
||||||
"tinystdio/matchcaseprefix.c",
|
"libc/tinystdio/matchcaseprefix.c",
|
||||||
"tinystdio/perror.c",
|
"libc/tinystdio/perror.c",
|
||||||
//"tinystdio/posixiob.c", // posix-io
|
//"libc/tinystdio/posixiob.c", // posix-io
|
||||||
//"tinystdio/posixio.c", // posix-io
|
//"libc/tinystdio/posixio.c", // posix-io
|
||||||
"tinystdio/printf.c",
|
"libc/tinystdio/printf.c",
|
||||||
"tinystdio/putchar.c",
|
"libc/tinystdio/putchar.c",
|
||||||
"tinystdio/puts.c",
|
"libc/tinystdio/puts.c",
|
||||||
"tinystdio/ryu_divpow2.c",
|
"libc/tinystdio/ryu_divpow2.c",
|
||||||
"tinystdio/ryu_log10.c",
|
"libc/tinystdio/ryu_log10.c",
|
||||||
"tinystdio/ryu_log2pow5.c",
|
"libc/tinystdio/ryu_log2pow5.c",
|
||||||
"tinystdio/ryu_pow5bits.c",
|
"libc/tinystdio/ryu_pow5bits.c",
|
||||||
"tinystdio/ryu_table.c",
|
"libc/tinystdio/ryu_table.c",
|
||||||
"tinystdio/ryu_umul128.c",
|
"libc/tinystdio/ryu_umul128.c",
|
||||||
"tinystdio/scanf.c",
|
"libc/tinystdio/scanf.c",
|
||||||
"tinystdio/setbuf.c",
|
"libc/tinystdio/setbuf.c",
|
||||||
"tinystdio/setvbuf.c",
|
"libc/tinystdio/setvbuf.c",
|
||||||
//"tinystdio/sflags.c", // posix-io
|
//"libc/tinystdio/sflags.c", // posix-io
|
||||||
"tinystdio/snprintf.c",
|
"libc/tinystdio/snprintf.c",
|
||||||
"tinystdio/snprintfd.c",
|
"libc/tinystdio/snprintfd.c",
|
||||||
"tinystdio/snprintff.c",
|
"libc/tinystdio/snprintff.c",
|
||||||
"tinystdio/sprintf.c",
|
"libc/tinystdio/sprintf.c",
|
||||||
"tinystdio/sprintfd.c",
|
"libc/tinystdio/sprintfd.c",
|
||||||
"tinystdio/sprintff.c",
|
"libc/tinystdio/sprintff.c",
|
||||||
"tinystdio/sscanf.c",
|
"libc/tinystdio/sscanf.c",
|
||||||
"tinystdio/strfromd.c",
|
"libc/tinystdio/strfromd.c",
|
||||||
"tinystdio/strfromf.c",
|
"libc/tinystdio/strfromf.c",
|
||||||
"tinystdio/strtod.c",
|
"libc/tinystdio/strtod.c",
|
||||||
"tinystdio/strtod_l.c",
|
"libc/tinystdio/strtod_l.c",
|
||||||
"tinystdio/strtof.c",
|
"libc/tinystdio/strtof.c",
|
||||||
//"tinystdio/strtold.c", // have_long_double and not long_double_equals_double
|
//"libc/tinystdio/strtold.c", // have_long_double and not long_double_equals_double
|
||||||
//"tinystdio/strtold_l.c", // have_long_double and not long_double_equals_double
|
//"libc/tinystdio/strtold_l.c", // have_long_double and not long_double_equals_double
|
||||||
"tinystdio/ungetc.c",
|
"libc/tinystdio/ungetc.c",
|
||||||
"tinystdio/vasprintf.c",
|
"libc/tinystdio/vasprintf.c",
|
||||||
"tinystdio/vfiprintf.c",
|
"libc/tinystdio/vfiprintf.c",
|
||||||
"tinystdio/vfiscanf.c",
|
"libc/tinystdio/vfiscanf.c",
|
||||||
"tinystdio/vfprintf.c",
|
"libc/tinystdio/vfprintf.c",
|
||||||
"tinystdio/vfprintff.c",
|
"libc/tinystdio/vfprintff.c",
|
||||||
"tinystdio/vfscanf.c",
|
"libc/tinystdio/vfscanf.c",
|
||||||
"tinystdio/vfscanff.c",
|
"libc/tinystdio/vfscanff.c",
|
||||||
"tinystdio/vprintf.c",
|
"libc/tinystdio/vprintf.c",
|
||||||
"tinystdio/vscanf.c",
|
"libc/tinystdio/vscanf.c",
|
||||||
"tinystdio/vsnprintf.c",
|
"libc/tinystdio/vsnprintf.c",
|
||||||
"tinystdio/vsprintf.c",
|
"libc/tinystdio/vsprintf.c",
|
||||||
"tinystdio/vsscanf.c",
|
"libc/tinystdio/vsscanf.c",
|
||||||
|
|
||||||
"string/bcmp.c",
|
"libc/string/bcmp.c",
|
||||||
"string/bcopy.c",
|
"libc/string/bcopy.c",
|
||||||
"string/bzero.c",
|
"libc/string/bzero.c",
|
||||||
"string/explicit_bzero.c",
|
"libc/string/explicit_bzero.c",
|
||||||
"string/ffsl.c",
|
"libc/string/ffsl.c",
|
||||||
"string/ffsll.c",
|
"libc/string/ffsll.c",
|
||||||
"string/fls.c",
|
"libc/string/fls.c",
|
||||||
"string/flsl.c",
|
"libc/string/flsl.c",
|
||||||
"string/flsll.c",
|
"libc/string/flsll.c",
|
||||||
"string/gnu_basename.c",
|
"libc/string/gnu_basename.c",
|
||||||
"string/index.c",
|
"libc/string/index.c",
|
||||||
"string/memccpy.c",
|
"libc/string/memccpy.c",
|
||||||
"string/memchr.c",
|
"libc/string/memchr.c",
|
||||||
"string/memcmp.c",
|
"libc/string/memcmp.c",
|
||||||
"string/memcpy.c",
|
"libc/string/memcpy.c",
|
||||||
"string/memmem.c",
|
"libc/string/memmem.c",
|
||||||
"string/memmove.c",
|
"libc/string/memmove.c",
|
||||||
"string/mempcpy.c",
|
"libc/string/mempcpy.c",
|
||||||
"string/memrchr.c",
|
"libc/string/memrchr.c",
|
||||||
"string/memset.c",
|
"libc/string/memset.c",
|
||||||
"string/rawmemchr.c",
|
"libc/string/rawmemchr.c",
|
||||||
"string/rindex.c",
|
"libc/string/rindex.c",
|
||||||
"string/stpcpy.c",
|
"libc/string/stpcpy.c",
|
||||||
"string/stpncpy.c",
|
"libc/string/stpncpy.c",
|
||||||
"string/strcasecmp.c",
|
"libc/string/strcasecmp.c",
|
||||||
"string/strcasecmp_l.c",
|
"libc/string/strcasecmp_l.c",
|
||||||
"string/strcasestr.c",
|
"libc/string/strcasestr.c",
|
||||||
"string/strcat.c",
|
"libc/string/strcat.c",
|
||||||
"string/strchr.c",
|
"libc/string/strchr.c",
|
||||||
"string/strchrnul.c",
|
"libc/string/strchrnul.c",
|
||||||
"string/strcmp.c",
|
"libc/string/strcmp.c",
|
||||||
"string/strcoll.c",
|
"libc/string/strcoll.c",
|
||||||
"string/strcoll_l.c",
|
"libc/string/strcoll_l.c",
|
||||||
"string/strcpy.c",
|
"libc/string/strcpy.c",
|
||||||
"string/strcspn.c",
|
"libc/string/strcspn.c",
|
||||||
"string/strdup.c",
|
"libc/string/strdup.c",
|
||||||
"string/strerror.c",
|
"libc/string/strerror.c",
|
||||||
"string/strerror_r.c",
|
"libc/string/strerror_r.c",
|
||||||
"string/strlcat.c",
|
"libc/string/strlcat.c",
|
||||||
"string/strlcpy.c",
|
"libc/string/strlcpy.c",
|
||||||
"string/strlen.c",
|
"libc/string/strlen.c",
|
||||||
"string/strlwr.c",
|
"libc/string/strlwr.c",
|
||||||
"string/strncasecmp.c",
|
"libc/string/strncasecmp.c",
|
||||||
"string/strncasecmp_l.c",
|
"libc/string/strncasecmp_l.c",
|
||||||
"string/strncat.c",
|
"libc/string/strncat.c",
|
||||||
"string/strncmp.c",
|
"libc/string/strncmp.c",
|
||||||
"string/strncpy.c",
|
"libc/string/strncpy.c",
|
||||||
"string/strndup.c",
|
"libc/string/strndup.c",
|
||||||
"string/strnlen.c",
|
"libc/string/strnlen.c",
|
||||||
"string/strnstr.c",
|
"libc/string/strnstr.c",
|
||||||
"string/strpbrk.c",
|
"libc/string/strpbrk.c",
|
||||||
"string/strrchr.c",
|
"libc/string/strrchr.c",
|
||||||
"string/strsep.c",
|
"libc/string/strsep.c",
|
||||||
"string/strsignal.c",
|
"libc/string/strsignal.c",
|
||||||
"string/strspn.c",
|
"libc/string/strspn.c",
|
||||||
"string/strstr.c",
|
"libc/string/strstr.c",
|
||||||
"string/strtok.c",
|
"libc/string/strtok.c",
|
||||||
"string/strtok_r.c",
|
"libc/string/strtok_r.c",
|
||||||
"string/strupr.c",
|
"libc/string/strupr.c",
|
||||||
"string/strverscmp.c",
|
"libc/string/strverscmp.c",
|
||||||
"string/strxfrm.c",
|
"libc/string/strxfrm.c",
|
||||||
"string/strxfrm_l.c",
|
"libc/string/strxfrm_l.c",
|
||||||
"string/swab.c",
|
"libc/string/swab.c",
|
||||||
"string/timingsafe_bcmp.c",
|
"libc/string/timingsafe_bcmp.c",
|
||||||
"string/timingsafe_memcmp.c",
|
"libc/string/timingsafe_memcmp.c",
|
||||||
"string/u_strerr.c",
|
"libc/string/u_strerr.c",
|
||||||
"string/wcpcpy.c",
|
"libc/string/wcpcpy.c",
|
||||||
"string/wcpncpy.c",
|
"libc/string/wcpncpy.c",
|
||||||
"string/wcscasecmp.c",
|
"libc/string/wcscasecmp.c",
|
||||||
"string/wcscasecmp_l.c",
|
"libc/string/wcscasecmp_l.c",
|
||||||
"string/wcscat.c",
|
"libc/string/wcscat.c",
|
||||||
"string/wcschr.c",
|
"libc/string/wcschr.c",
|
||||||
"string/wcscmp.c",
|
"libc/string/wcscmp.c",
|
||||||
"string/wcscoll.c",
|
"libc/string/wcscoll.c",
|
||||||
"string/wcscoll_l.c",
|
"libc/string/wcscoll_l.c",
|
||||||
"string/wcscpy.c",
|
"libc/string/wcscpy.c",
|
||||||
"string/wcscspn.c",
|
"libc/string/wcscspn.c",
|
||||||
"string/wcsdup.c",
|
"libc/string/wcsdup.c",
|
||||||
"string/wcslcat.c",
|
"libc/string/wcslcat.c",
|
||||||
"string/wcslcpy.c",
|
"libc/string/wcslcpy.c",
|
||||||
"string/wcslen.c",
|
"libc/string/wcslen.c",
|
||||||
"string/wcsncasecmp.c",
|
"libc/string/wcsncasecmp.c",
|
||||||
"string/wcsncasecmp_l.c",
|
"libc/string/wcsncasecmp_l.c",
|
||||||
"string/wcsncat.c",
|
"libc/string/wcsncat.c",
|
||||||
"string/wcsncmp.c",
|
"libc/string/wcsncmp.c",
|
||||||
"string/wcsncpy.c",
|
"libc/string/wcsncpy.c",
|
||||||
"string/wcsnlen.c",
|
"libc/string/wcsnlen.c",
|
||||||
"string/wcspbrk.c",
|
"libc/string/wcspbrk.c",
|
||||||
"string/wcsrchr.c",
|
"libc/string/wcsrchr.c",
|
||||||
"string/wcsspn.c",
|
"libc/string/wcsspn.c",
|
||||||
"string/wcsstr.c",
|
"libc/string/wcsstr.c",
|
||||||
"string/wcstok.c",
|
"libc/string/wcstok.c",
|
||||||
"string/wcswidth.c",
|
"libc/string/wcswidth.c",
|
||||||
"string/wcsxfrm.c",
|
"libc/string/wcsxfrm.c",
|
||||||
"string/wcsxfrm_l.c",
|
"libc/string/wcsxfrm_l.c",
|
||||||
"string/wcwidth.c",
|
"libc/string/wcwidth.c",
|
||||||
"string/wmemchr.c",
|
"libc/string/wmemchr.c",
|
||||||
"string/wmemcmp.c",
|
"libc/string/wmemcmp.c",
|
||||||
"string/wmemcpy.c",
|
"libc/string/wmemcpy.c",
|
||||||
"string/wmemmove.c",
|
"libc/string/wmemmove.c",
|
||||||
"string/wmempcpy.c",
|
"libc/string/wmempcpy.c",
|
||||||
"string/wmemset.c",
|
"libc/string/wmemset.c",
|
||||||
"string/xpg_strerror_r.c",
|
"libc/string/xpg_strerror_r.c",
|
||||||
|
|
||||||
|
"libm/common/sf_finite.c",
|
||||||
|
"libm/common/sf_copysign.c",
|
||||||
|
"libm/common/sf_modf.c",
|
||||||
|
"libm/common/sf_scalbn.c",
|
||||||
|
"libm/common/sf_cbrt.c",
|
||||||
|
"libm/common/sf_exp10.c",
|
||||||
|
"libm/common/sf_expm1.c",
|
||||||
|
"libm/common/sf_ilogb.c",
|
||||||
|
"libm/common/sf_infinity.c",
|
||||||
|
"libm/common/sf_isinf.c",
|
||||||
|
"libm/common/sf_isinff.c",
|
||||||
|
"libm/common/sf_isnan.c",
|
||||||
|
"libm/common/sf_isnanf.c",
|
||||||
|
"libm/common/sf_issignaling.c",
|
||||||
|
"libm/common/sf_log1p.c",
|
||||||
|
"libm/common/sf_nan.c",
|
||||||
|
"libm/common/sf_nextafter.c",
|
||||||
|
"libm/common/sf_pow10.c",
|
||||||
|
"libm/common/sf_rint.c",
|
||||||
|
"libm/common/sf_logb.c",
|
||||||
|
"libm/common/sf_fdim.c",
|
||||||
|
"libm/common/sf_fma.c",
|
||||||
|
"libm/common/sf_fmax.c",
|
||||||
|
"libm/common/sf_fmin.c",
|
||||||
|
"libm/common/sf_fpclassify.c",
|
||||||
|
"libm/common/sf_lrint.c",
|
||||||
|
"libm/common/sf_llrint.c",
|
||||||
|
"libm/common/sf_lround.c",
|
||||||
|
"libm/common/sf_llround.c",
|
||||||
|
"libm/common/sf_nearbyint.c",
|
||||||
|
"libm/common/sf_remquo.c",
|
||||||
|
"libm/common/sf_round.c",
|
||||||
|
"libm/common/sf_scalbln.c",
|
||||||
|
"libm/common/sf_trunc.c",
|
||||||
|
"libm/common/sf_exp.c",
|
||||||
|
"libm/common/sf_exp2.c",
|
||||||
|
"libm/common/sf_exp2_data.c",
|
||||||
|
"libm/common/sf_log.c",
|
||||||
|
"libm/common/sf_log_data.c",
|
||||||
|
"libm/common/sf_log2.c",
|
||||||
|
"libm/common/sf_log2_data.c",
|
||||||
|
"libm/common/sf_pow_log2_data.c",
|
||||||
|
"libm/common/sf_pow.c",
|
||||||
|
|
||||||
|
"libm/common/s_finite.c",
|
||||||
|
"libm/common/s_copysign.c",
|
||||||
|
"libm/common/s_modf.c",
|
||||||
|
"libm/common/s_scalbn.c",
|
||||||
|
"libm/common/s_cbrt.c",
|
||||||
|
"libm/common/s_exp10.c",
|
||||||
|
"libm/common/s_expm1.c",
|
||||||
|
"libm/common/s_ilogb.c",
|
||||||
|
"libm/common/s_infinity.c",
|
||||||
|
"libm/common/s_isinf.c",
|
||||||
|
"libm/common/s_isinfd.c",
|
||||||
|
"libm/common/s_isnan.c",
|
||||||
|
"libm/common/s_isnand.c",
|
||||||
|
"libm/common/s_issignaling.c",
|
||||||
|
"libm/common/s_log1p.c",
|
||||||
|
"libm/common/s_nan.c",
|
||||||
|
"libm/common/s_nextafter.c",
|
||||||
|
"libm/common/s_pow10.c",
|
||||||
|
"libm/common/s_rint.c",
|
||||||
|
"libm/common/s_logb.c",
|
||||||
|
"libm/common/s_log2.c",
|
||||||
|
"libm/common/s_fdim.c",
|
||||||
|
"libm/common/s_fma.c",
|
||||||
|
"libm/common/s_fmax.c",
|
||||||
|
"libm/common/s_fmin.c",
|
||||||
|
"libm/common/s_fpclassify.c",
|
||||||
|
"libm/common/s_lrint.c",
|
||||||
|
"libm/common/s_llrint.c",
|
||||||
|
"libm/common/s_lround.c",
|
||||||
|
"libm/common/s_llround.c",
|
||||||
|
"libm/common/s_nearbyint.c",
|
||||||
|
"libm/common/s_remquo.c",
|
||||||
|
"libm/common/s_round.c",
|
||||||
|
"libm/common/s_scalbln.c",
|
||||||
|
"libm/common/s_signbit.c",
|
||||||
|
"libm/common/s_trunc.c",
|
||||||
|
"libm/common/exp.c",
|
||||||
|
"libm/common/exp2.c",
|
||||||
|
"libm/common/exp_data.c",
|
||||||
|
"libm/common/math_err_with_errno.c",
|
||||||
|
"libm/common/math_err_xflow.c",
|
||||||
|
"libm/common/math_err_uflow.c",
|
||||||
|
"libm/common/math_err_oflow.c",
|
||||||
|
"libm/common/math_err_divzero.c",
|
||||||
|
"libm/common/math_err_invalid.c",
|
||||||
|
"libm/common/math_err_may_uflow.c",
|
||||||
|
"libm/common/math_err_check_uflow.c",
|
||||||
|
"libm/common/math_err_check_oflow.c",
|
||||||
|
"libm/common/log.c",
|
||||||
|
"libm/common/log_data.c",
|
||||||
|
"libm/common/log2.c",
|
||||||
|
"libm/common/log2_data.c",
|
||||||
|
"libm/common/pow.c",
|
||||||
|
"libm/common/pow_log_data.c",
|
||||||
|
|
||||||
|
"libm/math/e_acos.c",
|
||||||
|
"libm/math/e_acosh.c",
|
||||||
|
"libm/math/e_asin.c",
|
||||||
|
"libm/math/e_atan2.c",
|
||||||
|
"libm/math/e_atanh.c",
|
||||||
|
"libm/math/e_cosh.c",
|
||||||
|
"libm/math/e_exp.c",
|
||||||
|
"libm/math/ef_acos.c",
|
||||||
|
"libm/math/ef_acosh.c",
|
||||||
|
"libm/math/ef_asin.c",
|
||||||
|
"libm/math/ef_atan2.c",
|
||||||
|
"libm/math/ef_atanh.c",
|
||||||
|
"libm/math/ef_cosh.c",
|
||||||
|
"libm/math/ef_exp.c",
|
||||||
|
"libm/math/ef_fmod.c",
|
||||||
|
"libm/math/ef_hypot.c",
|
||||||
|
"libm/math/ef_j0.c",
|
||||||
|
"libm/math/ef_j1.c",
|
||||||
|
"libm/math/ef_jn.c",
|
||||||
|
"libm/math/ef_lgamma.c",
|
||||||
|
"libm/math/ef_log10.c",
|
||||||
|
"libm/math/ef_log.c",
|
||||||
|
"libm/math/e_fmod.c",
|
||||||
|
"libm/math/ef_pow.c",
|
||||||
|
"libm/math/ef_remainder.c",
|
||||||
|
"libm/math/ef_rem_pio2.c",
|
||||||
|
"libm/math/ef_scalb.c",
|
||||||
|
"libm/math/ef_sinh.c",
|
||||||
|
"libm/math/ef_sqrt.c",
|
||||||
|
"libm/math/ef_tgamma.c",
|
||||||
|
"libm/math/e_hypot.c",
|
||||||
|
"libm/math/e_j0.c",
|
||||||
|
"libm/math/e_j1.c",
|
||||||
|
"libm/math/e_jn.c",
|
||||||
|
"libm/math/e_lgamma.c",
|
||||||
|
"libm/math/e_log10.c",
|
||||||
|
"libm/math/e_log.c",
|
||||||
|
"libm/math/e_pow.c",
|
||||||
|
"libm/math/e_remainder.c",
|
||||||
|
"libm/math/e_rem_pio2.c",
|
||||||
|
"libm/math/erf_lgamma.c",
|
||||||
|
"libm/math/er_lgamma.c",
|
||||||
|
"libm/math/e_scalb.c",
|
||||||
|
"libm/math/e_sinh.c",
|
||||||
|
"libm/math/e_sqrt.c",
|
||||||
|
"libm/math/e_tgamma.c",
|
||||||
|
"libm/math/s_asinh.c",
|
||||||
|
"libm/math/s_atan.c",
|
||||||
|
"libm/math/s_ceil.c",
|
||||||
|
"libm/math/s_cos.c",
|
||||||
|
"libm/math/s_erf.c",
|
||||||
|
"libm/math/s_fabs.c",
|
||||||
|
"libm/math/sf_asinh.c",
|
||||||
|
"libm/math/sf_atan.c",
|
||||||
|
"libm/math/sf_ceil.c",
|
||||||
|
"libm/math/sf_cos.c",
|
||||||
|
"libm/math/sf_erf.c",
|
||||||
|
"libm/math/sf_fabs.c",
|
||||||
|
"libm/math/sf_floor.c",
|
||||||
|
"libm/math/sf_frexp.c",
|
||||||
|
"libm/math/sf_ldexp.c",
|
||||||
|
"libm/math/s_floor.c",
|
||||||
|
"libm/math/s_frexp.c",
|
||||||
|
"libm/math/sf_signif.c",
|
||||||
|
"libm/math/sf_sin.c",
|
||||||
|
"libm/math/sf_tan.c",
|
||||||
|
"libm/math/sf_tanh.c",
|
||||||
|
"libm/math/s_ldexp.c",
|
||||||
|
"libm/math/s_signif.c",
|
||||||
|
"libm/math/s_sin.c",
|
||||||
|
"libm/math/s_tan.c",
|
||||||
|
"libm/math/s_tanh.c",
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -10,7 +10,7 @@ package builder
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ func convertELFFileToUF2File(infile, outfile string, uf2FamilyID string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return ioutil.WriteFile(outfile, output, 0644)
|
return os.WriteFile(outfile, output, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertBinToUF2 converts the binary bytes in input to UF2 formatted data.
|
// convertBinToUF2 converts the binary bytes in input to UF2 formatted data.
|
||||||
|
|||||||
+72
-31
@@ -32,6 +32,7 @@ type cgoPackage struct {
|
|||||||
errors []error
|
errors []error
|
||||||
currentDir string // current working directory
|
currentDir string // current working directory
|
||||||
packageDir string // full path to the package to process
|
packageDir string // full path to the package to process
|
||||||
|
importPath string
|
||||||
fset *token.FileSet
|
fset *token.FileSet
|
||||||
tokenFiles map[string]*token.File
|
tokenFiles map[string]*token.File
|
||||||
definedGlobally map[string]ast.Node
|
definedGlobally map[string]ast.Node
|
||||||
@@ -39,12 +40,15 @@ type cgoPackage struct {
|
|||||||
cflags []string // CFlags from #cgo lines
|
cflags []string // CFlags from #cgo lines
|
||||||
ldflags []string // LDFlags from #cgo lines
|
ldflags []string // LDFlags from #cgo lines
|
||||||
visitedFiles map[string][]byte
|
visitedFiles map[string][]byte
|
||||||
|
cgoHeaders []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// cgoFile holds information only for a single Go file (with one or more
|
// cgoFile holds information only for a single Go file (with one or more
|
||||||
// `import "C"` statements).
|
// `import "C"` statements).
|
||||||
type cgoFile struct {
|
type cgoFile struct {
|
||||||
*cgoPackage
|
*cgoPackage
|
||||||
|
file *ast.File
|
||||||
|
index int
|
||||||
defined map[string]ast.Node
|
defined map[string]ast.Node
|
||||||
names map[string]clangCursor
|
names map[string]clangCursor
|
||||||
}
|
}
|
||||||
@@ -158,9 +162,10 @@ func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
|||||||
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
|
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
|
||||||
// hashes of the accessed C header files. If there is one or more error, it
|
// hashes of the accessed C header files. If there is one or more error, it
|
||||||
// returns these in the []error slice but still modifies the AST.
|
// returns these in the []error slice but still modifies the AST.
|
||||||
func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
||||||
p := &cgoPackage{
|
p := &cgoPackage{
|
||||||
currentDir: dir,
|
currentDir: dir,
|
||||||
|
importPath: importPath,
|
||||||
fset: fset,
|
fset: fset,
|
||||||
tokenFiles: map[string]*token.File{},
|
tokenFiles: map[string]*token.File{},
|
||||||
definedGlobally: map[string]ast.Node{},
|
definedGlobally: map[string]ast.Node{},
|
||||||
@@ -210,13 +215,13 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Patch some types, for example *C.char in C.CString.
|
// Patch some types, for example *C.char in C.CString.
|
||||||
cf := p.newCGoFile()
|
cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
|
||||||
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
|
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
|
||||||
return cf.walker(cursor, nil)
|
return cf.walker(cursor, nil)
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
// Find `import "C"` C fragments in the file.
|
// Find `import "C"` C fragments in the file.
|
||||||
cgoHeaders := make([]string, len(files)) // combined CGo header fragment for each file
|
p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
var cgoHeader string
|
var cgoHeader string
|
||||||
for i := 0; i < len(f.Decls); i++ {
|
for i := 0; i < len(f.Decls); i++ {
|
||||||
@@ -275,7 +280,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
cgoHeader += fragment
|
cgoHeader += fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
cgoHeaders[i] = cgoHeader
|
p.cgoHeaders[i] = cgoHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define CFlags that will be used while parsing the package.
|
// Define CFlags that will be used while parsing the package.
|
||||||
@@ -289,7 +294,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve types such as C.int, C.longlong, etc from C.
|
// Retrieve types such as C.int, C.longlong, etc from C.
|
||||||
p.newCGoFile().readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
|
p.newCGoFile(nil, -1).readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
|
||||||
gen := &ast.GenDecl{
|
gen := &ast.GenDecl{
|
||||||
TokPos: token.NoPos,
|
TokPos: token.NoPos,
|
||||||
Tok: token.TYPE,
|
Tok: token.TYPE,
|
||||||
@@ -303,8 +308,8 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
|
|
||||||
// Process CGo imports for each file.
|
// Process CGo imports for each file.
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
cf := p.newCGoFile()
|
cf := p.newCGoFile(f, i)
|
||||||
cf.readNames(cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
cf.readNames(p.cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
||||||
for _, name := range builtinAliases {
|
for _, name := range builtinAliases {
|
||||||
// Names such as C.int should not be obtained from C.
|
// Names such as C.int should not be obtained from C.
|
||||||
// This works around an issue in picolibc that has `#define int`
|
// This works around an issue in picolibc that has `#define int`
|
||||||
@@ -320,12 +325,14 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
// Print the newly generated in-memory AST, for debugging.
|
// Print the newly generated in-memory AST, for debugging.
|
||||||
//ast.Print(fset, p.generated)
|
//ast.Print(fset, p.generated)
|
||||||
|
|
||||||
return p.generated, cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
return p.generated, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *cgoPackage) newCGoFile() *cgoFile {
|
func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
|
||||||
return &cgoFile{
|
return &cgoFile{
|
||||||
cgoPackage: p,
|
cgoPackage: p,
|
||||||
|
file: file,
|
||||||
|
index: index,
|
||||||
defined: make(map[string]ast.Node),
|
defined: make(map[string]ast.Node),
|
||||||
names: make(map[string]clangCursor),
|
names: make(map[string]clangCursor),
|
||||||
}
|
}
|
||||||
@@ -493,15 +500,15 @@ func (p *cgoPackage) makeUnionField(typ *elaboratedTypeInfo) *ast.StructType {
|
|||||||
// createUnionAccessor creates a function that returns a typed pointer to a
|
// createUnionAccessor creates a function that returns a typed pointer to a
|
||||||
// union field for each field in a union. For example:
|
// union field for each field in a union. For example:
|
||||||
//
|
//
|
||||||
// func (union *C.union_1) unionfield_d() *float64 {
|
// func (union *C.union_1) unionfield_d() *float64 {
|
||||||
// return (*float64)(unsafe.Pointer(&union.$union))
|
// return (*float64)(unsafe.Pointer(&union.$union))
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Where C.union_1 is defined as:
|
// Where C.union_1 is defined as:
|
||||||
//
|
//
|
||||||
// type C.union_1 struct{
|
// type C.union_1 struct{
|
||||||
// $union uint64
|
// $union uint64
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// The returned pointer can be used to get or set the field, or get the pointer
|
// The returned pointer can be used to get or set the field, or get the pointer
|
||||||
// to a subfield.
|
// to a subfield.
|
||||||
@@ -617,9 +624,9 @@ func (p *cgoPackage) createUnionAccessor(field *ast.Field, typeName string) {
|
|||||||
|
|
||||||
// createBitfieldGetter creates a bitfield getter function like the following:
|
// createBitfieldGetter creates a bitfield getter function like the following:
|
||||||
//
|
//
|
||||||
// func (s *C.struct_foo) bitfield_b() byte {
|
// func (s *C.struct_foo) bitfield_b() byte {
|
||||||
// return (s.__bitfield_1 >> 5) & 0x1
|
// return (s.__bitfield_1 >> 5) & 0x1
|
||||||
// }
|
// }
|
||||||
func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string) {
|
func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string) {
|
||||||
// The value to return from the getter.
|
// The value to return from the getter.
|
||||||
// Not complete: this is just an expression to get the complete field.
|
// Not complete: this is just an expression to get the complete field.
|
||||||
@@ -729,15 +736,15 @@ func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string
|
|||||||
|
|
||||||
// createBitfieldSetter creates a bitfield setter function like the following:
|
// createBitfieldSetter creates a bitfield setter function like the following:
|
||||||
//
|
//
|
||||||
// func (s *C.struct_foo) set_bitfield_b(value byte) {
|
// func (s *C.struct_foo) set_bitfield_b(value byte) {
|
||||||
// s.__bitfield_1 = s.__bitfield_1 ^ 0x60 | ((value & 1) << 5)
|
// s.__bitfield_1 = s.__bitfield_1 ^ 0x60 | ((value & 1) << 5)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Or the following:
|
// Or the following:
|
||||||
//
|
//
|
||||||
// func (s *C.struct_foo) set_bitfield_c(value byte) {
|
// func (s *C.struct_foo) set_bitfield_c(value byte) {
|
||||||
// s.__bitfield_1 = s.__bitfield_1 & 0x3f | (value << 6)
|
// s.__bitfield_1 = s.__bitfield_1 & 0x3f | (value << 6)
|
||||||
// }
|
// }
|
||||||
func (p *cgoPackage) createBitfieldSetter(bitfield bitfieldInfo, typeName string) {
|
func (p *cgoPackage) createBitfieldSetter(bitfield bitfieldInfo, typeName string) {
|
||||||
// The full field with all bitfields.
|
// The full field with all bitfields.
|
||||||
var field ast.Expr = &ast.SelectorExpr{
|
var field ast.Expr = &ast.SelectorExpr{
|
||||||
@@ -1117,8 +1124,11 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
|
|||||||
return alias
|
return alias
|
||||||
}
|
}
|
||||||
node := f.getASTDeclNode(name, found, iscall)
|
node := f.getASTDeclNode(name, found, iscall)
|
||||||
if _, ok := node.(*ast.FuncDecl); ok && !iscall {
|
if node, ok := node.(*ast.FuncDecl); ok {
|
||||||
return "C." + name + "$funcaddr"
|
if !iscall {
|
||||||
|
return node.Name.Name + "$funcaddr"
|
||||||
|
}
|
||||||
|
return node.Name.Name
|
||||||
}
|
}
|
||||||
return "C." + name
|
return "C." + name
|
||||||
}
|
}
|
||||||
@@ -1142,7 +1152,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
// Original cgo reports an error like
|
// Original cgo reports an error like
|
||||||
// cgo: inconsistent definitions for C.myint
|
// cgo: inconsistent definitions for C.myint
|
||||||
// which is far less helpful.
|
// which is far less helpful.
|
||||||
f.addError(getPos(node), "defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
|
f.addError(getPos(node), name+" defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
|
||||||
}
|
}
|
||||||
f.defined[name] = node
|
f.defined[name] = node
|
||||||
return node
|
return node
|
||||||
@@ -1150,11 +1160,39 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
|
|
||||||
// The declaration has no AST node. Create it now.
|
// The declaration has no AST node. Create it now.
|
||||||
f.defined[name] = nil
|
f.defined[name] = nil
|
||||||
node, elaboratedType := f.createASTNode(name, found)
|
node, extra := f.createASTNode(name, found)
|
||||||
f.defined[name] = node
|
f.defined[name] = node
|
||||||
f.definedGlobally[name] = node
|
|
||||||
switch node := node.(type) {
|
switch node := node.(type) {
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
|
if strings.HasPrefix(node.Doc.List[0].Text, "//export _Cgo_static_") {
|
||||||
|
// Static function. Only accessible in the current Go file.
|
||||||
|
globalName := strings.TrimPrefix(node.Doc.List[0].Text, "//export ")
|
||||||
|
// Make an alias. Normally this is done using the alias function
|
||||||
|
// attribute, but MacOS for some reason doesn't support this (even
|
||||||
|
// though the linker has support for aliases in the form of N_INDR).
|
||||||
|
// Therefore, create an actual function for MacOS.
|
||||||
|
var params []string
|
||||||
|
for _, param := range node.Type.Params.List {
|
||||||
|
params = append(params, param.Names[0].Name)
|
||||||
|
}
|
||||||
|
callInst := fmt.Sprintf("%s(%s);", name, strings.Join(params, ", "))
|
||||||
|
if node.Type.Results != nil {
|
||||||
|
callInst = "return " + callInst
|
||||||
|
}
|
||||||
|
aliasDeclaration := fmt.Sprintf(`
|
||||||
|
#ifdef __APPLE__
|
||||||
|
%s {
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
extern __typeof(%s) %s __attribute__((alias(%#v)));
|
||||||
|
#endif
|
||||||
|
`, extra.(string), callInst, name, globalName, name)
|
||||||
|
f.cgoHeaders[f.index] += "\n\n" + aliasDeclaration
|
||||||
|
} else {
|
||||||
|
// Regular (non-static) function.
|
||||||
|
f.definedGlobally[name] = node
|
||||||
|
}
|
||||||
f.generated.Decls = append(f.generated.Decls, node)
|
f.generated.Decls = append(f.generated.Decls, node)
|
||||||
// Also add a declaration like the following:
|
// Also add a declaration like the following:
|
||||||
// var C.foo$funcaddr unsafe.Pointer
|
// var C.foo$funcaddr unsafe.Pointer
|
||||||
@@ -1162,7 +1200,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
Tok: token.VAR,
|
Tok: token.VAR,
|
||||||
Specs: []ast.Spec{
|
Specs: []ast.Spec{
|
||||||
&ast.ValueSpec{
|
&ast.ValueSpec{
|
||||||
Names: []*ast.Ident{{Name: "C." + name + "$funcaddr"}},
|
Names: []*ast.Ident{{Name: node.Name.Name + "$funcaddr"}},
|
||||||
Type: &ast.SelectorExpr{
|
Type: &ast.SelectorExpr{
|
||||||
X: &ast.Ident{Name: "unsafe"},
|
X: &ast.Ident{Name: "unsafe"},
|
||||||
Sel: &ast.Ident{Name: "Pointer"},
|
Sel: &ast.Ident{Name: "Pointer"},
|
||||||
@@ -1171,8 +1209,10 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
|
f.definedGlobally[name] = node
|
||||||
f.generated.Decls = append(f.generated.Decls, node)
|
f.generated.Decls = append(f.generated.Decls, node)
|
||||||
case *ast.TypeSpec:
|
case *ast.TypeSpec:
|
||||||
|
f.definedGlobally[name] = node
|
||||||
f.generated.Decls = append(f.generated.Decls, &ast.GenDecl{
|
f.generated.Decls = append(f.generated.Decls, &ast.GenDecl{
|
||||||
Tok: token.TYPE,
|
Tok: token.TYPE,
|
||||||
Specs: []ast.Spec{node},
|
Specs: []ast.Spec{node},
|
||||||
@@ -1186,7 +1226,8 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
|||||||
|
|
||||||
// If this is a struct or union it may need bitfields or union accessor
|
// If this is a struct or union it may need bitfields or union accessor
|
||||||
// methods.
|
// methods.
|
||||||
if elaboratedType != nil {
|
switch elaboratedType := extra.(type) {
|
||||||
|
case *elaboratedTypeInfo:
|
||||||
// Add struct bitfields.
|
// Add struct bitfields.
|
||||||
for _, bitfield := range elaboratedType.bitfields {
|
for _, bitfield := range elaboratedType.bitfields {
|
||||||
f.createBitfieldGetter(bitfield, "C."+name)
|
f.createBitfieldGetter(bitfield, "C."+name)
|
||||||
|
|||||||
+4
-19
@@ -5,12 +5,11 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/build"
|
|
||||||
"go/format"
|
"go/format"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -40,20 +39,6 @@ func TestCGo(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
name := name // avoid a race condition
|
name := name // avoid a race condition
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
// Skip tests that require specific Go version.
|
|
||||||
if name == "errors" {
|
|
||||||
ok := false
|
|
||||||
for _, version := range build.Default.ReleaseTags {
|
|
||||||
if version == "go1.16" {
|
|
||||||
ok = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
t.Skip("Results for errors test are only valid for Go 1.16+")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the AST in memory.
|
// Read the AST in memory.
|
||||||
path := filepath.Join("testdata", name+".go")
|
path := filepath.Join("testdata", name+".go")
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
@@ -63,7 +48,7 @@ func TestCGo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process the AST with CGo.
|
// Process the AST with CGo.
|
||||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags, "")
|
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags, "")
|
||||||
|
|
||||||
// Check the AST for type errors.
|
// Check the AST for type errors.
|
||||||
var typecheckErrors []error
|
var typecheckErrors []error
|
||||||
@@ -107,7 +92,7 @@ func TestCGo(t *testing.T) {
|
|||||||
|
|
||||||
// Read the file with the expected output, to compare against.
|
// Read the file with the expected output, to compare against.
|
||||||
outfile := filepath.Join("testdata", name+".out.go")
|
outfile := filepath.Join("testdata", name+".out.go")
|
||||||
expectedBytes, err := ioutil.ReadFile(outfile)
|
expectedBytes, err := os.ReadFile(outfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not read expected output: %v", err)
|
t.Fatalf("could not read expected output: %v", err)
|
||||||
}
|
}
|
||||||
@@ -118,7 +103,7 @@ func TestCGo(t *testing.T) {
|
|||||||
// It is not. Test failed.
|
// It is not. Test failed.
|
||||||
if *flagUpdate {
|
if *flagUpdate {
|
||||||
// Update the file with the expected data.
|
// Update the file with the expected data.
|
||||||
err := ioutil.WriteFile(outfile, []byte(actual), 0666)
|
err := os.WriteFile(outfile, []byte(actual), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("could not write updated output file:", err)
|
t.Error("could not write updated output file:", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-4
@@ -4,7 +4,9 @@ package cgo
|
|||||||
// modification. It does not touch the AST itself.
|
// modification. It does not touch the AST itself.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/scanner"
|
"go/scanner"
|
||||||
@@ -43,6 +45,8 @@ typedef struct {
|
|||||||
GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);
|
GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);
|
||||||
unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);
|
unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);
|
||||||
CXString tinygo_clang_getCursorSpelling(GoCXCursor c);
|
CXString tinygo_clang_getCursorSpelling(GoCXCursor c);
|
||||||
|
CXString tinygo_clang_getCursorPrettyPrinted(GoCXCursor c, CXPrintingPolicy Policy);
|
||||||
|
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(GoCXCursor c);
|
||||||
enum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c);
|
enum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c);
|
||||||
CXType tinygo_clang_getCursorType(GoCXCursor c);
|
CXType tinygo_clang_getCursorType(GoCXCursor c);
|
||||||
GoCXCursor tinygo_clang_getTypeDeclaration(CXType t);
|
GoCXCursor tinygo_clang_getTypeDeclaration(CXType t);
|
||||||
@@ -50,6 +54,7 @@ CXType tinygo_clang_getTypedefDeclUnderlyingType(GoCXCursor c);
|
|||||||
CXType tinygo_clang_getCursorResultType(GoCXCursor c);
|
CXType tinygo_clang_getCursorResultType(GoCXCursor c);
|
||||||
int tinygo_clang_Cursor_getNumArguments(GoCXCursor c);
|
int tinygo_clang_Cursor_getNumArguments(GoCXCursor c);
|
||||||
GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);
|
GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);
|
||||||
|
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(GoCXCursor c);
|
||||||
CXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c);
|
CXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c);
|
||||||
CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c);
|
CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c);
|
||||||
CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);
|
CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);
|
||||||
@@ -189,7 +194,7 @@ func (f *cgoFile) readNames(fragment string, cflags []string, filename string, c
|
|||||||
|
|
||||||
// Convert the AST node under the given Clang cursor to a Go AST node and return
|
// Convert the AST node under the given Clang cursor to a Go AST node and return
|
||||||
// it.
|
// it.
|
||||||
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaboratedTypeInfo) {
|
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
|
||||||
kind := C.tinygo_clang_getCursorKind(c)
|
kind := C.tinygo_clang_getCursorKind(c)
|
||||||
pos := f.getCursorPosition(c)
|
pos := f.getCursorPosition(c)
|
||||||
switch kind {
|
switch kind {
|
||||||
@@ -200,19 +205,43 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaborat
|
|||||||
Kind: ast.Fun,
|
Kind: ast.Fun,
|
||||||
Name: "C." + name,
|
Name: "C." + name,
|
||||||
}
|
}
|
||||||
|
exportName := name
|
||||||
|
localName := name
|
||||||
|
var stringSignature string
|
||||||
|
if C.tinygo_clang_Cursor_getStorageClass(c) == C.CX_SC_Static {
|
||||||
|
// A static function is assigned a globally unique symbol name based
|
||||||
|
// on the file path (like _Cgo_static_2d09198adbf58f4f4655_foo) and
|
||||||
|
// has a different Go name in the form of C.foo!symbols.go instead
|
||||||
|
// of just C.foo.
|
||||||
|
path := f.importPath + "/" + filepath.Base(f.fset.File(f.file.Pos()).Name())
|
||||||
|
staticIDBuf := sha256.Sum256([]byte(path))
|
||||||
|
staticID := hex.EncodeToString(staticIDBuf[:10])
|
||||||
|
exportName = "_Cgo_static_" + staticID + "_" + name
|
||||||
|
localName = name + "!" + filepath.Base(path)
|
||||||
|
|
||||||
|
// Create a signature. This is necessary for MacOS to forward the
|
||||||
|
// call, because MacOS doesn't support aliases like ELF and PE do.
|
||||||
|
// (There is N_INDR but __attribute__((alias("..."))) doesn't work).
|
||||||
|
policy := C.tinygo_clang_getCursorPrintingPolicy(c)
|
||||||
|
defer C.clang_PrintingPolicy_dispose(policy)
|
||||||
|
C.clang_PrintingPolicy_setProperty(policy, C.CXPrintingPolicy_TerseOutput, 1)
|
||||||
|
stringSignature = getString(C.tinygo_clang_getCursorPrettyPrinted(c, policy))
|
||||||
|
stringSignature = strings.Replace(stringSignature, " "+name+"(", " "+exportName+"(", 1)
|
||||||
|
stringSignature = strings.TrimPrefix(stringSignature, "static ")
|
||||||
|
}
|
||||||
args := make([]*ast.Field, numArgs)
|
args := make([]*ast.Field, numArgs)
|
||||||
decl := &ast.FuncDecl{
|
decl := &ast.FuncDecl{
|
||||||
Doc: &ast.CommentGroup{
|
Doc: &ast.CommentGroup{
|
||||||
List: []*ast.Comment{
|
List: []*ast.Comment{
|
||||||
{
|
{
|
||||||
Slash: pos - 1,
|
Slash: pos - 1,
|
||||||
Text: "//export " + name,
|
Text: "//export " + exportName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Name: &ast.Ident{
|
Name: &ast.Ident{
|
||||||
NamePos: pos,
|
NamePos: pos,
|
||||||
Name: "C." + name,
|
Name: "C." + localName,
|
||||||
Obj: obj,
|
Obj: obj,
|
||||||
},
|
},
|
||||||
Type: &ast.FuncType{
|
Type: &ast.FuncType{
|
||||||
@@ -263,7 +292,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaborat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj.Decl = decl
|
obj.Decl = decl
|
||||||
return decl, nil
|
return decl, stringSignature
|
||||||
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
|
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
|
||||||
typ := f.makeASTRecordType(c, pos)
|
typ := f.makeASTRecordType(c, pos)
|
||||||
typeName := "C." + name
|
typeName := "C." + name
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
//go:build !byollvm && llvm13
|
|
||||||
// +build !byollvm,llvm13
|
|
||||||
|
|
||||||
package cgo
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo linux CFLAGS: -I/usr/lib/llvm-13/include
|
|
||||||
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@13/include
|
|
||||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@13/include
|
|
||||||
#cgo freebsd CFLAGS: -I/usr/local/llvm13/include
|
|
||||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-13/lib -lclang
|
|
||||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@13/lib -lclang -lffi
|
|
||||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@13/lib -lclang -lffi
|
|
||||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm13/lib -lclang
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build !byollvm && !llvm13
|
//go:build !byollvm
|
||||||
// +build !byollvm,!llvm13
|
// +build !byollvm
|
||||||
|
|
||||||
package cgo
|
package cgo
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,14 @@ CXString tinygo_clang_getCursorSpelling(CXCursor c) {
|
|||||||
return clang_getCursorSpelling(c);
|
return clang_getCursorSpelling(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CXString tinygo_clang_getCursorPrettyPrinted(CXCursor c, CXPrintingPolicy policy) {
|
||||||
|
return clang_getCursorPrettyPrinted(c, policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(CXCursor c) {
|
||||||
|
return clang_getCursorPrintingPolicy(c);
|
||||||
|
}
|
||||||
|
|
||||||
enum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) {
|
enum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) {
|
||||||
return clang_getCursorKind(c);
|
return clang_getCursorKind(c);
|
||||||
}
|
}
|
||||||
@@ -45,6 +53,10 @@ CXCursor tinygo_clang_Cursor_getArgument(CXCursor c, unsigned i) {
|
|||||||
return clang_Cursor_getArgument(c, i);
|
return clang_Cursor_getArgument(c, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(CXCursor c) {
|
||||||
|
return clang_Cursor_getStorageClass(c);
|
||||||
|
}
|
||||||
|
|
||||||
CXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) {
|
CXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) {
|
||||||
return clang_getCursorLocation(c);
|
return clang_getCursorLocation(c);
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
@@ -5,6 +5,7 @@ package main
|
|||||||
int foo(int a, int b);
|
int foo(int a, int b);
|
||||||
void variadic0();
|
void variadic0();
|
||||||
void variadic2(int x, int y, ...);
|
void variadic2(int x, int y, ...);
|
||||||
|
static void staticfunc(int x);
|
||||||
|
|
||||||
// Global variable signatures.
|
// Global variable signatures.
|
||||||
extern int someValue;
|
extern int someValue;
|
||||||
@@ -16,6 +17,7 @@ func accessFunctions() {
|
|||||||
C.foo(3, 4)
|
C.foo(3, 4)
|
||||||
C.variadic0()
|
C.variadic0()
|
||||||
C.variadic2(3, 5)
|
C.variadic2(3, 5)
|
||||||
|
C.staticfunc(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func accessGlobals() {
|
func accessGlobals() {
|
||||||
|
|||||||
Vendored
+5
@@ -55,5 +55,10 @@ func C.variadic2(x C.int, y C.int)
|
|||||||
|
|
||||||
var C.variadic2$funcaddr unsafe.Pointer
|
var C.variadic2$funcaddr unsafe.Pointer
|
||||||
|
|
||||||
|
//export _Cgo_static_173c95a79b6df1980521_staticfunc
|
||||||
|
func C.staticfunc!symbols.go(x C.int)
|
||||||
|
|
||||||
|
var C.staticfunc!symbols.go$funcaddr unsafe.Pointer
|
||||||
|
|
||||||
//go:extern someValue
|
//go:extern someValue
|
||||||
var C.someValue C.int
|
var C.someValue C.int
|
||||||
|
|||||||
+20
-6
@@ -73,9 +73,7 @@ func (c *Config) BuildTags() []string {
|
|||||||
for i := 1; i <= c.GoMinorVersion; i++ {
|
for i := 1; i <= c.GoMinorVersion; i++ {
|
||||||
tags = append(tags, fmt.Sprintf("go1.%d", i))
|
tags = append(tags, fmt.Sprintf("go1.%d", i))
|
||||||
}
|
}
|
||||||
if extraTags := strings.Fields(c.Options.Tags); len(extraTags) != 0 {
|
tags = append(tags, c.Options.Tags...)
|
||||||
tags = append(tags, extraTags...)
|
|
||||||
}
|
|
||||||
return tags
|
return tags
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,6 +175,15 @@ func (c *Config) AutomaticStackSize() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StackSize returns the default stack size to be used for goroutines, if the
|
||||||
|
// stack size could not be determined automatically at compile time.
|
||||||
|
func (c *Config) StackSize() uint64 {
|
||||||
|
if c.Options.StackSize != 0 {
|
||||||
|
return c.Options.StackSize
|
||||||
|
}
|
||||||
|
return c.Target.DefaultStackSize
|
||||||
|
}
|
||||||
|
|
||||||
// UseThinLTO returns whether ThinLTO should be used for the given target. Some
|
// UseThinLTO returns whether ThinLTO should be used for the given target. Some
|
||||||
// targets (such as wasm) are not yet supported.
|
// targets (such as wasm) are not yet supported.
|
||||||
// We should try and remove as many exceptions as possible in the future, so
|
// We should try and remove as many exceptions as possible in the future, so
|
||||||
@@ -442,13 +449,13 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
|
|||||||
if openocdInterface == "" {
|
if openocdInterface == "" {
|
||||||
return nil, errors.New("OpenOCD programmer not set")
|
return nil, errors.New("OpenOCD programmer not set")
|
||||||
}
|
}
|
||||||
if !regexp.MustCompile("^[\\p{L}0-9_-]+$").MatchString(openocdInterface) {
|
if !regexp.MustCompile(`^[\p{L}0-9_-]+$`).MatchString(openocdInterface) {
|
||||||
return nil, fmt.Errorf("OpenOCD programmer has an invalid name: %#v", openocdInterface)
|
return nil, fmt.Errorf("OpenOCD programmer has an invalid name: %#v", openocdInterface)
|
||||||
}
|
}
|
||||||
if c.Target.OpenOCDTarget == "" {
|
if c.Target.OpenOCDTarget == "" {
|
||||||
return nil, errors.New("OpenOCD chip not set")
|
return nil, errors.New("OpenOCD chip not set")
|
||||||
}
|
}
|
||||||
if !regexp.MustCompile("^[\\p{L}0-9_-]+$").MatchString(c.Target.OpenOCDTarget) {
|
if !regexp.MustCompile(`^[\p{L}0-9_-]+$`).MatchString(c.Target.OpenOCDTarget) {
|
||||||
return nil, fmt.Errorf("OpenOCD target has an invalid name: %#v", c.Target.OpenOCDTarget)
|
return nil, fmt.Errorf("OpenOCD target has an invalid name: %#v", c.Target.OpenOCDTarget)
|
||||||
}
|
}
|
||||||
if c.Target.OpenOCDTransport != "" && c.Target.OpenOCDTransport != "swd" {
|
if c.Target.OpenOCDTransport != "" && c.Target.OpenOCDTransport != "swd" {
|
||||||
@@ -459,7 +466,14 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
|
|||||||
args = append(args, "-c", cmd)
|
args = append(args, "-c", cmd)
|
||||||
}
|
}
|
||||||
if c.Target.OpenOCDTransport != "" {
|
if c.Target.OpenOCDTransport != "" {
|
||||||
args = append(args, "-c", "transport select "+c.Target.OpenOCDTransport)
|
transport := c.Target.OpenOCDTransport
|
||||||
|
if transport == "swd" {
|
||||||
|
switch openocdInterface {
|
||||||
|
case "stlink-dap":
|
||||||
|
transport = "dapdirect_swd"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args = append(args, "-c", "transport select "+transport)
|
||||||
}
|
}
|
||||||
args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
|
args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
|
||||||
return args, nil
|
return args, nil
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -27,8 +28,10 @@ type Options struct {
|
|||||||
GC string
|
GC string
|
||||||
PanicStrategy string
|
PanicStrategy string
|
||||||
Scheduler string
|
Scheduler string
|
||||||
|
StackSize uint64 // goroutine stack size (if none could be automatically determined)
|
||||||
Serial string
|
Serial string
|
||||||
Work bool // -work flag to print temporary build directory
|
Work bool // -work flag to print temporary build directory
|
||||||
|
InterpTimeout time.Duration
|
||||||
PrintIR bool
|
PrintIR bool
|
||||||
DumpSSA bool
|
DumpSSA bool
|
||||||
VerifyIR bool
|
VerifyIR bool
|
||||||
@@ -38,7 +41,7 @@ type Options struct {
|
|||||||
PrintSizes string
|
PrintSizes string
|
||||||
PrintAllocs *regexp.Regexp // regexp string
|
PrintAllocs *regexp.Regexp // regexp string
|
||||||
PrintStacks bool
|
PrintStacks bool
|
||||||
Tags string
|
Tags []string
|
||||||
WasmAbi string
|
WasmAbi string
|
||||||
GlobalValues map[string]map[string]string // map[pkgpath]map[varname]value
|
GlobalValues map[string]map[string]string // map[pkgpath]map[varname]value
|
||||||
TestConfig TestConfig
|
TestConfig TestConfig
|
||||||
@@ -47,6 +50,8 @@ type Options struct {
|
|||||||
LLVMFeatures string
|
LLVMFeatures string
|
||||||
Directory string
|
Directory string
|
||||||
PrintJSON bool
|
PrintJSON bool
|
||||||
|
Monitor bool
|
||||||
|
BaudRate int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify performs a validation on the given options, raising an error if options are not valid.
|
// Verify performs a validation on the given options, raising an error if options are not valid.
|
||||||
|
|||||||
+28
-13
@@ -65,7 +65,7 @@ type TargetSpec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// overrideProperties overrides all properties that are set in child into itself using reflection.
|
// overrideProperties overrides all properties that are set in child into itself using reflection.
|
||||||
func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
|
func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
|
||||||
specType := reflect.TypeOf(spec).Elem()
|
specType := reflect.TypeOf(spec).Elem()
|
||||||
specValue := reflect.ValueOf(spec).Elem()
|
specValue := reflect.ValueOf(spec).Elem()
|
||||||
childValue := reflect.ValueOf(child).Elem()
|
childValue := reflect.ValueOf(child).Elem()
|
||||||
@@ -88,12 +88,22 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
|
|||||||
if !src.IsNil() {
|
if !src.IsNil() {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
}
|
}
|
||||||
case reflect.Slice: // for slices, append the field
|
case reflect.Slice: // for slices, append the field and check for duplicates
|
||||||
dst.Set(reflect.AppendSlice(dst, src))
|
dst.Set(reflect.AppendSlice(dst, src))
|
||||||
|
for i := 0; i < dst.Len(); i++ {
|
||||||
|
v := dst.Index(i).String()
|
||||||
|
for j := i + 1; j < dst.Len(); j++ {
|
||||||
|
w := dst.Index(j).String()
|
||||||
|
if v == w {
|
||||||
|
return fmt.Errorf("duplicate value '%s' in field %s", v, field.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic("unknown field type : " + kind.String())
|
return fmt.Errorf("unknown field type: %s", kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// load reads a target specification from the JSON in the given io.Reader. It
|
// load reads a target specification from the JSON in the given io.Reader. It
|
||||||
@@ -108,10 +118,10 @@ func (spec *TargetSpec) load(r io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// loadFromGivenStr loads the TargetSpec from the given string that could be:
|
// loadFromGivenStr loads the TargetSpec from the given string that could be:
|
||||||
// - targets/ directory inside the compiler sources
|
// - targets/ directory inside the compiler sources
|
||||||
// - a relative or absolute path to custom (project specific) target specification .json file;
|
// - a relative or absolute path to custom (project specific) target specification .json file;
|
||||||
// the Inherits[] could contain the files from target folder (ex. stm32f4disco)
|
// the Inherits[] could contain the files from target folder (ex. stm32f4disco)
|
||||||
// as well as path to custom files (ex. myAwesomeProject.json)
|
// as well as path to custom files (ex. myAwesomeProject.json)
|
||||||
func (spec *TargetSpec) loadFromGivenStr(str string) error {
|
func (spec *TargetSpec) loadFromGivenStr(str string) error {
|
||||||
path := ""
|
path := ""
|
||||||
if strings.HasSuffix(str, ".json") {
|
if strings.HasSuffix(str, ".json") {
|
||||||
@@ -141,11 +151,17 @@ func (spec *TargetSpec) resolveInherits() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
newSpec.overrideProperties(subtarget)
|
err = newSpec.overrideProperties(subtarget)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When all properties are loaded, make sure they are properly inherited.
|
// When all properties are loaded, make sure they are properly inherited.
|
||||||
newSpec.overrideProperties(spec)
|
err := newSpec.overrideProperties(spec)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
*spec = *newSpec
|
*spec = *newSpec
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -193,11 +209,10 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
|
|||||||
// triples for historical reasons) have the form:
|
// triples for historical reasons) have the form:
|
||||||
// arch-vendor-os-environment
|
// arch-vendor-os-environment
|
||||||
target := llvmarch + "-unknown-" + llvmos
|
target := llvmarch + "-unknown-" + llvmos
|
||||||
if options.GOARCH == "arm" {
|
|
||||||
target += "-gnueabihf"
|
|
||||||
}
|
|
||||||
if options.GOOS == "windows" {
|
if options.GOOS == "windows" {
|
||||||
target += "-gnu"
|
target += "-gnu"
|
||||||
|
} else if options.GOARCH == "arm" {
|
||||||
|
target += "-gnueabihf"
|
||||||
}
|
}
|
||||||
return defaultTarget(options.GOOS, options.GOARCH, target)
|
return defaultTarget(options.GOOS, options.GOARCH, target)
|
||||||
}
|
}
|
||||||
@@ -213,7 +228,7 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
|
|||||||
// it includes all parents as specified in the "inherits" key.
|
// it includes all parents as specified in the "inherits" key.
|
||||||
err = spec.resolveInherits()
|
err = spec.resolveInherits()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("%s : %w", options.Target, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if spec.Scheduler == "asyncify" {
|
if spec.Scheduler == "asyncify" {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package compileopts
|
package compileopts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"errors"
|
||||||
|
"io/fs"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -17,7 +18,7 @@ func TestLoadTarget(t *testing.T) {
|
|||||||
t.Error("LoadTarget should have failed with non existing target")
|
t.Error("LoadTarget should have failed with non existing target")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !os.IsNotExist(err) {
|
if !errors.Is(err, fs.ErrNotExist) {
|
||||||
t.Error("LoadTarget failed for wrong reason:", err)
|
t.Error("LoadTarget failed for wrong reason:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-43
@@ -16,6 +16,8 @@ import "tinygo.org/x/go-llvm"
|
|||||||
|
|
||||||
var stdlibAliases = map[string]string{
|
var stdlibAliases = map[string]string{
|
||||||
// crypto packages
|
// crypto packages
|
||||||
|
"crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric",
|
||||||
|
"crypto/ed25519/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric",
|
||||||
"crypto/md5.block": "crypto/md5.blockGeneric",
|
"crypto/md5.block": "crypto/md5.blockGeneric",
|
||||||
"crypto/sha1.block": "crypto/sha1.blockGeneric",
|
"crypto/sha1.block": "crypto/sha1.blockGeneric",
|
||||||
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
|
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
|
||||||
@@ -23,53 +25,10 @@ var stdlibAliases = map[string]string{
|
|||||||
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
|
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
|
||||||
|
|
||||||
// math package
|
// math package
|
||||||
"math.Asin": "math.asin",
|
|
||||||
"math.Asinh": "math.asinh",
|
|
||||||
"math.Acos": "math.acos",
|
|
||||||
"math.Acosh": "math.acosh",
|
|
||||||
"math.Atan": "math.atan",
|
|
||||||
"math.Atanh": "math.atanh",
|
|
||||||
"math.Atan2": "math.atan2",
|
|
||||||
"math.Cbrt": "math.cbrt",
|
|
||||||
"math.Ceil": "math.ceil",
|
|
||||||
"math.archCeil": "math.ceil",
|
|
||||||
"math.Cos": "math.cos",
|
|
||||||
"math.Cosh": "math.cosh",
|
|
||||||
"math.Erf": "math.erf",
|
|
||||||
"math.Erfc": "math.erfc",
|
|
||||||
"math.Exp": "math.exp",
|
|
||||||
"math.archExp": "math.exp",
|
|
||||||
"math.Expm1": "math.expm1",
|
|
||||||
"math.Exp2": "math.exp2",
|
|
||||||
"math.archExp2": "math.exp2",
|
|
||||||
"math.Floor": "math.floor",
|
|
||||||
"math.archFloor": "math.floor",
|
|
||||||
"math.Frexp": "math.frexp",
|
|
||||||
"math.Hypot": "math.hypot",
|
|
||||||
"math.archHypot": "math.hypot",
|
"math.archHypot": "math.hypot",
|
||||||
"math.Ldexp": "math.ldexp",
|
|
||||||
"math.Log": "math.log",
|
|
||||||
"math.archLog": "math.log",
|
|
||||||
"math.Log1p": "math.log1p",
|
|
||||||
"math.Log10": "math.log10",
|
|
||||||
"math.Log2": "math.log2",
|
|
||||||
"math.Max": "math.max",
|
|
||||||
"math.archMax": "math.max",
|
"math.archMax": "math.max",
|
||||||
"math.Min": "math.min",
|
|
||||||
"math.archMin": "math.min",
|
"math.archMin": "math.min",
|
||||||
"math.Mod": "math.mod",
|
|
||||||
"math.Modf": "math.modf",
|
|
||||||
"math.archModf": "math.modf",
|
"math.archModf": "math.modf",
|
||||||
"math.Pow": "math.pow",
|
|
||||||
"math.Remainder": "math.remainder",
|
|
||||||
"math.Sin": "math.sin",
|
|
||||||
"math.Sinh": "math.sinh",
|
|
||||||
"math.Sqrt": "math.sqrt",
|
|
||||||
"math.archSqrt": "math.sqrt",
|
|
||||||
"math.Tan": "math.tan",
|
|
||||||
"math.Tanh": "math.tanh",
|
|
||||||
"math.Trunc": "math.trunc",
|
|
||||||
"math.archTrunc": "math.trunc",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// createAlias implements the function (in the builder) as a call to the alias
|
// createAlias implements the function (in the builder) as a call to the alias
|
||||||
|
|||||||
+22
-23
@@ -22,10 +22,6 @@ import (
|
|||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var typeParamUnderlyingType = func(t types.Type) types.Type {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
llvm.InitializeAllTargets()
|
llvm.InitializeAllTargets()
|
||||||
llvm.InitializeAllTargetMCs()
|
llvm.InitializeAllTargetMCs()
|
||||||
@@ -345,7 +341,6 @@ func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
|
|||||||
// makeLLVMType creates a LLVM type for a Go type. Don't call this, use
|
// makeLLVMType creates a LLVM type for a Go type. Don't call this, use
|
||||||
// getLLVMType instead.
|
// getLLVMType instead.
|
||||||
func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
|
func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
|
||||||
goType = typeParamUnderlyingType(goType)
|
|
||||||
switch typ := goType.(type) {
|
switch typ := goType.(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elemType := c.getLLVMType(typ.Elem())
|
elemType := c.getLLVMType(typ.Elem())
|
||||||
@@ -420,6 +415,8 @@ func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
|
|||||||
members[i] = c.getLLVMType(typ.Field(i).Type())
|
members[i] = c.getLLVMType(typ.Field(i).Type())
|
||||||
}
|
}
|
||||||
return c.ctx.StructType(members, false)
|
return c.ctx.StructType(members, false)
|
||||||
|
case *types.TypeParam:
|
||||||
|
return c.getLLVMType(typ.Underlying())
|
||||||
case *types.Tuple:
|
case *types.Tuple:
|
||||||
members := make([]llvm.Type, typ.Len())
|
members := make([]llvm.Type, typ.Len())
|
||||||
for i := 0; i < typ.Len(); i++ {
|
for i := 0; i < typ.Len(); i++ {
|
||||||
@@ -455,7 +452,6 @@ func (c *compilerContext) getDIType(typ types.Type) llvm.Metadata {
|
|||||||
// createDIType creates a new DWARF type. Don't call this function directly,
|
// createDIType creates a new DWARF type. Don't call this function directly,
|
||||||
// call getDIType instead.
|
// call getDIType instead.
|
||||||
func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
||||||
typ = typeParamUnderlyingType(typ)
|
|
||||||
llvmType := c.getLLVMType(typ)
|
llvmType := c.getLLVMType(typ)
|
||||||
sizeInBytes := c.targetData.TypeAllocSize(llvmType)
|
sizeInBytes := c.targetData.TypeAllocSize(llvmType)
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
@@ -619,6 +615,8 @@ func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
|||||||
})
|
})
|
||||||
temporaryMDNode.ReplaceAllUsesWith(md)
|
temporaryMDNode.ReplaceAllUsesWith(md)
|
||||||
return md
|
return md
|
||||||
|
case *types.TypeParam:
|
||||||
|
return c.getDIType(typ.Underlying())
|
||||||
default:
|
default:
|
||||||
panic("unknown type while generating DWARF debug type: " + typ.String())
|
panic("unknown type while generating DWARF debug type: " + typ.String())
|
||||||
}
|
}
|
||||||
@@ -688,7 +686,7 @@ func (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata {
|
|||||||
Name: param.Name(),
|
Name: param.Name(),
|
||||||
File: b.getDIFile(pos.Filename),
|
File: b.getDIFile(pos.Filename),
|
||||||
Line: pos.Line,
|
Line: pos.Line,
|
||||||
Type: b.getDIType(variable.Type()),
|
Type: b.getDIType(param.Type()),
|
||||||
AlwaysPreserve: true,
|
AlwaysPreserve: true,
|
||||||
ArgNo: i + 1,
|
ArgNo: i + 1,
|
||||||
})
|
})
|
||||||
@@ -792,6 +790,12 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
|
|||||||
}
|
}
|
||||||
// Create the function definition.
|
// Create the function definition.
|
||||||
b := newBuilder(c, irbuilder, member)
|
b := newBuilder(c, irbuilder, member)
|
||||||
|
if _, ok := mathToLLVMMapping[member.RelString(nil)]; ok {
|
||||||
|
// The body of this function (if there is one) is ignored and
|
||||||
|
// replaced with a LLVM intrinsic call.
|
||||||
|
b.defineMathOp()
|
||||||
|
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()
|
||||||
@@ -1026,7 +1030,7 @@ func (c *compilerContext) getEmbedFileString(file *loader.EmbedFile) llvm.Value
|
|||||||
// parameters, create basic blocks, and set up debug information.
|
// parameters, create basic blocks, and set up debug information.
|
||||||
// This is separated out from createFunction() so that it is also usable to
|
// This is separated out from createFunction() so that it is also usable to
|
||||||
// define compiler intrinsics like the atomic operations in sync/atomic.
|
// define compiler intrinsics like the atomic operations in sync/atomic.
|
||||||
func (b *builder) createFunctionStart() {
|
func (b *builder) createFunctionStart(intrinsic bool) {
|
||||||
if b.DumpSSA {
|
if b.DumpSSA {
|
||||||
fmt.Printf("\nfunc %s:\n", b.fn)
|
fmt.Printf("\nfunc %s:\n", b.fn)
|
||||||
}
|
}
|
||||||
@@ -1099,20 +1103,20 @@ func (b *builder) createFunctionStart() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pre-create all basic blocks in the function.
|
// Pre-create all basic blocks in the function.
|
||||||
for _, block := range b.fn.DomPreorder() {
|
|
||||||
llvmBlock := b.ctx.AddBasicBlock(b.llvmFn, block.Comment)
|
|
||||||
b.blockEntries[block] = llvmBlock
|
|
||||||
b.blockExits[block] = llvmBlock
|
|
||||||
}
|
|
||||||
var entryBlock llvm.BasicBlock
|
var entryBlock llvm.BasicBlock
|
||||||
if len(b.fn.Blocks) != 0 {
|
if intrinsic {
|
||||||
// Normal functions have an entry block.
|
|
||||||
entryBlock = b.blockEntries[b.fn.Blocks[0]]
|
|
||||||
} else {
|
|
||||||
// This function isn't defined in Go SSA. It is probably a compiler
|
// This function isn't defined in Go SSA. It is probably a compiler
|
||||||
// intrinsic (like an atomic operation). Create the entry block
|
// intrinsic (like an atomic operation). Create the entry block
|
||||||
// manually.
|
// manually.
|
||||||
entryBlock = b.ctx.AddBasicBlock(b.llvmFn, "entry")
|
entryBlock = b.ctx.AddBasicBlock(b.llvmFn, "entry")
|
||||||
|
} else {
|
||||||
|
for _, block := range b.fn.DomPreorder() {
|
||||||
|
llvmBlock := b.ctx.AddBasicBlock(b.llvmFn, block.Comment)
|
||||||
|
b.blockEntries[block] = llvmBlock
|
||||||
|
b.blockExits[block] = llvmBlock
|
||||||
|
}
|
||||||
|
// Normal functions have an entry block.
|
||||||
|
entryBlock = b.blockEntries[b.fn.Blocks[0]]
|
||||||
}
|
}
|
||||||
b.SetInsertPointAtEnd(entryBlock)
|
b.SetInsertPointAtEnd(entryBlock)
|
||||||
|
|
||||||
@@ -1194,7 +1198,7 @@ func (b *builder) createFunctionStart() {
|
|||||||
// function must not yet be defined, otherwise this function will create a
|
// function must not yet be defined, otherwise this function will create a
|
||||||
// diagnostic.
|
// diagnostic.
|
||||||
func (b *builder) createFunction() {
|
func (b *builder) createFunction() {
|
||||||
b.createFunctionStart()
|
b.createFunctionStart(false)
|
||||||
|
|
||||||
// Fill blocks with instructions.
|
// Fill blocks with instructions.
|
||||||
for _, block := range b.fn.DomPreorder() {
|
for _, block := range b.fn.DomPreorder() {
|
||||||
@@ -1656,11 +1660,6 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
// applied) function call. If it is anonymous, it may be a closure.
|
// applied) function call. If it is anonymous, it may be a closure.
|
||||||
name := fn.RelString(nil)
|
name := fn.RelString(nil)
|
||||||
switch {
|
switch {
|
||||||
case name == "math.Ceil" || name == "math.Floor" || name == "math.Sqrt" || name == "math.Trunc":
|
|
||||||
result, ok := b.createMathOp(instr)
|
|
||||||
if ok {
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
case name == "device.Asm" || name == "device/arm.Asm" || name == "device/arm64.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm":
|
case name == "device.Asm" || name == "device/arm.Asm" || name == "device/arm64.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm":
|
||||||
return b.createInlineAsm(instr.Args)
|
return b.createInlineAsm(instr.Args)
|
||||||
case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
|
case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
//go:build go1.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package compiler
|
|
||||||
|
|
||||||
// Workaround for Go 1.17 support. Should be removed once we drop Go 1.17
|
|
||||||
// support.
|
|
||||||
|
|
||||||
import "go/types"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
typeParamUnderlyingType = func(t types.Type) types.Type {
|
|
||||||
if t, ok := t.(*types.TypeParam); ok {
|
|
||||||
return t.Underlying()
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,13 +3,12 @@ package compiler
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"go/types"
|
"go/types"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
|
||||||
"github.com/tinygo-org/tinygo/loader"
|
"github.com/tinygo-org/tinygo/loader"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
@@ -28,18 +27,6 @@ type testCase struct {
|
|||||||
func TestCompiler(t *testing.T) {
|
func TestCompiler(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Determine LLVM version.
|
|
||||||
llvmMajor, err := strconv.Atoi(strings.SplitN(llvm.Version, ".", 2)[0])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("could not parse LLVM version:", llvm.Version)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine Go minor version (e.g. 16 in go1.16.3).
|
|
||||||
_, goMinor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("could not read Go version:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which tests to run, depending on the Go and LLVM versions.
|
// Determine which tests to run, depending on the Go and LLVM versions.
|
||||||
tests := []testCase{
|
tests := []testCase{
|
||||||
{"basic.go", "", ""},
|
{"basic.go", "", ""},
|
||||||
@@ -54,20 +41,8 @@ func TestCompiler(t *testing.T) {
|
|||||||
{"goroutine.go", "wasm", "asyncify"},
|
{"goroutine.go", "wasm", "asyncify"},
|
||||||
{"goroutine.go", "cortex-m-qemu", "tasks"},
|
{"goroutine.go", "cortex-m-qemu", "tasks"},
|
||||||
{"channel.go", "", ""},
|
{"channel.go", "", ""},
|
||||||
{"intrinsics.go", "cortex-m-qemu", ""},
|
|
||||||
{"intrinsics.go", "wasm", ""},
|
|
||||||
{"gc.go", "", ""},
|
{"gc.go", "", ""},
|
||||||
}
|
}
|
||||||
if llvmMajor >= 12 {
|
|
||||||
tests = append(tests, testCase{"intrinsics.go", "cortex-m-qemu", ""})
|
|
||||||
tests = append(tests, testCase{"intrinsics.go", "wasm", ""})
|
|
||||||
}
|
|
||||||
if goMinor >= 17 {
|
|
||||||
tests = append(tests, testCase{"go1.17.go", "", ""})
|
|
||||||
}
|
|
||||||
if goMinor >= 18 {
|
|
||||||
tests = append(tests, testCase{"generics.go", "", ""})
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
name := tc.file
|
name := tc.file
|
||||||
@@ -104,7 +79,7 @@ func TestCompiler(t *testing.T) {
|
|||||||
RelocationModel: config.RelocationModel(),
|
RelocationModel: config.RelocationModel(),
|
||||||
Scheduler: config.Scheduler(),
|
Scheduler: config.Scheduler(),
|
||||||
AutomaticStackSize: config.AutomaticStackSize(),
|
AutomaticStackSize: config.AutomaticStackSize(),
|
||||||
DefaultStackSize: config.Target.DefaultStackSize,
|
DefaultStackSize: config.StackSize(),
|
||||||
NeedsStackObjects: config.NeedsStackObjects(),
|
NeedsStackObjects: config.NeedsStackObjects(),
|
||||||
}
|
}
|
||||||
machine, err := NewTargetMachine(compilerConfig)
|
machine, err := NewTargetMachine(compilerConfig)
|
||||||
@@ -162,14 +137,14 @@ func TestCompiler(t *testing.T) {
|
|||||||
|
|
||||||
// Update test if needed. Do not check the result.
|
// Update test if needed. Do not check the result.
|
||||||
if *flagUpdate {
|
if *flagUpdate {
|
||||||
err := ioutil.WriteFile(outPath, []byte(mod.String()), 0666)
|
err := os.WriteFile(outPath, []byte(mod.String()), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("failed to write updated output file:", err)
|
t.Error("failed to write updated output file:", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expected, err := ioutil.ReadFile(outPath)
|
expected, err := os.ReadFile(outPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("failed to read golden file:", err)
|
t.Fatal("failed to read golden file:", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,16 +120,16 @@ func (b *builder) createGo(instr *ssa.Go) {
|
|||||||
// createGoroutineStartWrapper creates a wrapper for the task-based
|
// createGoroutineStartWrapper creates a wrapper for the task-based
|
||||||
// implementation of goroutines. For example, to call a function like this:
|
// implementation of goroutines. For example, to call a function like this:
|
||||||
//
|
//
|
||||||
// func add(x, y int) int { ... }
|
// func add(x, y int) int { ... }
|
||||||
//
|
//
|
||||||
// It creates a wrapper like this:
|
// It creates a wrapper like this:
|
||||||
//
|
//
|
||||||
// func add$gowrapper(ptr *unsafe.Pointer) {
|
// func add$gowrapper(ptr *unsafe.Pointer) {
|
||||||
// args := (*struct{
|
// args := (*struct{
|
||||||
// x, y int
|
// x, y int
|
||||||
// })(ptr)
|
// })(ptr)
|
||||||
// add(args.x, args.y)
|
// add(args.x, args.y)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// This is useful because the task-based goroutine start implementation only
|
// This is useful because the task-based goroutine start implementation only
|
||||||
// allows a single (pointer) argument to the newly started goroutine. Also, it
|
// allows a single (pointer) argument to the newly started goroutine. Also, it
|
||||||
|
|||||||
+22
-22
@@ -17,7 +17,7 @@ import (
|
|||||||
// operands or return values. It is useful for trivial instructions, like wfi in
|
// operands or return values. It is useful for trivial instructions, like wfi in
|
||||||
// ARM or sleep in AVR.
|
// ARM or sleep in AVR.
|
||||||
//
|
//
|
||||||
// func Asm(asm string)
|
// func Asm(asm string)
|
||||||
//
|
//
|
||||||
// The provided assembly must be a constant.
|
// The provided assembly must be a constant.
|
||||||
func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
|
func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
|
||||||
@@ -31,17 +31,17 @@ func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
|
|||||||
// This is a compiler builtin, which allows assembly to be called in a flexible
|
// This is a compiler builtin, which allows assembly to be called in a flexible
|
||||||
// way.
|
// way.
|
||||||
//
|
//
|
||||||
// func AsmFull(asm string, regs map[string]interface{}) uintptr
|
// func AsmFull(asm string, regs map[string]interface{}) uintptr
|
||||||
//
|
//
|
||||||
// The asm parameter must be a constant string. The regs parameter must be
|
// The asm parameter must be a constant string. The regs parameter must be
|
||||||
// provided immediately. For example:
|
// provided immediately. For example:
|
||||||
//
|
//
|
||||||
// arm.AsmFull(
|
// arm.AsmFull(
|
||||||
// "str {value}, {result}",
|
// "str {value}, {result}",
|
||||||
// map[string]interface{}{
|
// map[string]interface{}{
|
||||||
// "value": 1
|
// "value": 1
|
||||||
// "result": &dest,
|
// "result": &dest,
|
||||||
// })
|
// })
|
||||||
func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) {
|
func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) {
|
||||||
asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)
|
asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)
|
||||||
registers := map[string]llvm.Value{}
|
registers := map[string]llvm.Value{}
|
||||||
@@ -132,11 +132,11 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
// This is a compiler builtin which emits an inline SVCall instruction. It can
|
// This is a compiler builtin which emits an inline SVCall instruction. It can
|
||||||
// be one of:
|
// be one of:
|
||||||
//
|
//
|
||||||
// func SVCall0(num uintptr) uintptr
|
// func SVCall0(num uintptr) uintptr
|
||||||
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||||
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||||
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||||
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||||
//
|
//
|
||||||
// The num parameter must be a constant. All other parameters may be any scalar
|
// The num parameter must be a constant. All other parameters may be any scalar
|
||||||
// value supported by LLVM inline assembly.
|
// value supported by LLVM inline assembly.
|
||||||
@@ -169,11 +169,11 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) {
|
|||||||
// This is a compiler builtin which emits an inline SVCall instruction. It can
|
// This is a compiler builtin which emits an inline SVCall instruction. It can
|
||||||
// be one of:
|
// be one of:
|
||||||
//
|
//
|
||||||
// func SVCall0(num uintptr) uintptr
|
// func SVCall0(num uintptr) uintptr
|
||||||
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||||
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||||
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||||
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||||
//
|
//
|
||||||
// The num parameter must be a constant. All other parameters may be any scalar
|
// The num parameter must be a constant. All other parameters may be any scalar
|
||||||
// value supported by LLVM inline assembly.
|
// value supported by LLVM inline assembly.
|
||||||
@@ -206,10 +206,10 @@ func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error) {
|
|||||||
|
|
||||||
// This is a compiler builtin which emits CSR instructions. It can be one of:
|
// This is a compiler builtin which emits CSR instructions. It can be one of:
|
||||||
//
|
//
|
||||||
// func (csr CSR) Get() uintptr
|
// func (csr CSR) Get() uintptr
|
||||||
// func (csr CSR) Set(uintptr)
|
// func (csr CSR) Set(uintptr)
|
||||||
// func (csr CSR) SetBits(uintptr) uintptr
|
// func (csr CSR) SetBits(uintptr) uintptr
|
||||||
// func (csr CSR) ClearBits(uintptr) uintptr
|
// func (csr CSR) ClearBits(uintptr) uintptr
|
||||||
//
|
//
|
||||||
// The csr parameter (method receiver) must be a constant. Other parameter can
|
// The csr parameter (method receiver) must be a constant. Other parameter can
|
||||||
// be any value.
|
// be any value.
|
||||||
|
|||||||
@@ -550,8 +550,8 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llv
|
|||||||
// internally to match interfaces and to call the correct method on an
|
// internally to match interfaces and to call the correct method on an
|
||||||
// interface. Examples:
|
// interface. Examples:
|
||||||
//
|
//
|
||||||
// String() string
|
// String() string
|
||||||
// Read([]byte) (int, error)
|
// Read([]byte) (int, error)
|
||||||
func methodSignature(method *types.Func) string {
|
func methodSignature(method *types.Func) string {
|
||||||
return method.Name() + signature(method.Type().(*types.Signature))
|
return method.Name() + signature(method.Type().(*types.Signature))
|
||||||
}
|
}
|
||||||
@@ -559,8 +559,8 @@ func methodSignature(method *types.Func) string {
|
|||||||
// Make a readable version of a function (pointer) signature.
|
// Make a readable version of a function (pointer) signature.
|
||||||
// Examples:
|
// Examples:
|
||||||
//
|
//
|
||||||
// () string
|
// () string
|
||||||
// (string, int) (int, error)
|
// (string, int) (int, error)
|
||||||
func signature(sig *types.Signature) string {
|
func signature(sig *types.Signature) string {
|
||||||
s := ""
|
s := ""
|
||||||
if sig.Params().Len() == 0 {
|
if sig.Params().Len() == 0 {
|
||||||
|
|||||||
+30
-42
@@ -7,7 +7,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/ssa"
|
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,7 +28,7 @@ func (b *builder) defineIntrinsicFunction() {
|
|||||||
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
||||||
b.createVolatileStore()
|
b.createVolatileStore()
|
||||||
case strings.HasPrefix(name, "sync/atomic.") && token.IsExported(b.fn.Name()):
|
case strings.HasPrefix(name, "sync/atomic.") && token.IsExported(b.fn.Name()):
|
||||||
b.createFunctionStart()
|
b.createFunctionStart(true)
|
||||||
returnValue := b.createAtomicOp(b.fn.Name())
|
returnValue := b.createAtomicOp(b.fn.Name())
|
||||||
if !returnValue.IsNil() {
|
if !returnValue.IsNil() {
|
||||||
b.CreateRet(returnValue)
|
b.CreateRet(returnValue)
|
||||||
@@ -44,7 +43,7 @@ func (b *builder) defineIntrinsicFunction() {
|
|||||||
// specially by optimization passes possibly resulting in better generated code,
|
// specially by optimization passes possibly resulting in better generated code,
|
||||||
// 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()
|
b.createFunctionStart(true)
|
||||||
fnName := "llvm." + b.fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
fnName := "llvm." + b.fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
||||||
llvmFn := b.mod.NamedFunction(fnName)
|
llvmFn := b.mod.NamedFunction(fnName)
|
||||||
if llvmFn.IsNil() {
|
if llvmFn.IsNil() {
|
||||||
@@ -64,7 +63,7 @@ func (b *builder) createMemoryCopyImpl() {
|
|||||||
// memory, declaring the function if needed. These calls will be lowered to
|
// memory, declaring the function if needed. These calls will be lowered to
|
||||||
// regular libc memset calls if they aren't optimized out in a different way.
|
// regular libc memset calls if they aren't optimized out in a different way.
|
||||||
func (b *builder) createMemoryZeroImpl() {
|
func (b *builder) createMemoryZeroImpl() {
|
||||||
b.createFunctionStart()
|
b.createFunctionStart(true)
|
||||||
fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
||||||
llvmFn := b.mod.NamedFunction(fnName)
|
llvmFn := b.mod.NamedFunction(fnName)
|
||||||
if llvmFn.IsNil() {
|
if llvmFn.IsNil() {
|
||||||
@@ -82,55 +81,44 @@ func (b *builder) createMemoryZeroImpl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mathToLLVMMapping = map[string]string{
|
var mathToLLVMMapping = map[string]string{
|
||||||
"math.Sqrt": "llvm.sqrt.f64",
|
|
||||||
"math.Floor": "llvm.floor.f64",
|
|
||||||
"math.Ceil": "llvm.ceil.f64",
|
"math.Ceil": "llvm.ceil.f64",
|
||||||
|
"math.Exp": "llvm.exp.f64",
|
||||||
|
"math.Exp2": "llvm.exp2.f64",
|
||||||
|
"math.Floor": "llvm.floor.f64",
|
||||||
|
"math.Log": "llvm.log.f64",
|
||||||
|
"math.Sqrt": "llvm.sqrt.f64",
|
||||||
"math.Trunc": "llvm.trunc.f64",
|
"math.Trunc": "llvm.trunc.f64",
|
||||||
}
|
}
|
||||||
|
|
||||||
// createMathOp tries to lower the given call as a LLVM math intrinsic, if
|
// defineMathOp defines a math function body as a call to a LLVM intrinsic,
|
||||||
// possible. It returns the call result if possible, and a boolean whether it
|
// instead of the regular Go implementation. This allows LLVM to reason about
|
||||||
// succeeded. If it doesn't succeed, the architecture doesn't support the given
|
// the math operation and (depending on the architecture) allows it to lower the
|
||||||
// intrinsic.
|
// operation to very fast floating point instructions. If this is not possible,
|
||||||
func (b *builder) createMathOp(call *ssa.CallCommon) (llvm.Value, bool) {
|
// LLVM will emit a call to a libm function that implements the same operation.
|
||||||
// Check whether this intrinsic is supported on the given GOARCH.
|
//
|
||||||
// If it is unsupported, this can have two reasons:
|
// One example of an optimization that LLVM can do is to convert
|
||||||
//
|
// float32(math.Sqrt(float64(v))) to a 32-bit floating point operation, which is
|
||||||
// 1. LLVM can expand the intrinsic inline (using float instructions), but
|
// beneficial on architectures where 64-bit floating point operations are (much)
|
||||||
// the result doesn't pass the tests of the math package.
|
// more expensive than 32-bit ones.
|
||||||
// 2. LLVM cannot expand the intrinsic inline, will therefore lower it as a
|
func (b *builder) defineMathOp() {
|
||||||
// libm function call, but the libm function call also fails the math
|
b.createFunctionStart(true)
|
||||||
// package tests.
|
llvmName := mathToLLVMMapping[b.fn.RelString(nil)]
|
||||||
//
|
if llvmName == "" {
|
||||||
// Whatever the implementation, it must pass the tests in the math package
|
panic("unreachable: unknown math operation") // sanity check
|
||||||
// so unfortunately only the below intrinsic+architecture combinations are
|
|
||||||
// supported.
|
|
||||||
name := call.StaticCallee().RelString(nil)
|
|
||||||
switch name {
|
|
||||||
case "math.Ceil", "math.Floor", "math.Trunc":
|
|
||||||
if b.GOARCH != "wasm" && b.GOARCH != "arm64" {
|
|
||||||
return llvm.Value{}, false
|
|
||||||
}
|
|
||||||
case "math.Sqrt":
|
|
||||||
if b.GOARCH != "wasm" && b.GOARCH != "amd64" && b.GOARCH != "386" {
|
|
||||||
return llvm.Value{}, false
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return llvm.Value{}, false // only the above functions are supported.
|
|
||||||
}
|
}
|
||||||
|
llvmFn := b.mod.NamedFunction(llvmName)
|
||||||
llvmFn := b.mod.NamedFunction(mathToLLVMMapping[name])
|
|
||||||
if llvmFn.IsNil() {
|
if llvmFn.IsNil() {
|
||||||
// The intrinsic doesn't exist yet, so declare it.
|
// The intrinsic doesn't exist yet, so declare it.
|
||||||
// At the moment, all supported intrinsics have the form "double
|
// At the moment, all supported intrinsics have the form "double
|
||||||
// foo(double %x)" so we can hardcode the signature here.
|
// foo(double %x)" so we can hardcode the signature here.
|
||||||
llvmType := llvm.FunctionType(b.ctx.DoubleType(), []llvm.Type{b.ctx.DoubleType()}, false)
|
llvmType := llvm.FunctionType(b.ctx.DoubleType(), []llvm.Type{b.ctx.DoubleType()}, false)
|
||||||
llvmFn = llvm.AddFunction(b.mod, mathToLLVMMapping[name], llvmType)
|
llvmFn = llvm.AddFunction(b.mod, llvmName, llvmType)
|
||||||
}
|
}
|
||||||
// Create a call to the intrinsic.
|
// Create a call to the intrinsic.
|
||||||
args := make([]llvm.Value, len(call.Args))
|
args := make([]llvm.Value, len(b.fn.Params))
|
||||||
for i, arg := range call.Args {
|
for i, param := range b.fn.Params {
|
||||||
args[i] = b.getValue(arg)
|
args[i] = b.getValue(param)
|
||||||
}
|
}
|
||||||
return b.CreateCall(llvmFn, args, ""), true
|
result := b.CreateCall(llvmFn, args, "")
|
||||||
|
b.CreateRet(result)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -152,7 +152,7 @@ func (s *stdSizes) Sizeof(T types.Type) int64 {
|
|||||||
return align(offsets[n-1]+s.Sizeof(fields[n-1].Type()), maxAlign)
|
return align(offsets[n-1]+s.Sizeof(fields[n-1].Type()), maxAlign)
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
return s.PtrSize * 2
|
return s.PtrSize * 2
|
||||||
case *types.Pointer:
|
case *types.Pointer, *types.Chan, *types.Map:
|
||||||
return s.PtrSize
|
return s.PtrSize
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
// Func values in TinyGo are two words in size.
|
// Func values in TinyGo are two words in size.
|
||||||
|
|||||||
+12
-10
@@ -163,18 +163,20 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
|
|||||||
// External/exported functions may not retain pointer values.
|
// External/exported functions may not retain pointer values.
|
||||||
// https://golang.org/cmd/cgo/#hdr-Passing_pointers
|
// https://golang.org/cmd/cgo/#hdr-Passing_pointers
|
||||||
if info.exported {
|
if info.exported {
|
||||||
// Set the wasm-import-module attribute if the function's module is set.
|
if c.archFamily() == "wasm32" {
|
||||||
if info.module != "" {
|
|
||||||
|
|
||||||
// We need to add the wasm-import-module and the wasm-import-name
|
// We need to add the wasm-import-module and the wasm-import-name
|
||||||
wasmImportModuleAttr := c.ctx.CreateStringAttribute("wasm-import-module", info.module)
|
// attributes.
|
||||||
llvmFn.AddFunctionAttr(wasmImportModuleAttr)
|
module := info.module
|
||||||
|
if module == "" {
|
||||||
// Add the Wasm Import Name, if we are a named wasm import
|
module = "env"
|
||||||
if info.importName != "" {
|
|
||||||
wasmImportNameAttr := c.ctx.CreateStringAttribute("wasm-import-name", info.importName)
|
|
||||||
llvmFn.AddFunctionAttr(wasmImportNameAttr)
|
|
||||||
}
|
}
|
||||||
|
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-module", module))
|
||||||
|
|
||||||
|
name := info.importName
|
||||||
|
if name == "" {
|
||||||
|
name = info.linkName
|
||||||
|
}
|
||||||
|
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-name", name))
|
||||||
}
|
}
|
||||||
nocaptureKind := llvm.AttributeKindID("nocapture")
|
nocaptureKind := llvm.AttributeKindID("nocapture")
|
||||||
nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)
|
nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)
|
||||||
|
|||||||
Vendored
-41
@@ -1,41 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// Test changes to the language introduced in Go 1.17.
|
|
||||||
// For details, see: https://tip.golang.org/doc/go1.17#language
|
|
||||||
// These tests should be merged into the regular slice tests once Go 1.17 is the
|
|
||||||
// minimun Go version for TinyGo.
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
func Add32(p unsafe.Pointer, len int) unsafe.Pointer {
|
|
||||||
return unsafe.Add(p, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Add64(p unsafe.Pointer, len int64) unsafe.Pointer {
|
|
||||||
return unsafe.Add(p, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SliceToArray(s []int) *[4]int {
|
|
||||||
return (*[4]int)(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SliceToArrayConst() *[4]int {
|
|
||||||
s := make([]int, 6)
|
|
||||||
return (*[4]int)(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SliceInt(ptr *int, len int) []int {
|
|
||||||
return unsafe.Slice(ptr, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SliceUint16(ptr *byte, len uint16) []byte {
|
|
||||||
return unsafe.Slice(ptr, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SliceUint64(ptr *int, len uint64) []int {
|
|
||||||
return unsafe.Slice(ptr, len)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SliceInt64(ptr *int, len int64) []int {
|
|
||||||
return unsafe.Slice(ptr, len)
|
|
||||||
}
|
|
||||||
Vendored
-161
@@ -1,161 +0,0 @@
|
|||||||
; ModuleID = 'go1.17.go'
|
|
||||||
source_filename = "go1.17.go"
|
|
||||||
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
|
|
||||||
target triple = "wasm32-unknown-wasi"
|
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
|
|
||||||
|
|
||||||
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden void @main.init(i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden i8* @main.Add32(i8* %p, i32 %len, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = getelementptr i8, i8* %p, i32 %len
|
|
||||||
call void @runtime.trackPointer(i8* %0, i8* undef) #2
|
|
||||||
ret i8* %0
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden i8* @main.Add64(i8* %p, i64 %len, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = trunc i64 %len to i32
|
|
||||||
%1 = getelementptr i8, i8* %p, i32 %0
|
|
||||||
call void @runtime.trackPointer(i8* %1, i8* undef) #2
|
|
||||||
ret i8* %1
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden [4 x i32]* @main.SliceToArray(i32* %s.data, i32 %s.len, i32 %s.cap, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = icmp ult i32 %s.len, 4
|
|
||||||
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
|
|
||||||
|
|
||||||
slicetoarray.next: ; preds = %entry
|
|
||||||
%1 = bitcast i32* %s.data to [4 x i32]*
|
|
||||||
ret [4 x i32]* %1
|
|
||||||
|
|
||||||
slicetoarray.throw: ; preds = %entry
|
|
||||||
call void @runtime.sliceToArrayPointerPanic(i8* undef) #2
|
|
||||||
unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
declare void @runtime.sliceToArrayPointerPanic(i8*) #0
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%makeslice = call i8* @runtime.alloc(i32 24, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2
|
|
||||||
call void @runtime.trackPointer(i8* nonnull %makeslice, i8* undef) #2
|
|
||||||
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
|
|
||||||
|
|
||||||
slicetoarray.next: ; preds = %entry
|
|
||||||
%0 = bitcast i8* %makeslice to [4 x i32]*
|
|
||||||
ret [4 x i32]* %0
|
|
||||||
|
|
||||||
slicetoarray.throw: ; preds = %entry
|
|
||||||
unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden { i32*, i32, i32 } @main.SliceInt(i32* dereferenceable_or_null(4) %ptr, i32 %len, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = icmp ugt i32 %len, 1073741823
|
|
||||||
%1 = icmp eq i32* %ptr, null
|
|
||||||
%2 = icmp ne i32 %len, 0
|
|
||||||
%3 = and i1 %1, %2
|
|
||||||
%4 = or i1 %3, %0
|
|
||||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
|
||||||
|
|
||||||
unsafe.Slice.next: ; preds = %entry
|
|
||||||
%5 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
|
||||||
%6 = insertvalue { i32*, i32, i32 } %5, i32 %len, 1
|
|
||||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %len, 2
|
|
||||||
%8 = bitcast i32* %ptr to i8*
|
|
||||||
call void @runtime.trackPointer(i8* %8, i8* undef) #2
|
|
||||||
ret { i32*, i32, i32 } %7
|
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
|
||||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
|
||||||
unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
declare void @runtime.unsafeSlicePanic(i8*) #0
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden { i8*, i32, i32 } @main.SliceUint16(i8* dereferenceable_or_null(1) %ptr, i16 %len, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = icmp eq i8* %ptr, null
|
|
||||||
%1 = icmp ne i16 %len, 0
|
|
||||||
%2 = and i1 %0, %1
|
|
||||||
br i1 %2, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
|
||||||
|
|
||||||
unsafe.Slice.next: ; preds = %entry
|
|
||||||
%3 = zext i16 %len to i32
|
|
||||||
%4 = insertvalue { i8*, i32, i32 } undef, i8* %ptr, 0
|
|
||||||
%5 = insertvalue { i8*, i32, i32 } %4, i32 %3, 1
|
|
||||||
%6 = insertvalue { i8*, i32, i32 } %5, i32 %3, 2
|
|
||||||
call void @runtime.trackPointer(i8* %ptr, i8* undef) #2
|
|
||||||
ret { i8*, i32, i32 } %6
|
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
|
||||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
|
||||||
unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden { i32*, i32, i32 } @main.SliceUint64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = icmp ugt i64 %len, 1073741823
|
|
||||||
%1 = icmp eq i32* %ptr, null
|
|
||||||
%2 = icmp ne i64 %len, 0
|
|
||||||
%3 = and i1 %1, %2
|
|
||||||
%4 = or i1 %3, %0
|
|
||||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
|
||||||
|
|
||||||
unsafe.Slice.next: ; preds = %entry
|
|
||||||
%5 = trunc i64 %len to i32
|
|
||||||
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
|
||||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
|
|
||||||
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
|
|
||||||
%9 = bitcast i32* %ptr to i8*
|
|
||||||
call void @runtime.trackPointer(i8* %9, i8* undef) #2
|
|
||||||
ret { i32*, i32, i32 } %8
|
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
|
||||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
|
||||||
unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden { i32*, i32, i32 } @main.SliceInt64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = icmp ugt i64 %len, 1073741823
|
|
||||||
%1 = icmp eq i32* %ptr, null
|
|
||||||
%2 = icmp ne i64 %len, 0
|
|
||||||
%3 = and i1 %1, %2
|
|
||||||
%4 = or i1 %3, %0
|
|
||||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
|
||||||
|
|
||||||
unsafe.Slice.next: ; preds = %entry
|
|
||||||
%5 = trunc i64 %len to i32
|
|
||||||
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
|
||||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
|
|
||||||
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
|
|
||||||
%9 = bitcast i32* %ptr to i8*
|
|
||||||
call void @runtime.trackPointer(i8* %9, i8* undef) #2
|
|
||||||
ret { i32*, i32, i32 } %8
|
|
||||||
|
|
||||||
unsafe.Slice.throw: ; preds = %entry
|
|
||||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
|
||||||
unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
|
||||||
attributes #2 = { nounwind }
|
|
||||||
-34
@@ -1,34 +0,0 @@
|
|||||||
; ModuleID = 'intrinsics.go'
|
|
||||||
source_filename = "intrinsics.go"
|
|
||||||
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
|
|
||||||
target triple = "thumbv7m-unknown-unknown-eabi"
|
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden void @main.init(i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden double @main.mySqrt(double %x, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = call double @math.Sqrt(double %x, i8* undef) #2
|
|
||||||
ret double %0
|
|
||||||
}
|
|
||||||
|
|
||||||
declare double @math.Sqrt(double, i8*) #0
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden double @main.myTrunc(double %x, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = call double @math.Trunc(double %x, i8* undef) #2
|
|
||||||
ret double %0
|
|
||||||
}
|
|
||||||
|
|
||||||
declare double @math.Trunc(double, i8*) #0
|
|
||||||
|
|
||||||
attributes #0 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+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" }
|
|
||||||
attributes #1 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+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" }
|
|
||||||
attributes #2 = { nounwind }
|
|
||||||
Vendored
-38
@@ -1,38 +0,0 @@
|
|||||||
; ModuleID = 'intrinsics.go'
|
|
||||||
source_filename = "intrinsics.go"
|
|
||||||
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
|
|
||||||
target triple = "wasm32-unknown-wasi"
|
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
|
|
||||||
|
|
||||||
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden void @main.init(i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden double @main.mySqrt(double %x, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = call double @llvm.sqrt.f64(double %x)
|
|
||||||
ret double %0
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
|
|
||||||
declare double @llvm.sqrt.f64(double) #2
|
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define hidden double @main.myTrunc(double %x, i8* %context) unnamed_addr #1 {
|
|
||||||
entry:
|
|
||||||
%0 = call double @llvm.trunc.f64(double %x)
|
|
||||||
ret double %0
|
|
||||||
}
|
|
||||||
|
|
||||||
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
|
|
||||||
declare double @llvm.trunc.f64(double) #2
|
|
||||||
|
|
||||||
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
|
||||||
attributes #2 = { nofree nosync nounwind readnone speculatable willreturn }
|
|
||||||
Vendored
-14
@@ -1,14 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
// Test how intrinsics are lowered: either as regular calls to the math
|
|
||||||
// functions or as LLVM builtins (such as llvm.sqrt.f64).
|
|
||||||
|
|
||||||
import "math"
|
|
||||||
|
|
||||||
func mySqrt(x float64) float64 {
|
|
||||||
return math.Sqrt(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func myTrunc(x float64) float64 {
|
|
||||||
return math.Trunc(x)
|
|
||||||
}
|
|
||||||
Vendored
+10
@@ -3,44 +3,53 @@ package main
|
|||||||
import _ "unsafe"
|
import _ "unsafe"
|
||||||
|
|
||||||
// Creates an external global with name extern_global.
|
// Creates an external global with name extern_global.
|
||||||
|
//
|
||||||
//go:extern extern_global
|
//go:extern extern_global
|
||||||
var externGlobal [0]byte
|
var externGlobal [0]byte
|
||||||
|
|
||||||
// Creates a
|
// Creates a
|
||||||
|
//
|
||||||
//go:align 32
|
//go:align 32
|
||||||
var alignedGlobal [4]uint32
|
var alignedGlobal [4]uint32
|
||||||
|
|
||||||
// Test conflicting pragmas (the last one counts).
|
// Test conflicting pragmas (the last one counts).
|
||||||
|
//
|
||||||
//go:align 64
|
//go:align 64
|
||||||
//go:align 16
|
//go:align 16
|
||||||
var alignedGlobal16 [4]uint32
|
var alignedGlobal16 [4]uint32
|
||||||
|
|
||||||
// Test exported functions.
|
// Test exported functions.
|
||||||
|
//
|
||||||
//export extern_func
|
//export extern_func
|
||||||
func externFunc() {
|
func externFunc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a function in a different package using go:linkname.
|
// Define a function in a different package using go:linkname.
|
||||||
|
//
|
||||||
//go:linkname withLinkageName1 somepkg.someFunction1
|
//go:linkname withLinkageName1 somepkg.someFunction1
|
||||||
func withLinkageName1() {
|
func withLinkageName1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import a function from a different package using go:linkname.
|
// Import a function from a different package using go:linkname.
|
||||||
|
//
|
||||||
//go:linkname withLinkageName2 somepkg.someFunction2
|
//go:linkname withLinkageName2 somepkg.someFunction2
|
||||||
func withLinkageName2()
|
func withLinkageName2()
|
||||||
|
|
||||||
// Function has an 'inline hint', similar to the inline keyword in C.
|
// Function has an 'inline hint', similar to the inline keyword in C.
|
||||||
|
//
|
||||||
//go:inline
|
//go:inline
|
||||||
func inlineFunc() {
|
func inlineFunc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function should never be inlined, equivalent to GCC
|
// Function should never be inlined, equivalent to GCC
|
||||||
// __attribute__((noinline)).
|
// __attribute__((noinline)).
|
||||||
|
//
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func noinlineFunc() {
|
func noinlineFunc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function should have the specified section.
|
// This function should have the specified section.
|
||||||
|
//
|
||||||
//go:section .special_function_section
|
//go:section .special_function_section
|
||||||
func functionInSection() {
|
func functionInSection() {
|
||||||
}
|
}
|
||||||
@@ -51,6 +60,7 @@ func exportedFunctionInSection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This function should not: it's only a declaration and not a definition.
|
// This function should not: it's only a declaration and not a definition.
|
||||||
|
//
|
||||||
//go:section .special_function_section
|
//go:section .special_function_section
|
||||||
func undefinedFunctionNotInSection()
|
func undefinedFunctionNotInSection()
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-2
@@ -62,7 +62,7 @@ declare void @main.undefinedFunctionNotInSection(i8*) #0
|
|||||||
|
|
||||||
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" }
|
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" "wasm-import-module"="env" "wasm-import-name"="extern_func" }
|
||||||
attributes #3 = { inlinehint nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
attributes #3 = { inlinehint nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #4 = { noinline nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
attributes #4 = { noinline nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" }
|
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" "wasm-import-module"="env" "wasm-import-name"="exportedFunctionInSection" }
|
||||||
|
|||||||
Vendored
+35
@@ -1,5 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
func sliceLen(ints []int) int {
|
func sliceLen(ints []int) int {
|
||||||
return len(ints)
|
return len(ints)
|
||||||
}
|
}
|
||||||
@@ -41,3 +43,36 @@ func makeArraySlice(len int) [][3]byte {
|
|||||||
func makeInt32Slice(len int) []int32 {
|
func makeInt32Slice(len int) []int32 {
|
||||||
return make([]int32, len)
|
return make([]int32, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Add32(p unsafe.Pointer, len int) unsafe.Pointer {
|
||||||
|
return unsafe.Add(p, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Add64(p unsafe.Pointer, len int64) unsafe.Pointer {
|
||||||
|
return unsafe.Add(p, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceToArray(s []int) *[4]int {
|
||||||
|
return (*[4]int)(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceToArrayConst() *[4]int {
|
||||||
|
s := make([]int, 6)
|
||||||
|
return (*[4]int)(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceInt(ptr *int, len int) []int {
|
||||||
|
return unsafe.Slice(ptr, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceUint16(ptr *byte, len uint16) []byte {
|
||||||
|
return unsafe.Slice(ptr, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceUint64(ptr *int, len uint64) []int {
|
||||||
|
return unsafe.Slice(ptr, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceInt64(ptr *int, len int64) []int {
|
||||||
|
return unsafe.Slice(ptr, len)
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+143
@@ -183,6 +183,149 @@ slice.throw: ; preds = %entry
|
|||||||
unreachable
|
unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define hidden i8* @main.Add32(i8* %p, i32 %len, i8* %context) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
%0 = getelementptr i8, i8* %p, i32 %len
|
||||||
|
call void @runtime.trackPointer(i8* %0, i8* undef) #2
|
||||||
|
ret i8* %0
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define hidden i8* @main.Add64(i8* %p, i64 %len, i8* %context) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
%0 = trunc i64 %len to i32
|
||||||
|
%1 = getelementptr i8, i8* %p, i32 %0
|
||||||
|
call void @runtime.trackPointer(i8* %1, i8* undef) #2
|
||||||
|
ret i8* %1
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define hidden [4 x i32]* @main.SliceToArray(i32* %s.data, i32 %s.len, i32 %s.cap, i8* %context) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
%0 = icmp ult i32 %s.len, 4
|
||||||
|
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
|
||||||
|
|
||||||
|
slicetoarray.next: ; preds = %entry
|
||||||
|
%1 = bitcast i32* %s.data to [4 x i32]*
|
||||||
|
ret [4 x i32]* %1
|
||||||
|
|
||||||
|
slicetoarray.throw: ; preds = %entry
|
||||||
|
call void @runtime.sliceToArrayPointerPanic(i8* undef) #2
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @runtime.sliceToArrayPointerPanic(i8*) #0
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
%makeslice = call i8* @runtime.alloc(i32 24, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2
|
||||||
|
call void @runtime.trackPointer(i8* nonnull %makeslice, i8* undef) #2
|
||||||
|
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
|
||||||
|
|
||||||
|
slicetoarray.next: ; preds = %entry
|
||||||
|
%0 = bitcast i8* %makeslice to [4 x i32]*
|
||||||
|
ret [4 x i32]* %0
|
||||||
|
|
||||||
|
slicetoarray.throw: ; preds = %entry
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define hidden { i32*, i32, i32 } @main.SliceInt(i32* dereferenceable_or_null(4) %ptr, i32 %len, i8* %context) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
%0 = icmp ugt i32 %len, 1073741823
|
||||||
|
%1 = icmp eq i32* %ptr, null
|
||||||
|
%2 = icmp ne i32 %len, 0
|
||||||
|
%3 = and i1 %1, %2
|
||||||
|
%4 = or i1 %3, %0
|
||||||
|
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||||
|
|
||||||
|
unsafe.Slice.next: ; preds = %entry
|
||||||
|
%5 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||||
|
%6 = insertvalue { i32*, i32, i32 } %5, i32 %len, 1
|
||||||
|
%7 = insertvalue { i32*, i32, i32 } %6, i32 %len, 2
|
||||||
|
%8 = bitcast i32* %ptr to i8*
|
||||||
|
call void @runtime.trackPointer(i8* %8, i8* undef) #2
|
||||||
|
ret { i32*, i32, i32 } %7
|
||||||
|
|
||||||
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
|
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @runtime.unsafeSlicePanic(i8*) #0
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define hidden { i8*, i32, i32 } @main.SliceUint16(i8* dereferenceable_or_null(1) %ptr, i16 %len, i8* %context) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
%0 = icmp eq i8* %ptr, null
|
||||||
|
%1 = icmp ne i16 %len, 0
|
||||||
|
%2 = and i1 %0, %1
|
||||||
|
br i1 %2, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||||
|
|
||||||
|
unsafe.Slice.next: ; preds = %entry
|
||||||
|
%3 = zext i16 %len to i32
|
||||||
|
%4 = insertvalue { i8*, i32, i32 } undef, i8* %ptr, 0
|
||||||
|
%5 = insertvalue { i8*, i32, i32 } %4, i32 %3, 1
|
||||||
|
%6 = insertvalue { i8*, i32, i32 } %5, i32 %3, 2
|
||||||
|
call void @runtime.trackPointer(i8* %ptr, i8* undef) #2
|
||||||
|
ret { i8*, i32, i32 } %6
|
||||||
|
|
||||||
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
|
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define hidden { i32*, i32, i32 } @main.SliceUint64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
%0 = icmp ugt i64 %len, 1073741823
|
||||||
|
%1 = icmp eq i32* %ptr, null
|
||||||
|
%2 = icmp ne i64 %len, 0
|
||||||
|
%3 = and i1 %1, %2
|
||||||
|
%4 = or i1 %3, %0
|
||||||
|
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||||
|
|
||||||
|
unsafe.Slice.next: ; preds = %entry
|
||||||
|
%5 = trunc i64 %len to i32
|
||||||
|
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||||
|
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
|
||||||
|
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
|
||||||
|
%9 = bitcast i32* %ptr to i8*
|
||||||
|
call void @runtime.trackPointer(i8* %9, i8* undef) #2
|
||||||
|
ret { i32*, i32, i32 } %8
|
||||||
|
|
||||||
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
|
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define hidden { i32*, i32, i32 } @main.SliceInt64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 {
|
||||||
|
entry:
|
||||||
|
%0 = icmp ugt i64 %len, 1073741823
|
||||||
|
%1 = icmp eq i32* %ptr, null
|
||||||
|
%2 = icmp ne i64 %len, 0
|
||||||
|
%3 = and i1 %1, %2
|
||||||
|
%4 = or i1 %3, %0
|
||||||
|
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||||
|
|
||||||
|
unsafe.Slice.next: ; preds = %entry
|
||||||
|
%5 = trunc i64 %len to i32
|
||||||
|
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||||
|
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
|
||||||
|
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
|
||||||
|
%9 = bitcast i32* %ptr to i8*
|
||||||
|
call void @runtime.trackPointer(i8* %9, i8* undef) #2
|
||||||
|
ret { i32*, i32, i32 } %8
|
||||||
|
|
||||||
|
unsafe.Slice.throw: ; preds = %entry
|
||||||
|
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||||
attributes #2 = { nounwind }
|
attributes #2 = { nounwind }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ package compiler
|
|||||||
// createVolatileLoad is the implementation of the intrinsic function
|
// createVolatileLoad is the implementation of the intrinsic function
|
||||||
// runtime/volatile.LoadT().
|
// runtime/volatile.LoadT().
|
||||||
func (b *builder) createVolatileLoad() {
|
func (b *builder) createVolatileLoad() {
|
||||||
b.createFunctionStart()
|
b.createFunctionStart(true)
|
||||||
addr := b.getValue(b.fn.Params[0])
|
addr := b.getValue(b.fn.Params[0])
|
||||||
b.createNilCheck(b.fn.Params[0], addr, "deref")
|
b.createNilCheck(b.fn.Params[0], addr, "deref")
|
||||||
val := b.CreateLoad(addr, "")
|
val := b.CreateLoad(addr, "")
|
||||||
@@ -17,7 +17,7 @@ func (b *builder) createVolatileLoad() {
|
|||||||
// createVolatileStore is the implementation of the intrinsic function
|
// createVolatileStore is the implementation of the intrinsic function
|
||||||
// runtime/volatile.StoreT().
|
// runtime/volatile.StoreT().
|
||||||
func (b *builder) createVolatileStore() {
|
func (b *builder) createVolatileStore() {
|
||||||
b.createFunctionStart()
|
b.createFunctionStart(true)
|
||||||
addr := b.getValue(b.fn.Params[0])
|
addr := b.getValue(b.fn.Params[0])
|
||||||
val := b.getValue(b.fn.Params[1])
|
val := b.getValue(b.fn.Params[1])
|
||||||
b.createNilCheck(b.fn.Params[0], addr, "deref")
|
b.createNilCheck(b.fn.Params[0], addr, "deref")
|
||||||
|
|||||||
+5
-2
@@ -8,6 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/buildutil"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -111,9 +112,11 @@ func TestCorpus(t *testing.T) {
|
|||||||
|
|
||||||
opts := optionsFromTarget(target, sema)
|
opts := optionsFromTarget(target, sema)
|
||||||
opts.Directory = dir
|
opts.Directory = dir
|
||||||
opts.Tags = repo.Tags
|
var tags buildutil.TagsFlag
|
||||||
|
tags.Set(repo.Tags)
|
||||||
|
opts.Tags = []string(tags)
|
||||||
|
|
||||||
passed, err := Test(path, out, out, &opts, false, testing.Verbose(), false, "", "", "", "")
|
passed, err := Test(path, out, out, &opts, false, testing.Verbose(), false, "", "", "", false, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("test error: %v", err)
|
t.Errorf("test error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tinygo-org/tinygo
|
module github.com/tinygo-org/tinygo
|
||||||
|
|
||||||
go 1.16
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aykevl/go-wasm v0.0.2-0.20220616010729-4a0a888aebdc
|
github.com/aykevl/go-wasm v0.0.2-0.20220616010729-4a0a888aebdc
|
||||||
@@ -9,11 +9,25 @@ require (
|
|||||||
github.com/chromedp/chromedp v0.7.6
|
github.com/chromedp/chromedp v0.7.6
|
||||||
github.com/gofrs/flock v0.8.1
|
github.com/gofrs/flock v0.8.1
|
||||||
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/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
||||||
github.com/mattn/go-colorable v0.1.8
|
github.com/mattn/go-colorable v0.1.8
|
||||||
go.bug.st/serial v1.1.3
|
github.com/mattn/go-tty v0.0.4
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
go.bug.st/serial v1.3.5
|
||||||
|
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
||||||
golang.org/x/tools v0.1.11
|
golang.org/x/tools v0.1.11
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887
|
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||||
|
github.com/creack/goselect v0.1.2 // indirect
|
||||||
|
github.com/gobwas/httphead v0.1.0 // indirect
|
||||||
|
github.com/gobwas/pool v0.2.1 // indirect
|
||||||
|
github.com/gobwas/ws v1.1.0 // indirect
|
||||||
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA
|
|||||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
github.com/creack/goselect v0.1.2 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 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||||
@@ -23,61 +22,47 @@ 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/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/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/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
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.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
|
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
|
||||||
|
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
go.bug.st/serial v1.3.5/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
|
||||||
go.bug.st/serial v1.1.3 h1:YEBxJa9pKS9Wdg46B/jiaKbvvbUrjhZZZITfJHEJhaE=
|
|
||||||
go.bug.st/serial v1.1.3/go.mod h1:8TT7u/SwwNIpJ8QaG4s+HTjFt9ReXs2cdOU7ZEk50Dk=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
||||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
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=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887 h1:k+Y1DU/WoBDkTkRJGF149yk3S2K2VhNglN435DXDS5s=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc=
|
||||||
|
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||||
|
|||||||
+9
-4
@@ -6,6 +6,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
"os/user"
|
||||||
@@ -41,10 +42,14 @@ var TINYGOROOT string
|
|||||||
func Get(name string) string {
|
func Get(name string) string {
|
||||||
switch name {
|
switch name {
|
||||||
case "GOOS":
|
case "GOOS":
|
||||||
if dir := os.Getenv("GOOS"); dir != "" {
|
goos := os.Getenv("GOOS")
|
||||||
return dir
|
if goos == "" {
|
||||||
|
goos = runtime.GOOS
|
||||||
}
|
}
|
||||||
return runtime.GOOS
|
if goos == "android" {
|
||||||
|
goos = "linux"
|
||||||
|
}
|
||||||
|
return goos
|
||||||
case "GOARCH":
|
case "GOARCH":
|
||||||
if dir := os.Getenv("GOARCH"); dir != "" {
|
if dir := os.Getenv("GOARCH"); dir != "" {
|
||||||
return dir
|
return dir
|
||||||
@@ -122,7 +127,7 @@ func findWasmOpt() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(path)
|
||||||
if err != nil && os.IsNotExist(err) {
|
if err != nil && errors.Is(err, fs.ErrNotExist) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -4,7 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -12,7 +12,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.25.0"
|
const Version = "0.26.0-dev"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// This variable is set at build time using -ldflags parameters.
|
// This variable is set at build time using -ldflags parameters.
|
||||||
@@ -54,10 +54,10 @@ func GetGorootVersion(goroot string) (major, minor int, err error) {
|
|||||||
// toolchain for the given GOROOT path. It is usually of the form `go1.x.y` but
|
// toolchain for the given GOROOT path. It is usually of the form `go1.x.y` but
|
||||||
// can have some variations (for beta releases, for example).
|
// can have some variations (for beta releases, for example).
|
||||||
func GorootVersionString(goroot string) (string, error) {
|
func GorootVersionString(goroot string) (string, error) {
|
||||||
if data, err := ioutil.ReadFile(filepath.Join(goroot, "VERSION")); err == nil {
|
if data, err := os.ReadFile(filepath.Join(goroot, "VERSION")); err == nil {
|
||||||
return string(data), nil
|
return string(data), nil
|
||||||
|
|
||||||
} else if data, err := ioutil.ReadFile(filepath.Join(
|
} else if data, err := os.ReadFile(filepath.Join(
|
||||||
goroot, "src", "internal", "buildcfg", "zbootstrap.go")); err == nil {
|
goroot, "src", "internal", "buildcfg", "zbootstrap.go")); err == nil {
|
||||||
|
|
||||||
r := regexp.MustCompile("const version = `(.*)`")
|
r := regexp.MustCompile("const version = `(.*)`")
|
||||||
|
|||||||
+7
-5
@@ -30,10 +30,11 @@ type runner struct {
|
|||||||
objects []object // slice of objects in memory
|
objects []object // slice of objects in memory
|
||||||
globals map[llvm.Value]int // map from global to index in objects slice
|
globals map[llvm.Value]int // map from global to index in objects slice
|
||||||
start time.Time
|
start time.Time
|
||||||
|
timeout time.Duration
|
||||||
callsExecuted uint64
|
callsExecuted uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRunner(mod llvm.Module, debug bool) *runner {
|
func newRunner(mod llvm.Module, timeout time.Duration, debug bool) *runner {
|
||||||
r := runner{
|
r := runner{
|
||||||
mod: mod,
|
mod: mod,
|
||||||
targetData: llvm.NewTargetData(mod.DataLayout()),
|
targetData: llvm.NewTargetData(mod.DataLayout()),
|
||||||
@@ -42,6 +43,7 @@ func newRunner(mod llvm.Module, debug bool) *runner {
|
|||||||
objects: []object{{}},
|
objects: []object{{}},
|
||||||
globals: make(map[llvm.Value]int),
|
globals: make(map[llvm.Value]int),
|
||||||
start: time.Now(),
|
start: time.Now(),
|
||||||
|
timeout: timeout,
|
||||||
}
|
}
|
||||||
r.pointerSize = uint32(r.targetData.PointerSize())
|
r.pointerSize = uint32(r.targetData.PointerSize())
|
||||||
r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0)
|
r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0)
|
||||||
@@ -58,8 +60,8 @@ func (r *runner) dispose() {
|
|||||||
|
|
||||||
// Run evaluates runtime.initAll function as much as possible at compile time.
|
// Run evaluates runtime.initAll function as much as possible at compile time.
|
||||||
// Set debug to true if it should print output while running.
|
// Set debug to true if it should print output while running.
|
||||||
func Run(mod llvm.Module, debug bool) error {
|
func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
|
||||||
r := newRunner(mod, debug)
|
r := newRunner(mod, timeout, debug)
|
||||||
defer r.dispose()
|
defer r.dispose()
|
||||||
|
|
||||||
initAll := mod.NamedFunction("runtime.initAll")
|
initAll := mod.NamedFunction("runtime.initAll")
|
||||||
@@ -199,10 +201,10 @@ func Run(mod llvm.Module, debug bool) error {
|
|||||||
|
|
||||||
// RunFunc evaluates a single package initializer at compile time.
|
// RunFunc evaluates a single package initializer at compile time.
|
||||||
// Set debug to true if it should print output while running.
|
// Set debug to true if it should print output while running.
|
||||||
func RunFunc(fn llvm.Value, debug bool) error {
|
func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error {
|
||||||
// Create and initialize *runner object.
|
// Create and initialize *runner object.
|
||||||
mod := fn.GlobalParent()
|
mod := fn.GlobalParent()
|
||||||
r := newRunner(mod, debug)
|
r := newRunner(mod, timeout, debug)
|
||||||
defer r.dispose()
|
defer r.dispose()
|
||||||
initName := fn.Name()
|
initName := fn.Name()
|
||||||
if !strings.HasSuffix(initName, ".init") {
|
if !strings.HasSuffix(initName, ".init") {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package interp
|
package interp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
@@ -53,7 +53,7 @@ func runTest(t *testing.T, pathPrefix string) {
|
|||||||
defer mod.Dispose()
|
defer mod.Dispose()
|
||||||
|
|
||||||
// Perform the transform.
|
// Perform the transform.
|
||||||
err = Run(mod, false)
|
err = Run(mod, 10*time.Minute, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err, match := err.(*Error); match {
|
if err, match := err.(*Error); match {
|
||||||
println(err.Error())
|
println(err.Error())
|
||||||
@@ -87,7 +87,7 @@ func runTest(t *testing.T, pathPrefix string) {
|
|||||||
pm.Run(mod)
|
pm.Run(mod)
|
||||||
|
|
||||||
// Read the expected output IR.
|
// Read the expected output IR.
|
||||||
out, err := ioutil.ReadFile(pathPrefix + ".out.ll")
|
out, err := os.ReadFile(pathPrefix + ".out.ll")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not read output file %s: %v", pathPrefix+".out.ll", err)
|
t.Fatalf("could not read output file %s: %v", pathPrefix+".out.ll", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
locals := make([]value, len(fn.locals))
|
locals := make([]value, len(fn.locals))
|
||||||
r.callsExecuted++
|
r.callsExecuted++
|
||||||
|
|
||||||
t0 := time.Since(r.start)
|
|
||||||
|
|
||||||
// Parameters are considered a kind of local values.
|
// Parameters are considered a kind of local values.
|
||||||
for i, param := range params {
|
for i, param := range params {
|
||||||
locals[i] = param
|
locals[i] = param
|
||||||
@@ -143,11 +141,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
}
|
}
|
||||||
switch inst.opcode {
|
switch inst.opcode {
|
||||||
case llvm.Ret:
|
case llvm.Ret:
|
||||||
const maxInterpSeconds = 180
|
if time.Since(r.start) > r.timeout {
|
||||||
if t0 > maxInterpSeconds*time.Second {
|
// Running for more than the allowed timeout; This shouldn't happen, but it does.
|
||||||
// Running for more than maxInterpSeconds seconds. This should never happen, but does.
|
|
||||||
// See github.com/tinygo-org/tinygo/issues/2124
|
// See github.com/tinygo-org/tinygo/issues/2124
|
||||||
return nil, mem, r.errorAt(fn.blocks[0].instructions[0], fmt.Errorf("interp: running for more than %d seconds, timing out (executed calls: %d)", maxInterpSeconds, r.callsExecuted))
|
return nil, mem, r.errorAt(fn.blocks[0].instructions[0], fmt.Errorf("interp: running for more than %s, timing out (executed calls: %d)", r.timeout, r.callsExecuted))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(operands) != 0 {
|
if len(operands) != 0 {
|
||||||
@@ -372,6 +369,11 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
nBytes := uint32(operands[3].Uint())
|
nBytes := uint32(operands[3].Uint())
|
||||||
dstObj := mem.getWritable(dst.index())
|
dstObj := mem.getWritable(dst.index())
|
||||||
dstBuf := dstObj.buffer.asRawValue(r)
|
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)
|
srcBuf := mem.get(src.index()).buffer.asRawValue(r)
|
||||||
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
||||||
dstObj.buffer = dstBuf
|
dstObj.buffer = dstBuf
|
||||||
|
|||||||
+13
-6
@@ -17,6 +17,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -45,7 +46,7 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the overrides needed for the goroot.
|
// Find the overrides needed for the goroot.
|
||||||
overrides := pathsToOverride(needsSyscallPackage(config.BuildTags()))
|
overrides := pathsToOverride(config.GoMinorVersion, needsSyscallPackage(config.BuildTags()))
|
||||||
|
|
||||||
// Resolve the merge links within the goroot.
|
// Resolve the merge links within the goroot.
|
||||||
merge, err := listGorootMergeLinks(goroot, tinygoroot, overrides)
|
merge, err := listGorootMergeLinks(goroot, tinygoroot, overrides)
|
||||||
@@ -83,7 +84,7 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a temporary directory to construct the goroot within.
|
// Create a temporary directory to construct the goroot within.
|
||||||
tmpgoroot, err := ioutil.TempDir(goenv.Get("GOCACHE"), cachedGorootName+".tmp")
|
tmpgoroot, err := os.MkdirTemp(goenv.Get("GOCACHE"), cachedGorootName+".tmp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -122,13 +123,13 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
|
|||||||
// Rename the new merged gorooot into place.
|
// Rename the new merged gorooot into place.
|
||||||
err = os.Rename(tmpgoroot, cachedgoroot)
|
err = os.Rename(tmpgoroot, cachedgoroot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsExist(err) {
|
if errors.Is(err, fs.ErrExist) {
|
||||||
// Another invocation of TinyGo also seems to have created a GOROOT.
|
// Another invocation of TinyGo also seems to have created a GOROOT.
|
||||||
// Use that one instead. Our new GOROOT will be automatically
|
// Use that one instead. Our new GOROOT will be automatically
|
||||||
// deleted by the defer above.
|
// deleted by the defer above.
|
||||||
return cachedgoroot, nil
|
return cachedgoroot, nil
|
||||||
}
|
}
|
||||||
if runtime.GOOS == "windows" && os.IsPermission(err) {
|
if runtime.GOOS == "windows" && errors.Is(err, fs.ErrPermission) {
|
||||||
// On Windows, a rename with a destination directory that already
|
// On Windows, a rename with a destination directory that already
|
||||||
// exists does not result in an IsExist error, but rather in an
|
// exists does not result in an IsExist error, but rather in an
|
||||||
// access denied error. To be sure, check for this case by checking
|
// access denied error. To be sure, check for this case by checking
|
||||||
@@ -222,7 +223,7 @@ func needsSyscallPackage(buildTags []string) bool {
|
|||||||
|
|
||||||
// The boolean indicates whether to merge the subdirs. True means merge, false
|
// The boolean indicates whether to merge the subdirs. True means merge, false
|
||||||
// means use the TinyGo version.
|
// means use the TinyGo version.
|
||||||
func pathsToOverride(needsSyscallPackage bool) map[string]bool {
|
func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
||||||
paths := map[string]bool{
|
paths := map[string]bool{
|
||||||
"": true,
|
"": true,
|
||||||
"crypto/": true,
|
"crypto/": true,
|
||||||
@@ -234,7 +235,6 @@ func pathsToOverride(needsSyscallPackage bool) map[string]bool {
|
|||||||
"internal/bytealg/": false,
|
"internal/bytealg/": false,
|
||||||
"internal/reflectlite/": false,
|
"internal/reflectlite/": false,
|
||||||
"internal/task/": false,
|
"internal/task/": false,
|
||||||
"internal/itoa/": false, // TODO: Remove when we drop support for go 1.16
|
|
||||||
"machine/": false,
|
"machine/": false,
|
||||||
"net/": true,
|
"net/": true,
|
||||||
"os/": true,
|
"os/": true,
|
||||||
@@ -243,6 +243,13 @@ func pathsToOverride(needsSyscallPackage bool) map[string]bool {
|
|||||||
"sync/": true,
|
"sync/": true,
|
||||||
"testing/": true,
|
"testing/": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if goMinor >= 19 {
|
||||||
|
paths["crypto/internal/"] = true
|
||||||
|
paths["crypto/internal/boring/"] = true
|
||||||
|
paths["crypto/internal/boring/sig/"] = false
|
||||||
|
}
|
||||||
|
|
||||||
if needsSyscallPackage {
|
if needsSyscallPackage {
|
||||||
paths["syscall/"] = true // include syscall/js
|
paths["syscall/"] = true // include syscall/js
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-9
@@ -13,7 +13,6 @@ import (
|
|||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
@@ -28,8 +27,6 @@ import (
|
|||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var addInstances func(*types.Info)
|
|
||||||
|
|
||||||
// Program holds all packages and some metadata about the program as a whole.
|
// Program holds all packages and some metadata about the program as a whole.
|
||||||
type Program struct {
|
type Program struct {
|
||||||
config *compileopts.Config
|
config *compileopts.Config
|
||||||
@@ -159,6 +156,7 @@ func Load(config *compileopts.Config, inputPkg string, clangHeaders string, type
|
|||||||
EmbedGlobals: make(map[string][]*EmbedFile),
|
EmbedGlobals: make(map[string][]*EmbedFile),
|
||||||
info: types.Info{
|
info: types.Info{
|
||||||
Types: make(map[ast.Expr]types.TypeAndValue),
|
Types: make(map[ast.Expr]types.TypeAndValue),
|
||||||
|
Instances: make(map[*ast.Ident]types.Instance),
|
||||||
Defs: make(map[*ast.Ident]types.Object),
|
Defs: make(map[*ast.Ident]types.Object),
|
||||||
Uses: make(map[*ast.Ident]types.Object),
|
Uses: make(map[*ast.Ident]types.Object),
|
||||||
Implicits: make(map[ast.Node]types.Object),
|
Implicits: make(map[ast.Node]types.Object),
|
||||||
@@ -166,9 +164,6 @@ func Load(config *compileopts.Config, inputPkg string, clangHeaders string, type
|
|||||||
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if addInstances != nil {
|
|
||||||
addInstances(&pkg.info)
|
|
||||||
}
|
|
||||||
err := decoder.Decode(&pkg.PackageJSON)
|
err := decoder.Decode(&pkg.PackageJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@@ -269,7 +264,7 @@ func (p *Program) getOriginalPath(path string) string {
|
|||||||
originalPath = realgorootPath
|
originalPath = realgorootPath
|
||||||
}
|
}
|
||||||
maybeInTinyGoRoot := false
|
maybeInTinyGoRoot := false
|
||||||
for prefix := range pathsToOverride(needsSyscallPackage(p.config.BuildTags())) {
|
for prefix := range pathsToOverride(p.config.GoMinorVersion, needsSyscallPackage(p.config.BuildTags())) {
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
prefix = strings.ReplaceAll(prefix, "/", "\\")
|
prefix = strings.ReplaceAll(prefix, "/", "\\")
|
||||||
}
|
}
|
||||||
@@ -335,7 +330,7 @@ func (p *Package) OriginalDir() string {
|
|||||||
// parseFile is a wrapper around parser.ParseFile.
|
// parseFile is a wrapper around parser.ParseFile.
|
||||||
func (p *Package) parseFile(path string, mode parser.Mode) (*ast.File, error) {
|
func (p *Package) parseFile(path string, mode parser.Mode) (*ast.File, error) {
|
||||||
originalPath := p.program.getOriginalPath(path)
|
originalPath := p.program.getOriginalPath(path)
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -445,7 +440,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
|||||||
var initialCFlags []string
|
var initialCFlags []string
|
||||||
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
||||||
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
||||||
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.program.fset, initialCFlags, p.program.clangHeaders)
|
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.ImportPath, p.program.fset, initialCFlags, p.program.clangHeaders)
|
||||||
p.CFlags = append(initialCFlags, cflags...)
|
p.CFlags = append(initialCFlags, cflags...)
|
||||||
p.CGoHeaders = headerCode
|
p.CGoHeaders = headerCode
|
||||||
for path, hash := range accessedFiles {
|
for path, hash := range accessedFiles {
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
//go:build go1.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package loader
|
|
||||||
|
|
||||||
// Workaround for Go 1.17 support. Should be removed once we drop Go 1.17
|
|
||||||
// support.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/ast"
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
addInstances = func(info *types.Info) {
|
|
||||||
info.Instances = make(map[*ast.Ident]types.Instance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,12 +26,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/shlex"
|
"github.com/google/shlex"
|
||||||
|
"github.com/inhies/go-bytesize"
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/tinygo-org/tinygo/builder"
|
"github.com/tinygo-org/tinygo/builder"
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
"github.com/tinygo-org/tinygo/interp"
|
"github.com/tinygo-org/tinygo/interp"
|
||||||
"github.com/tinygo-org/tinygo/loader"
|
"github.com/tinygo-org/tinygo/loader"
|
||||||
|
"golang.org/x/tools/go/buildutil"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
|
|
||||||
"go.bug.st/serial"
|
"go.bug.st/serial"
|
||||||
@@ -194,7 +196,7 @@ func Build(pkgName, outpath string, options *compileopts.Options) error {
|
|||||||
|
|
||||||
// Test runs the tests in the given package. Returns whether the test passed and
|
// Test runs the tests in the given package. Returns whether the test passed and
|
||||||
// possibly an error if the test failed to run.
|
// possibly an error if the test failed to run.
|
||||||
func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options, testCompileOnly, testVerbose, testShort bool, testRunRegexp string, testBenchRegexp string, testBenchTime string, outpath string) (bool, error) {
|
func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options, testCompileOnly, testVerbose, testShort bool, testRunRegexp string, testBenchRegexp string, testBenchTime string, testBenchMem bool, outpath string) (bool, error) {
|
||||||
options.TestConfig.CompileTestBinary = true
|
options.TestConfig.CompileTestBinary = true
|
||||||
config, err := builder.NewConfig(options)
|
config, err := builder.NewConfig(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -218,6 +220,9 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
|||||||
if testBenchTime != "" {
|
if testBenchTime != "" {
|
||||||
flags = append(flags, "-test.benchtime="+testBenchTime)
|
flags = append(flags, "-test.benchtime="+testBenchTime)
|
||||||
}
|
}
|
||||||
|
if testBenchMem {
|
||||||
|
flags = append(flags, "-test.benchmem")
|
||||||
|
}
|
||||||
|
|
||||||
passed := false
|
passed := false
|
||||||
err = buildAndRun(pkgName, config, os.Stdout, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
err = buildAndRun(pkgName, config, os.Stdout, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||||
@@ -239,18 +244,37 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
|||||||
// Tests are always run in the package directory.
|
// Tests are always run in the package directory.
|
||||||
cmd.Dir = result.MainDir
|
cmd.Dir = result.MainDir
|
||||||
|
|
||||||
// Wasmtime needs a few extra flags to work.
|
// wasmtime is the default emulator used for `-target=wasi`. wasmtime
|
||||||
|
// is a WebAssembly runtime CLI with WASI enabled by default. However,
|
||||||
|
// only stdio are allowed by default. For example, while STDOUT routes
|
||||||
|
// to the host, other files don't. It also does not inherit environment
|
||||||
|
// variables from the host. Some tests read testdata files, often from
|
||||||
|
// outside the package directory. Other tests require temporary
|
||||||
|
// writeable directories. We allow this by adding wasmtime flags below.
|
||||||
if config.EmulatorName() == "wasmtime" {
|
if config.EmulatorName() == "wasmtime" {
|
||||||
// Add directories to the module root, but skip the current working
|
// At this point, The current working directory is at the package
|
||||||
// directory which is already added by buildAndRun.
|
// directory. Ex. $GOROOT/src/compress/flate for compress/flate.
|
||||||
|
// buildAndRun has already added arguments for wasmtime, that allow
|
||||||
|
// read-access to files such as "testdata/huffman-zero.in".
|
||||||
|
//
|
||||||
|
// Ex. main(.wasm) --dir=. -- -test.v
|
||||||
|
|
||||||
|
// Below adds additional wasmtime flags in case a test reads files
|
||||||
|
// outside its directory, like "../testdata/e.txt". This allows any
|
||||||
|
// relative directory up to the module root, even if the test never
|
||||||
|
// reads any files.
|
||||||
|
//
|
||||||
|
// Ex. --dir=.. --dir=../.. --dir=../../..
|
||||||
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
|
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
|
||||||
var args []string
|
var args []string
|
||||||
for _, d := range dirs[1:] {
|
for _, d := range dirs[1:] {
|
||||||
args = append(args, "--dir="+d)
|
args = append(args, "--dir="+d)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
|
// Some tests create temp directories using os.MkdirTemp or via
|
||||||
tmpdir, err := ioutil.TempDir("", "tinygotmp")
|
// t.TempDir(). Create a writeable directory and map it to the
|
||||||
|
// default tempDir environment variable: TMPDIR.
|
||||||
|
tmpdir, err := os.MkdirTemp("", "tinygotmp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create temporary directory: %w", err)
|
return fmt.Errorf("failed to create temporary directory: %w", err)
|
||||||
}
|
}
|
||||||
@@ -258,7 +282,8 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
|||||||
// TODO: add option to not delete temp dir for debugging?
|
// TODO: add option to not delete temp dir for debugging?
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
// Insert new argments at the front of the command line argments.
|
// The below re-organizes the arguments so that the current
|
||||||
|
// directory is added last.
|
||||||
args = append(args, cmd.Args[1:]...)
|
args = append(args, cmd.Args[1:]...)
|
||||||
cmd.Args = append(cmd.Args[:1:1], args...)
|
cmd.Args = append(cmd.Args[:1:1], args...)
|
||||||
}
|
}
|
||||||
@@ -398,7 +423,6 @@ func Flash(pkgName, port 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}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case "msd":
|
case "msd":
|
||||||
switch fileExt {
|
switch fileExt {
|
||||||
case ".uf2":
|
case ".uf2":
|
||||||
@@ -406,13 +430,11 @@ func Flash(pkgName, port 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}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case ".hex":
|
case ".hex":
|
||||||
err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options)
|
err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to flash", result.Binary, err}
|
return &commandError{"failed to flash", result.Binary, err}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
default:
|
default:
|
||||||
return errors.New("mass storage device flashing currently only supports uf2 and hex")
|
return errors.New("mass storage device flashing currently only supports uf2 and hex")
|
||||||
}
|
}
|
||||||
@@ -433,7 +455,6 @@ func Flash(pkgName, port 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}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case "bmp":
|
case "bmp":
|
||||||
gdb, err := config.Target.LookupGDB()
|
gdb, err := config.Target.LookupGDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -452,10 +473,13 @@ func Flash(pkgName, port 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}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
||||||
}
|
}
|
||||||
|
if options.Monitor {
|
||||||
|
return Monitor("", options)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,18 +1039,6 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
|||||||
// available in the system.
|
// available in the system.
|
||||||
ports = secondaryPorts
|
ports = secondaryPorts
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ports) == 0 {
|
|
||||||
// fallback
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "darwin":
|
|
||||||
ports, err = filepath.Glob("/dev/cu.usb*")
|
|
||||||
case "linux":
|
|
||||||
ports, err = filepath.Glob("/dev/ttyACM*")
|
|
||||||
case "windows":
|
|
||||||
ports, err = serial.GetPortsList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return "", errors.New("unable to search for a default USB device to be flashed on this OS")
|
return "", errors.New("unable to search for a default USB device to be flashed on this OS")
|
||||||
}
|
}
|
||||||
@@ -1040,7 +1052,9 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(portCandidates) == 0 {
|
if len(portCandidates) == 0 {
|
||||||
if len(ports) == 1 {
|
if len(usbInterfaces) > 0 {
|
||||||
|
return "", errors.New("unable to search for a default USB device - use -port flag, available ports are " + strings.Join(ports, ", "))
|
||||||
|
} else if len(ports) == 1 {
|
||||||
return ports[0], nil
|
return ports[0], nil
|
||||||
} else {
|
} else {
|
||||||
return "", errors.New("multiple serial ports available - use -port flag, available ports are " + strings.Join(ports, ", "))
|
return "", errors.New("multiple serial ports available - use -port flag, available ports are " + strings.Join(ports, ", "))
|
||||||
@@ -1105,6 +1119,7 @@ func usage(command string) {
|
|||||||
fmt.Fprintln(os.Stderr, " flash: compile and flash to the device")
|
fmt.Fprintln(os.Stderr, " flash: compile and flash to the device")
|
||||||
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
|
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
|
||||||
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
|
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
|
||||||
|
fmt.Fprintln(os.Stderr, " monitor: open communication port")
|
||||||
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
|
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
|
||||||
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
|
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
|
||||||
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
||||||
@@ -1294,11 +1309,19 @@ func main() {
|
|||||||
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
|
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
|
||||||
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
|
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
|
||||||
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
|
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
|
||||||
|
interpTimeout := flag.Duration("interp-timeout", 180*time.Second, "interp optimization pass timeout")
|
||||||
printIR := flag.Bool("printir", false, "print LLVM IR")
|
printIR := flag.Bool("printir", false, "print LLVM IR")
|
||||||
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
||||||
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
||||||
tags := flag.String("tags", "", "a space-separated list of extra build tags")
|
var tags buildutil.TagsFlag
|
||||||
|
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
||||||
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
||||||
|
var stackSize uint64
|
||||||
|
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
|
||||||
|
size, err := bytesize.Parse(s)
|
||||||
|
stackSize = uint64(size)
|
||||||
|
return err
|
||||||
|
})
|
||||||
printSize := flag.String("size", "", "print sizes (none, short, full)")
|
printSize := flag.String("size", "", "print sizes (none, short, full)")
|
||||||
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
||||||
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
||||||
@@ -1313,6 +1336,8 @@ func main() {
|
|||||||
wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
||||||
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
||||||
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
||||||
|
monitor := flag.Bool("monitor", false, "enable serial monitor")
|
||||||
|
baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor")
|
||||||
|
|
||||||
var flagJSON, flagDeps, flagTest bool
|
var flagJSON, flagDeps, flagTest bool
|
||||||
if command == "help" || command == "list" || command == "info" || command == "build" {
|
if command == "help" || command == "list" || command == "info" || command == "build" {
|
||||||
@@ -1330,6 +1355,7 @@ func main() {
|
|||||||
var testBenchRegexp *string
|
var testBenchRegexp *string
|
||||||
var testBenchTime *string
|
var testBenchTime *string
|
||||||
var testRunRegexp *string
|
var testRunRegexp *string
|
||||||
|
var testBenchMem *bool
|
||||||
if command == "help" || command == "test" {
|
if command == "help" || command == "test" {
|
||||||
testCompileOnlyFlag = flag.Bool("c", false, "compile the test binary but do not run it")
|
testCompileOnlyFlag = flag.Bool("c", false, "compile the test binary but do not run it")
|
||||||
testVerboseFlag = flag.Bool("v", false, "verbose: print additional output")
|
testVerboseFlag = flag.Bool("v", false, "verbose: print additional output")
|
||||||
@@ -1337,6 +1363,7 @@ func main() {
|
|||||||
testRunRegexp = flag.String("run", "", "run: regexp of tests to run")
|
testRunRegexp = flag.String("run", "", "run: regexp of tests to run")
|
||||||
testBenchRegexp = flag.String("bench", "", "run: regexp of benchmarks to run")
|
testBenchRegexp = flag.String("bench", "", "run: regexp of benchmarks to run")
|
||||||
testBenchTime = flag.String("benchtime", "", "run each benchmark for duration `d`")
|
testBenchTime = flag.String("benchtime", "", "run each benchmark for duration `d`")
|
||||||
|
testBenchMem = flag.Bool("benchmem", false, "show memory stats for benchmarks")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Early command processing, before commands are interpreted by the Go flag
|
// Early command processing, before commands are interpreted by the Go flag
|
||||||
@@ -1377,12 +1404,14 @@ func main() {
|
|||||||
GOARCH: goenv.Get("GOARCH"),
|
GOARCH: goenv.Get("GOARCH"),
|
||||||
GOARM: goenv.Get("GOARM"),
|
GOARM: goenv.Get("GOARM"),
|
||||||
Target: *target,
|
Target: *target,
|
||||||
|
StackSize: stackSize,
|
||||||
Opt: *opt,
|
Opt: *opt,
|
||||||
GC: *gc,
|
GC: *gc,
|
||||||
PanicStrategy: *panicStrategy,
|
PanicStrategy: *panicStrategy,
|
||||||
Scheduler: *scheduler,
|
Scheduler: *scheduler,
|
||||||
Serial: *serial,
|
Serial: *serial,
|
||||||
Work: *work,
|
Work: *work,
|
||||||
|
InterpTimeout: *interpTimeout,
|
||||||
PrintIR: *printIR,
|
PrintIR: *printIR,
|
||||||
DumpSSA: *dumpSSA,
|
DumpSSA: *dumpSSA,
|
||||||
VerifyIR: *verifyIR,
|
VerifyIR: *verifyIR,
|
||||||
@@ -1391,13 +1420,15 @@ func main() {
|
|||||||
PrintSizes: *printSize,
|
PrintSizes: *printSize,
|
||||||
PrintStacks: *printStacks,
|
PrintStacks: *printStacks,
|
||||||
PrintAllocs: printAllocs,
|
PrintAllocs: printAllocs,
|
||||||
Tags: *tags,
|
Tags: []string(tags),
|
||||||
GlobalValues: globalVarValues,
|
GlobalValues: globalVarValues,
|
||||||
WasmAbi: *wasmAbi,
|
WasmAbi: *wasmAbi,
|
||||||
Programmer: *programmer,
|
Programmer: *programmer,
|
||||||
OpenOCDCommands: ocdCommands,
|
OpenOCDCommands: ocdCommands,
|
||||||
LLVMFeatures: *llvmFeatures,
|
LLVMFeatures: *llvmFeatures,
|
||||||
PrintJSON: flagJSON,
|
PrintJSON: flagJSON,
|
||||||
|
Monitor: *monitor,
|
||||||
|
BaudRate: *baudrate,
|
||||||
}
|
}
|
||||||
if *printCommands {
|
if *printCommands {
|
||||||
options.PrintCommands = printCommand
|
options.PrintCommands = printCommand
|
||||||
@@ -1465,7 +1496,7 @@ func main() {
|
|||||||
fmt.Fprintf(os.Stderr, "Unknown library: %s\n", name)
|
fmt.Fprintf(os.Stderr, "Unknown library: %s\n", name)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
tmpdir, err := ioutil.TempDir("", "tinygo*")
|
tmpdir, err := os.MkdirTemp("", "tinygo*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
}
|
}
|
||||||
@@ -1566,7 +1597,7 @@ func main() {
|
|||||||
defer close(buf.done)
|
defer close(buf.done)
|
||||||
stdout := (*testStdout)(buf)
|
stdout := (*testStdout)(buf)
|
||||||
stderr := (*testStderr)(buf)
|
stderr := (*testStderr)(buf)
|
||||||
passed, err := Test(pkgName, stdout, stderr, options, *testCompileOnlyFlag, *testVerboseFlag, *testShortFlag, *testRunRegexp, *testBenchRegexp, *testBenchTime, outpath)
|
passed, err := Test(pkgName, stdout, stderr, options, *testCompileOnlyFlag, *testVerboseFlag, *testShortFlag, *testRunRegexp, *testBenchRegexp, *testBenchTime, *testBenchMem, outpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printCompilerError(func(args ...interface{}) {
|
printCompilerError(func(args ...interface{}) {
|
||||||
fmt.Fprintln(stderr, args...)
|
fmt.Fprintln(stderr, args...)
|
||||||
@@ -1588,6 +1619,9 @@ func main() {
|
|||||||
fmt.Println("FAIL")
|
fmt.Println("FAIL")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
case "monitor":
|
||||||
|
err := Monitor(*port, options)
|
||||||
|
handleCompilerError(err)
|
||||||
case "targets":
|
case "targets":
|
||||||
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
||||||
entries, err := ioutil.ReadDir(dir)
|
entries, err := ioutil.ReadDir(dir)
|
||||||
@@ -1666,7 +1700,6 @@ func main() {
|
|||||||
fmt.Printf("LLVM triple: %s\n", config.Triple())
|
fmt.Printf("LLVM triple: %s\n", config.Triple())
|
||||||
fmt.Printf("GOOS: %s\n", config.GOOS())
|
fmt.Printf("GOOS: %s\n", config.GOOS())
|
||||||
fmt.Printf("GOARCH: %s\n", config.GOARCH())
|
fmt.Printf("GOARCH: %s\n", config.GOARCH())
|
||||||
fmt.Printf("GOARM: %s\n", config.GOARM())
|
|
||||||
fmt.Printf("build tags: %s\n", strings.Join(config.BuildTags(), " "))
|
fmt.Printf("build tags: %s\n", strings.Join(config.BuildTags(), " "))
|
||||||
fmt.Printf("garbage collector: %s\n", config.GC())
|
fmt.Printf("garbage collector: %s\n", config.GC())
|
||||||
fmt.Printf("scheduler: %s\n", config.Scheduler())
|
fmt.Printf("scheduler: %s\n", config.Scheduler())
|
||||||
|
|||||||
+41
-36
@@ -10,7 +10,6 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -52,6 +51,7 @@ func TestBuild(t *testing.T) {
|
|||||||
"embed/",
|
"embed/",
|
||||||
"float.go",
|
"float.go",
|
||||||
"gc.go",
|
"gc.go",
|
||||||
|
"generics.go",
|
||||||
"goroutines.go",
|
"goroutines.go",
|
||||||
"init.go",
|
"init.go",
|
||||||
"init_multi.go",
|
"init_multi.go",
|
||||||
@@ -66,21 +66,10 @@ func TestBuild(t *testing.T) {
|
|||||||
"stdlib.go",
|
"stdlib.go",
|
||||||
"string.go",
|
"string.go",
|
||||||
"structs.go",
|
"structs.go",
|
||||||
|
"testing.go",
|
||||||
|
"timers.go",
|
||||||
"zeroalloc.go",
|
"zeroalloc.go",
|
||||||
}
|
}
|
||||||
_, minor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("could not read version from GOROOT:", err)
|
|
||||||
}
|
|
||||||
if minor >= 17 {
|
|
||||||
tests = append(tests, "go1.17.go")
|
|
||||||
}
|
|
||||||
if minor >= 18 {
|
|
||||||
tests = append(tests, "generics.go")
|
|
||||||
tests = append(tests, "testing_go118.go")
|
|
||||||
} else {
|
|
||||||
tests = append(tests, "testing.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),
|
||||||
@@ -181,6 +170,14 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range tests {
|
for _, name := range tests {
|
||||||
|
if options.GOOS == "linux" && (options.GOARCH == "arm" || options.GOARCH == "386") {
|
||||||
|
switch name {
|
||||||
|
case "timers.go":
|
||||||
|
// Timer tests do not work because syscall.seek is implemented
|
||||||
|
// as Assembly in mainline Go and causes linker failure
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
if options.Target == "simavr" {
|
if options.Target == "simavr" {
|
||||||
// Not all tests are currently supported on AVR.
|
// Not all tests are currently supported on AVR.
|
||||||
// Skip the ones that aren't.
|
// Skip the ones that aren't.
|
||||||
@@ -193,7 +190,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
|||||||
// Does not pass due to high mark false positive rate.
|
// Does not pass due to high mark false positive rate.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case "json.go", "stdlib.go", "testing.go", "testing_go118.go":
|
case "json.go", "stdlib.go", "testing.go":
|
||||||
// Breaks interp.
|
// Breaks interp.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -209,6 +206,11 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
|||||||
// CGo does not work on AVR.
|
// CGo does not work on AVR.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
case "timers.go":
|
||||||
|
// Doesn't compile:
|
||||||
|
// panic: compiler: could not store type code number inside interface type code
|
||||||
|
continue
|
||||||
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,10 +262,11 @@ func emuCheck(t *testing.T, options compileopts.Options) {
|
|||||||
t.Fatal("failed to load target spec:", err)
|
t.Fatal("failed to load target spec:", err)
|
||||||
}
|
}
|
||||||
if spec.Emulator != "" {
|
if spec.Emulator != "" {
|
||||||
_, err := exec.LookPath(strings.SplitN(spec.Emulator, " ", 2)[0])
|
emulatorCommand := strings.SplitN(spec.Emulator, " ", 2)[0]
|
||||||
|
_, err := exec.LookPath(emulatorCommand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, exec.ErrNotFound) {
|
if errors.Is(err, exec.ErrNotFound) {
|
||||||
t.Skipf("emulator not installed: %q", spec.Emulator[0])
|
t.Skipf("emulator not installed: %q", emulatorCommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Errorf("searching for emulator: %v", err)
|
t.Errorf("searching for emulator: %v", err)
|
||||||
@@ -275,14 +278,15 @@ func emuCheck(t *testing.T, options compileopts.Options) {
|
|||||||
func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
|
func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
|
||||||
return compileopts.Options{
|
return compileopts.Options{
|
||||||
// GOOS/GOARCH are only used if target == ""
|
// GOOS/GOARCH are only used if target == ""
|
||||||
GOOS: goenv.Get("GOOS"),
|
GOOS: goenv.Get("GOOS"),
|
||||||
GOARCH: goenv.Get("GOARCH"),
|
GOARCH: goenv.Get("GOARCH"),
|
||||||
GOARM: goenv.Get("GOARM"),
|
GOARM: goenv.Get("GOARM"),
|
||||||
Target: target,
|
Target: target,
|
||||||
Semaphore: sema,
|
Semaphore: sema,
|
||||||
Debug: true,
|
InterpTimeout: 180 * time.Second,
|
||||||
VerifyIR: true,
|
Debug: true,
|
||||||
Opt: "z",
|
VerifyIR: true,
|
||||||
|
Opt: "z",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,12 +296,13 @@ func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
|
|||||||
func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options {
|
func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options {
|
||||||
parts := strings.Split(osarch, "/")
|
parts := strings.Split(osarch, "/")
|
||||||
options := compileopts.Options{
|
options := compileopts.Options{
|
||||||
GOOS: parts[0],
|
GOOS: parts[0],
|
||||||
GOARCH: parts[1],
|
GOARCH: parts[1],
|
||||||
Semaphore: sema,
|
Semaphore: sema,
|
||||||
Debug: true,
|
InterpTimeout: 180 * time.Second,
|
||||||
VerifyIR: true,
|
Debug: true,
|
||||||
Opt: "z",
|
VerifyIR: true,
|
||||||
|
Opt: "z",
|
||||||
}
|
}
|
||||||
if options.GOARCH == "arm" {
|
if options.GOARCH == "arm" {
|
||||||
options.GOARM = parts[2]
|
options.GOARM = parts[2]
|
||||||
@@ -319,7 +324,7 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
|||||||
if path[len(path)-1] == '/' {
|
if path[len(path)-1] == '/' {
|
||||||
txtpath = path + "out.txt"
|
txtpath = path + "out.txt"
|
||||||
}
|
}
|
||||||
expected, err := ioutil.ReadFile(txtpath)
|
expected, err := os.ReadFile(txtpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("could not read expected output file:", err)
|
t.Fatal("could not read expected output file:", err)
|
||||||
}
|
}
|
||||||
@@ -430,7 +435,7 @@ func TestTest(t *testing.T) {
|
|||||||
defer out.Close()
|
defer out.Close()
|
||||||
|
|
||||||
opts := targ.opts
|
opts := targ.opts
|
||||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/pass", out, out, &opts, false, false, false, "", "", "", "")
|
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/pass", out, out, &opts, false, false, false, "", "", "", false, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("test error: %v", err)
|
t.Errorf("test error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -451,7 +456,7 @@ func TestTest(t *testing.T) {
|
|||||||
defer out.Close()
|
defer out.Close()
|
||||||
|
|
||||||
opts := targ.opts
|
opts := targ.opts
|
||||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/fail", out, out, &opts, false, false, false, "", "", "", "")
|
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/fail", out, out, &opts, false, false, false, "", "", "", false, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("test error: %v", err)
|
t.Errorf("test error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -478,7 +483,7 @@ func TestTest(t *testing.T) {
|
|||||||
|
|
||||||
var output bytes.Buffer
|
var output bytes.Buffer
|
||||||
opts := targ.opts
|
opts := targ.opts
|
||||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/nothing", io.MultiWriter(&output, out), out, &opts, false, false, false, "", "", "", "")
|
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/nothing", io.MultiWriter(&output, out), out, &opts, false, false, false, "", "", "", false, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("test error: %v", err)
|
t.Errorf("test error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -502,7 +507,7 @@ func TestTest(t *testing.T) {
|
|||||||
defer out.Close()
|
defer out.Close()
|
||||||
|
|
||||||
opts := targ.opts
|
opts := targ.opts
|
||||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/builderr", out, out, &opts, false, false, false, "", "", "", "")
|
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/builderr", out, out, &opts, false, false, false, "", "", "", false, "")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("test did not error")
|
t.Error("test did not error")
|
||||||
}
|
}
|
||||||
|
|||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/mattn/go-tty"
|
||||||
|
"github.com/tinygo-org/tinygo/builder"
|
||||||
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
|
"go.bug.st/serial"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Monitor connects to the given port and reads/writes the serial port.
|
||||||
|
func Monitor(port string, options *compileopts.Options) error {
|
||||||
|
config, err := builder.NewConfig(options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wait := 300
|
||||||
|
for i := 0; i <= wait; i++ {
|
||||||
|
port, err = getDefaultPort(port, config.Target.SerialPort)
|
||||||
|
if err != nil {
|
||||||
|
if i < wait {
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
br := options.BaudRate
|
||||||
|
if br <= 0 {
|
||||||
|
br = 115200
|
||||||
|
}
|
||||||
|
|
||||||
|
wait = 300
|
||||||
|
var p serial.Port
|
||||||
|
for i := 0; i <= wait; i++ {
|
||||||
|
p, err = serial.Open(port, &serial.Mode{BaudRate: br})
|
||||||
|
if err != nil {
|
||||||
|
if i < wait {
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
tty, err := tty.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer tty.Close()
|
||||||
|
|
||||||
|
sig := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sig, os.Interrupt)
|
||||||
|
defer signal.Stop(sig)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-sig
|
||||||
|
tty.Close()
|
||||||
|
os.Exit(0)
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Printf("Connected to %s. Press Ctrl-C to exit.\n", port)
|
||||||
|
|
||||||
|
errCh := make(chan error, 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
buf := make([]byte, 100*1024)
|
||||||
|
for {
|
||||||
|
n, err := p.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
errCh <- fmt.Errorf("read error: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("%v", string(buf[:n]))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
r, err := tty.ReadRune()
|
||||||
|
if err != nil {
|
||||||
|
errCh <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p.Write([]byte(string(r)))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return <-errCh
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Package sig stubs crypto/internal/boring/sig
|
||||||
|
package sig
|
||||||
|
|
||||||
|
// BoringCrypto indicates that the BoringCrypto module is present.
|
||||||
|
func BoringCrypto() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIPSOnly indicates that package crypto/tls/fipsonly is present.
|
||||||
|
func FIPSOnly() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// StandardCrypto indicates that standard Go crypto is present.
|
||||||
|
func StandardCrypto() {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,5 +27,6 @@ func (r *reader) Read(b []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// void arc4random_buf(void *buf, size_t buflen);
|
// void arc4random_buf(void *buf, size_t buflen);
|
||||||
|
//
|
||||||
//export arc4random_buf
|
//export arc4random_buf
|
||||||
func libc_arc4random_buf(buf unsafe.Pointer, buflen uint)
|
func libc_arc4random_buf(buf unsafe.Pointer, buflen uint)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build stm32 || (sam && atsamd51) || (sam && atsame5x)
|
//go:build nrf || stm32 || (sam && atsamd51) || (sam && atsame5x)
|
||||||
// +build stm32 sam,atsamd51 sam,atsame5x
|
// +build nrf stm32 sam,atsamd51 sam,atsame5x
|
||||||
|
|
||||||
package rand
|
package rand
|
||||||
|
|
||||||
|
|||||||
@@ -38,5 +38,6 @@ func (r *reader) Read(b []byte) (n int, err error) {
|
|||||||
// Cryptographically secure random number generator.
|
// Cryptographically secure random number generator.
|
||||||
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rand-s?view=msvc-170
|
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rand-s?view=msvc-170
|
||||||
// errno_t rand_s(unsigned int* randomValue);
|
// errno_t rand_s(unsigned int* randomValue);
|
||||||
|
//
|
||||||
//export rand_s
|
//export rand_s
|
||||||
func libc_rand_s(randomValue *uint32) int32
|
func libc_rand_s(randomValue *uint32) int32
|
||||||
|
|||||||
+29
-29
@@ -2,31 +2,31 @@
|
|||||||
//
|
//
|
||||||
// Original copyright:
|
// Original copyright:
|
||||||
//
|
//
|
||||||
// Copyright (c) 2009 - 2015 ARM LIMITED
|
// Copyright (c) 2009 - 2015 ARM LIMITED
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are met:
|
// modification, are permitted provided that the following conditions are met:
|
||||||
// - Redistributions of source code must retain the above copyright
|
// - Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
// - Redistributions in binary form must reproduce the above copyright
|
// - Redistributions in binary form must reproduce the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer in the
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
// documentation and/or other materials provided with the distribution.
|
// documentation and/or other materials provided with the distribution.
|
||||||
// - Neither the name of ARM nor the names of its contributors may be used
|
// - Neither the name of ARM nor the names of its contributors may be used
|
||||||
// to endorse or promote products derived from this software without
|
// to endorse or promote products derived from this software without
|
||||||
// specific prior written permission.
|
// specific prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
// ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
package arm
|
package arm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -46,12 +46,12 @@ func Asm(asm string)
|
|||||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||||
// recognizes template values in the form {name}, like so:
|
// recognizes template values in the form {name}, like so:
|
||||||
//
|
//
|
||||||
// arm.AsmFull(
|
// arm.AsmFull(
|
||||||
// "str {value}, {result}",
|
// "str {value}, {result}",
|
||||||
// map[string]interface{}{
|
// map[string]interface{}{
|
||||||
// "value": 1
|
// "value": 1
|
||||||
// "result": &dest,
|
// "result": &dest,
|
||||||
// })
|
// })
|
||||||
//
|
//
|
||||||
// You can use {} in the asm string (which expands to a register) to set the
|
// You can use {} in the asm string (which expands to a register) to set the
|
||||||
// return value.
|
// return value.
|
||||||
|
|||||||
@@ -60,5 +60,6 @@ const (
|
|||||||
|
|
||||||
// Call a semihosting function.
|
// Call a semihosting function.
|
||||||
// TODO: implement it here using inline assembly.
|
// TODO: implement it here using inline assembly.
|
||||||
|
//
|
||||||
//go:linkname SemihostingCall SemihostingCall
|
//go:linkname SemihostingCall SemihostingCall
|
||||||
func SemihostingCall(num int, arg uintptr) int
|
func SemihostingCall(num int, arg uintptr) int
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ func Asm(asm string)
|
|||||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||||
// recognizes template values in the form {name}, like so:
|
// recognizes template values in the form {name}, like so:
|
||||||
//
|
//
|
||||||
// arm.AsmFull(
|
// arm.AsmFull(
|
||||||
// "str {value}, {result}",
|
// "str {value}, {result}",
|
||||||
// map[string]interface{}{
|
// map[string]interface{}{
|
||||||
// "value": 1
|
// "value": 1
|
||||||
// "result": &dest,
|
// "result": &dest,
|
||||||
// })
|
// })
|
||||||
//
|
//
|
||||||
// You can use {} in the asm string (which expands to a register) to set the
|
// You can use {} in the asm string (which expands to a register) to set the
|
||||||
// return value.
|
// return value.
|
||||||
|
|||||||
+6
-6
@@ -9,12 +9,12 @@ func Asm(asm string)
|
|||||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||||
// recognizes template values in the form {name}, like so:
|
// recognizes template values in the form {name}, like so:
|
||||||
//
|
//
|
||||||
// arm.AsmFull(
|
// arm.AsmFull(
|
||||||
// "str {value}, {result}",
|
// "str {value}, {result}",
|
||||||
// map[string]interface{}{
|
// map[string]interface{}{
|
||||||
// "value": 1
|
// "value": 1
|
||||||
// "result": &dest,
|
// "result": &dest,
|
||||||
// })
|
// })
|
||||||
//
|
//
|
||||||
// You can use {} in the asm string (which expands to a register) to set the
|
// You can use {} in the asm string (which expands to a register) to set the
|
||||||
// return value.
|
// return value.
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ func Asm(asm string)
|
|||||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||||
// recognizes template values in the form {name}, like so:
|
// recognizes template values in the form {name}, like so:
|
||||||
//
|
//
|
||||||
// avr.AsmFull(
|
// avr.AsmFull(
|
||||||
// "str {value}, {result}",
|
// "str {value}, {result}",
|
||||||
// map[string]interface{}{
|
// map[string]interface{}{
|
||||||
// "value": 1
|
// "value": 1
|
||||||
// "result": &dest,
|
// "result": &dest,
|
||||||
// })
|
// })
|
||||||
//
|
//
|
||||||
// You can use {} in the asm string (which expands to a register) to set the
|
// You can use {} in the asm string (which expands to a register) to set the
|
||||||
// return value.
|
// return value.
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ func Asm(asm string)
|
|||||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||||
// recognizes template values in the form {name}, like so:
|
// recognizes template values in the form {name}, like so:
|
||||||
//
|
//
|
||||||
// arm.AsmFull(
|
// arm.AsmFull(
|
||||||
// "st {value}, {result}",
|
// "st {value}, {result}",
|
||||||
// map[string]interface{}{
|
// map[string]interface{}{
|
||||||
// "value": 1
|
// "value": 1
|
||||||
// "result": &dest,
|
// "result": &dest,
|
||||||
// })
|
// })
|
||||||
//
|
//
|
||||||
// You can use {} in the asm string (which expands to a register) to set the
|
// You can use {} in the asm string (which expands to a register) to set the
|
||||||
// return value.
|
// return value.
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
// Reads multiple rp2040 ADC channels concurrently. Including the internal temperature sensor
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"machine"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type celsius float32
|
|
||||||
|
|
||||||
func (c celsius) String() string {
|
|
||||||
return fmt.Sprintf("%4.1f℃", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// rp2040 ADC is 12 bits. Reading are shifted <<4 to fill the 16-bit range.
|
|
||||||
var adcReading [3]uint16
|
|
||||||
|
|
||||||
func readADC(a machine.ADC, w time.Duration, i int) {
|
|
||||||
for {
|
|
||||||
adcReading[i] = a.Get()
|
|
||||||
time.Sleep(w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
machine.InitADC()
|
|
||||||
a0 := machine.ADC{machine.ADC0} // GPIO26 input
|
|
||||||
a1 := machine.ADC{machine.ADC1} // GPIO27 input
|
|
||||||
a2 := machine.ADC{machine.ADC2} // GPIO28 input
|
|
||||||
t := machine.ADC_TEMP_SENSOR // Internal Temperature sensor
|
|
||||||
// Configure sets the GPIOs to PinAnalog mode
|
|
||||||
a0.Configure(machine.ADCConfig{})
|
|
||||||
a1.Configure(machine.ADCConfig{})
|
|
||||||
a2.Configure(machine.ADCConfig{})
|
|
||||||
// Configure powers on the temperature sensor
|
|
||||||
t.Configure(machine.ADCConfig{})
|
|
||||||
|
|
||||||
// Safe to read concurrently
|
|
||||||
go readADC(a0, 10*time.Millisecond, 0)
|
|
||||||
go readADC(a1, 17*time.Millisecond, 1)
|
|
||||||
go readADC(a2, 29*time.Millisecond, 2)
|
|
||||||
|
|
||||||
for {
|
|
||||||
fmt.Printf("ADC0: %5d ADC1: %5d ADC2: %5d Temp: %v\n\r", adcReading[0], adcReading[1], adcReading[2], celsius(float32(t.ReadTemperature())/1000))
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// Example using the i2s hardware interface on the Adafruit Circuit Playground Express
|
// Example using the i2s hardware interface on the Adafruit Circuit Playground Express
|
||||||
// to read data from the onboard MEMS microphone.
|
// to read data from the onboard MEMS microphone.
|
||||||
//
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// Read the internal temperature sensor of the chip.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type celsius float32
|
||||||
|
|
||||||
|
func (c celsius) String() string {
|
||||||
|
return fmt.Sprintf("%4.1f℃", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
for {
|
||||||
|
temp := celsius(float32(machine.ReadTemperature()) / 1000)
|
||||||
|
println("temperature:", temp.String())
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@ main: clean wasm_exec
|
|||||||
cp ./main/index.html ./html/
|
cp ./main/index.html ./html/
|
||||||
|
|
||||||
wasm_exec:
|
wasm_exec:
|
||||||
cp ../../../targets/wasm_exec.js ./html/
|
cp `tinygo env TINYGOROOT`/targets/wasm_exec.js ./html/
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf ./html
|
rm -rf ./html
|
||||||
|
|||||||
@@ -21,12 +21,14 @@ $ tinygo build -o ./wasm.wasm -target wasm ./main/main.go
|
|||||||
This creates a `wasm.wasm` file, which we can load in JavaScript and execute in
|
This creates a `wasm.wasm` file, which we can load in JavaScript and execute in
|
||||||
a browser.
|
a browser.
|
||||||
|
|
||||||
This examples folder contains two examples that can be built using `make`:
|
Next, choose which example you want to use:
|
||||||
|
* [callback](callback): Defines and configures callbacks in Wasm.
|
||||||
```bash
|
* [export](export): Defines callbacks in Wasm, but configures them in JavaScript.
|
||||||
$ make export
|
* [invoke](invoke): Invokes a function defined in JavaScript from Wasm.
|
||||||
```
|
* [main](main): Prints a message to the JavaScript console from Wasm.
|
||||||
|
* [slices](slices): Splits an Array defined in JavaScript from Wasm.
|
||||||
|
|
||||||
|
Let's say you chose [main](main), you'd build it like so:
|
||||||
```bash
|
```bash
|
||||||
$ make main
|
$ make main
|
||||||
```
|
```
|
||||||
@@ -42,12 +44,8 @@ Serving ./html on http://localhost:8080
|
|||||||
|
|
||||||
Use your web browser to visit http://localhost:8080.
|
Use your web browser to visit http://localhost:8080.
|
||||||
|
|
||||||
* The wasm "export" example displays a simple math equation using HTML, with
|
* Tip: Open the browser development tools (e.g. Right-click, Inspect in
|
||||||
the result calculated dynamically using WebAssembly. Changing any of the
|
FireFox) to see console output.
|
||||||
values on the left hand side triggers the exported wasm `update` function to
|
|
||||||
recalculate the result.
|
|
||||||
* The wasm "main" example uses `println` to write to your browser JavaScript
|
|
||||||
console. You may need to open the browser development tools console to see it.
|
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ import (
|
|||||||
var a, b int
|
var a, b int
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
wait := make(chan struct{}, 0)
|
||||||
document := js.Global().Get("document")
|
document := js.Global().Get("document")
|
||||||
document.Call("getElementById", "a").Set("oninput", updater(&a))
|
document.Call("getElementById", "a").Set("oninput", updater(&a))
|
||||||
document.Call("getElementById", "b").Set("oninput", updater(&b))
|
document.Call("getElementById", "b").Set("oninput", updater(&b))
|
||||||
update()
|
update()
|
||||||
|
<-wait
|
||||||
}
|
}
|
||||||
|
|
||||||
func updater(n *int) js.Func {
|
func updater(n *int) js.Func {
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
internal/itoa is new to go as of 1.17.
|
|
||||||
This directory should be removed when tinygo drops support for go 1.16.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
// 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:])
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
// 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
.functype start_unwind (i32) -> ()
|
.functype start_unwind (i32) -> ()
|
||||||
.import_module start_unwind, asyncify
|
.import_module start_unwind, asyncify
|
||||||
|
.import_name start_unwind, start_unwind
|
||||||
.functype stop_unwind () -> ()
|
.functype stop_unwind () -> ()
|
||||||
.import_module stop_unwind, asyncify
|
.import_module stop_unwind, asyncify
|
||||||
|
.import_name stop_unwind, stop_unwind
|
||||||
.functype start_rewind (i32) -> ()
|
.functype start_rewind (i32) -> ()
|
||||||
.import_module start_rewind, asyncify
|
.import_module start_rewind, asyncify
|
||||||
|
.import_name start_rewind, start_rewind
|
||||||
.functype stop_rewind () -> ()
|
.functype stop_rewind () -> ()
|
||||||
.import_module stop_rewind, asyncify
|
.import_module stop_rewind, asyncify
|
||||||
|
.import_name stop_rewind, stop_rewind
|
||||||
|
|
||||||
.global tinygo_unwind
|
.global tinygo_unwind
|
||||||
.hidden tinygo_unwind
|
.hidden tinygo_unwind
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ func swapTask(oldStack uintptr, newStack *uintptr)
|
|||||||
// startTask is a small wrapper function that sets up the first (and only)
|
// startTask is a small wrapper function that sets up the first (and only)
|
||||||
// argument to the new goroutine and makes sure it is exited when the goroutine
|
// argument to the new goroutine and makes sure it is exited when the goroutine
|
||||||
// finishes.
|
// finishes.
|
||||||
|
//
|
||||||
//go:extern tinygo_startTask
|
//go:extern tinygo_startTask
|
||||||
var startTask [0]uint8
|
var startTask [0]uint8
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
// Windows on amd64 has a slightly different ABI than other (*nix) systems.
|
// Windows on amd64 has a slightly different ABI than other (*nix) systems.
|
||||||
// Therefore, assembly functions need to be tweaked slightly.
|
// Therefore, assembly functions need to be tweaked slightly.
|
||||||
|
//
|
||||||
|
// The calling convention is described here:
|
||||||
|
// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
|
||||||
|
|
||||||
.section .text.tinygo_startTask,"ax"
|
.section .text.tinygo_startTask,"ax"
|
||||||
.global tinygo_startTask
|
.global tinygo_startTask
|
||||||
@@ -17,8 +20,9 @@ tinygo_startTask:
|
|||||||
// Branch to the "goroutine start" function.
|
// Branch to the "goroutine start" function.
|
||||||
callq *%r12
|
callq *%r12
|
||||||
|
|
||||||
// After return, exit this goroutine. This is a tail call.
|
// After return, exit this goroutine.
|
||||||
jmp tinygo_pause
|
// This has to be a call, not a jump, to keep the stack correctly aligned.
|
||||||
|
callq tinygo_pause
|
||||||
|
|
||||||
.global tinygo_swapTask
|
.global tinygo_swapTask
|
||||||
.section .text.tinygo_swapTask,"ax"
|
.section .text.tinygo_swapTask,"ax"
|
||||||
@@ -35,6 +39,17 @@ tinygo_swapTask:
|
|||||||
pushq %rsi
|
pushq %rsi
|
||||||
pushq %rdi
|
pushq %rdi
|
||||||
pushq %rbp
|
pushq %rbp
|
||||||
|
sub $160, %rsp
|
||||||
|
movaps %xmm6, 144(%rsp)
|
||||||
|
movaps %xmm7, 128(%rsp)
|
||||||
|
movaps %xmm8, 112(%rsp)
|
||||||
|
movaps %xmm9, 96(%rsp)
|
||||||
|
movaps %xmm10, 80(%rsp)
|
||||||
|
movaps %xmm11, 64(%rsp)
|
||||||
|
movaps %xmm12, 48(%rsp)
|
||||||
|
movaps %xmm13, 32(%rsp)
|
||||||
|
movaps %xmm14, 16(%rsp)
|
||||||
|
movaps %xmm15, 0(%rsp)
|
||||||
pushq %rbx
|
pushq %rbx
|
||||||
|
|
||||||
// Save the current stack pointer in oldStack.
|
// Save the current stack pointer in oldStack.
|
||||||
@@ -45,6 +60,17 @@ tinygo_swapTask:
|
|||||||
|
|
||||||
// Load saved register from the new stack.
|
// Load saved register from the new stack.
|
||||||
popq %rbx
|
popq %rbx
|
||||||
|
movaps 0(%rsp), %xmm15
|
||||||
|
movaps 16(%rsp), %xmm14
|
||||||
|
movaps 32(%rsp), %xmm13
|
||||||
|
movaps 48(%rsp), %xmm12
|
||||||
|
movaps 64(%rsp), %xmm11
|
||||||
|
movaps 80(%rsp), %xmm10
|
||||||
|
movaps 96(%rsp), %xmm9
|
||||||
|
movaps 112(%rsp), %xmm8
|
||||||
|
movaps 128(%rsp), %xmm7
|
||||||
|
movaps 144(%rsp), %xmm6
|
||||||
|
add $160, %rsp
|
||||||
popq %rbp
|
popq %rbp
|
||||||
popq %rdi
|
popq %rdi
|
||||||
popq %rsi
|
popq %rsi
|
||||||
|
|||||||
@@ -13,15 +13,34 @@ var systemStack uintptr
|
|||||||
// calleeSavedRegs is the list of registers that must be saved and restored when
|
// calleeSavedRegs is the list of registers that must be saved and restored when
|
||||||
// switching between tasks. Also see task_stack_amd64_windows.S that relies on
|
// switching between tasks. Also see task_stack_amd64_windows.S that relies on
|
||||||
// the exact layout of this struct.
|
// the exact layout of this struct.
|
||||||
|
// The calling convention is described here:
|
||||||
|
// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
|
||||||
|
// Most importantly, these are the registers we need to save/restore:
|
||||||
|
//
|
||||||
|
// > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14,
|
||||||
|
// > R15, and XMM6-XMM15 nonvolatile. They must be saved and restored by a
|
||||||
|
// > function that uses them.
|
||||||
type calleeSavedRegs struct {
|
type calleeSavedRegs struct {
|
||||||
rbx uintptr
|
// Note: rbx is placed here so that the stack is correctly aligned when
|
||||||
rbp uintptr
|
// loading/storing the xmm registers.
|
||||||
rdi uintptr
|
rbx uintptr
|
||||||
rsi uintptr
|
xmm15 [2]uint64
|
||||||
r12 uintptr
|
xmm14 [2]uint64
|
||||||
r13 uintptr
|
xmm13 [2]uint64
|
||||||
r14 uintptr
|
xmm12 [2]uint64
|
||||||
r15 uintptr
|
xmm11 [2]uint64
|
||||||
|
xmm10 [2]uint64
|
||||||
|
xmm9 [2]uint64
|
||||||
|
xmm8 [2]uint64
|
||||||
|
xmm7 [2]uint64
|
||||||
|
xmm6 [2]uint64
|
||||||
|
rbp uintptr
|
||||||
|
rdi uintptr
|
||||||
|
rsi uintptr
|
||||||
|
r12 uintptr
|
||||||
|
r13 uintptr
|
||||||
|
r14 uintptr
|
||||||
|
r15 uintptr
|
||||||
|
|
||||||
pc uintptr
|
pc uintptr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ type calleeSavedRegs struct {
|
|||||||
|
|
||||||
// archInit runs architecture-specific setup for the goroutine startup.
|
// archInit runs architecture-specific setup for the goroutine startup.
|
||||||
// Note: adding //go:noinline to work around an AVR backend bug.
|
// Note: adding //go:noinline to work around an AVR backend bug.
|
||||||
|
//
|
||||||
//go:noinline
|
//go:noinline
|
||||||
func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {
|
func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {
|
||||||
// Store the initial sp for the startTask function (implemented in assembly).
|
// Store the initial sp for the startTask function (implemented in assembly).
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
// This contains the pin mappings for the Arduino MKR1000 board.
|
// This contains the pin mappings for the Arduino MKR1000 board.
|
||||||
//
|
//
|
||||||
// For more information, see: https://store.arduino.cc/usa/arduino-mkr1000-with-headers-mounted
|
// For more information, see: https://store.arduino.cc/usa/arduino-mkr1000-with-headers-mounted
|
||||||
//
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
// This contains the pin mappings for the Arduino MKR WiFi 1010 board.
|
// This contains the pin mappings for the Arduino MKR WiFi 1010 board.
|
||||||
//
|
//
|
||||||
// For more information, see: https://store.arduino.cc/usa/mkr-wifi-1010
|
// For more information, see: https://store.arduino.cc/usa/mkr-wifi-1010
|
||||||
//
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
// This contains the pin mappings for the Arduino Nano33 IoT board.
|
// This contains the pin mappings for the Arduino Nano33 IoT board.
|
||||||
//
|
//
|
||||||
// For more information, see: https://store.arduino.cc/nano-33-iot
|
// For more information, see: https://store.arduino.cc/nano-33-iot
|
||||||
//
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// GPIO Pins
|
// GPIO Pins
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
// used to reset into bootloader
|
// used to reset into bootloader
|
||||||
const RESET_MAGIC_VALUE = 0x07738135
|
const resetMagicValue = 0x07738135
|
||||||
|
|
||||||
// GPIO Pins - Digital Low
|
// GPIO Pins - Digital Low
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
PB0 = portB + 0
|
PB0 = portB + 0
|
||||||
PB1 = portB + 1
|
PB1 = portB + 1 // peripherals: Timer1 channel A
|
||||||
PB2 = portB + 2
|
PB2 = portB + 2 // peripherals: Timer1 channel B
|
||||||
PB3 = portB + 3
|
PB3 = portB + 3 // peripherals: Timer2 channel A
|
||||||
PB4 = portB + 4
|
PB4 = portB + 4
|
||||||
PB5 = portB + 5
|
PB5 = portB + 5
|
||||||
PB6 = portB + 6
|
PB6 = portB + 6
|
||||||
@@ -30,9 +30,9 @@ const (
|
|||||||
PD0 = portD + 0
|
PD0 = portD + 0
|
||||||
PD1 = portD + 1
|
PD1 = portD + 1
|
||||||
PD2 = portD + 2
|
PD2 = portD + 2
|
||||||
PD3 = portD + 3
|
PD3 = portD + 3 // peripherals: Timer2 channel B
|
||||||
PD4 = portD + 4
|
PD4 = portD + 4
|
||||||
PD5 = portD + 5
|
PD5 = portD + 5 // peripherals: Timer0 channel B
|
||||||
PD6 = portD + 6
|
PD6 = portD + 6 // peripherals: Timer0 channel A
|
||||||
PD7 = portD + 7
|
PD7 = portD + 7
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,38 +10,38 @@ func CPUFrequency() uint32 {
|
|||||||
|
|
||||||
// Hardware pins
|
// Hardware pins
|
||||||
const (
|
const (
|
||||||
PA00 Pin = 0
|
PA00 Pin = 0 // peripherals: TCC2 channel 0
|
||||||
PA01 Pin = 1
|
PA01 Pin = 1 // peripherals: TCC2 channel 1
|
||||||
PA02 Pin = 2
|
PA02 Pin = 2
|
||||||
PA03 Pin = 3
|
PA03 Pin = 3
|
||||||
PA04 Pin = 4
|
PA04 Pin = 4 // peripherals: TCC0 channel 0
|
||||||
PA05 Pin = 5
|
PA05 Pin = 5 // peripherals: TCC0 channel 1
|
||||||
PA06 Pin = 6
|
PA06 Pin = 6 // peripherals: TCC1 channel 0
|
||||||
PA07 Pin = 7
|
PA07 Pin = 7 // peripherals: TCC1 channel 1
|
||||||
PA08 Pin = 8
|
PA08 Pin = 8 // peripherals: TCC0 channel 0, TCC1 channel 2
|
||||||
PA09 Pin = 9
|
PA09 Pin = 9 // peripherals: TCC0 channel 1, TCC1 channel 3
|
||||||
PA10 Pin = 10
|
PA10 Pin = 10 // peripherals: TCC1 channel 0, TCC0 channel 2
|
||||||
PA11 Pin = 11
|
PA11 Pin = 11 // peripherals: TCC1 channel 1, TCC0 channel 3
|
||||||
PA12 Pin = 12
|
PA12 Pin = 12 // peripherals: TCC2 channel 0, TCC0 channel 2
|
||||||
PA13 Pin = 13
|
PA13 Pin = 13 // peripherals: TCC2 channel 1, TCC0 channel 3
|
||||||
PA14 Pin = 14
|
PA14 Pin = 14 // peripherals: TCC0 channel 0
|
||||||
PA15 Pin = 15
|
PA15 Pin = 15 // peripherals: TCC0 channel 1
|
||||||
PA16 Pin = 16
|
PA16 Pin = 16 // peripherals: TCC2 channel 0, TCC0 channel 2
|
||||||
PA17 Pin = 17
|
PA17 Pin = 17 // peripherals: TCC2 channel 1, TCC0 channel 3
|
||||||
PA18 Pin = 18
|
PA18 Pin = 18 // peripherals: TCC0 channel 2
|
||||||
PA19 Pin = 19
|
PA19 Pin = 19 // peripherals: TCC0 channel 3
|
||||||
PA20 Pin = 20
|
PA20 Pin = 20 // peripherals: TCC0 channel 2
|
||||||
PA21 Pin = 21
|
PA21 Pin = 21 // peripherals: TCC0 channel 3
|
||||||
PA22 Pin = 22
|
PA22 Pin = 22 // peripherals: TCC0 channel 0
|
||||||
PA23 Pin = 23
|
PA23 Pin = 23 // peripherals: TCC0 channel 1
|
||||||
PA24 Pin = 24
|
PA24 Pin = 24 // peripherals: TCC1 channel 2
|
||||||
PA25 Pin = 25
|
PA25 Pin = 25 // peripherals: TCC1 channel 3
|
||||||
PA26 Pin = 26
|
PA26 Pin = 26
|
||||||
PA27 Pin = 27
|
PA27 Pin = 27
|
||||||
PA28 Pin = 28
|
PA28 Pin = 28
|
||||||
PA29 Pin = 29
|
PA29 Pin = 29
|
||||||
PA30 Pin = 30
|
PA30 Pin = 30 // peripherals: TCC1 channel 0
|
||||||
PA31 Pin = 31
|
PA31 Pin = 31 // peripherals: TCC1 channel 1
|
||||||
PB00 Pin = 32
|
PB00 Pin = 32
|
||||||
PB01 Pin = 33
|
PB01 Pin = 33
|
||||||
PB02 Pin = 34
|
PB02 Pin = 34
|
||||||
@@ -52,14 +52,14 @@ const (
|
|||||||
PB07 Pin = 39
|
PB07 Pin = 39
|
||||||
PB08 Pin = 40
|
PB08 Pin = 40
|
||||||
PB09 Pin = 41
|
PB09 Pin = 41
|
||||||
PB10 Pin = 42
|
PB10 Pin = 42 // peripherals: TCC0 channel 0
|
||||||
PB11 Pin = 43
|
PB11 Pin = 43 // peripherals: TCC0 channel 1
|
||||||
PB12 Pin = 44
|
PB12 Pin = 44 // peripherals: TCC0 channel 2
|
||||||
PB13 Pin = 45
|
PB13 Pin = 45 // peripherals: TCC0 channel 3
|
||||||
PB14 Pin = 46
|
PB14 Pin = 46
|
||||||
PB15 Pin = 47
|
PB15 Pin = 47
|
||||||
PB16 Pin = 48
|
PB16 Pin = 48 // peripherals: TCC0 channel 0
|
||||||
PB17 Pin = 49
|
PB17 Pin = 49 // peripherals: TCC0 channel 1
|
||||||
PB18 Pin = 50
|
PB18 Pin = 50
|
||||||
PB19 Pin = 51
|
PB19 Pin = 51
|
||||||
PB20 Pin = 52
|
PB20 Pin = 52
|
||||||
@@ -72,6 +72,6 @@ const (
|
|||||||
PB27 Pin = 59
|
PB27 Pin = 59
|
||||||
PB28 Pin = 60
|
PB28 Pin = 60
|
||||||
PB29 Pin = 61
|
PB29 Pin = 61
|
||||||
PB30 Pin = 62
|
PB30 Pin = 62 // peripherals: TCC0 channel 0, TCC1 channel 2
|
||||||
PB31 Pin = 63
|
PB31 Pin = 63 // peripherals: TCC0 channel 1, TCC1 channel 3
|
||||||
)
|
)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user