mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-30 08:38:41 +00:00
Compare commits
165 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf0b7edc78 | |||
| a32cda7a4c | |||
| b251ce7b33 | |||
| 1abe1203a3 | |||
| 8b360ec911 | |||
| 93654544b3 | |||
| 050d516264 | |||
| 9a8328fcb7 | |||
| 6812a4dc04 | |||
| 8568d4f625 | |||
| bd56636d58 | |||
| 4fe3a379a5 | |||
| fce42fc7fa | |||
| 5d177d1328 | |||
| 9eb4a6268a | |||
| 11a402de95 | |||
| cdd9198888 | |||
| 6055e6eb23 | |||
| 9239c61edb | |||
| 008b373df4 | |||
| c387a09f54 | |||
| 5bb3ca2618 | |||
| a4ea85b303 | |||
| 27d38a9663 | |||
| ee497a296b | |||
| 6b31ee1e93 | |||
| cad6a57077 | |||
| 52233790cc | |||
| 9160f3f16d | |||
| 69d7ed5cda | |||
| 111661658b | |||
| 3000b2d15e | |||
| c89f026532 | |||
| e09b1d06f5 | |||
| 0590ccb260 | |||
| fe0acb1670 | |||
| d58c7d2521 | |||
| 85f5411d60 | |||
| c5de68622e | |||
| 8fb93fbac4 | |||
| ef3b3c0d6a | |||
| 2dc46a851b | |||
| f3afc7bbf3 | |||
| 4858b27120 | |||
| 7f507a7026 | |||
| 83227e68df | |||
| 09a3c6a16b | |||
| f613cb41a3 | |||
| e060e588ab | |||
| 8dfb317d28 | |||
| 9cedd78d9c | |||
| 20a27746b2 | |||
| c78df85015 | |||
| c0d257d682 | |||
| 7af24c7864 | |||
| 3dc1e403ea | |||
| 1deee3ec5a | |||
| 0f9f316db2 | |||
| 0dd521e1d1 | |||
| 1dcdd5f2d2 | |||
| dcd8ee63a8 | |||
| b8bf0ac3f1 | |||
| 73571dd423 | |||
| 8872229a0b | |||
| 7e05efa274 | |||
| b02cea0321 | |||
| 8823a934a3 | |||
| 6ac02cc34c | |||
| e259598b68 | |||
| f159573975 | |||
| 234234af15 | |||
| 3d68804702 | |||
| 38efca1e2d | |||
| 0a75dd82b9 | |||
| fbc748f152 | |||
| 881aba1785 | |||
| aa421bf655 | |||
| 1fb1f08233 | |||
| 0b5d300d94 | |||
| 2fdcabdcce | |||
| d066b5c232 | |||
| 836ab95192 | |||
| cf8f4d65f2 | |||
| 06b19cde2d | |||
| 42ae9a665f | |||
| c55c996c5d | |||
| 6fb90b6fc4 | |||
| 6f31712b7d | |||
| e295770363 | |||
| 486b99961d | |||
| 4a98db4c86 | |||
| c534fa1b6f | |||
| eed78338e6 | |||
| 5141638cbf | |||
| 5d4f795aec | |||
| db8603e378 | |||
| bc098da93f | |||
| e49e93f22c | |||
| 7d4bf09b1a | |||
| 320f21524e | |||
| 4117055611 | |||
| 603fff78d4 | |||
| d4b1467e4c | |||
| 4cf8ad2bee | |||
| 96c60f9692 | |||
| 99ce46669b | |||
| a1b4eafa07 | |||
| ccbe03795a | |||
| 3f69c32a55 | |||
| b176494e44 | |||
| 0243a5b8be | |||
| 1fac41d535 | |||
| 1472fb6032 | |||
| 0fd3d785a3 | |||
| b9c0aa77bf | |||
| 4c28f1b875 | |||
| 0791603c86 | |||
| 095312fa3f | |||
| 7e647a5e81 | |||
| 29c1d7c68d | |||
| ecb7eebcff | |||
| a680bfbb7a | |||
| bf23839931 | |||
| 6b15a72895 | |||
| 08fd49fe60 | |||
| d65e3deccf | |||
| cbfa85be6a | |||
| 6c23f27f73 | |||
| 31a3a7c84b | |||
| a9a225ba26 | |||
| 58d0499e55 | |||
| b24af78327 | |||
| b406422277 | |||
| cfed3f0213 | |||
| d75e14245b | |||
| af8244e868 | |||
| f962e2fd15 | |||
| 5746154cc0 | |||
| e9d9ae8781 | |||
| 52ffd6aa98 | |||
| 644356c220 | |||
| 47a622a903 | |||
| 4417374b53 | |||
| 262291a80a | |||
| cdd267fa10 | |||
| 850a5fdbfb | |||
| 4b2edc9a26 | |||
| f2fef290c9 | |||
| 010cc13e9e | |||
| ac7e370c72 | |||
| 77ec9b6369 | |||
| aa8e0bb509 | |||
| 372d9e0f5e | |||
| d139fa5e0f | |||
| 367fb9d40e | |||
| 98a6ed8059 | |||
| 641a7e5cb9 | |||
| 3fa7d6cc40 | |||
| e497b5c5ba | |||
| 23dc861ddb | |||
| b2ccf12e98 | |||
| 23479c92d3 | |||
| 3458726234 | |||
| a7a69d38a4 | |||
| 4210200070 |
@@ -22,15 +22,16 @@ commands:
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- llvm-source-13-v1
|
||||
- llvm-source-14-v1
|
||||
- run:
|
||||
name: "Fetch LLVM source"
|
||||
command: make llvm-source
|
||||
- save_cache:
|
||||
key: llvm-source-13-v1
|
||||
key: llvm-source-14-v1
|
||||
paths:
|
||||
- llvm-project/clang/lib/Headers
|
||||
- llvm-project/clang/include
|
||||
- llvm-project/compiler-rt
|
||||
- llvm-project/lld/include
|
||||
- llvm-project/llvm/include
|
||||
hack-ninja-jobs:
|
||||
@@ -85,10 +86,10 @@ commands:
|
||||
- run: go install -tags=llvm<<parameters.llvm>> .
|
||||
- restore_cache:
|
||||
keys:
|
||||
- wasi-libc-sysroot-systemclang-v3
|
||||
- wasi-libc-sysroot-systemclang-v5
|
||||
- run: make wasi-libc
|
||||
- save_cache:
|
||||
key: wasi-libc-sysroot-systemclang-v3
|
||||
key: wasi-libc-sysroot-systemclang-v5
|
||||
paths:
|
||||
- lib/wasi-libc/sysroot
|
||||
- run: make gen-device -j4
|
||||
@@ -107,9 +108,9 @@ jobs:
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "11"
|
||||
test-llvm12-go116:
|
||||
test-llvm12-go117:
|
||||
docker:
|
||||
- image: circleci/golang:1.16-buster
|
||||
- image: circleci/golang:1.17-buster
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "12"
|
||||
@@ -118,4 +119,4 @@ workflows:
|
||||
test-all:
|
||||
jobs:
|
||||
- test-llvm11-go115
|
||||
- test-llvm12-go116
|
||||
- test-llvm12-go117
|
||||
|
||||
@@ -10,12 +10,12 @@ on:
|
||||
jobs:
|
||||
build-macos:
|
||||
name: build-macos
|
||||
runs-on: macos-10.15
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17'
|
||||
go-version: '1.18.1'
|
||||
- name: Install Dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -35,10 +35,11 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-13-macos-v1
|
||||
key: llvm-source-14-macos-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
llvm-project/compiler-rt
|
||||
llvm-project/lld/include
|
||||
llvm-project/llvm/include
|
||||
- name: Download LLVM source
|
||||
@@ -48,7 +49,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-13-macos-v2
|
||||
key: llvm-build-14-macos-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -66,7 +67,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-v1
|
||||
key: wasi-libc-sysroot-v3
|
||||
path: lib/wasi-libc/sysroot
|
||||
- name: Build wasi-libc
|
||||
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||
@@ -76,6 +77,8 @@ jobs:
|
||||
run: make test GOTESTFLAGS="-v -short"
|
||||
- name: Build TinyGo release tarball
|
||||
run: make release -j3
|
||||
- name: Test stdlib packages
|
||||
run: make tinygo-test
|
||||
- name: Make release artifact
|
||||
shell: bash
|
||||
run: cp -p build/release.tar.gz build/tinygo.darwin-amd64.tar.gz
|
||||
|
||||
@@ -57,3 +57,27 @@ jobs:
|
||||
--header 'Content-Type: application/json' \
|
||||
-d '{"branch": "dev"}' \
|
||||
-u "${{ secrets.CIRCLECI_API_TOKEN }}"
|
||||
- name: Trigger Bluetooth repo build on CircleCI
|
||||
run: |
|
||||
curl --location --request POST 'https://circleci.com/api/v2/project/github/tinygo-org/bluetooth/pipeline' \
|
||||
--header 'Content-Type: application/json' \
|
||||
-d '{"branch": "dev"}' \
|
||||
-u "${{ secrets.CIRCLECI_API_TOKEN }}"
|
||||
- name: Trigger TinyFS repo build on CircleCI
|
||||
run: |
|
||||
curl --location --request POST 'https://circleci.com/api/v2/project/github/tinygo-org/tinyfs/pipeline' \
|
||||
--header 'Content-Type: application/json' \
|
||||
-d '{"branch": "dev"}' \
|
||||
-u "${{ secrets.CIRCLECI_API_TOKEN }}"
|
||||
- name: Trigger TinyFont repo build on CircleCI
|
||||
run: |
|
||||
curl --location --request POST 'https://circleci.com/api/v2/project/github/tinygo-org/tinyfont/pipeline' \
|
||||
--header 'Content-Type: application/json' \
|
||||
-d '{"branch": "dev"}' \
|
||||
-u "${{ secrets.CIRCLECI_API_TOKEN }}"
|
||||
- name: Trigger TinyDraw repo build on CircleCI
|
||||
run: |
|
||||
curl --location --request POST 'https://circleci.com/api/v2/project/github/tinygo-org/tinydraw/pipeline' \
|
||||
--header 'Content-Type: application/json' \
|
||||
-d '{"branch": "dev"}' \
|
||||
-u "${{ secrets.CIRCLECI_API_TOKEN }}"
|
||||
|
||||
+119
-12
@@ -26,7 +26,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17'
|
||||
go-version: '1.18.1'
|
||||
- name: Cache Go
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
@@ -38,10 +38,11 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-13-linux-v1
|
||||
key: llvm-source-14-linux-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
llvm-project/compiler-rt
|
||||
llvm-project/lld/include
|
||||
llvm-project/llvm/include
|
||||
- name: Download LLVM source
|
||||
@@ -51,7 +52,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-13-linux-v1
|
||||
key: llvm-build-14-linux-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -76,14 +77,13 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-linux-asserts-v2
|
||||
key: wasi-libc-sysroot-linux-asserts-v4
|
||||
path: lib/wasi-libc/sysroot
|
||||
- name: Build wasi-libc
|
||||
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||
run: make wasi-libc
|
||||
- name: Install fpm
|
||||
run: |
|
||||
sudo apt-get install ruby ruby-dev
|
||||
sudo gem install --no-document fpm
|
||||
- name: Build TinyGo release
|
||||
run: |
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
- name: Publish release artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release-double-zipped
|
||||
name: linux-amd64-double-zipped
|
||||
path: |
|
||||
/tmp/tinygo.linux-amd64.tar.gz
|
||||
/tmp/tinygo_amd64.deb
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17'
|
||||
go-version: '1.18.1'
|
||||
- name: Install wasmtime
|
||||
run: |
|
||||
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
- name: Download release artifact
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: release-double-zipped
|
||||
name: linux-amd64-double-zipped
|
||||
- name: Extract release tarball
|
||||
run: |
|
||||
mkdir -p ~/lib
|
||||
@@ -159,7 +159,7 @@ jobs:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17'
|
||||
go-version: '1.18.1'
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
@@ -179,10 +179,11 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-13-linux-asserts-v1
|
||||
key: llvm-source-14-linux-asserts-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
llvm-project/compiler-rt
|
||||
llvm-project/lld/include
|
||||
llvm-project/llvm/include
|
||||
- name: Download LLVM source
|
||||
@@ -192,7 +193,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-13-linux-asserts-v1
|
||||
key: llvm-build-14-linux-asserts-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -217,7 +218,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-linux-asserts-v2
|
||||
key: wasi-libc-sysroot-linux-asserts-v4
|
||||
path: lib/wasi-libc/sysroot
|
||||
- name: Build wasi-libc
|
||||
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||
@@ -239,3 +240,109 @@ jobs:
|
||||
rm xtensa-esp32-elf-gcc8_2_0-esp-2020r2-linux-amd64.tar.gz
|
||||
- run: make smoketest
|
||||
- run: make wasmtest
|
||||
- run: make tinygo-baremetal
|
||||
build-linux-arm:
|
||||
# Build ARM Linux binaries, ready for release.
|
||||
# This intentionally uses an older Linux image, so that we compile against
|
||||
# an older glibc version and therefore are compatible with a wide range of
|
||||
# Linux distributions.
|
||||
# It is set to "needs: build-linux" because it modifies the release created
|
||||
# in that process to avoid doing lots of duplicate work and to avoid
|
||||
# complications around precompiled libraries such as compiler-rt shipped as
|
||||
# part of the release tarball.
|
||||
runs-on: ubuntu-18.04
|
||||
needs: build-linux
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Install apt dependencies
|
||||
run: |
|
||||
sudo apt-get install --no-install-recommends \
|
||||
qemu-user \
|
||||
g++-arm-linux-gnueabihf \
|
||||
libc6-dev-armhf-cross
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17'
|
||||
- name: Cache Go
|
||||
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
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
llvm-project/compiler-rt
|
||||
llvm-project/lld/include
|
||||
llvm-project/llvm/include
|
||||
- name: Download LLVM source
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-arm-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
# fetch LLVM source
|
||||
rm -rf llvm-project
|
||||
make llvm-source
|
||||
# Install build dependencies.
|
||||
sudo apt-get install --no-install-recommends ninja-build
|
||||
# build!
|
||||
make llvm-build CROSS=arm-linux-gnueabihf
|
||||
# Remove unnecessary object files (to reduce cache size).
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
- name: Cache Binaryen
|
||||
uses: actions/cache@v2
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-arm-v1
|
||||
path: build/wasm-opt
|
||||
- name: Build Binaryen
|
||||
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
sudo apt-get install --no-install-recommends ninja-build
|
||||
git submodule update --init lib/binaryen
|
||||
make CROSS=arm-linux-gnueabihf binaryen
|
||||
- name: Install fpm
|
||||
run: |
|
||||
sudo gem install --no-document fpm
|
||||
- name: Build TinyGo binary
|
||||
run: |
|
||||
make CROSS=arm-linux-gnueabihf
|
||||
- name: Download amd64 release
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: linux-amd64-double-zipped
|
||||
- name: Extract amd64 release
|
||||
run: |
|
||||
mkdir -p build/release
|
||||
tar -xf tinygo.linux-amd64.tar.gz -C build/release tinygo
|
||||
- name: Modify release
|
||||
run: |
|
||||
cp -p build/tinygo build/release/tinygo/bin
|
||||
cp -p build/wasm-opt build/release/tinygo/bin
|
||||
- name: Create arm release
|
||||
run: |
|
||||
make release deb RELEASEONLY=1 DEB_ARCH=armhf
|
||||
cp -p build/release.tar.gz /tmp/tinygo.linux-arm.tar.gz
|
||||
cp -p build/release.deb /tmp/tinygo_armhf.deb
|
||||
- name: Publish release artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: linux-arm-double-zipped
|
||||
path: |
|
||||
/tmp/tinygo.linux-arm.tar.gz
|
||||
/tmp/tinygo_armhf.deb
|
||||
|
||||
@@ -9,13 +9,13 @@ on:
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.17'
|
||||
- uses: MinoruSekine/setup-scoop@v1
|
||||
go-version: '1.18.1'
|
||||
- uses: brechtm/setup-scoop@v2
|
||||
- name: Install Dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -35,10 +35,11 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-13-windows-v1
|
||||
key: llvm-source-14-windows-v1
|
||||
path: |
|
||||
llvm-project/clang/lib/Headers
|
||||
llvm-project/clang/include
|
||||
llvm-project/compiler-rt
|
||||
llvm-project/lld/include
|
||||
llvm-project/llvm/include
|
||||
- name: Download LLVM source
|
||||
@@ -48,7 +49,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-13-windows-v1
|
||||
key: llvm-build-14-windows-v1
|
||||
path: llvm-build
|
||||
- name: Build LLVM
|
||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||
@@ -65,11 +66,14 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-v1
|
||||
key: wasi-libc-sysroot-v3
|
||||
path: lib/wasi-libc/sysroot
|
||||
- name: Build wasi-libc
|
||||
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||
run: make wasi-libc
|
||||
- name: Install wasmtime
|
||||
run: |
|
||||
scoop install wasmtime
|
||||
- name: Test TinyGo
|
||||
shell: bash
|
||||
run: make test GOTESTFLAGS="-v -short"
|
||||
@@ -95,3 +99,5 @@ jobs:
|
||||
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0 XTENSA=0
|
||||
- name: Test stdlib packages
|
||||
run: make tinygo-test
|
||||
- name: Test stdlib packages on wasi
|
||||
run: make tinygo-test-wasi-fast
|
||||
|
||||
+3
-4
@@ -10,10 +10,6 @@
|
||||
[submodule "lib/cmsis-svd"]
|
||||
path = lib/cmsis-svd
|
||||
url = https://github.com/tinygo-org/cmsis-svd
|
||||
[submodule "lib/compiler-rt"]
|
||||
path = lib/compiler-rt
|
||||
url = https://github.com/llvm-mirror/compiler-rt.git
|
||||
branch = release_80
|
||||
[submodule "lib/wasi-libc"]
|
||||
path = lib/wasi-libc
|
||||
url = https://github.com/CraneStation/wasi-libc
|
||||
@@ -32,3 +28,6 @@
|
||||
[submodule "lib/mingw-w64"]
|
||||
path = lib/mingw-w64
|
||||
url = https://github.com/mingw-w64/mingw-w64.git
|
||||
[submodule "lib/macos-minimal-sdk"]
|
||||
path = lib/macos-minimal-sdk
|
||||
url = https://github.com/aykevl/macos-minimal-sdk.git
|
||||
|
||||
@@ -1,3 +1,101 @@
|
||||
0.23.0
|
||||
---
|
||||
|
||||
* **command line**
|
||||
- add `-work` flag
|
||||
- add Go 1.18 support
|
||||
- add LLVM 14 support
|
||||
- `run`: add support for command-line parameters
|
||||
- `build`: calculate default output path if `-o` is not specified
|
||||
- `build`: add JSON output
|
||||
- `test`: support multiple test binaries with `-c`
|
||||
- `test`: support flags like `-v` on all targets (including emulated firmware)
|
||||
* **compiler**
|
||||
- add support for ThinLTO
|
||||
- use compiler-rt from LLVM
|
||||
- `builder`: prefer GNU build ID over Go build ID for caching
|
||||
- `builder`: add support for cross compiling to Darwin
|
||||
- `builder`: support machine outlining pass in stacksize calculation
|
||||
- `builder`: disable asynchronous unwind tables
|
||||
- `compileopts`: fix emulator configuration on non-amd64 Linux architectures
|
||||
- `compiler`: move allocations > 256 bytes to the heap
|
||||
- `compiler`: fix incorrect `unsafe.Alignof` on some 32-bit architectures
|
||||
- `compiler`: accept alias for slice `cap` builtin
|
||||
- `compiler`: allow slices of empty structs
|
||||
- `compiler`: fix difference in aliases in interface methods
|
||||
- `compiler`: make `RawSyscall` an alias for `Syscall`
|
||||
- `compiler`: remove support for memory references in `AsmFull`
|
||||
- `loader`: only add Clang header path for CGo
|
||||
- `transform`: fix poison value in heap-to-stack transform
|
||||
* **standard library**
|
||||
- `internal/fuzz`: add this package as a shim
|
||||
- `os`: implement readdir for darwin and linux
|
||||
- `os`: add `DirFS`, which is used by many programs to access readdir.
|
||||
- `os`: isWine: be compatible with older versions of wine, too
|
||||
- `os`: implement `RemoveAll`
|
||||
- `os`: Use a `uintptr` for `NewFile`
|
||||
- `os`: add stubs for `exec.ExitError` and `ProcessState.ExitCode`
|
||||
- `os`: export correct values for `DevNull` for each OS
|
||||
- `os`: improve support for `Signal` by fixing various bugs
|
||||
- `os`: implement `File.Fd` method
|
||||
- `os`: implement `UserHomeDir`
|
||||
- `os`: add `exec.ProcessState` stub
|
||||
- `os`: implement `Pipe` for darwin
|
||||
- `os`: define stub `ErrDeadlineExceeded`
|
||||
- `reflect`: add stubs for more missing methods
|
||||
- `reflect`: rename `reflect.Ptr` to `reflect.Pointer`
|
||||
- `reflect`: add `Value.FieldByIndexErr` stub
|
||||
- `runtime`: fix various small GC bugs
|
||||
- `runtime`: use memzero for leaking collector instead of manually zeroing objects
|
||||
- `runtime`: implement `memhash`
|
||||
- `runtime`: implement `fastrand`
|
||||
- `runtime`: add stub for `debug.ReadBuildInfo`
|
||||
- `runtime`: add stub for `NumCPU`
|
||||
- `runtime`: don't inline `runtime.alloc` with `-gc=leaking`
|
||||
- `runtime`: add `Version`
|
||||
- `runtime`: add stubs for `NumCgoCall` and `NumGoroutine`
|
||||
- `runtime`: stub {Lock,Unlock}OSThread on Windows
|
||||
- `runtime`: be able to deal with a very small heap
|
||||
- `syscall`: make `Environ` return a copy of the environment
|
||||
- `syscall`: implement getpagesize and munmap
|
||||
- `syscall`: `wasi`: define `MAP_SHARED` and `PROT_READ`
|
||||
- `syscall`: stub mmap(), munmap(), MAP_SHARED, PROT_READ, SIGBUS, etc. on nonhosted targets
|
||||
- `syscall`: darwin: more complete list of signals
|
||||
- `syscall`: `wasi`: more complete list of signals
|
||||
- `syscall`: stub `WaitStatus`
|
||||
- `syscall/js`: allow copyBytesTo(Go|JS) to use `Uint8ClampedArray`
|
||||
- `testing`: implement `TempDir`
|
||||
- `testing`: nudge type TB closer to upstream; should be a no-op change.
|
||||
- `testing`: on baremetal platforms, use simpler test matcher
|
||||
* **targets**
|
||||
- `atsamd`: fix usbcdc initialization when `-serial=uart`
|
||||
- `atsamd51`: allow higher frequency when using SPI
|
||||
- `esp`: support CGo
|
||||
- `esp32c3`: add support for input pin
|
||||
- `esp32c3`: add support for GPIO interrupts
|
||||
- `esp32c3`: add support to receive UART data
|
||||
- `rp2040`: fix PWM bug at high frequency
|
||||
- `rp2040`: fix some minor I2C bugs
|
||||
- `rp2040`: fix incorrect inline assembly
|
||||
- `rp2040`: fix spurious i2c STOP during write+read transaction
|
||||
- `rp2040`: improve ADC support
|
||||
- `wasi`: remove `--export-dynamic` linker flag
|
||||
- `wasm`: remove heap allocator from wasi-libc
|
||||
* **boards**
|
||||
- `circuitplay-bluefruit`: move pin mappings so board can be compiled for WASM use in Playground
|
||||
- `esp32-c3-12f`: add the ESP32-C3-12f Kit
|
||||
- `m5stamp-c3`: add pin setting of UART
|
||||
- `macropad-rp2040`: add the Adafruit MacroPad RP2040 board
|
||||
- `nano-33-ble`: typo in LPS22HB peripheral definition and documentation (#2579)
|
||||
- `teensy41`: add the Teensy 4.1 board
|
||||
- `teensy40`: add ADC support
|
||||
- `teensy40`: add SPI support
|
||||
- `thingplus-rp2040`: add the SparkFun Thing Plus RP2040 board
|
||||
- `wioterminal`: add DefaultUART
|
||||
- `wioterminal`: verify written data when flashing through OpenOCD
|
||||
- `xiao-ble`: add XIAO BLE nRF52840 support
|
||||
|
||||
|
||||
0.22.0
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||
FROM golang:1.17 AS tinygo-llvm
|
||||
FROM golang:1.18 AS tinygo-llvm
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
||||
|
||||
@@ -10,7 +10,7 @@ LLD_SRC ?= $(LLVM_PROJECTDIR)/lld
|
||||
|
||||
# Try to autodetect LLVM build tools.
|
||||
# Versions are listed here in descending priority order.
|
||||
LLVM_VERSIONS = 13 12 11
|
||||
LLVM_VERSIONS = 14 13 12 11
|
||||
errifempty = $(if $(1),$(1),$(error $(2)))
|
||||
detect = $(shell which $(call errifempty,$(firstword $(foreach p,$(2),$(shell command -v $(p) 2> /dev/null && echo $(p)))),failed to locate $(1) at any of: $(2)))
|
||||
toolSearchPathsVersion = $(1)-$(2)
|
||||
@@ -50,6 +50,29 @@ else
|
||||
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
|
||||
endif
|
||||
|
||||
# Cross compiling support.
|
||||
ifneq ($(CROSS),)
|
||||
CC = $(CROSS)-gcc
|
||||
CXX = $(CROSS)-g++
|
||||
LLVM_OPTION += \
|
||||
-DCMAKE_C_COMPILER=$(CC) \
|
||||
-DCMAKE_CXX_COMPILER=$(CXX) \
|
||||
-DLLVM_DEFAULT_TARGET_TRIPLE=$(CROSS) \
|
||||
-DCROSS_TOOLCHAIN_FLAGS_NATIVE="-UCMAKE_C_COMPILER;-UCMAKE_CXX_COMPILER"
|
||||
ifeq ($(CROSS), arm-linux-gnueabihf)
|
||||
# Assume we're building on a Debian-like distro, with QEMU installed.
|
||||
LLVM_CONFIG_PREFIX = qemu-arm -L /usr/arm-linux-gnueabihf/
|
||||
# The CMAKE_SYSTEM_NAME flag triggers cross compilation mode.
|
||||
LLVM_OPTION += \
|
||||
-DCMAKE_SYSTEM_NAME=Linux \
|
||||
-DLLVM_TARGET_ARCH=ARM
|
||||
GOENVFLAGS = GOARCH=arm CC=$(CC) CXX=$(CXX) CGO_ENABLED=1
|
||||
BINARYEN_OPTION += -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX)
|
||||
else
|
||||
$(error Unknown cross compilation target: $(CROSS))
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr gen-device-rp
|
||||
|
||||
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf debuginfopdb executionengine frontendopenmp instrumentation interpreter ipo irreader libdriver linker lto mc mcjit objcarcopts option profiledata scalaropts support target windowsmanifest
|
||||
@@ -73,6 +96,8 @@ ifeq ($(OS),Windows_NT)
|
||||
else ifeq ($(shell uname -s),Darwin)
|
||||
MD5SUM = md5
|
||||
|
||||
CGO_LDFLAGS += -lxar
|
||||
|
||||
USE_SYSTEM_BINARYEN ?= 1
|
||||
|
||||
else ifeq ($(shell uname -s),FreeBSD)
|
||||
@@ -89,11 +114,11 @@ CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGe
|
||||
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
|
||||
|
||||
# Libraries that should be linked in for the statically linked LLD.
|
||||
LLD_LIB_NAMES = lldCOFF lldCommon lldCore lldDriver lldELF lldMachO lldMinGW lldReaderWriter lldWasm lldYAML
|
||||
LLD_LIB_NAMES = lldCOFF lldCommon lldELF lldMachO lldMinGW lldWasm
|
||||
LLD_LIBS = $(START_GROUP) $(addprefix -l,$(LLD_LIB_NAMES)) $(END_GROUP)
|
||||
|
||||
# Other libraries that are needed to link TinyGo.
|
||||
EXTRA_LIB_NAMES = LLVMInterpreter
|
||||
EXTRA_LIB_NAMES = LLVMInterpreter LLVMMCA LLVMX86TargetMCA
|
||||
|
||||
# All libraries to be built and linked with the tinygo binary (lib/lib*.a).
|
||||
LIB_NAMES = clang $(CLANG_LIB_NAMES) $(LLD_LIB_NAMES) $(EXTRA_LIB_NAMES)
|
||||
@@ -108,9 +133,9 @@ NINJA_BUILD_TARGETS = clang llvm-config llvm-ar llvm-nm $(addprefix lib/lib,$(ad
|
||||
|
||||
# For static linking.
|
||||
ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","")
|
||||
CGO_CPPFLAGS+=$(shell $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include
|
||||
CGO_CPPFLAGS+=$(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include
|
||||
CGO_CXXFLAGS=-std=c++14
|
||||
CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
|
||||
CGO_LDFLAGS+=-L$(abspath $(LLVM_BUILDDIR)/lib) -lclang $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_CONFIG_PREFIX) $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
|
||||
endif
|
||||
|
||||
clean:
|
||||
@@ -173,7 +198,7 @@ gen-device-rp: build/gen-device-svd
|
||||
|
||||
# Get LLVM sources.
|
||||
$(LLVM_PROJECTDIR)/llvm:
|
||||
git clone -b xtensa_release_13.0.0 --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
|
||||
git clone -b xtensa_release_14.0.0-patched --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
|
||||
llvm-source: $(LLVM_PROJECTDIR)/llvm
|
||||
|
||||
# Configure LLVM.
|
||||
@@ -200,25 +225,24 @@ endif
|
||||
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
||||
lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
|
||||
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
|
||||
cd lib/wasi-libc && make -j4 WASM_CFLAGS="-O2 -g -DNDEBUG" WASM_CC=$(CLANG) WASM_AR=$(LLVM_AR) WASM_NM=$(LLVM_NM)
|
||||
cd lib/wasi-libc && make -j4 WASM_CFLAGS="-O2 -g -DNDEBUG" MALLOC_IMPL=none WASM_CC=$(CLANG) WASM_AR=$(LLVM_AR) WASM_NM=$(LLVM_NM)
|
||||
|
||||
|
||||
# Build the Go compiler.
|
||||
tinygo:
|
||||
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " make llvm-source"; echo " make $(LLVM_BUILDDIR)"; exit 1; fi
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags byollvm -ldflags="-X main.gitSha1=`git rev-parse --short HEAD`" .
|
||||
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags byollvm -ldflags="-X github.com/tinygo-org/tinygo/goenv.GitSha1=`git rev-parse --short HEAD`" .
|
||||
test: wasi-libc
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=20m -buildmode exe -tags byollvm ./builder ./cgo ./compileopts ./compiler ./interp ./transform .
|
||||
|
||||
# Tests that 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 = \
|
||||
compress/bzip2 \
|
||||
compress/flate \
|
||||
crypto/dsa \
|
||||
index/suffixarray \
|
||||
|
||||
TEST_PACKAGES_BASE = \
|
||||
# Standard library packages that pass tests quickly on darwin, linux, wasi, and windows
|
||||
TEST_PACKAGES_FAST = \
|
||||
compress/zlib \
|
||||
container/heap \
|
||||
container/list \
|
||||
@@ -247,6 +271,7 @@ TEST_PACKAGES_BASE = \
|
||||
internal/profile \
|
||||
math \
|
||||
math/cmplx \
|
||||
net \
|
||||
net/http/internal/ascii \
|
||||
net/mail \
|
||||
os \
|
||||
@@ -260,40 +285,70 @@ TEST_PACKAGES_BASE = \
|
||||
unicode/utf16 \
|
||||
unicode/utf8 \
|
||||
|
||||
# Standard library packages that pass tests natively
|
||||
TEST_PACKAGES := \
|
||||
$(TEST_PACKAGES_BASE)
|
||||
# archive/zip 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
|
||||
# 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
|
||||
|
||||
# archive/zip requires ReadAt, which is not yet supported on windows
|
||||
ifneq ($(OS),Windows_NT)
|
||||
TEST_PACKAGES := \
|
||||
$(TEST_PACKAGES) \
|
||||
archive/zip
|
||||
# Additional standard library packages that pass tests on individual platforms
|
||||
TEST_PACKAGES_LINUX := \
|
||||
archive/zip \
|
||||
compress/flate \
|
||||
compress/lzw \
|
||||
debug/dwarf \
|
||||
debug/plan9obj \
|
||||
io/fs \
|
||||
testing/fstest
|
||||
|
||||
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
|
||||
|
||||
TEST_PACKAGES_WINDOWS := \
|
||||
compress/lzw
|
||||
|
||||
# Report platforms on which each standard library package is known to pass tests
|
||||
jointmp := $(shell echo /tmp/join.$$$$)
|
||||
report-stdlib-tests-pass:
|
||||
@for t in $(TEST_PACKAGES_DARWIN); do echo "$$t darwin"; done | sort > $(jointmp).darwin
|
||||
@for t in $(TEST_PACKAGES_LINUX); do echo "$$t linux"; done | sort > $(jointmp).linux
|
||||
@for t in $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW); do echo "$$t darwin linux wasi windows"; done | sort > $(jointmp).portable
|
||||
@join -a1 -a2 $(jointmp).darwin $(jointmp).linux | \
|
||||
join -a1 -a2 - $(jointmp).portable
|
||||
@rm $(jointmp).*
|
||||
|
||||
# Standard library packages that pass tests quickly on the current platform
|
||||
ifeq ($(shell uname),Darwin)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
||||
endif
|
||||
ifeq ($(shell uname),Linux)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
||||
endif
|
||||
ifeq ($(OS),Windows_NT)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
||||
endif
|
||||
|
||||
# Standard library packages that pass tests on wasi
|
||||
TEST_PACKAGES_WASI = \
|
||||
$(TEST_PACKAGES_BASE)
|
||||
|
||||
# Test known-working standard library packages.
|
||||
# TODO: parallelize, and only show failing tests (no implied -v flag).
|
||||
.PHONY: tinygo-test
|
||||
tinygo-test:
|
||||
$(TINYGO) test $(TEST_PACKAGES) $(TEST_PACKAGES_SLOW)
|
||||
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-test-fast:
|
||||
$(TINYGO) test $(TEST_PACKAGES)
|
||||
$(TINYGO) test $(TEST_PACKAGES_HOST)
|
||||
tinygo-bench:
|
||||
$(TINYGO) test -bench . $(TEST_PACKAGES) $(TEST_PACKAGES_SLOW)
|
||||
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-bench-fast:
|
||||
$(TINYGO) test -bench . $(TEST_PACKAGES)
|
||||
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST)
|
||||
|
||||
# Same thing, except for wasi rather than the current platform.
|
||||
tinygo-test-wasi:
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_WASI) $(TEST_PACKAGES_SLOW)
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-test-wasi-fast:
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_WASI)
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST)
|
||||
tinygo-bench-wasi:
|
||||
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_WASI) $(TEST_PACKAGES_SLOW)
|
||||
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-bench-wasi-fast:
|
||||
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_WASI)
|
||||
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST)
|
||||
|
||||
# Test external packages in a large corpus.
|
||||
test-corpus:
|
||||
@@ -303,10 +358,16 @@ test-corpus-fast:
|
||||
test-corpus-wasi: wasi-libc
|
||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasi
|
||||
|
||||
tinygo-baremetal:
|
||||
# Regression tests that run on a baremetal target and don't fit in either main_test.go or smoketest.
|
||||
# regression test for #2666: e.g. encoding/hex must pass on baremetal
|
||||
$(TINYGO) test -target cortex-m-qemu encoding/hex
|
||||
|
||||
.PHONY: smoketest
|
||||
smoketest:
|
||||
$(TINYGO) version
|
||||
# compile-only platform-independent examples
|
||||
cd tests/text/template/smoke && $(TINYGO) test -c && rm -f smoke.test
|
||||
# regression test for #2563
|
||||
cd tests/os/smoke && $(TINYGO) test -c -target=pybadge && rm smoke.test
|
||||
# test all examples (except pwm)
|
||||
@@ -354,6 +415,8 @@ ifneq ($(WASM), 0)
|
||||
@$(MD5SUM) test.wasm
|
||||
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_express examples/blinky1
|
||||
@$(MD5SUM) test.wasm
|
||||
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_bluefruit examples/blinky1
|
||||
@$(MD5SUM) test.wasm
|
||||
endif
|
||||
# test all targets/boards
|
||||
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
|
||||
@@ -442,6 +505,8 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=qtpy examples/serial
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=teensy41 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=teensy40 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=teensy36 examples/blinky1
|
||||
@@ -468,6 +533,8 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=macropad-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
# test pwm
|
||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
||||
@$(MD5SUM) test.hex
|
||||
@@ -566,6 +633,7 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
GOOS=linux GOARCH=arm $(TINYGO) build -size short -o test.elf ./testdata/cgo
|
||||
GOOS=windows GOARCH=amd64 $(TINYGO) build -size short -o test.exe ./testdata/cgo
|
||||
GOOS=darwin GOARCH=amd64 $(TINYGO) build -o test ./testdata/cgo
|
||||
ifneq ($(OS),Windows_NT)
|
||||
# TODO: this does not yet work on Windows. Somehow, unused functions are
|
||||
# not garbage collected.
|
||||
@@ -580,7 +648,7 @@ build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN
|
||||
@mkdir -p build/release/tinygo/bin
|
||||
@mkdir -p build/release/tinygo/lib/clang/include
|
||||
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
||||
@mkdir -p build/release/tinygo/lib/compiler-rt/lib
|
||||
@mkdir -p build/release/tinygo/lib/macos-minimal-sdk
|
||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
||||
@mkdir -p build/release/tinygo/lib/musl/arch
|
||||
@@ -601,9 +669,7 @@ endif
|
||||
@cp -p $(abspath $(CLANG_SRC))/lib/Headers/*.h build/release/tinygo/lib/clang/include
|
||||
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
|
||||
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
|
||||
@cp -rp lib/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt/lib
|
||||
@cp -rp lib/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt
|
||||
@cp -rp lib/compiler-rt/README.txt build/release/tinygo/lib/compiler-rt
|
||||
@cp -rp lib/macos-minimal-sdk/* build/release/tinygo/lib/macos-minimal-sdk
|
||||
@cp -rp lib/musl/arch/aarch64 build/release/tinygo/lib/musl/arch
|
||||
@cp -rp lib/musl/arch/arm build/release/tinygo/lib/musl/arch
|
||||
@cp -rp lib/musl/arch/generic build/release/tinygo/lib/musl/arch
|
||||
@@ -639,6 +705,8 @@ endif
|
||||
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
|
||||
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
||||
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
|
||||
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
|
||||
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
|
||||
@cp -rp src build/release/tinygo/src
|
||||
@cp -rp targets build/release/tinygo/targets
|
||||
./build/tinygo build-library -target=cortex-m0 -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0/compiler-rt compiler-rt
|
||||
@@ -648,12 +716,18 @@ endif
|
||||
./build/tinygo build-library -target=cortex-m0plus -o build/release/tinygo/pkg/thumbv6m-unknown-unknown-eabi-cortex-m0plus/picolibc picolibc
|
||||
./build/tinygo build-library -target=cortex-m4 -o build/release/tinygo/pkg/thumbv7em-unknown-unknown-eabi-cortex-m4/picolibc picolibc
|
||||
|
||||
release: build/release
|
||||
release:
|
||||
tar -czf build/release.tar.gz -C build/release tinygo
|
||||
|
||||
deb: build/release
|
||||
DEB_ARCH ?= native
|
||||
deb:
|
||||
@mkdir -p build/release-deb/usr/local/bin
|
||||
@mkdir -p build/release-deb/usr/local/lib
|
||||
cp -ar build/release/tinygo build/release-deb/usr/local/lib/tinygo
|
||||
ln -sf ../lib/tinygo/bin/tinygo build/release-deb/usr/local/bin/tinygo
|
||||
fpm -f -s dir -t deb -n tinygo -v $(shell grep "const Version = " goenv/version.go | awk '{print $$NF}') -m '@tinygo-org' --description='TinyGo is a Go compiler for small places.' --license='BSD 3-Clause' --url=https://tinygo.org/ --deb-changelog CHANGELOG.md -p build/release.deb -C ./build/release-deb
|
||||
fpm -f -s dir -t deb -n tinygo -a $(DEB_ARCH) -v $(shell grep "const Version = " goenv/version.go | awk '{print $$NF}') -m '@tinygo-org' --description='TinyGo is a Go compiler for small places.' --license='BSD 3-Clause' --url=https://tinygo.org/ --deb-changelog CHANGELOG.md -p build/release.deb -C ./build/release-deb
|
||||
|
||||
ifneq ($(RELEASEONLY), 1)
|
||||
release: build/release
|
||||
deb: build/release
|
||||
endif
|
||||
|
||||
@@ -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.
|
||||
|
||||
The following 80 microcontroller boards are currently supported:
|
||||
The following 85 microcontroller boards are currently supported:
|
||||
|
||||
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
||||
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
||||
@@ -59,6 +59,7 @@ The following 80 microcontroller boards are currently supported:
|
||||
* [Adafruit ItsyBitsy M0](https://www.adafruit.com/product/3727)
|
||||
* [Adafruit ItsyBitsy M4](https://www.adafruit.com/product/3800)
|
||||
* [Adafruit ItsyBitsy nRF52840](https://www.adafruit.com/product/4481)
|
||||
* [Adafruit MacroPad RP2040](https://www.adafruit.com/product/5100)
|
||||
* [Adafruit Matrix Portal M4](https://www.adafruit.com/product/4745)
|
||||
* [Adafruit Metro M4 Express Airlift](https://www.adafruit.com/product/4000)
|
||||
* [Adafruit PyBadge](https://www.adafruit.com/product/4200)
|
||||
@@ -84,6 +85,7 @@ The following 80 microcontroller boards are currently supported:
|
||||
* [Dragino LoRaWAN GPS Tracker LGT-92](http://www.dragino.com/products/lora-lorawan-end-node/item/142-lgt-92.html)
|
||||
* [ESP32 - Core board](https://www.espressif.com/en/products/socs/esp32)
|
||||
* [ESP32 - mini32](https://www.espressif.com/en/products/socs/esp32)
|
||||
* [ESP32-C3-12f](https://www.espressif.com/en/products/socs/esp32-c3)
|
||||
* [ESP8266 - d1mini](https://www.espressif.com/en/products/socs/esp8266)
|
||||
* [ESP8266 - NodeMCU](https://www.espressif.com/en/products/socs/esp8266)
|
||||
* [Game Boy Advance](https://en.wikipedia.org/wiki/Game_Boy_Advance)
|
||||
@@ -106,14 +108,17 @@ The following 80 microcontroller boards are currently supported:
|
||||
* [PineTime DevKit](https://www.pine64.org/pinetime/)
|
||||
* [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.1](https://www.pjrc.com/store/teensy41.html)
|
||||
* [ProductivityOpen P1AM-100](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html)
|
||||
* [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/)
|
||||
* [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 XIAO BLE](https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.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 Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
||||
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1)
|
||||
* [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" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
|
||||
* [ST Micro "Nucleo" L031K6](https://www.st.com/ja/evaluation-tools/nucleo-l031k6.html)
|
||||
|
||||
+80
-17
@@ -37,8 +37,14 @@ import (
|
||||
// BuildResult is the output of a build. This includes the binary itself and
|
||||
// some other metadata that is obtained while building the binary.
|
||||
type BuildResult struct {
|
||||
// The executable directly from the linker, usually including debug
|
||||
// information. Used for GDB for example.
|
||||
Executable string
|
||||
|
||||
// A path to the output binary. It will be removed after Build returns, so
|
||||
// if it should be kept it must be copied or moved away.
|
||||
// It is often the same as Executable, but differs if the output format is
|
||||
// .hex for example (instead of the usual ELF).
|
||||
Binary string
|
||||
|
||||
// The directory of the main package. This is useful for testing as the test
|
||||
@@ -99,7 +105,20 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
if config.Options.Work {
|
||||
fmt.Printf("WORK=%s\n", dir)
|
||||
} else {
|
||||
defer os.RemoveAll(dir)
|
||||
}
|
||||
|
||||
// Look up the build cache directory, which is used to speed up incremental
|
||||
// builds.
|
||||
cacheDir := goenv.Get("GOCACHE")
|
||||
if cacheDir == "off" {
|
||||
// Use temporary build directory instead, effectively disabling the
|
||||
// build cache.
|
||||
cacheDir = dir
|
||||
}
|
||||
|
||||
// Check for a libc dependency.
|
||||
// As a side effect, this also creates the headers for the given libc, if
|
||||
@@ -107,6 +126,9 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
root := goenv.Get("TINYGOROOT")
|
||||
var libcDependencies []*compileJob
|
||||
switch config.Target.Libc {
|
||||
case "darwin-libSystem":
|
||||
job := makeDarwinLibSystemJob(config, dir)
|
||||
libcDependencies = append(libcDependencies, job)
|
||||
case "musl":
|
||||
job, unlock, err := Musl.load(config, dir)
|
||||
if err != nil {
|
||||
@@ -188,6 +210,21 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
var packageJobs []*compileJob
|
||||
packageBitcodePaths := make(map[string]string)
|
||||
packageActionIDs := make(map[string]string)
|
||||
|
||||
if config.Options.GlobalValues["runtime"]["buildVersion"] == "" {
|
||||
version := goenv.Version
|
||||
if strings.HasSuffix(goenv.Version, "-dev") && goenv.GitSha1 != "" {
|
||||
version += "-" + goenv.GitSha1
|
||||
}
|
||||
if config.Options.GlobalValues == nil {
|
||||
config.Options.GlobalValues = make(map[string]map[string]string)
|
||||
}
|
||||
if config.Options.GlobalValues["runtime"] == nil {
|
||||
config.Options.GlobalValues["runtime"] = make(map[string]string)
|
||||
}
|
||||
config.Options.GlobalValues["runtime"]["buildVersion"] = version
|
||||
}
|
||||
|
||||
for _, pkg := range lprogram.Sorted() {
|
||||
pkg := pkg // necessary to avoid a race condition
|
||||
|
||||
@@ -231,12 +268,6 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
|
||||
// Determine the path of the bitcode file (which is a serialized version
|
||||
// of a LLVM module).
|
||||
cacheDir := goenv.Get("GOCACHE")
|
||||
if cacheDir == "off" {
|
||||
// Use temporary build directory instead, effectively disabling the
|
||||
// build cache.
|
||||
cacheDir = dir
|
||||
}
|
||||
bitcodePath := filepath.Join(cacheDir, "pkg-"+hex.EncodeToString(hash[:])+".bc")
|
||||
packageBitcodePaths[pkg.ImportPath] = bitcodePath
|
||||
|
||||
@@ -409,7 +440,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
// Load and link all the bitcode files. This does not yet optimize
|
||||
// anything, it only links the bitcode files together.
|
||||
ctx := llvm.NewContext()
|
||||
mod = ctx.NewModule("")
|
||||
mod = ctx.NewModule("main")
|
||||
for _, pkg := range lprogram.Sorted() {
|
||||
pkgMod, err := ctx.ParseBitcodeFile(packageBitcodePaths[pkg.ImportPath])
|
||||
if err != nil {
|
||||
@@ -505,8 +536,14 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
}
|
||||
return ioutil.WriteFile(outpath, llvmBuf.Bytes(), 0666)
|
||||
case ".bc":
|
||||
data := llvm.WriteBitcodeToMemoryBuffer(mod).Bytes()
|
||||
return ioutil.WriteFile(outpath, data, 0666)
|
||||
var buf llvm.MemoryBuffer
|
||||
if config.UseThinLTO() {
|
||||
buf = llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)
|
||||
} else {
|
||||
buf = llvm.WriteBitcodeToMemoryBuffer(mod)
|
||||
}
|
||||
defer buf.Dispose()
|
||||
return ioutil.WriteFile(outpath, buf.Bytes(), 0666)
|
||||
case ".ll":
|
||||
data := []byte(mod.String())
|
||||
return ioutil.WriteFile(outpath, data, 0666)
|
||||
@@ -526,10 +563,17 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
dependencies: []*compileJob{programJob},
|
||||
result: objfile,
|
||||
run: func(*compileJob) error {
|
||||
llvmBuf, err := machine.EmitToMemoryBuffer(mod, llvm.ObjectFile)
|
||||
if err != nil {
|
||||
return err
|
||||
var llvmBuf llvm.MemoryBuffer
|
||||
if config.UseThinLTO() {
|
||||
llvmBuf = llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)
|
||||
} else {
|
||||
var err error
|
||||
llvmBuf, err = machine.EmitToMemoryBuffer(mod, llvm.ObjectFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer llvmBuf.Dispose()
|
||||
return ioutil.WriteFile(objfile, llvmBuf.Bytes(), 0666)
|
||||
},
|
||||
}
|
||||
@@ -562,7 +606,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
job := &compileJob{
|
||||
description: "compile extra file " + path,
|
||||
run: func(job *compileJob) error {
|
||||
result, err := compileAndCacheCFile(abspath, dir, config.CFlags(), config.Options.PrintCommands)
|
||||
result, err := compileAndCacheCFile(abspath, dir, config.CFlags(), config.UseThinLTO(), config.Options.PrintCommands)
|
||||
job.result = result
|
||||
return err
|
||||
},
|
||||
@@ -580,7 +624,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
job := &compileJob{
|
||||
description: "compile CGo file " + abspath,
|
||||
run: func(job *compileJob) error {
|
||||
result, err := compileAndCacheCFile(abspath, dir, pkg.CFlags, config.Options.PrintCommands)
|
||||
result, err := compileAndCacheCFile(abspath, dir, pkg.CFlags, config.UseThinLTO(), config.Options.PrintCommands)
|
||||
job.result = result
|
||||
return err
|
||||
},
|
||||
@@ -649,6 +693,24 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
if config.Options.PrintCommands != nil {
|
||||
config.Options.PrintCommands(config.Target.Linker, ldflags...)
|
||||
}
|
||||
if config.UseThinLTO() {
|
||||
ldflags = append(ldflags,
|
||||
"--thinlto-cache-dir="+filepath.Join(cacheDir, "thinlto"),
|
||||
"-plugin-opt=mcpu="+config.CPU(),
|
||||
"-plugin-opt=O"+strconv.Itoa(optLevel),
|
||||
"-plugin-opt=thinlto")
|
||||
if config.CodeModel() != "default" {
|
||||
ldflags = append(ldflags,
|
||||
"-mllvm", "-code-model="+config.CodeModel())
|
||||
}
|
||||
if sizeLevel >= 2 {
|
||||
// Workaround with roughly the same effect as
|
||||
// https://reviews.llvm.org/D119342.
|
||||
// Can hopefully be removed in LLVM 15.
|
||||
ldflags = append(ldflags,
|
||||
"-mllvm", "--rotation-max-header-size=0")
|
||||
}
|
||||
}
|
||||
err = link(config.Target.Linker, ldflags...)
|
||||
if err != nil {
|
||||
return &commandError{"failed to link", executable, err}
|
||||
@@ -779,7 +841,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "esp32", "esp32c3", "esp8266":
|
||||
case "esp32", "esp32-img", "esp32c3", "esp8266":
|
||||
// Special format for the ESP family of chips (parsed by the ROM
|
||||
// bootloader).
|
||||
tmppath = filepath.Join(dir, "main"+outext)
|
||||
@@ -811,6 +873,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
}
|
||||
|
||||
return action(BuildResult{
|
||||
Executable: executable,
|
||||
Binary: tmppath,
|
||||
MainDir: lprogram.MainPkg().Dir,
|
||||
ModuleRoot: moduleroot,
|
||||
@@ -839,7 +902,7 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
||||
}
|
||||
}
|
||||
|
||||
if config.GOOS() != "darwin" {
|
||||
if config.GOOS() != "darwin" && !config.UseThinLTO() {
|
||||
transform.ApplyFunctionSections(mod) // -ffunction-sections
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -30,6 +30,7 @@ func ReadBuildID() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var gnuID, goID []byte
|
||||
for _, section := range file.Sections {
|
||||
if section.Type != elf.SHT_NOTE ||
|
||||
(section.Name != ".note.gnu.build-id" && section.Name != ".note.go.buildid") {
|
||||
@@ -40,7 +41,16 @@ func ReadBuildID() ([]byte, error) {
|
||||
if uint64(n) != section.Size || err != nil {
|
||||
return nil, fmt.Errorf("could not read build id: %w", err)
|
||||
}
|
||||
return buf, nil
|
||||
if section.Name == ".note.gnu.build-id" {
|
||||
gnuID = buf
|
||||
} else {
|
||||
goID = buf
|
||||
}
|
||||
}
|
||||
if gnuID != nil {
|
||||
return gnuID, nil
|
||||
} else if goID != nil {
|
||||
return goID, nil
|
||||
}
|
||||
case "darwin":
|
||||
// Read the LC_UUID load command, which contains the equivalent of a
|
||||
|
||||
+14
-1
@@ -1,7 +1,11 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
)
|
||||
|
||||
// These are the GENERIC_SOURCES according to CMakeList.txt.
|
||||
@@ -72,6 +76,7 @@ var genericBuiltins = []string{
|
||||
"floatunsisf.c",
|
||||
"floatuntidf.c",
|
||||
"floatuntisf.c",
|
||||
"fp_mode.c",
|
||||
//"int_util.c",
|
||||
"lshrdi3.c",
|
||||
"lshrti3.c",
|
||||
@@ -161,7 +166,15 @@ var CompilerRT = Library{
|
||||
cflags: func(target, headerPath string) []string {
|
||||
return []string{"-Werror", "-Wall", "-std=c11", "-nostdlibinc"}
|
||||
},
|
||||
sourceDir: "lib/compiler-rt/lib/builtins",
|
||||
sourceDir: func() string {
|
||||
llvmDir := filepath.Join(goenv.Get("TINYGOROOT"), "llvm-project/compiler-rt/lib/builtins")
|
||||
if _, err := os.Stat(llvmDir); err == nil {
|
||||
// Release build.
|
||||
return llvmDir
|
||||
}
|
||||
// Development build.
|
||||
return filepath.Join(goenv.Get("TINYGOROOT"), "lib/compiler-rt-builtins")
|
||||
},
|
||||
librarySources: func(target string) []string {
|
||||
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
|
||||
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
|
||||
|
||||
+14
-6
@@ -56,7 +56,7 @@ import (
|
||||
// depfile but without invalidating its name. For this reason, the depfile is
|
||||
// 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.
|
||||
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands func(string, ...string)) (string, error) {
|
||||
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool, printCommands func(string, ...string)) (string, error) {
|
||||
// Hash input file.
|
||||
fileHash, err := hashFile(abspath)
|
||||
if err != nil {
|
||||
@@ -67,6 +67,11 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
||||
unlock := lock(filepath.Join(goenv.Get("GOCACHE"), fileHash+".c.lock"))
|
||||
defer unlock()
|
||||
|
||||
ext := ".o"
|
||||
if thinlto {
|
||||
ext = ".bc"
|
||||
}
|
||||
|
||||
// Create cache key for the dependencies file.
|
||||
buf, err := json.Marshal(struct {
|
||||
Path string
|
||||
@@ -99,7 +104,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
||||
}
|
||||
|
||||
// Obtain hashes of all the files listed as a dependency.
|
||||
outpath, err := makeCFileCachePath(dependencies, depfileNameHash)
|
||||
outpath, err := makeCFileCachePath(dependencies, depfileNameHash, ext)
|
||||
if err == nil {
|
||||
if _, err := os.Stat(outpath); err == nil {
|
||||
return outpath, nil
|
||||
@@ -112,7 +117,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
||||
return "", err
|
||||
}
|
||||
|
||||
objTmpFile, err := ioutil.TempFile(goenv.Get("GOCACHE"), "tmp-*.o")
|
||||
objTmpFile, err := ioutil.TempFile(goenv.Get("GOCACHE"), "tmp-*"+ext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -124,6 +129,9 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
||||
depTmpFile.Close()
|
||||
flags := append([]string{}, cflags...) // copy cflags
|
||||
flags = append(flags, "-MD", "-MV", "-MTdeps", "-MF", depTmpFile.Name()) // autogenerate dependencies
|
||||
if thinlto {
|
||||
flags = append(flags, "-flto=thin")
|
||||
}
|
||||
flags = append(flags, "-c", "-o", objTmpFile.Name(), abspath)
|
||||
if strings.ToLower(filepath.Ext(abspath)) == ".s" {
|
||||
// If this is an assembly file (.s or .S, lowercase or uppercase), then
|
||||
@@ -181,7 +189,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
||||
}
|
||||
|
||||
// Move temporary object file to final location.
|
||||
outpath, err := makeCFileCachePath(dependencySlice, depfileNameHash)
|
||||
outpath, err := makeCFileCachePath(dependencySlice, depfileNameHash, ext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -196,7 +204,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
||||
// Create a cache path (a path in GOCACHE) to store the output of a compiler
|
||||
// job. This path is based on the dep file name (which is a hash of metadata
|
||||
// including compiler flags) and the hash of all input files in the paths slice.
|
||||
func makeCFileCachePath(paths []string, depfileNameHash string) (string, error) {
|
||||
func makeCFileCachePath(paths []string, depfileNameHash, ext string) (string, error) {
|
||||
// Hash all input files.
|
||||
fileHashes := make(map[string]string, len(paths))
|
||||
for _, path := range paths {
|
||||
@@ -221,7 +229,7 @@ func makeCFileCachePath(paths []string, depfileNameHash string) (string, error)
|
||||
outFileNameBuf := sha512.Sum512_224(buf)
|
||||
cacheKey := hex.EncodeToString(outFileNameBuf[:])
|
||||
|
||||
outpath := filepath.Join(goenv.Get("GOCACHE"), "obj-"+cacheKey+".o")
|
||||
outpath := filepath.Join(goenv.Get("GOCACHE"), "obj-"+cacheKey+ext)
|
||||
return outpath, nil
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -38,6 +38,7 @@
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCTargetOptions.h"
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
#include "llvm/Option/OptTable.h"
|
||||
@@ -51,7 +52,6 @@
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@@ -120,7 +120,6 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
|
||||
llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
|
||||
.Case("none", llvm::DebugCompressionType::None)
|
||||
.Case("zlib", llvm::DebugCompressionType::Z)
|
||||
.Case("zlib-gnu", llvm::DebugCompressionType::GNU)
|
||||
.Default(llvm::DebugCompressionType::None);
|
||||
}
|
||||
|
||||
@@ -382,7 +381,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
|
||||
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
|
||||
Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
|
||||
/*DWARFMustBeAtTheEnd*/ true));
|
||||
Str.get()->InitSections(Opts.NoExecStack);
|
||||
Str.get()->initSections(Opts.NoExecStack, *STI);
|
||||
}
|
||||
|
||||
// When -fembed-bitcode is passed to clang_as, a 1-byte marker
|
||||
@@ -442,7 +441,7 @@ bool ExecuteAssembler(AssemblerInvocation &Opts,
|
||||
return Failed;
|
||||
}
|
||||
|
||||
static void LLVMErrorHandler(void *UserData, const std::string &Message,
|
||||
static void LLVMErrorHandler(void *UserData, const char *Message,
|
||||
bool GenCrashDiag) {
|
||||
DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
|
||||
|
||||
|
||||
+2
-2
@@ -33,8 +33,8 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
|
||||
}
|
||||
if major != 1 || minor < 15 || minor > 17 {
|
||||
return nil, fmt.Errorf("requires go version 1.15 through 1.17, got go%d.%d", major, minor)
|
||||
if major != 1 || minor < 15 || minor > 18 {
|
||||
return nil, fmt.Errorf("requires go version 1.15 through 1.18, got go%d.%d", major, minor)
|
||||
}
|
||||
|
||||
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
// Create a job that builds a Darwin libSystem.dylib stub library. This library
|
||||
// contains all the symbols needed so that we can link against it, but it
|
||||
// doesn't contain any real symbol implementations.
|
||||
func makeDarwinLibSystemJob(config *compileopts.Config, tmpdir string) *compileJob {
|
||||
return &compileJob{
|
||||
description: "compile Darwin libSystem.dylib",
|
||||
run: func(job *compileJob) (err error) {
|
||||
arch := strings.Split(config.Triple(), "-")[0]
|
||||
job.result = filepath.Join(tmpdir, "libSystem.dylib")
|
||||
objpath := filepath.Join(tmpdir, "libSystem.o")
|
||||
inpath := filepath.Join(goenv.Get("TINYGOROOT"), "lib/macos-minimal-sdk/src", arch, "libSystem.s")
|
||||
|
||||
// Compile assembly file to object file.
|
||||
flags := []string{
|
||||
"-nostdlib",
|
||||
"--target=" + config.Triple(),
|
||||
"-c",
|
||||
"-o", objpath,
|
||||
inpath,
|
||||
}
|
||||
if config.Options.PrintCommands != nil {
|
||||
config.Options.PrintCommands("clang", flags...)
|
||||
}
|
||||
err = runCCompiler(flags...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Link object file to dynamic library.
|
||||
platformVersion := strings.TrimPrefix(strings.Split(config.Triple(), "-")[2], "macosx")
|
||||
flavor := "darwin"
|
||||
if strings.Split(llvm.Version, ".")[0] < "13" {
|
||||
flavor = "darwinnew" // needed on LLVM 12 and below
|
||||
}
|
||||
flags = []string{
|
||||
"-flavor", flavor,
|
||||
"-demangle",
|
||||
"-dynamic",
|
||||
"-dylib",
|
||||
"-arch", arch,
|
||||
"-platform_version", "macos", platformVersion, platformVersion,
|
||||
"-install_name", "/usr/lib/libSystem.B.dylib",
|
||||
"-o", job.result,
|
||||
objpath,
|
||||
}
|
||||
if config.Options.PrintCommands != nil {
|
||||
config.Options.PrintCommands("ld.lld", flags...)
|
||||
}
|
||||
return link("ld.lld", flags...)
|
||||
},
|
||||
}
|
||||
}
|
||||
+30
-3
@@ -15,6 +15,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type espImageSegment struct {
|
||||
@@ -78,15 +79,31 @@ func makeESPFirmareImage(infile, outfile, format string) error {
|
||||
// An added benefit is that we don't need to check for errors all the time.
|
||||
outf := &bytes.Buffer{}
|
||||
|
||||
// Separate esp32 and esp32-img. The -img suffix indicates we should make an
|
||||
// image, not just a binary to be flashed at 0x1000 for example.
|
||||
chip := format
|
||||
makeImage := false
|
||||
if strings.HasSuffix(format, "-img") {
|
||||
makeImage = true
|
||||
chip = format[:len(format)-len("-img")]
|
||||
}
|
||||
|
||||
if makeImage {
|
||||
// The bootloader starts at 0x1000, or 4096.
|
||||
// TinyGo doesn't use a separate bootloader and runs the entire
|
||||
// application in the bootloader location.
|
||||
outf.Write(make([]byte, 4096))
|
||||
}
|
||||
|
||||
// Chip IDs. Source:
|
||||
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L22
|
||||
chip_id := map[string]uint16{
|
||||
"esp32": 0x0000,
|
||||
"esp32c3": 0x0005,
|
||||
}[format]
|
||||
}[chip]
|
||||
|
||||
// Image header.
|
||||
switch format {
|
||||
switch chip {
|
||||
case "esp32", "esp32c3":
|
||||
// Header format:
|
||||
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71
|
||||
@@ -155,12 +172,22 @@ func makeESPFirmareImage(infile, outfile, format string) error {
|
||||
outf.Write(make([]byte, 15-outf.Len()%16))
|
||||
outf.WriteByte(checksum)
|
||||
|
||||
if format != "esp8266" {
|
||||
if chip != "esp8266" {
|
||||
// SHA256 hash (to protect against image corruption, not for security).
|
||||
hash := sha256.Sum256(outf.Bytes())
|
||||
outf.Write(hash[:])
|
||||
}
|
||||
|
||||
// QEMU (or more precisely, qemu-system-xtensa from Espressif) expects the
|
||||
// image to be a certain size.
|
||||
if makeImage {
|
||||
// Use a default image size of 4MB.
|
||||
grow := 4096*1024 - outf.Len()
|
||||
if grow > 0 {
|
||||
outf.Write(make([]byte, grow))
|
||||
}
|
||||
}
|
||||
|
||||
// Write the image to the output file.
|
||||
return ioutil.WriteFile(outfile, outf.Bytes(), 0666)
|
||||
}
|
||||
|
||||
+21
-5
@@ -24,8 +24,8 @@ type Library struct {
|
||||
// cflags returns the C flags specific to this library
|
||||
cflags func(target, headerPath string) []string
|
||||
|
||||
// The source directory, relative to TINYGOROOT.
|
||||
sourceDir string
|
||||
// The source directory.
|
||||
sourceDir func() string
|
||||
|
||||
// The source files, relative to sourceDir.
|
||||
librarySources func(target string) []string
|
||||
@@ -103,6 +103,10 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
err = os.Chmod(temporaryHeaderPath, 0o755) // TempDir uses 0o700 by default
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
err = os.Rename(temporaryHeaderPath, headerPath)
|
||||
if err != nil {
|
||||
switch {
|
||||
@@ -149,7 +153,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
|
||||
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables")
|
||||
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||
}
|
||||
if strings.HasPrefix(target, "riscv32-") {
|
||||
args = append(args, "-march=rv32imac", "-mabi=ilp32", "-fforce-enable-int128")
|
||||
@@ -157,6 +161,12 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
if strings.HasPrefix(target, "riscv64-") {
|
||||
args = append(args, "-march=rv64gc", "-mabi=lp64")
|
||||
}
|
||||
if strings.HasPrefix(target, "xtensa") {
|
||||
// Hack to work around an issue in the Xtensa port:
|
||||
// https://github.com/espressif/llvm-project/issues/52
|
||||
// Hopefully this will be fixed soon (LLVM 14).
|
||||
args = append(args, "-D__ELF__")
|
||||
}
|
||||
|
||||
var once sync.Once
|
||||
|
||||
@@ -182,11 +192,17 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chmod(f.Name(), 0o644) // TempFile uses 0o600 by default
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Store this archive in the cache.
|
||||
return os.Rename(f.Name(), archiveFilePath)
|
||||
},
|
||||
}
|
||||
|
||||
sourceDir := l.sourceDir()
|
||||
|
||||
// Create jobs to compile all sources. These jobs are depended upon by the
|
||||
// archive job above, so must be run first.
|
||||
for _, path := range l.librarySources(target) {
|
||||
@@ -195,7 +211,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
for strings.HasPrefix(cleanpath, "../") {
|
||||
cleanpath = cleanpath[3:]
|
||||
}
|
||||
srcpath := filepath.Join(goenv.Get("TINYGOROOT"), l.sourceDir, path)
|
||||
srcpath := filepath.Join(sourceDir, path)
|
||||
objpath := filepath.Join(dir, cleanpath+".o")
|
||||
os.MkdirAll(filepath.Dir(objpath), 0o777)
|
||||
objs = append(objs, objpath)
|
||||
@@ -219,7 +235,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
// (It could be done in parallel with creating the ar file, but it probably
|
||||
// won't make much of a difference in speed).
|
||||
if l.crt1Source != "" {
|
||||
srcpath := filepath.Join(goenv.Get("TINYGOROOT"), l.sourceDir, l.crt1Source)
|
||||
srcpath := filepath.Join(sourceDir, l.crt1Source)
|
||||
job.dependencies = append(job.dependencies, &compileJob{
|
||||
description: "compile " + srcpath,
|
||||
run: func(*compileJob) error {
|
||||
|
||||
+8
-3
@@ -8,17 +8,22 @@ extern "C" {
|
||||
|
||||
bool tinygo_link_elf(int argc, char **argv) {
|
||||
std::vector<const char*> args(argv, argv + argc);
|
||||
return lld::elf::link(args, false, llvm::outs(), llvm::errs());
|
||||
return lld::elf::link(args, llvm::outs(), llvm::errs(), false, false);
|
||||
}
|
||||
|
||||
bool tinygo_link_macho(int argc, char **argv) {
|
||||
std::vector<const char*> args(argv, argv + argc);
|
||||
return lld::macho::link(args, llvm::outs(), llvm::errs(), false, false);
|
||||
}
|
||||
|
||||
bool tinygo_link_mingw(int argc, char **argv) {
|
||||
std::vector<const char*> args(argv, argv + argc);
|
||||
return lld::mingw::link(args, false, llvm::outs(), llvm::errs());
|
||||
return lld::mingw::link(args, llvm::outs(), llvm::errs(), false, false);
|
||||
}
|
||||
|
||||
bool tinygo_link_wasm(int argc, char **argv) {
|
||||
std::vector<const char*> args(argv, argv + argc);
|
||||
return lld::wasm::link(args, false, llvm::outs(), llvm::errs());
|
||||
return lld::wasm::link(args, llvm::outs(), llvm::errs(), false, false);
|
||||
}
|
||||
|
||||
} // external "C"
|
||||
|
||||
@@ -26,6 +26,7 @@ var MinGW = Library{
|
||||
_, err = io.Copy(outf, inf)
|
||||
return err
|
||||
},
|
||||
sourceDir: func() string { return "" }, // unused
|
||||
cflags: func(target, headerPath string) []string {
|
||||
// No flags necessary because there are no files to compile.
|
||||
return nil
|
||||
|
||||
+1
-1
@@ -104,7 +104,7 @@ var Musl = Library{
|
||||
"-fno-stack-protector",
|
||||
}
|
||||
},
|
||||
sourceDir: "lib/musl/src",
|
||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl/src") },
|
||||
librarySources: func(target string) []string {
|
||||
arch := compileopts.MuslArchitecture(target)
|
||||
globs := []string{
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ var Picolibc = Library{
|
||||
"-I" + headerPath,
|
||||
}
|
||||
},
|
||||
sourceDir: "lib/picolibc/newlib/libc",
|
||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc") },
|
||||
librarySources: func(target string) []string {
|
||||
return picolibcSources
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build byollvm
|
||||
// +build byollvm
|
||||
|
||||
package builder
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
#include <stdlib.h>
|
||||
bool tinygo_clang_driver(int argc, char **argv);
|
||||
bool tinygo_link_elf(int argc, char **argv);
|
||||
bool tinygo_link_macho(int argc, char **argv);
|
||||
bool tinygo_link_mingw(int argc, char **argv);
|
||||
bool tinygo_link_wasm(int argc, char **argv);
|
||||
*/
|
||||
@@ -26,8 +28,13 @@ const hasBuiltinTools = true
|
||||
// linking statically with LLVM (with the byollvm build tag).
|
||||
func RunTool(tool string, args ...string) error {
|
||||
linker := "elf"
|
||||
if tool == "ld.lld" && len(args) >= 2 && args[0] == "-m" && args[1] == "i386pep" {
|
||||
linker = "mingw"
|
||||
if tool == "ld.lld" && len(args) >= 2 {
|
||||
if args[0] == "-m" && args[1] == "i386pep" {
|
||||
linker = "mingw"
|
||||
} else if args[0] == "-flavor" {
|
||||
linker = args[1]
|
||||
args = args[2:]
|
||||
}
|
||||
}
|
||||
args = append([]string{"tinygo:" + tool}, args...)
|
||||
|
||||
@@ -47,6 +54,8 @@ func RunTool(tool string, args ...string) error {
|
||||
ok = C.tinygo_clang_driver(C.int(len(args)), (**C.char)(buf))
|
||||
case "ld.lld":
|
||||
switch linker {
|
||||
case "darwin", "darwinnew": // darwinnew is only needed for LLVM 12 and below
|
||||
ok = C.tinygo_link_macho(C.int(len(args)), (**C.char)(buf))
|
||||
case "elf":
|
||||
ok = C.tinygo_link_elf(C.int(len(args)), (**C.char)(buf))
|
||||
case "mingw":
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build !byollvm
|
||||
// +build !byollvm
|
||||
|
||||
package builder
|
||||
|
||||
+4
-1
@@ -197,7 +197,7 @@ func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||
// 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
|
||||
// returns these in the []error slice but still modifies the AST.
|
||||
func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
||||
func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
||||
p := &cgoPackage{
|
||||
currentDir: dir,
|
||||
fset: fset,
|
||||
@@ -333,6 +333,9 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
||||
// have better alternatives anyway.
|
||||
cflagsForCGo := append([]string{"-D_FORTIFY_SOURCE=0"}, cflags...)
|
||||
cflagsForCGo = append(cflagsForCGo, p.cflags...)
|
||||
if clangHeaders != "" {
|
||||
cflagsForCGo = append(cflagsForCGo, "-isystem", clangHeaders)
|
||||
}
|
||||
|
||||
// Process CGo imports for each file.
|
||||
for i, f := range files {
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ func TestCGo(t *testing.T) {
|
||||
}
|
||||
|
||||
// Process the AST with CGo.
|
||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags)
|
||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags, "")
|
||||
|
||||
// Check the AST for type errors.
|
||||
var typecheckErrors []error
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
/*
|
||||
#include <clang-c/Index.h> // if this fails, install libclang-11-dev
|
||||
#include <clang-c/Index.h> // If this fails, libclang headers aren't available. Please take a look here: https://tinygo.org/docs/guides/build/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ package cgo
|
||||
|
||||
/*
|
||||
#cgo linux CFLAGS: -I/usr/lib/llvm-11/include
|
||||
#cgo darwin amd64 CFLAGS: -I/usr/local/opt/llvm@11/include
|
||||
#cgo darwin arm64 CFLAGS: -I/opt/homebrew/opt/llvm@11/include
|
||||
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@11/include
|
||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@11/include
|
||||
#cgo freebsd CFLAGS: -I/usr/local/llvm11/include
|
||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-11/lib -lclang
|
||||
#cgo darwin amd64 LDFLAGS: -L/usr/local/opt/llvm@11/lib -lclang -lffi
|
||||
#cgo darwin arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@11/lib -lclang -lffi
|
||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@11/lib -lclang -lffi
|
||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@11/lib -lclang -lffi
|
||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm11/lib -lclang
|
||||
*/
|
||||
import "C"
|
||||
|
||||
@@ -5,12 +5,12 @@ package cgo
|
||||
|
||||
/*
|
||||
#cgo linux CFLAGS: -I/usr/lib/llvm-12/include
|
||||
#cgo darwin amd64 CFLAGS: -I/usr/local/opt/llvm@12/include
|
||||
#cgo darwin arm64 CFLAGS: -I/opt/homebrew/opt/llvm@12/include
|
||||
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@12/include
|
||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@12/include
|
||||
#cgo freebsd CFLAGS: -I/usr/local/llvm12/include
|
||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-12/lib -lclang
|
||||
#cgo darwin amd64 LDFLAGS: -L/usr/local/opt/llvm@12/lib -lclang -lffi
|
||||
#cgo darwin arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@12/lib -lclang -lffi
|
||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@12/lib -lclang -lffi
|
||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@12/lib -lclang -lffi
|
||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm12/lib -lclang
|
||||
*/
|
||||
import "C"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
//go:build !byollvm && !llvm11 && !llvm12
|
||||
// +build !byollvm,!llvm11,!llvm12
|
||||
//go:build !byollvm && !llvm11 && !llvm12 && !llvm14
|
||||
// +build !byollvm,!llvm11,!llvm12,!llvm14
|
||||
|
||||
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 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 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"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//go:build !byollvm && llvm14
|
||||
// +build !byollvm,llvm14
|
||||
|
||||
package cgo
|
||||
|
||||
/*
|
||||
#cgo linux CFLAGS: -I/usr/lib/llvm-14/include
|
||||
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@14/include
|
||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@14/include
|
||||
#cgo freebsd CFLAGS: -I/usr/local/llvm14/include
|
||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-14/lib -lclang
|
||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@14/lib -lclang -lffi
|
||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@14/lib -lclang -lffi
|
||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm14/lib -lclang
|
||||
*/
|
||||
import "C"
|
||||
@@ -3,7 +3,7 @@
|
||||
// are slightly different from the ones defined in libclang.go, but they
|
||||
// should be ABI compatible.
|
||||
|
||||
#include <clang-c/Index.h> // if this fails, install libclang-11-dev
|
||||
#include <clang-c/Index.h> // If this fails, libclang headers aren't available. Please take a look here: https://tinygo.org/docs/guides/build/
|
||||
|
||||
CXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu) {
|
||||
return clang_getTranslationUnitCursor(tu);
|
||||
|
||||
+101
-6
@@ -10,6 +10,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/google/shlex"
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
)
|
||||
|
||||
@@ -176,6 +177,34 @@ func (c *Config) AutomaticStackSize() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// UseThinLTO returns whether ThinLTO should be used for the given target. Some
|
||||
// targets (such as wasm) are not yet supported.
|
||||
// We should try and remove as many exceptions as possible in the future, so
|
||||
// that this optimization can be applied in more places.
|
||||
func (c *Config) UseThinLTO() bool {
|
||||
parts := strings.Split(c.Triple(), "-")
|
||||
if parts[0] == "wasm32" {
|
||||
// wasm-ld doesn't seem to support ThinLTO yet.
|
||||
return false
|
||||
}
|
||||
if parts[0] == "avr" || parts[0] == "xtensa" {
|
||||
// These use external (GNU) linkers which might perhaps support ThinLTO
|
||||
// through a plugin, but it's too much hassle to set up.
|
||||
return false
|
||||
}
|
||||
if len(parts) >= 2 && strings.HasPrefix(parts[2], "macos") {
|
||||
// We use an external linker here at the moment.
|
||||
return false
|
||||
}
|
||||
if len(parts) >= 2 && parts[2] == "windows" {
|
||||
// Linker error (undefined runtime.trackedGlobalsBitmap) when linking
|
||||
// for Windows. Disable it for now until that's figured out and fixed.
|
||||
return false
|
||||
}
|
||||
// Other architectures support ThinLTO.
|
||||
return true
|
||||
}
|
||||
|
||||
// RP2040BootPatch returns whether the RP2040 boot patch should be applied that
|
||||
// calculates and patches in the checksum for the 2nd stage bootloader.
|
||||
func (c *Config) RP2040BootPatch() bool {
|
||||
@@ -217,6 +246,29 @@ func (c *Config) LibcPath(name string) (path string, precompiled bool) {
|
||||
return filepath.Join(goenv.Get("GOCACHE"), name+"-"+archname), false
|
||||
}
|
||||
|
||||
// DefaultBinaryExtension returns the default extension for binaries, such as
|
||||
// .exe, .wasm, or no extension (depending on the target).
|
||||
func (c *Config) DefaultBinaryExtension() string {
|
||||
parts := strings.Split(c.Triple(), "-")
|
||||
if parts[0] == "wasm32" {
|
||||
// WebAssembly files always have the .wasm file extension.
|
||||
return ".wasm"
|
||||
}
|
||||
if len(parts) >= 3 && parts[2] == "windows" {
|
||||
// Windows uses .exe.
|
||||
return ".exe"
|
||||
}
|
||||
if len(parts) >= 3 && parts[2] == "unknown" {
|
||||
// There appears to be a convention to use the .elf file extension for
|
||||
// ELF files intended for microcontrollers. I'm not aware of the origin
|
||||
// of this, it's just something that is used by many projects.
|
||||
// I think it's a good tradition, so let's keep it.
|
||||
return ".elf"
|
||||
}
|
||||
// Linux, MacOS, etc, don't use a file extension. Use it as a fallback.
|
||||
return ""
|
||||
}
|
||||
|
||||
// CFlags returns the flags to pass to the C compiler. This is necessary for CGo
|
||||
// preprocessing.
|
||||
func (c *Config) CFlags() []string {
|
||||
@@ -225,12 +277,18 @@ func (c *Config) CFlags() []string {
|
||||
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
|
||||
}
|
||||
switch c.Target.Libc {
|
||||
case "darwin-libSystem":
|
||||
root := goenv.Get("TINYGOROOT")
|
||||
cflags = append(cflags,
|
||||
"--sysroot="+filepath.Join(root, "lib/macos-minimal-sdk/src"),
|
||||
)
|
||||
case "picolibc":
|
||||
root := goenv.Get("TINYGOROOT")
|
||||
picolibcDir := filepath.Join(root, "lib", "picolibc", "newlib", "libc")
|
||||
path, _ := c.LibcPath("picolibc")
|
||||
cflags = append(cflags,
|
||||
"--sysroot="+path,
|
||||
"-isystem", filepath.Join(path, "include"), // necessary for Xtensa
|
||||
"-isystem", filepath.Join(picolibcDir, "include"),
|
||||
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
|
||||
)
|
||||
@@ -337,6 +395,13 @@ func (c *Config) BinaryFormat(ext string) string {
|
||||
return c.Target.BinaryFormat
|
||||
}
|
||||
return "bin"
|
||||
case ".img":
|
||||
// Image file. Only defined for the ESP32 at the moment, where it is a
|
||||
// full (runnable) image that can be used in the Espressif QEMU fork.
|
||||
if c.Target.BinaryFormat != "" {
|
||||
return c.Target.BinaryFormat + "-img"
|
||||
}
|
||||
return "bin"
|
||||
case ".hex":
|
||||
// Similar to bin, but includes the start address and is thus usually a
|
||||
// better format.
|
||||
@@ -437,13 +502,43 @@ func (c *Config) WasmAbi() string {
|
||||
return c.Target.WasmAbi
|
||||
}
|
||||
|
||||
// Emulator returns the emulator target config
|
||||
func (c *Config) Emulator() []string {
|
||||
var emulator []string
|
||||
for _, s := range c.Target.Emulator {
|
||||
emulator = append(emulator, strings.ReplaceAll(s, "{root}", goenv.Get("TINYGOROOT")))
|
||||
// EmulatorName is a shorthand to get the command for this emulator, something
|
||||
// like qemu-system-arm or simavr.
|
||||
func (c *Config) EmulatorName() string {
|
||||
parts := strings.SplitN(c.Target.Emulator, " ", 2)
|
||||
if len(parts) > 1 {
|
||||
return parts[0]
|
||||
}
|
||||
return emulator
|
||||
return ""
|
||||
}
|
||||
|
||||
// EmulatorFormat returns the binary format for the emulator and the associated
|
||||
// file extension. An empty string means to pass directly whatever the linker
|
||||
// produces directly without conversion (usually ELF format).
|
||||
func (c *Config) EmulatorFormat() (format, fileExt string) {
|
||||
switch {
|
||||
case strings.Contains(c.Target.Emulator, "{img}"):
|
||||
return "img", ".img"
|
||||
default:
|
||||
return "", ""
|
||||
}
|
||||
}
|
||||
|
||||
// Emulator returns a ready-to-run command to run the given binary in an
|
||||
// emulator. Give it the format (returned by EmulatorFormat()) and the path to
|
||||
// the compiled binary.
|
||||
func (c *Config) Emulator(format, binary string) ([]string, error) {
|
||||
parts, err := shlex.Split(c.Target.Emulator)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse emulator command: %w", err)
|
||||
}
|
||||
var emulator []string
|
||||
for _, s := range parts {
|
||||
s = strings.ReplaceAll(s, "{root}", goenv.Get("TINYGOROOT"))
|
||||
s = strings.ReplaceAll(s, "{"+format+"}", binary)
|
||||
emulator = append(emulator, s)
|
||||
}
|
||||
return emulator, nil
|
||||
}
|
||||
|
||||
type TestConfig struct {
|
||||
|
||||
@@ -28,11 +28,12 @@ type Options struct {
|
||||
PanicStrategy string
|
||||
Scheduler string
|
||||
Serial string
|
||||
Work bool // -work flag to print temporary build directory
|
||||
PrintIR bool
|
||||
DumpSSA bool
|
||||
VerifyIR bool
|
||||
PrintCommands func(cmd string, args ...string)
|
||||
Semaphore chan struct{} // -p flag controls cap
|
||||
PrintCommands func(cmd string, args ...string) `json:"-"`
|
||||
Semaphore chan struct{} `json:"-"` // -p flag controls cap
|
||||
Debug bool
|
||||
PrintSizes string
|
||||
PrintAllocs *regexp.Regexp // regexp string
|
||||
@@ -45,6 +46,7 @@ type Options struct {
|
||||
OpenOCDCommands []string
|
||||
LLVMFeatures string
|
||||
Directory string
|
||||
PrintJSON bool
|
||||
}
|
||||
|
||||
// Verify performs a validation on the given options, raising an error if options are not valid.
|
||||
|
||||
+35
-24
@@ -44,8 +44,8 @@ type TargetSpec struct {
|
||||
LDFlags []string `json:"ldflags"`
|
||||
LinkerScript string `json:"linkerscript"`
|
||||
ExtraFiles []string `json:"extra-files"`
|
||||
RP2040BootPatch *bool `json:"rp2040-boot-patch"` // Patch RP2040 2nd stage bootloader checksum
|
||||
Emulator []string `json:"emulator" override:"copy"` // inherited Emulator must not be append
|
||||
RP2040BootPatch *bool `json:"rp2040-boot-patch"` // Patch RP2040 2nd stage bootloader checksum
|
||||
Emulator string `json:"emulator"`
|
||||
FlashCommand string `json:"flash-command"`
|
||||
GDB []string `json:"gdb"`
|
||||
PortReset string `json:"flash-1200-bps-reset"`
|
||||
@@ -59,6 +59,7 @@ type TargetSpec struct {
|
||||
OpenOCDTarget string `json:"openocd-target"`
|
||||
OpenOCDTransport string `json:"openocd-transport"`
|
||||
OpenOCDCommands []string `json:"openocd-commands"`
|
||||
OpenOCDVerify *bool `json:"openocd-verify"` // enable verify when flashing with openocd
|
||||
JLinkDevice string `json:"jlink-device"`
|
||||
CodeModel string `json:"code-model"`
|
||||
RelocationModel string `json:"relocation-model"`
|
||||
@@ -89,19 +90,8 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
|
||||
if !src.IsNil() {
|
||||
dst.Set(src)
|
||||
}
|
||||
case reflect.Slice: // for slices...
|
||||
if src.Len() > 0 { // ... if not empty ...
|
||||
switch tag := field.Tag.Get("override"); tag {
|
||||
case "copy":
|
||||
// copy the field of child to spec
|
||||
dst.Set(src)
|
||||
case "append", "":
|
||||
// or append the field of child to spec
|
||||
dst.Set(reflect.AppendSlice(dst, src))
|
||||
default:
|
||||
panic("override mode must be 'copy' or 'append' (default). I don't know how to '" + tag + "'.")
|
||||
}
|
||||
}
|
||||
case reflect.Slice: // for slices, append the field
|
||||
dst.Set(reflect.AppendSlice(dst, src))
|
||||
default:
|
||||
panic("unknown field type : " + kind.String())
|
||||
}
|
||||
@@ -258,7 +248,7 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
||||
spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
||||
case "arm":
|
||||
spec.CPU = "generic"
|
||||
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables")
|
||||
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||
switch strings.Split(triple, "-")[0] {
|
||||
case "armv5":
|
||||
spec.Features = "+armv5t,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
|
||||
@@ -272,8 +262,20 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
||||
spec.Features = "+neon"
|
||||
}
|
||||
if goos == "darwin" {
|
||||
spec.CFlags = append(spec.CFlags, "-isysroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk")
|
||||
spec.LDFlags = append(spec.LDFlags, "-Wl,-dead_strip")
|
||||
spec.Linker = "ld.lld"
|
||||
spec.Libc = "darwin-libSystem"
|
||||
arch := strings.Split(triple, "-")[0]
|
||||
platformVersion := strings.TrimPrefix(strings.Split(triple, "-")[2], "macosx")
|
||||
flavor := "darwin"
|
||||
if strings.Split(llvm.Version, ".")[0] < "13" {
|
||||
flavor = "darwinnew" // needed on LLVM 12 and below
|
||||
}
|
||||
spec.LDFlags = append(spec.LDFlags,
|
||||
"-flavor", flavor,
|
||||
"-dead_strip",
|
||||
"-arch", arch,
|
||||
"-platform_version", "macos", platformVersion, platformVersion,
|
||||
)
|
||||
} else if goos == "linux" {
|
||||
spec.Linker = "ld.lld"
|
||||
spec.RTLib = "compiler-rt"
|
||||
@@ -317,16 +319,25 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
||||
if goarch != runtime.GOARCH {
|
||||
// Some educated guesses as to how to invoke helper programs.
|
||||
spec.GDB = []string{"gdb-multiarch"}
|
||||
if goarch == "arm" && goos == "linux" {
|
||||
spec.Emulator = []string{"qemu-arm"}
|
||||
}
|
||||
if goarch == "arm64" && goos == "linux" {
|
||||
spec.Emulator = []string{"qemu-aarch64"}
|
||||
if goos == "linux" {
|
||||
switch goarch {
|
||||
case "386":
|
||||
// amd64 can _usually_ run 32-bit programs, so skip the emulator in that case.
|
||||
if runtime.GOARCH != "amd64" {
|
||||
spec.Emulator = "qemu-i386 {}"
|
||||
}
|
||||
case "amd64":
|
||||
spec.Emulator = "qemu-x86_64 {}"
|
||||
case "arm":
|
||||
spec.Emulator = "qemu-arm {}"
|
||||
case "arm64":
|
||||
spec.Emulator = "qemu-aarch64 {}"
|
||||
}
|
||||
}
|
||||
}
|
||||
if goos != runtime.GOOS {
|
||||
if goos == "windows" {
|
||||
spec.Emulator = []string{"wine"}
|
||||
spec.Emulator = "wine {}"
|
||||
}
|
||||
}
|
||||
return &spec, nil
|
||||
|
||||
@@ -29,7 +29,6 @@ func TestOverrideProperties(t *testing.T) {
|
||||
CPU: "baseCpu",
|
||||
CFlags: []string{"-base-foo", "-base-bar"},
|
||||
BuildTags: []string{"bt1", "bt2"},
|
||||
Emulator: []string{"be1", "be2"},
|
||||
DefaultStackSize: 42,
|
||||
AutoStackSize: &baseAutoStackSize,
|
||||
}
|
||||
@@ -38,7 +37,6 @@ func TestOverrideProperties(t *testing.T) {
|
||||
GOOS: "",
|
||||
CPU: "chlidCpu",
|
||||
CFlags: []string{"-child-foo", "-child-bar"},
|
||||
Emulator: []string{"ce1", "ce2"},
|
||||
AutoStackSize: &childAutoStackSize,
|
||||
DefaultStackSize: 64,
|
||||
}
|
||||
@@ -57,9 +55,6 @@ func TestOverrideProperties(t *testing.T) {
|
||||
if !reflect.DeepEqual(base.BuildTags, []string{"bt1", "bt2"}) {
|
||||
t.Errorf("Overriding failed : got %v", base.BuildTags)
|
||||
}
|
||||
if !reflect.DeepEqual(base.Emulator, []string{"ce1", "ce2"}) {
|
||||
t.Errorf("Overriding failed : got %v", base.Emulator)
|
||||
}
|
||||
if *base.AutoStackSize != false {
|
||||
t.Errorf("Overriding failed : got %v", base.AutoStackSize)
|
||||
}
|
||||
|
||||
+28
-10
@@ -234,10 +234,15 @@ func Sizes(machine llvm.TargetMachine) types.Sizes {
|
||||
panic("unknown pointer size")
|
||||
}
|
||||
|
||||
// Construct a complex128 type because that's likely the type with the
|
||||
// biggest alignment on most/all ABIs.
|
||||
ctx := llvm.NewContext()
|
||||
defer ctx.Dispose()
|
||||
complex128Type := ctx.StructType([]llvm.Type{ctx.DoubleType(), ctx.DoubleType()}, false)
|
||||
return &stdSizes{
|
||||
IntSize: int64(intWidth / 8),
|
||||
PtrSize: int64(targetData.PointerSize()),
|
||||
MaxAlign: int64(targetData.PrefTypeAlignment(targetData.IntPtrType())),
|
||||
MaxAlign: int64(targetData.ABITypeAlignment(complex128Type)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -952,10 +957,10 @@ func (b *builder) createFunction() {
|
||||
} else {
|
||||
fieldOffsets := b.expandFormalParamOffsets(llvmType)
|
||||
for i, field := range fields {
|
||||
expr := b.dibuilder.CreateExpression([]int64{
|
||||
0x1000, // DW_OP_LLVM_fragment
|
||||
int64(fieldOffsets[i]) * 8, // offset in bits
|
||||
int64(b.targetData.TypeAllocSize(field.Type())) * 8, // size in bits
|
||||
expr := b.dibuilder.CreateExpression([]uint64{
|
||||
0x1000, // DW_OP_LLVM_fragment
|
||||
fieldOffsets[i] * 8, // offset in bits
|
||||
b.targetData.TypeAllocSize(field.Type()) * 8, // size in bits
|
||||
})
|
||||
b.dibuilder.InsertValueAtEnd(field, dbgParam, expr, loc, entryBlock)
|
||||
}
|
||||
@@ -1228,7 +1233,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
||||
case "cap":
|
||||
value := argValues[0]
|
||||
var llvmCap llvm.Value
|
||||
switch argTypes[0].(type) {
|
||||
switch argTypes[0].Underlying().(type) {
|
||||
case *types.Chan:
|
||||
llvmCap = b.createRuntimeCall("chanCap", []llvm.Value{value}, "cap")
|
||||
case *types.Slice:
|
||||
@@ -1435,7 +1440,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
||||
return b.emitSV64Call(instr.Args)
|
||||
case strings.HasPrefix(name, "(device/riscv.CSR)."):
|
||||
return b.emitCSROperation(instr)
|
||||
case strings.HasPrefix(name, "syscall.Syscall"):
|
||||
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall"):
|
||||
return b.createSyscall(instr)
|
||||
case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
|
||||
return b.createRawSyscallNoError(instr)
|
||||
@@ -1464,6 +1469,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
||||
case *ssa.Function:
|
||||
// Regular function call. No context is necessary.
|
||||
context = llvm.Undef(b.i8ptrType)
|
||||
if info.variadic && len(fn.Params) == 0 {
|
||||
// This matches Clang, see: https://godbolt.org/z/Gqv49xKMq
|
||||
// Eventually we might be able to eliminate this special case
|
||||
// entirely. For details, see:
|
||||
// https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521
|
||||
fnType := llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false)
|
||||
callee = llvm.ConstBitCast(callee, llvm.PointerType(fnType, b.funcPtrAddrSpace))
|
||||
}
|
||||
case *ssa.MakeClosure:
|
||||
// A call on a func value, but the callee is trivial to find. For
|
||||
// example: immediately applied functions.
|
||||
@@ -1549,7 +1562,11 @@ func (c *compilerContext) maxSliceSize(elementType llvm.Type) uint64 {
|
||||
// Determine the maximum allowed size for a slice. The biggest possible
|
||||
// pointer (starting from 0) would be maxPointerValue*sizeof(elementType) so
|
||||
// divide by the element type to get the real maximum size.
|
||||
maxSize := maxPointerValue / c.targetData.TypeAllocSize(elementType)
|
||||
elementSize := c.targetData.TypeAllocSize(elementType)
|
||||
if elementSize == 0 {
|
||||
elementSize = 1
|
||||
}
|
||||
maxSize := maxPointerValue / elementSize
|
||||
|
||||
// len(slice) is an int. Make sure the length remains small enough to fit in
|
||||
// an int.
|
||||
@@ -1571,8 +1588,9 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
|
||||
switch expr := expr.(type) {
|
||||
case *ssa.Alloc:
|
||||
typ := b.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
|
||||
if expr.Heap {
|
||||
size := b.targetData.TypeAllocSize(typ)
|
||||
size := b.targetData.TypeAllocSize(typ)
|
||||
// Move all "large" allocations to the heap. This value is also transform.maxStackAlloc.
|
||||
if expr.Heap || size > 256 {
|
||||
// Calculate ^uintptr(0)
|
||||
maxSize := llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)).ZExtValue()
|
||||
if size > maxSize {
|
||||
|
||||
@@ -226,9 +226,9 @@ func filterIrrelevantIRLines(lines []string) []string {
|
||||
// Right now test outputs are for LLVM 12 and higher.
|
||||
continue
|
||||
}
|
||||
if llvmVersion < 13 && strings.HasPrefix(line, "target datalayout = ") {
|
||||
if llvmVersion < 14 && strings.HasPrefix(line, "target datalayout = ") {
|
||||
// The datalayout string may vary betewen LLVM versions.
|
||||
// Right now test outputs are for LLVM 13 and higher.
|
||||
// Right now test outputs are for LLVM 14 and higher.
|
||||
continue
|
||||
}
|
||||
out = append(out, line)
|
||||
|
||||
@@ -98,7 +98,10 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error)
|
||||
case llvm.IntegerTypeKind:
|
||||
constraints = append(constraints, "r")
|
||||
case llvm.PointerTypeKind:
|
||||
constraints = append(constraints, "*m")
|
||||
// Memory references require a type in LLVM 14, probably as a
|
||||
// preparation for opaque pointers.
|
||||
err = b.makeError(instr.Pos(), "support for pointer operands was dropped in TinyGo 0.23")
|
||||
return s
|
||||
default:
|
||||
err = b.makeError(instr.Pos(), "unknown type in inline assembly for value: "+name)
|
||||
return s
|
||||
|
||||
+79
-45
@@ -152,6 +152,27 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value {
|
||||
return structGlobal
|
||||
}
|
||||
|
||||
var basicTypes = [...]string{
|
||||
types.Bool: "bool",
|
||||
types.Int: "int",
|
||||
types.Int8: "int8",
|
||||
types.Int16: "int16",
|
||||
types.Int32: "int32",
|
||||
types.Int64: "int64",
|
||||
types.Uint: "uint",
|
||||
types.Uint8: "uint8",
|
||||
types.Uint16: "uint16",
|
||||
types.Uint32: "uint32",
|
||||
types.Uint64: "uint64",
|
||||
types.Uintptr: "uintptr",
|
||||
types.Float32: "float32",
|
||||
types.Float64: "float64",
|
||||
types.Complex64: "complex64",
|
||||
types.Complex128: "complex128",
|
||||
types.String: "string",
|
||||
types.UnsafePointer: "unsafe.Pointer",
|
||||
}
|
||||
|
||||
// getTypeCodeName returns a name for this type that can be used in the
|
||||
// interface lowering pass to assign type codes as expected by the reflect
|
||||
// package. See getTypeCodeNum.
|
||||
@@ -162,48 +183,7 @@ func getTypeCodeName(t types.Type) string {
|
||||
case *types.Array:
|
||||
return "array:" + strconv.FormatInt(t.Len(), 10) + ":" + getTypeCodeName(t.Elem())
|
||||
case *types.Basic:
|
||||
var kind string
|
||||
switch t.Kind() {
|
||||
case types.Bool:
|
||||
kind = "bool"
|
||||
case types.Int:
|
||||
kind = "int"
|
||||
case types.Int8:
|
||||
kind = "int8"
|
||||
case types.Int16:
|
||||
kind = "int16"
|
||||
case types.Int32:
|
||||
kind = "int32"
|
||||
case types.Int64:
|
||||
kind = "int64"
|
||||
case types.Uint:
|
||||
kind = "uint"
|
||||
case types.Uint8:
|
||||
kind = "uint8"
|
||||
case types.Uint16:
|
||||
kind = "uint16"
|
||||
case types.Uint32:
|
||||
kind = "uint32"
|
||||
case types.Uint64:
|
||||
kind = "uint64"
|
||||
case types.Uintptr:
|
||||
kind = "uintptr"
|
||||
case types.Float32:
|
||||
kind = "float32"
|
||||
case types.Float64:
|
||||
kind = "float64"
|
||||
case types.Complex64:
|
||||
kind = "complex64"
|
||||
case types.Complex128:
|
||||
kind = "complex128"
|
||||
case types.String:
|
||||
kind = "string"
|
||||
case types.UnsafePointer:
|
||||
kind = "unsafeptr"
|
||||
default:
|
||||
panic("unknown basic type: " + t.Name())
|
||||
}
|
||||
return "basic:" + kind
|
||||
return "basic:" + basicTypes[t.Kind()]
|
||||
case *types.Chan:
|
||||
return "chan:" + getTypeCodeName(t.Elem())
|
||||
case *types.Interface:
|
||||
@@ -591,23 +571,77 @@ func signature(sig *types.Signature) string {
|
||||
if i > 0 {
|
||||
s += ", "
|
||||
}
|
||||
s += sig.Params().At(i).Type().String()
|
||||
s += typestring(sig.Params().At(i).Type())
|
||||
}
|
||||
s += ")"
|
||||
}
|
||||
if sig.Results().Len() == 0 {
|
||||
// keep as-is
|
||||
} else if sig.Results().Len() == 1 {
|
||||
s += " " + sig.Results().At(0).Type().String()
|
||||
s += " " + typestring(sig.Results().At(0).Type())
|
||||
} else {
|
||||
s += " ("
|
||||
for i := 0; i < sig.Results().Len(); i++ {
|
||||
if i > 0 {
|
||||
s += ", "
|
||||
}
|
||||
s += sig.Results().At(i).Type().String()
|
||||
s += typestring(sig.Results().At(i).Type())
|
||||
}
|
||||
s += ")"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// typestring returns a stable (human-readable) type string for the given type
|
||||
// that can be used for interface equality checks. It is almost (but not
|
||||
// exactly) the same as calling t.String(). The main difference is some
|
||||
// normalization around `byte` vs `uint8` for example.
|
||||
func typestring(t types.Type) string {
|
||||
// See: https://github.com/golang/go/blob/master/src/go/types/typestring.go
|
||||
switch t := t.(type) {
|
||||
case *types.Array:
|
||||
return "[" + strconv.FormatInt(t.Len(), 10) + "]" + typestring(t.Elem())
|
||||
case *types.Basic:
|
||||
return basicTypes[t.Kind()]
|
||||
case *types.Chan:
|
||||
switch t.Dir() {
|
||||
case types.SendRecv:
|
||||
return "chan (" + typestring(t.Elem()) + ")"
|
||||
case types.SendOnly:
|
||||
return "chan<- (" + typestring(t.Elem()) + ")"
|
||||
case types.RecvOnly:
|
||||
return "<-chan (" + typestring(t.Elem()) + ")"
|
||||
default:
|
||||
panic("unknown channel direction")
|
||||
}
|
||||
case *types.Interface:
|
||||
methods := make([]string, t.NumMethods())
|
||||
for i := range methods {
|
||||
method := t.Method(i)
|
||||
methods[i] = method.Name() + signature(method.Type().(*types.Signature))
|
||||
}
|
||||
return "interface{" + strings.Join(methods, ";") + "}"
|
||||
case *types.Map:
|
||||
return "map[" + typestring(t.Key()) + "]" + typestring(t.Elem())
|
||||
case *types.Named:
|
||||
return t.String()
|
||||
case *types.Pointer:
|
||||
return "*" + typestring(t.Elem())
|
||||
case *types.Signature:
|
||||
return "func" + signature(t)
|
||||
case *types.Slice:
|
||||
return "[]" + typestring(t.Elem())
|
||||
case *types.Struct:
|
||||
fields := make([]string, t.NumFields())
|
||||
for i := range fields {
|
||||
field := t.Field(i)
|
||||
fields[i] = field.Name() + " " + typestring(field.Type())
|
||||
if tag := t.Tag(i); tag != "" {
|
||||
fields[i] += " " + strconv.Quote(tag)
|
||||
}
|
||||
}
|
||||
return "struct{" + strings.Join(fields, ";") + "}"
|
||||
default:
|
||||
panic("unknown type: " + t.String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (c *checker) checkType(t llvm.Type, checked map[llvm.Type]struct{}, special
|
||||
return fmt.Errorf("type %q uses global context", t.String())
|
||||
default:
|
||||
// we used some other context by accident
|
||||
return fmt.Errorf("type %q uses context %v instead of the main context %v", t.Context(), c.ctx)
|
||||
return fmt.Errorf("type %q uses context %v instead of the main context %v", t.String(), t.Context(), c.ctx)
|
||||
}
|
||||
|
||||
// if this is a composite type, check the components of the type
|
||||
|
||||
+13
-1
@@ -10,6 +10,13 @@ import (
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
// constants for hashmap algorithms; must match src/runtime/hashmap.go
|
||||
const (
|
||||
hashmapAlgorithmBinary = iota
|
||||
hashmapAlgorithmString
|
||||
hashmapAlgorithmInterface
|
||||
)
|
||||
|
||||
// createMakeMap creates a new map object (runtime.hashmap) by allocating and
|
||||
// initializing an appropriately sized object.
|
||||
func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
||||
@@ -17,22 +24,27 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
||||
keyType := mapType.Key().Underlying()
|
||||
llvmValueType := b.getLLVMType(mapType.Elem().Underlying())
|
||||
var llvmKeyType llvm.Type
|
||||
var alg uint64 // must match values in src/runtime/hashmap.go
|
||||
if t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {
|
||||
// String keys.
|
||||
llvmKeyType = b.getLLVMType(keyType)
|
||||
alg = hashmapAlgorithmString
|
||||
} else if hashmapIsBinaryKey(keyType) {
|
||||
// Trivially comparable keys.
|
||||
llvmKeyType = b.getLLVMType(keyType)
|
||||
alg = hashmapAlgorithmBinary
|
||||
} else {
|
||||
// All other keys. Implemented as map[interface{}]valueType for ease of
|
||||
// implementation.
|
||||
llvmKeyType = b.getLLVMRuntimeType("_interface")
|
||||
alg = hashmapAlgorithmInterface
|
||||
}
|
||||
keySize := b.targetData.TypeAllocSize(llvmKeyType)
|
||||
valueSize := b.targetData.TypeAllocSize(llvmValueType)
|
||||
llvmKeySize := llvm.ConstInt(b.ctx.Int8Type(), keySize, false)
|
||||
llvmValueSize := llvm.ConstInt(b.ctx.Int8Type(), valueSize, false)
|
||||
sizeHint := llvm.ConstInt(b.uintptrType, 8, false)
|
||||
algEnum := llvm.ConstInt(b.ctx.Int8Type(), alg, false)
|
||||
if expr.Reserve != nil {
|
||||
sizeHint = b.getValue(expr.Reserve)
|
||||
var err error
|
||||
@@ -41,7 +53,7 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
||||
return llvm.Value{}, err
|
||||
}
|
||||
}
|
||||
hashmap := b.createRuntimeCall("hashmapMake", []llvm.Value{llvmKeySize, llvmValueSize, sizeHint}, "")
|
||||
hashmap := b.createRuntimeCall("hashmapMake", []llvm.Value{llvmKeySize, llvmValueSize, sizeHint, algEnum}, "")
|
||||
return hashmap, nil
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'basic.go'
|
||||
source_filename = "basic.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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"
|
||||
|
||||
%main.kv = type { float }
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'channel.go'
|
||||
source_filename = "channel.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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"
|
||||
|
||||
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'float.go'
|
||||
source_filename = "float.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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*)
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'func.go'
|
||||
source_filename = "func.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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*)
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'gc.go'
|
||||
source_filename = "gc.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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"
|
||||
|
||||
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 }
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'go1.17.go'
|
||||
source_filename = "go1.17.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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*)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'goroutine.go'
|
||||
source_filename = "goroutine.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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"
|
||||
|
||||
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
||||
|
||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'interface.go'
|
||||
source_filename = "interface.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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"
|
||||
|
||||
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 }
|
||||
@@ -128,5 +128,5 @@ declare %runtime._string @"interface:{Error:func:{}{basic:string}}.Error$invoke"
|
||||
attributes #0 = { nounwind }
|
||||
attributes #1 = { "tinygo-methods"="reflect/methods.Error() string" }
|
||||
attributes #2 = { "tinygo-methods"="reflect/methods.String() string" }
|
||||
attributes #3 = { "tinygo-invoke"="main.$methods.foo(int) byte" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) byte" }
|
||||
attributes #3 = { "tinygo-invoke"="main.$methods.foo(int) uint8" "tinygo-methods"="reflect/methods.String() string; main.$methods.foo(int) uint8" }
|
||||
attributes #4 = { "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" }
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'intrinsics.go'
|
||||
source_filename = "intrinsics.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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*)
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'pointer.go'
|
||||
source_filename = "pointer.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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*)
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'pragma.go'
|
||||
source_filename = "pragma.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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"
|
||||
|
||||
@extern_global = external global [0 x i8], align 1
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'slice.go'
|
||||
source_filename = "slice.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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*)
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
; ModuleID = 'string.go'
|
||||
source_filename = "string.go"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
|
||||
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"
|
||||
|
||||
%runtime._string = type { i8*, i32 }
|
||||
|
||||
@@ -15,5 +15,5 @@ require (
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
||||
golang.org/x/tools v0.1.6-0.20210813165731-45389f592fe9
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
tinygo.org/x/go-llvm v0.0.0-20220121152956-4fa2ab2718f3
|
||||
tinygo.org/x/go-llvm v0.0.0-20220420140351-512c94c1e71f
|
||||
)
|
||||
|
||||
@@ -80,5 +80,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
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/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220121152956-4fa2ab2718f3 h1:vQSFy0kNQegAfL/F6iyWQa4bF941Xc1gyJUkGy2m448=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220121152956-4fa2ab2718f3/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220420140351-512c94c1e71f h1:9/J+NpFTpAhYcbh1mC4dr9W/aAPnwrUh8dmq21xWdSM=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220420140351-512c94c1e71f/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
|
||||
+9
-3
@@ -12,7 +12,13 @@ import (
|
||||
|
||||
// Version of TinyGo.
|
||||
// Update this value before release of new version of software.
|
||||
const Version = "0.22.0"
|
||||
const Version = "0.23.0"
|
||||
|
||||
var (
|
||||
// This variable is set at build time using -ldflags parameters.
|
||||
// See: https://stackoverflow.com/a/11355611
|
||||
GitSha1 string
|
||||
)
|
||||
|
||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||
// If the goroot cannot be determined, (0, 0) is returned.
|
||||
@@ -52,9 +58,9 @@ func GorootVersionString(goroot string) (string, error) {
|
||||
return string(data), nil
|
||||
|
||||
} else if data, err := ioutil.ReadFile(filepath.Join(
|
||||
goroot, "src", "runtime", "internal", "sys", "zversion.go")); err == nil {
|
||||
goroot, "src", "internal", "buildcfg", "zbootstrap.go")); err == nil {
|
||||
|
||||
r := regexp.MustCompile("const TheVersion = `(.*)`")
|
||||
r := regexp.MustCompile("const version = `(.*)`")
|
||||
matches := r.FindSubmatch(data)
|
||||
if len(matches) != 2 {
|
||||
return "", errors.New("Invalid go version output:\n" + string(data))
|
||||
|
||||
@@ -492,9 +492,9 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
||||
// Call a function with a definition available. Run it as usual,
|
||||
// possibly trying to recover from it if it failed to execute.
|
||||
if r.debug {
|
||||
argStrings := make([]string, len(operands))
|
||||
for i := range argStrings {
|
||||
argStrings[i] = operands[i+1].String()
|
||||
argStrings := make([]string, len(operands)-1)
|
||||
for i, v := range operands[1:] {
|
||||
argStrings[i] = v.String()
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, indent+"call:", callFn.name+"("+strings.Join(argStrings, ", ")+")")
|
||||
}
|
||||
|
||||
Vendored
+1
-4
@@ -1,8 +1,6 @@
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64--linux"
|
||||
|
||||
@"main$alloc.1" = internal unnamed_addr constant [6 x i8] c"\05\00{\00\00\04", align 8
|
||||
|
||||
declare void @runtime.printuint8(i8) local_unnamed_addr
|
||||
|
||||
declare void @runtime.printint16(i16) local_unnamed_addr
|
||||
@@ -17,7 +15,6 @@ entry:
|
||||
call void @runtime.printuint8(i8 3)
|
||||
call void @runtime.printuint8(i8 3)
|
||||
call void @runtime.printint16(i16 5)
|
||||
%int16SliceDst.val = load i16, i16* bitcast ([6 x i8]* @"main$alloc.1" to i16*), align 2
|
||||
call void @runtime.printint16(i16 %int16SliceDst.val)
|
||||
call void @runtime.printint16(i16 5)
|
||||
ret void
|
||||
}
|
||||
|
||||
Submodule lib/compiler-rt deleted from 5bc79797e1
Submodule
+1
Submodule lib/macos-minimal-sdk added at ebb736fda2
@@ -230,6 +230,7 @@ func pathsToOverride(needsSyscallPackage bool) map[string]bool {
|
||||
"device/": false,
|
||||
"examples/": false,
|
||||
"internal/": true,
|
||||
"internal/fuzz/": false,
|
||||
"internal/bytealg/": false,
|
||||
"internal/reflectlite/": false,
|
||||
"internal/task/": false,
|
||||
|
||||
+1
-4
@@ -418,10 +418,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
||||
var initialCFlags []string
|
||||
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
||||
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
||||
if p.program.clangHeaders != "" {
|
||||
initialCFlags = append(initialCFlags, "-isystem", p.program.clangHeaders)
|
||||
}
|
||||
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.program.fset, initialCFlags)
|
||||
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.program.fset, initialCFlags, p.program.clangHeaders)
|
||||
p.CFlags = append(initialCFlags, cflags...)
|
||||
p.CGoHeaders = headerCode
|
||||
for path, hash := range accessedFiles {
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
@@ -36,12 +37,6 @@ import (
|
||||
"go.bug.st/serial/enumerator"
|
||||
)
|
||||
|
||||
var (
|
||||
// This variable is set at build time using -ldflags parameters.
|
||||
// See: https://stackoverflow.com/a/11355611
|
||||
gitSha1 string
|
||||
)
|
||||
|
||||
// commandError is an error type to wrap os/exec.Command errors. This provides
|
||||
// some more information regarding what went wrong while running a command.
|
||||
type commandError struct {
|
||||
@@ -148,7 +143,27 @@ func Build(pkgName, outpath string, options *compileopts.Options) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if options.PrintJSON {
|
||||
b, err := json.MarshalIndent(config, "", " ")
|
||||
if err != nil {
|
||||
handleCompilerError(err)
|
||||
}
|
||||
fmt.Printf("%s\n", string(b))
|
||||
return nil
|
||||
}
|
||||
|
||||
return builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
|
||||
if outpath == "" {
|
||||
if strings.HasSuffix(pkgName, ".go") {
|
||||
// A Go file was specified directly on the command line.
|
||||
// Base the binary name off of it.
|
||||
outpath = filepath.Base(pkgName[:len(pkgName)-3]) + config.DefaultBinaryExtension()
|
||||
} else {
|
||||
// Pick a default output path based on the main directory.
|
||||
outpath = filepath.Base(result.MainDir) + config.DefaultBinaryExtension()
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Rename(result.Binary, outpath); err != nil {
|
||||
// Moving failed. Do a file copy.
|
||||
inf, err := os.Open(result.Binary)
|
||||
@@ -185,8 +200,26 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Pass test flags to the test binary.
|
||||
var flags []string
|
||||
if testVerbose {
|
||||
flags = append(flags, "-test.v")
|
||||
}
|
||||
if testShort {
|
||||
flags = append(flags, "-test.short")
|
||||
}
|
||||
if testRunRegexp != "" {
|
||||
flags = append(flags, "-test.run="+testRunRegexp)
|
||||
}
|
||||
if testBenchRegexp != "" {
|
||||
flags = append(flags, "-test.bench="+testBenchRegexp)
|
||||
}
|
||||
if testBenchTime != "" {
|
||||
flags = append(flags, "-test.benchtime="+testBenchTime)
|
||||
}
|
||||
|
||||
passed := false
|
||||
err = builder.Build(pkgName, outpath, config, func(result builder.BuildResult) error {
|
||||
err = buildAndRun(pkgName, config, os.Stdout, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||
if testCompileOnly || outpath != "" {
|
||||
// Write test binary to the specified file name.
|
||||
if outpath == "" {
|
||||
@@ -202,27 +235,52 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run the test.
|
||||
config.Options.Semaphore <- struct{}{}
|
||||
defer func() {
|
||||
<-config.Options.Semaphore
|
||||
}()
|
||||
start := time.Now()
|
||||
var err error
|
||||
passed, err = runPackageTest(config, stdout, stderr, result, testVerbose, testShort, testRunRegexp, testBenchRegexp, testBenchTime)
|
||||
if err != nil {
|
||||
return err
|
||||
// Tests are always run in the package directory.
|
||||
cmd.Dir = result.MainDir
|
||||
|
||||
// Wasmtime needs a few extra flags to work.
|
||||
if config.EmulatorName() == "wasmtime" {
|
||||
// Add directories to the module root, but skip the current working
|
||||
// directory which is already added by buildAndRun.
|
||||
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
|
||||
var args []string
|
||||
for _, d := range dirs[1:] {
|
||||
args = append(args, "--dir="+d)
|
||||
}
|
||||
|
||||
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
|
||||
tmpdir, err := ioutil.TempDir("", "tinygotmp")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temporary directory: %w", err)
|
||||
}
|
||||
args = append(args, "--dir="+tmpdir, "--env=TMPDIR="+tmpdir)
|
||||
// TODO: add option to not delete temp dir for debugging?
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// Insert new argments at the front of the command line argments.
|
||||
args = append(args, cmd.Args[1:]...)
|
||||
cmd.Args = append(cmd.Args[:1:1], args...)
|
||||
}
|
||||
|
||||
// Run the test.
|
||||
start := time.Now()
|
||||
err = cmd.Run()
|
||||
duration := time.Since(start)
|
||||
|
||||
// Print the result.
|
||||
importPath := strings.TrimSuffix(result.ImportPath, ".test")
|
||||
passed = err == nil
|
||||
if passed {
|
||||
fmt.Fprintf(stdout, "ok \t%s\t%.3fs\n", importPath, duration.Seconds())
|
||||
} else {
|
||||
fmt.Fprintf(stdout, "FAIL\t%s\t%.3fs\n", importPath, duration.Seconds())
|
||||
}
|
||||
return nil
|
||||
if _, ok := err.(*exec.ExitError); ok {
|
||||
// Binary exited with a non-zero exit code, which means the test
|
||||
// failed.
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
})
|
||||
if err, ok := err.(loader.NoTestFilesError); ok {
|
||||
fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", err.ImportPath)
|
||||
@@ -245,81 +303,6 @@ func dirsToModuleRoot(maindir, modroot string) []string {
|
||||
return dirs
|
||||
}
|
||||
|
||||
// runPackageTest runs a test binary that was previously built. The return
|
||||
// values are whether the test passed and any errors encountered while trying to
|
||||
// run the binary.
|
||||
func runPackageTest(config *compileopts.Config, stdout, stderr io.Writer, result builder.BuildResult, testVerbose, testShort bool, testRunRegexp string, testBenchRegexp string, testBenchTime string) (bool, error) {
|
||||
var cmd *exec.Cmd
|
||||
emulator := config.Emulator()
|
||||
if len(emulator) == 0 {
|
||||
// Run directly.
|
||||
var flags []string
|
||||
if testVerbose {
|
||||
flags = append(flags, "-test.v")
|
||||
}
|
||||
if testShort {
|
||||
flags = append(flags, "-test.short")
|
||||
}
|
||||
if testRunRegexp != "" {
|
||||
flags = append(flags, "-test.run="+testRunRegexp)
|
||||
}
|
||||
if testBenchRegexp != "" {
|
||||
flags = append(flags, "-test.bench="+testBenchRegexp)
|
||||
}
|
||||
if testBenchTime != "" {
|
||||
flags = append(flags, "-test.benchtime="+testBenchTime)
|
||||
}
|
||||
cmd = executeCommand(config.Options, result.Binary, flags...)
|
||||
} else {
|
||||
// Run in an emulator.
|
||||
args := append(emulator[1:], result.Binary)
|
||||
if emulator[0] == "wasmtime" {
|
||||
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
|
||||
tmpdir, err := ioutil.TempDir("", "tinygotmp")
|
||||
if err != nil {
|
||||
return false, &commandError{"failed to create temporary directory", "tinygotmp", err}
|
||||
}
|
||||
args = append(args, "--dir="+tmpdir, "--env=TMPDIR="+tmpdir)
|
||||
// TODO: add option to not delete temp dir for debugging?
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// allow reading from directories up to module root
|
||||
for _, d := range dirsToModuleRoot(result.MainDir, result.ModuleRoot) {
|
||||
args = append(args, "--dir="+d)
|
||||
}
|
||||
|
||||
// mark end of wasmtime arguments and start of program ones: --
|
||||
args = append(args, "--")
|
||||
if testVerbose {
|
||||
args = append(args, "-test.v")
|
||||
}
|
||||
if testShort {
|
||||
args = append(args, "-test.short")
|
||||
}
|
||||
if testRunRegexp != "" {
|
||||
args = append(args, "-test.run="+testRunRegexp)
|
||||
}
|
||||
if testBenchRegexp != "" {
|
||||
args = append(args, "-test.bench="+testBenchRegexp)
|
||||
}
|
||||
}
|
||||
cmd = executeCommand(config.Options, emulator[0], args...)
|
||||
}
|
||||
cmd.Dir = result.MainDir
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
if _, ok := err.(*exec.ExitError); ok {
|
||||
// Binary exited with a non-zero exit code, which means the test
|
||||
// failed.
|
||||
return false, nil
|
||||
}
|
||||
return false, &commandError{"failed to run compiled binary", result.Binary, err}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Flash builds and flashes the built binary to the given serial port.
|
||||
func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
config, err := builder.NewConfig(options)
|
||||
@@ -439,7 +422,11 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
args = append(args, "-c", "program "+filepath.ToSlash(result.Binary)+" reset exit")
|
||||
exit := " reset exit"
|
||||
if config.Target.OpenOCDVerify != nil && *config.Target.OpenOCDVerify {
|
||||
exit = " verify" + exit
|
||||
}
|
||||
args = append(args, "-c", "program "+filepath.ToSlash(result.Binary)+exit)
|
||||
cmd := executeCommand(config.Options, "openocd", args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
@@ -496,18 +483,19 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
||||
return err
|
||||
}
|
||||
|
||||
return builder.Build(pkgName, "", config, func(result builder.BuildResult) error {
|
||||
format, fileExt := config.EmulatorFormat()
|
||||
return builder.Build(pkgName, fileExt, config, func(result builder.BuildResult) error {
|
||||
// Find a good way to run GDB.
|
||||
gdbInterface, openocdInterface := config.Programmer()
|
||||
switch gdbInterface {
|
||||
case "msd", "command", "":
|
||||
emulator := config.Emulator()
|
||||
if len(emulator) != 0 {
|
||||
if emulator[0] == "mgba" {
|
||||
emulator := config.EmulatorName()
|
||||
if emulator != "" {
|
||||
if emulator == "mgba" {
|
||||
gdbInterface = "mgba"
|
||||
} else if emulator[0] == "simavr" {
|
||||
} else if emulator == "simavr" {
|
||||
gdbInterface = "simavr"
|
||||
} else if strings.HasPrefix(emulator[0], "qemu-system-") {
|
||||
} else if strings.HasPrefix(emulator, "qemu-system-") {
|
||||
gdbInterface = "qemu"
|
||||
} else {
|
||||
// Assume QEMU as an emulator.
|
||||
@@ -526,6 +514,10 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
||||
port := ""
|
||||
var gdbCommands []string
|
||||
var daemon *exec.Cmd
|
||||
emulator, err := config.Emulator(format, result.Binary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch gdbInterface {
|
||||
case "native":
|
||||
// Run GDB directly.
|
||||
@@ -575,33 +567,29 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
||||
}
|
||||
case "qemu":
|
||||
port = ":1234"
|
||||
emulator := config.Emulator()
|
||||
// Run in an emulator.
|
||||
args := append(emulator[1:], result.Binary, "-s", "-S")
|
||||
args := append(emulator[1:], "-s", "-S")
|
||||
daemon = executeCommand(config.Options, emulator[0], args...)
|
||||
daemon.Stdout = os.Stdout
|
||||
daemon.Stderr = os.Stderr
|
||||
case "qemu-user":
|
||||
port = ":1234"
|
||||
emulator := config.Emulator()
|
||||
// Run in an emulator.
|
||||
args := append(emulator[1:], "-g", "1234", result.Binary)
|
||||
args := append(emulator[1:], "-g", "1234")
|
||||
daemon = executeCommand(config.Options, emulator[0], args...)
|
||||
daemon.Stdout = os.Stdout
|
||||
daemon.Stderr = os.Stderr
|
||||
case "mgba":
|
||||
port = ":2345"
|
||||
emulator := config.Emulator()
|
||||
// Run in an emulator.
|
||||
args := append(emulator[1:], result.Binary, "-g")
|
||||
args := append(emulator[1:], "-g")
|
||||
daemon = executeCommand(config.Options, emulator[0], args...)
|
||||
daemon.Stdout = os.Stdout
|
||||
daemon.Stderr = os.Stderr
|
||||
case "simavr":
|
||||
port = ":1234"
|
||||
emulator := config.Emulator()
|
||||
// Run in an emulator.
|
||||
args := append(emulator[1:], "-g", result.Binary)
|
||||
args := append(emulator[1:], "-g")
|
||||
daemon = executeCommand(config.Options, emulator[0], args...)
|
||||
daemon.Stdout = os.Stdout
|
||||
daemon.Stderr = os.Stderr
|
||||
@@ -646,7 +634,7 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
||||
// Construct and execute a gdb or lldb command.
|
||||
// By default: gdb -ex run <binary>
|
||||
// Exit the debugger with Ctrl-D.
|
||||
params := []string{result.Binary}
|
||||
params := []string{result.Executable}
|
||||
switch debugger {
|
||||
case "gdb":
|
||||
if port != "" {
|
||||
@@ -678,9 +666,9 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return &commandError{"failed to run " + cmdName + " with", result.Binary, err}
|
||||
return &commandError{"failed to run " + cmdName + " with", result.Executable, err}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -690,44 +678,134 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
||||
// the options, it will run the program directly on the host or will run it in
|
||||
// an emulator. For example, -target=wasm will cause the binary to be run inside
|
||||
// of a WebAssembly VM.
|
||||
func Run(pkgName string, options *compileopts.Options) error {
|
||||
func Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {
|
||||
config, err := builder.NewConfig(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return builder.Build(pkgName, ".elf", config, func(result builder.BuildResult) error {
|
||||
emulator := config.Emulator()
|
||||
if len(emulator) == 0 {
|
||||
// Run directly.
|
||||
cmd := executeCommand(config.Options, result.Binary)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
if err, ok := err.(*exec.ExitError); ok && err.Exited() {
|
||||
// Workaround for QEMU which always exits with an error.
|
||||
return nil
|
||||
}
|
||||
return &commandError{"failed to run compiled binary", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
// Run in an emulator.
|
||||
args := append(emulator[1:], result.Binary)
|
||||
cmd := executeCommand(config.Options, emulator[0], args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
if err, ok := err.(*exec.ExitError); ok && err.Exited() {
|
||||
// Workaround for QEMU which always exits with an error.
|
||||
return nil
|
||||
}
|
||||
return &commandError{"failed to run emulator with", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
return buildAndRun(pkgName, config, os.Stdout, cmdArgs, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||
return cmd.Run()
|
||||
})
|
||||
}
|
||||
|
||||
// buildAndRun builds and runs the given program, writing output to stdout and
|
||||
// errors to os.Stderr. It takes care of emulators (qemu, wasmtime, etc) and
|
||||
// passes command line arguments and evironment variables in a way appropriate
|
||||
// for the given emulator.
|
||||
func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, cmdArgs, environmentVars []string, timeout time.Duration, run func(cmd *exec.Cmd, result builder.BuildResult) error) error {
|
||||
// Determine whether we're on a system that supports environment variables
|
||||
// and command line parameters (operating systems, WASI) or not (baremetal,
|
||||
// WebAssembly in the browser). If we're on a system without an environment,
|
||||
// we need to pass command line arguments and environment variables through
|
||||
// global variables (built into the binary directly) instead of the
|
||||
// conventional way.
|
||||
needsEnvInVars := config.GOOS() == "js"
|
||||
for _, tag := range config.BuildTags() {
|
||||
if tag == "baremetal" {
|
||||
needsEnvInVars = true
|
||||
}
|
||||
}
|
||||
var args, env []string
|
||||
if needsEnvInVars {
|
||||
runtimeGlobals := make(map[string]string)
|
||||
if len(cmdArgs) != 0 {
|
||||
runtimeGlobals["osArgs"] = strings.Join(cmdArgs, "\x00")
|
||||
}
|
||||
if len(environmentVars) != 0 {
|
||||
runtimeGlobals["osEnv"] = strings.Join(environmentVars, "\x00")
|
||||
}
|
||||
if len(runtimeGlobals) != 0 {
|
||||
// This sets the global variables like they would be set with
|
||||
// `-ldflags="-X=runtime.osArgs=first\x00second`.
|
||||
// The runtime package has two variables (osArgs and osEnv) that are
|
||||
// both strings, from which the parameters and environment variables
|
||||
// are read.
|
||||
config.Options.GlobalValues = map[string]map[string]string{
|
||||
"runtime": runtimeGlobals,
|
||||
}
|
||||
}
|
||||
} else if config.EmulatorName() == "wasmtime" {
|
||||
// Wasmtime needs some special flags to pass environment variables
|
||||
// and allow reading from the current directory.
|
||||
args = append(args, "--dir=.")
|
||||
for _, v := range environmentVars {
|
||||
args = append(args, "--env", v)
|
||||
}
|
||||
if len(cmdArgs) != 0 {
|
||||
// mark end of wasmtime arguments and start of program ones: --
|
||||
args = append(args, "--")
|
||||
args = append(args, cmdArgs...)
|
||||
}
|
||||
} else {
|
||||
// Pass environment variables and command line parameters as usual.
|
||||
// This also works on qemu-aarch64 etc.
|
||||
args = cmdArgs
|
||||
env = environmentVars
|
||||
}
|
||||
|
||||
format, fileExt := config.EmulatorFormat()
|
||||
return builder.Build(pkgName, fileExt, config, func(result builder.BuildResult) error {
|
||||
// If needed, set a timeout on the command. This is done in tests so
|
||||
// they don't waste resources on a stalled test.
|
||||
var ctx context.Context
|
||||
if timeout != 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
// Set up the command.
|
||||
var name string
|
||||
if config.Target.Emulator == "" {
|
||||
name = result.Binary
|
||||
} else {
|
||||
emulator, err := config.Emulator(format, result.Binary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name = emulator[0]
|
||||
emuArgs := append([]string(nil), emulator[1:]...)
|
||||
args = append(emuArgs, args...)
|
||||
}
|
||||
var cmd *exec.Cmd
|
||||
if ctx != nil {
|
||||
cmd = exec.CommandContext(ctx, name, args...)
|
||||
} else {
|
||||
cmd = exec.Command(name, args...)
|
||||
}
|
||||
cmd.Env = env
|
||||
|
||||
// Configure stdout/stderr. The stdout may go to a buffer, not a real
|
||||
// stdout.
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if config.EmulatorName() == "simavr" {
|
||||
cmd.Stdout = nil // don't print initial load commands
|
||||
cmd.Stderr = stdout
|
||||
}
|
||||
|
||||
// If this is a test, reserve CPU time for it so that increased
|
||||
// parallelism doesn't blow up memory usage. If this isn't a test but
|
||||
// simply `tinygo run`, then it is practically a no-op.
|
||||
config.Options.Semaphore <- struct{}{}
|
||||
defer func() {
|
||||
<-config.Options.Semaphore
|
||||
}()
|
||||
|
||||
// Run binary.
|
||||
if config.Options.PrintCommands != nil {
|
||||
config.Options.PrintCommands(cmd.Path, cmd.Args...)
|
||||
}
|
||||
err := run(cmd, result)
|
||||
if err != nil {
|
||||
if ctx != nil && ctx.Err() == context.DeadlineExceeded {
|
||||
stdout.Write([]byte(fmt.Sprintf("--- timeout of %s exceeded, terminating...\n", timeout)))
|
||||
err = ctx.Err()
|
||||
}
|
||||
return &commandError{"failed to run compiled binary", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1012,8 +1090,8 @@ func getBMPPorts() (gdbPort, uartPort string, err error) {
|
||||
|
||||
func usage(command string) {
|
||||
version := goenv.Version
|
||||
if strings.HasSuffix(version, "-dev") && gitSha1 != "" {
|
||||
version += "-" + gitSha1
|
||||
if strings.HasSuffix(version, "-dev") && goenv.GitSha1 != "" {
|
||||
version += "-" + goenv.GitSha1
|
||||
}
|
||||
|
||||
switch command {
|
||||
@@ -1187,6 +1265,7 @@ func main() {
|
||||
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
||||
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
|
||||
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
|
||||
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
|
||||
printIR := flag.Bool("printir", false, "print LLVM IR")
|
||||
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
||||
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
||||
@@ -1207,13 +1286,13 @@ func main() {
|
||||
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
||||
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
||||
|
||||
var flagJSON, flagDeps, flagTest *bool
|
||||
if command == "help" || command == "list" || command == "info" {
|
||||
flagJSON = flag.Bool("json", false, "print data in JSON format")
|
||||
var flagJSON, flagDeps, flagTest bool
|
||||
if command == "help" || command == "list" || command == "info" || command == "build" {
|
||||
flag.BoolVar(&flagJSON, "json", false, "print data in JSON format")
|
||||
}
|
||||
if command == "help" || command == "list" {
|
||||
flagDeps = flag.Bool("deps", false, "supply -deps flag to go list")
|
||||
flagTest = flag.Bool("test", false, "supply -test flag to go list")
|
||||
flag.BoolVar(&flagDeps, "deps", false, "supply -deps flag to go list")
|
||||
flag.BoolVar(&flagTest, "test", false, "supply -test flag to go list")
|
||||
}
|
||||
var outpath string
|
||||
if command == "help" || command == "build" || command == "build-library" || command == "test" {
|
||||
@@ -1275,6 +1354,7 @@ func main() {
|
||||
PanicStrategy: *panicStrategy,
|
||||
Scheduler: *scheduler,
|
||||
Serial: *serial,
|
||||
Work: *work,
|
||||
PrintIR: *printIR,
|
||||
DumpSSA: *dumpSSA,
|
||||
VerifyIR: *verifyIR,
|
||||
@@ -1289,6 +1369,7 @@ func main() {
|
||||
Programmer: *programmer,
|
||||
OpenOCDCommands: ocdCommands,
|
||||
LLVMFeatures: *llvmFeatures,
|
||||
PrintJSON: flagJSON,
|
||||
}
|
||||
if *printCommands {
|
||||
options.PrintCommands = printCommand
|
||||
@@ -1317,11 +1398,6 @@ func main() {
|
||||
|
||||
switch command {
|
||||
case "build":
|
||||
if outpath == "" {
|
||||
fmt.Fprintln(os.Stderr, "No output filename supplied (-o).")
|
||||
usage(command)
|
||||
os.Exit(1)
|
||||
}
|
||||
pkgName := "."
|
||||
if flag.NArg() == 1 {
|
||||
pkgName = filepath.ToSlash(flag.Arg(0))
|
||||
@@ -1395,13 +1471,13 @@ func main() {
|
||||
handleCompilerError(err)
|
||||
}
|
||||
case "run":
|
||||
if flag.NArg() != 1 {
|
||||
if flag.NArg() < 1 {
|
||||
fmt.Fprintln(os.Stderr, "No package specified.")
|
||||
usage(command)
|
||||
os.Exit(1)
|
||||
}
|
||||
pkgName := filepath.ToSlash(flag.Arg(0))
|
||||
err := Run(pkgName, options)
|
||||
err := Run(pkgName, options, flag.Args()[1:])
|
||||
handleCompilerError(err)
|
||||
case "test":
|
||||
var pkgNames []string
|
||||
@@ -1411,8 +1487,8 @@ func main() {
|
||||
if len(pkgNames) == 0 {
|
||||
pkgNames = []string{"."}
|
||||
}
|
||||
if *testCompileOnlyFlag && len(pkgNames) > 1 {
|
||||
fmt.Println("cannot use -c flag with multiple packages")
|
||||
if outpath != "" && len(pkgNames) > 1 {
|
||||
fmt.Println("cannot use -o flag with multiple packages")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -1497,7 +1573,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == nil {
|
||||
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
|
||||
// This doesn't look like a regular target file, but rather like
|
||||
// a parent target (such as targets/cortex-m.json).
|
||||
continue
|
||||
@@ -1530,7 +1606,7 @@ func main() {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if *flagJSON {
|
||||
if flagJSON {
|
||||
json, _ := json.MarshalIndent(struct {
|
||||
GOROOT string `json:"goroot"`
|
||||
GOOS string `json:"goos"`
|
||||
@@ -1569,13 +1645,13 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
var extraArgs []string
|
||||
if *flagJSON {
|
||||
if flagJSON {
|
||||
extraArgs = append(extraArgs, "-json")
|
||||
}
|
||||
if *flagDeps {
|
||||
if flagDeps {
|
||||
extraArgs = append(extraArgs, "-deps")
|
||||
}
|
||||
if *flagTest {
|
||||
if flagTest {
|
||||
extraArgs = append(extraArgs, "-test")
|
||||
}
|
||||
cmd, err := loader.List(config, extraArgs, flag.Args())
|
||||
@@ -1612,8 +1688,8 @@ func main() {
|
||||
goversion = s
|
||||
}
|
||||
version := goenv.Version
|
||||
if strings.HasSuffix(goenv.Version, "-dev") && gitSha1 != "" {
|
||||
version += "-" + gitSha1
|
||||
if strings.HasSuffix(goenv.Version, "-dev") && goenv.GitSha1 != "" {
|
||||
version += "-" + goenv.GitSha1
|
||||
}
|
||||
fmt.Printf("tinygo version %s %s/%s (using go version %s and LLVM version %s)\n", version, runtime.GOOS, runtime.GOARCH, goversion, llvm.Version)
|
||||
case "env":
|
||||
|
||||
+36
-121
@@ -6,7 +6,6 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
@@ -14,7 +13,6 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
@@ -31,6 +29,13 @@ const TESTDATA = "testdata"
|
||||
|
||||
var testTarget = flag.String("target", "", "override test target")
|
||||
|
||||
var supportedLinuxArches = map[string]string{
|
||||
"AMD64Linux": "linux/amd64",
|
||||
"X86Linux": "linux/386",
|
||||
"ARMLinux": "linux/arm/6",
|
||||
"ARM64Linux": "linux/arm64",
|
||||
}
|
||||
|
||||
var sema = make(chan struct{}, runtime.NumCPU())
|
||||
|
||||
func TestBuild(t *testing.T) {
|
||||
@@ -59,7 +64,6 @@ func TestBuild(t *testing.T) {
|
||||
"stdlib.go",
|
||||
"string.go",
|
||||
"structs.go",
|
||||
"testing.go",
|
||||
"zeroalloc.go",
|
||||
}
|
||||
_, minor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
|
||||
@@ -69,6 +73,11 @@ func TestBuild(t *testing.T) {
|
||||
if minor >= 17 {
|
||||
tests = append(tests, "go1.17.go")
|
||||
}
|
||||
if minor >= 18 {
|
||||
tests = append(tests, "testing_go118.go")
|
||||
} else {
|
||||
tests = append(tests, "testing.go")
|
||||
}
|
||||
|
||||
if *testTarget != "" {
|
||||
// This makes it possible to run one specific test (instead of all),
|
||||
@@ -180,18 +189,14 @@ func TestBuild(t *testing.T) {
|
||||
})
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
t.Run("X86Linux", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runPlatTests(optionsFromOSARCH("linux/386", sema), tests, t)
|
||||
})
|
||||
t.Run("ARMLinux", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runPlatTests(optionsFromOSARCH("linux/arm/6", sema), tests, t)
|
||||
})
|
||||
t.Run("ARM64Linux", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runPlatTests(optionsFromOSARCH("linux/arm64", sema), tests, t)
|
||||
})
|
||||
for name, osArch := range supportedLinuxArches {
|
||||
options := optionsFromOSARCH(osArch, sema)
|
||||
if options.GOARCH != runtime.GOARCH { // Native architecture already run above.
|
||||
t.Run(name, func(t *testing.T) {
|
||||
runPlatTests(options, tests, t)
|
||||
})
|
||||
}
|
||||
}
|
||||
t.Run("WebAssembly", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runPlatTests(optionsFromTarget("wasm", sema), tests, t)
|
||||
@@ -218,7 +223,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
||||
runTest(name, options, t, nil, nil)
|
||||
})
|
||||
}
|
||||
if len(spec.Emulator) == 0 || spec.Emulator[0] != "simavr" {
|
||||
if !strings.HasPrefix(spec.Emulator, "simavr ") {
|
||||
t.Run("env.go", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
runTest("env.go", options, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"})
|
||||
@@ -252,8 +257,8 @@ func emuCheck(t *testing.T, options compileopts.Options) {
|
||||
if err != nil {
|
||||
t.Fatal("failed to load target spec:", err)
|
||||
}
|
||||
if len(spec.Emulator) != 0 {
|
||||
_, err := exec.LookPath(spec.Emulator[0])
|
||||
if spec.Emulator != "" {
|
||||
_, err := exec.LookPath(strings.SplitN(spec.Emulator, " ", 2)[0])
|
||||
if err != nil {
|
||||
if errors.Is(err, exec.ErrNotFound) {
|
||||
t.Skipf("emulator not installed: %q", spec.Emulator[0])
|
||||
@@ -317,117 +322,27 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
||||
t.Fatal("could not read expected output file:", err)
|
||||
}
|
||||
|
||||
// Create a temporary directory for test output files.
|
||||
tmpdir := t.TempDir()
|
||||
|
||||
// Determine whether we're on a system that supports environment variables
|
||||
// and command line parameters (operating systems, WASI) or not (baremetal,
|
||||
// WebAssembly in the browser). If we're on a system without an environment,
|
||||
// we need to pass command line arguments and environment variables through
|
||||
// global variables (built into the binary directly) instead of the
|
||||
// conventional way.
|
||||
spec, err := compileopts.LoadTarget(&options)
|
||||
config, err := builder.NewConfig(&options)
|
||||
if err != nil {
|
||||
t.Fatal("failed to load target spec:", err)
|
||||
}
|
||||
needsEnvInVars := spec.GOOS == "js"
|
||||
for _, tag := range spec.BuildTags {
|
||||
if tag == "baremetal" {
|
||||
needsEnvInVars = true
|
||||
}
|
||||
}
|
||||
if needsEnvInVars {
|
||||
runtimeGlobals := make(map[string]string)
|
||||
if len(cmdArgs) != 0 {
|
||||
runtimeGlobals["osArgs"] = strings.Join(cmdArgs, "\x00")
|
||||
}
|
||||
if len(environmentVars) != 0 {
|
||||
runtimeGlobals["osEnv"] = strings.Join(environmentVars, "\x00")
|
||||
}
|
||||
if len(runtimeGlobals) != 0 {
|
||||
// This sets the global variables like they would be set with
|
||||
// `-ldflags="-X=runtime.osArgs=first\x00second`.
|
||||
// The runtime package has two variables (osArgs and osEnv) that are
|
||||
// both strings, from which the parameters and environment variables
|
||||
// are read.
|
||||
options.GlobalValues = map[string]map[string]string{
|
||||
"runtime": runtimeGlobals,
|
||||
}
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Build the test binary.
|
||||
binary := filepath.Join(tmpdir, "test")
|
||||
if spec.GOOS == "windows" {
|
||||
binary += ".exe"
|
||||
}
|
||||
err = Build("./"+path, binary, &options)
|
||||
stdout := &bytes.Buffer{}
|
||||
err = buildAndRun("./"+path, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||
return cmd.Run()
|
||||
})
|
||||
if err != nil {
|
||||
printCompilerError(t.Log, err)
|
||||
t.Fail()
|
||||
return
|
||||
}
|
||||
|
||||
// Reserve CPU time for the test to run.
|
||||
// This attempts to ensure that the test is not CPU-starved.
|
||||
options.Semaphore <- struct{}{}
|
||||
defer func() { <-options.Semaphore }()
|
||||
|
||||
// Create the test command, taking care of emulators etc.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
var cmd *exec.Cmd
|
||||
|
||||
// make sure any special vars in the emulator definition are rewritten
|
||||
config := compileopts.Config{Target: spec}
|
||||
emulator := config.Emulator()
|
||||
|
||||
if len(emulator) == 0 {
|
||||
cmd = exec.CommandContext(ctx, binary)
|
||||
} else {
|
||||
args := append(emulator[1:], binary)
|
||||
cmd = exec.CommandContext(ctx, emulator[0], args...)
|
||||
}
|
||||
|
||||
if len(emulator) != 0 && emulator[0] == "wasmtime" {
|
||||
// Allow reading from the current directory.
|
||||
cmd.Args = append(cmd.Args, "--dir=.")
|
||||
for _, v := range environmentVars {
|
||||
cmd.Args = append(cmd.Args, "--env", v)
|
||||
}
|
||||
cmd.Args = append(cmd.Args, cmdArgs...)
|
||||
} else {
|
||||
if !needsEnvInVars {
|
||||
cmd.Args = append(cmd.Args, cmdArgs...) // works on qemu-aarch64 etc
|
||||
cmd.Env = append(cmd.Env, environmentVars...)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test.
|
||||
stdout := &bytes.Buffer{}
|
||||
if len(emulator) != 0 && emulator[0] == "simavr" {
|
||||
cmd.Stdout = os.Stderr
|
||||
cmd.Stderr = stdout
|
||||
} else {
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
t.Fatal("failed to start:", err)
|
||||
}
|
||||
err = cmd.Wait()
|
||||
|
||||
if cerr := ctx.Err(); cerr == context.DeadlineExceeded {
|
||||
stdout.WriteString("--- test ran too long, terminating...\n")
|
||||
err = cerr
|
||||
}
|
||||
|
||||
// putchar() prints CRLF, convert it to LF.
|
||||
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
|
||||
expected = bytes.Replace(expected, []byte{'\r', '\n'}, []byte{'\n'}, -1) // for Windows
|
||||
|
||||
if len(emulator) != 0 && emulator[0] == "simavr" {
|
||||
if config.EmulatorName() == "simavr" {
|
||||
// Strip simavr log formatting.
|
||||
actual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)
|
||||
actual = bytes.Replace(actual, []byte{0x1b, '[', '0', 'm'}, nil, -1)
|
||||
@@ -475,12 +390,12 @@ func TestTest(t *testing.T) {
|
||||
}
|
||||
if !testing.Short() {
|
||||
if runtime.GOOS == "linux" {
|
||||
targs = append(targs,
|
||||
// Linux
|
||||
targ{"X86Linux", optionsFromOSARCH("linux/386", sema)},
|
||||
targ{"ARMLinux", optionsFromOSARCH("linux/arm/6", sema)},
|
||||
targ{"ARM64Linux", optionsFromOSARCH("linux/arm64", sema)},
|
||||
)
|
||||
for name, osArch := range supportedLinuxArches {
|
||||
options := optionsFromOSARCH(osArch, sema)
|
||||
if options.GOARCH != runtime.GOARCH { // Native architecture already run above.
|
||||
targs = append(targs, targ{name, options})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targs = append(targs,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Hand created file. DO NOT DELETE.
|
||||
// Cortex-M System Control Block-related definitions.
|
||||
|
||||
//go:build cortexm
|
||||
// +build cortexm
|
||||
|
||||
package arm
|
||||
|
||||
@@ -142,18 +142,14 @@ func (mpu *MPU_Type) Enable(enable bool) {
|
||||
if enable {
|
||||
mpu.CTRL.Set(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk)
|
||||
SystemControl.SHCSR.SetBits(SCB_SHCSR_MEMFAULTENA_Msk)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
arm.Asm("isb 0xF")
|
||||
enableDcache(true)
|
||||
enableIcache(true)
|
||||
} else {
|
||||
enableIcache(false)
|
||||
enableDcache(false)
|
||||
arm.AsmFull(`
|
||||
dmb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dmb 0xF")
|
||||
SystemControl.SHCSR.ClearBits(SCB_SHCSR_MEMFAULTENA_Msk)
|
||||
mpu.CTRL.ClearBits(MPU_CTRL_ENABLE_Msk)
|
||||
}
|
||||
@@ -188,31 +184,21 @@ func (mpu *MPU_Type) SetRASR(size RegionSize, access AccessPerms, ext Extension,
|
||||
func enableIcache(enable bool) {
|
||||
if enable != SystemControl.CCR.HasBits(SCB_CCR_IC_Msk) {
|
||||
if enable {
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
arm.Asm("isb 0xF")
|
||||
SystemControl.ICIALLU.Set(0)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
arm.Asm("isb 0xF")
|
||||
SystemControl.CCR.SetBits(SCB_CCR_IC_Msk)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
arm.Asm("isb 0xF")
|
||||
} else {
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
arm.Asm("isb 0xF")
|
||||
SystemControl.CCR.ClearBits(SCB_CCR_IC_Msk)
|
||||
SystemControl.ICIALLU.Set(0)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
arm.Asm("isb 0xF")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -227,9 +213,7 @@ func enableDcache(enable bool) {
|
||||
if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) {
|
||||
if enable {
|
||||
SystemControl.CSSELR.Set(0)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
ccsidr := SystemControl.CCSIDR.Get()
|
||||
sets := (ccsidr & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos
|
||||
for sets != 0 {
|
||||
@@ -242,23 +226,15 @@ func enableDcache(enable bool) {
|
||||
}
|
||||
sets--
|
||||
}
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
SystemControl.CCR.SetBits(SCB_CCR_DC_Msk)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
arm.Asm("isb 0xF")
|
||||
} else {
|
||||
SystemControl.CSSELR.Set(0)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
SystemControl.CCR.ClearBits(SCB_CCR_DC_Msk)
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
dcacheCcsidr.Set(SystemControl.CCSIDR.Get())
|
||||
dcacheSets.Set((dcacheCcsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
|
||||
for dcacheSets.Get() != 0 {
|
||||
@@ -271,10 +247,8 @@ func enableDcache(enable bool) {
|
||||
}
|
||||
dcacheSets.Set(dcacheSets.Get() - 1)
|
||||
}
|
||||
arm.AsmFull(`
|
||||
dsb 0xF
|
||||
isb 0xF
|
||||
`, nil)
|
||||
arm.Asm("dsb 0xF")
|
||||
arm.Asm("isb 0xF")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// 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,3 +1,4 @@
|
||||
//go:build feather_m4_can
|
||||
// +build feather_m4_can
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build feather_m4_can
|
||||
// +build feather_m4_can
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build circuitplay_express
|
||||
// +build circuitplay_express
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build pyportal
|
||||
// +build pyportal
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build circuitplay_express
|
||||
// +build circuitplay_express
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build pca10040
|
||||
// +build pca10040
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build stm32
|
||||
// +build stm32
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build wioterminal
|
||||
// +build wioterminal
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino_mega1280
|
||||
// +build arduino_mega1280
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino
|
||||
// +build arduino
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build bluepill
|
||||
// +build bluepill
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build feather_m4
|
||||
// +build feather_m4
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build itsybitsy_m0
|
||||
// +build itsybitsy_m0
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build itsybitsy_m4
|
||||
// +build itsybitsy_m4
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build stm32f7
|
||||
// +build stm32f7
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build stm32l0
|
||||
// +build stm32l0
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build stm32l4
|
||||
// +build stm32l4
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build stm32l5
|
||||
// +build stm32l5
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build pico
|
||||
// +build pico
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build stm32f4disco
|
||||
// +build stm32f4disco
|
||||
|
||||
package main
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
// Package fuzz is a shim to allow compilation against Go 1.18.
|
||||
// It only defines a single type to work with testing/internal/testdeps,
|
||||
// and hide all the other new dependencies from this package.
|
||||
package fuzz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CorpusEntry represents an individual input for fuzzing.
|
||||
//
|
||||
// We must use an equivalent type in the testing and testing/internal/testdeps
|
||||
// packages, but testing can't import this package directly, and we don't want
|
||||
// to export this type from testing. Instead, we use the same struct type and
|
||||
// use a type alias (not a defined type) for convenience.
|
||||
type CorpusEntry = struct {
|
||||
Parent string
|
||||
|
||||
// Path is the path of the corpus file, if the entry was loaded from disk.
|
||||
// For other entries, including seed values provided by f.Add, Path is the
|
||||
// name of the test, e.g. seed#0 or its hash.
|
||||
Path string
|
||||
|
||||
// Data is the raw input data. Data should only be populated for seed
|
||||
// values. For on-disk corpus files, Data will be nil, as it will be loaded
|
||||
// from disk using Path.
|
||||
Data []byte
|
||||
|
||||
// Values is the unmarshaled values from a corpus file.
|
||||
Values []any
|
||||
|
||||
Generation int
|
||||
|
||||
// IsSeed indicates whether this entry is part of the seed corpus.
|
||||
IsSeed bool
|
||||
}
|
||||
|
||||
// CoordinateFuzzingOpts is a set of arguments for CoordinateFuzzing.
|
||||
// The zero value is valid for each field unless specified otherwise.
|
||||
type CoordinateFuzzingOpts struct {
|
||||
// Log is a writer for logging progress messages and warnings.
|
||||
// If nil, io.Discard will be used instead.
|
||||
Log io.Writer
|
||||
|
||||
// Timeout is the amount of wall clock time to spend fuzzing after the corpus
|
||||
// has loaded. If zero, there will be no time limit.
|
||||
Timeout time.Duration
|
||||
|
||||
// Limit is the number of random values to generate and test. If zero,
|
||||
// there will be no limit on the number of generated values.
|
||||
Limit int64
|
||||
|
||||
// MinimizeTimeout is the amount of wall clock time to spend minimizing
|
||||
// after discovering a crasher. If zero, there will be no time limit. If
|
||||
// MinimizeTimeout and MinimizeLimit are both zero, then minimization will
|
||||
// be disabled.
|
||||
MinimizeTimeout time.Duration
|
||||
|
||||
// MinimizeLimit is the maximum number of calls to the fuzz function to be
|
||||
// made while minimizing after finding a crash. If zero, there will be no
|
||||
// limit. Calls to the fuzz function made when minimizing also count toward
|
||||
// Limit. If MinimizeTimeout and MinimizeLimit are both zero, then
|
||||
// minimization will be disabled.
|
||||
MinimizeLimit int64
|
||||
|
||||
// parallel is the number of worker processes to run in parallel. If zero,
|
||||
// CoordinateFuzzing will run GOMAXPROCS workers.
|
||||
Parallel int
|
||||
|
||||
// Seed is a list of seed values added by the fuzz target with testing.F.Add
|
||||
// and in testdata.
|
||||
Seed []CorpusEntry
|
||||
|
||||
// Types is the list of types which make up a corpus entry.
|
||||
// Types must be set and must match values in Seed.
|
||||
Types []reflect.Type
|
||||
|
||||
// CorpusDir is a directory where files containing values that crash the
|
||||
// code being tested may be written. CorpusDir must be set.
|
||||
CorpusDir string
|
||||
|
||||
// CacheDir is a directory containing additional "interesting" values.
|
||||
// The fuzzer may derive new values from these, and may write new values here.
|
||||
CacheDir string
|
||||
}
|
||||
|
||||
// CoordinateFuzzing creates several worker processes and communicates with
|
||||
// them to test random inputs that could trigger crashes and expose bugs.
|
||||
// The worker processes run the same binary in the same directory with the
|
||||
// same environment variables as the coordinator process. Workers also run
|
||||
// with the same arguments as the coordinator, except with the -test.fuzzworker
|
||||
// flag prepended to the argument list.
|
||||
//
|
||||
// If a crash occurs, the function will return an error containing information
|
||||
// about the crash, which can be reported to the user.
|
||||
func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err error) {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// ReadCorpus reads the corpus from the provided dir. The returned corpus
|
||||
// entries are guaranteed to match the given types. Any malformed files will
|
||||
// be saved in a MalformedCorpusError and returned, along with the most recent
|
||||
// error.
|
||||
func ReadCorpus(dir string, types []reflect.Type) ([]CorpusEntry, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// CheckCorpus verifies that the types in vals match the expected types
|
||||
// provided.
|
||||
func CheckCorpus(vals []any, types []reflect.Type) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func ResetCoverage() {}
|
||||
func SnapshotCoverage() {}
|
||||
|
||||
// RunFuzzWorker is called in a worker process to communicate with the
|
||||
// coordinator process in order to fuzz random inputs. RunFuzzWorker loops
|
||||
// until the coordinator tells it to stop.
|
||||
//
|
||||
// fn is a wrapper on the fuzz function. It may return an error to indicate
|
||||
// a given input "crashed". The coordinator will also record a crasher if
|
||||
// the function times out or terminates the process.
|
||||
//
|
||||
// RunFuzzWorker returns an error if it could not communicate with the
|
||||
// coordinator process.
|
||||
func RunFuzzWorker(ctx context.Context, fn func(CorpusEntry) error) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino
|
||||
// +build arduino
|
||||
|
||||
package machine
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino_mega1280
|
||||
// +build arduino_mega1280
|
||||
|
||||
package machine
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino_mega2560
|
||||
// +build arduino_mega2560
|
||||
|
||||
package machine
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino_mkr1000
|
||||
// +build arduino_mkr1000
|
||||
|
||||
// This contains the pin mappings for the Arduino MKR1000 board.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino_mkrwifi1010
|
||||
// +build arduino_mkrwifi1010
|
||||
|
||||
// This contains the pin mappings for the Arduino MKR WiFi 1010 board.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino_nano
|
||||
// +build arduino_nano
|
||||
|
||||
package machine
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build arduino_nano33
|
||||
// +build arduino_nano33
|
||||
|
||||
// This contains the pin mappings for the Arduino Nano33 IoT board.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build sam && atsamd21 && arduino_zero
|
||||
// +build sam,atsamd21,arduino_zero
|
||||
|
||||
package machine
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build (avr && atmega328p) || arduino || arduino_nano
|
||||
// +build avr,atmega328p arduino arduino_nano
|
||||
|
||||
package machine
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user