mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-09 05:23:40 +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:
|
steps:
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- llvm-source-13-v1
|
- llvm-source-14-v1
|
||||||
- run:
|
- run:
|
||||||
name: "Fetch LLVM source"
|
name: "Fetch LLVM source"
|
||||||
command: make llvm-source
|
command: make llvm-source
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: llvm-source-13-v1
|
key: llvm-source-14-v1
|
||||||
paths:
|
paths:
|
||||||
- llvm-project/clang/lib/Headers
|
- llvm-project/clang/lib/Headers
|
||||||
- llvm-project/clang/include
|
- llvm-project/clang/include
|
||||||
|
- llvm-project/compiler-rt
|
||||||
- llvm-project/lld/include
|
- llvm-project/lld/include
|
||||||
- llvm-project/llvm/include
|
- llvm-project/llvm/include
|
||||||
hack-ninja-jobs:
|
hack-ninja-jobs:
|
||||||
@@ -85,10 +86,10 @@ commands:
|
|||||||
- run: go install -tags=llvm<<parameters.llvm>> .
|
- run: go install -tags=llvm<<parameters.llvm>> .
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- wasi-libc-sysroot-systemclang-v3
|
- wasi-libc-sysroot-systemclang-v5
|
||||||
- run: make wasi-libc
|
- run: make wasi-libc
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: wasi-libc-sysroot-systemclang-v3
|
key: wasi-libc-sysroot-systemclang-v5
|
||||||
paths:
|
paths:
|
||||||
- lib/wasi-libc/sysroot
|
- lib/wasi-libc/sysroot
|
||||||
- run: make gen-device -j4
|
- run: make gen-device -j4
|
||||||
@@ -107,9 +108,9 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "11"
|
llvm: "11"
|
||||||
test-llvm12-go116:
|
test-llvm12-go117:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/golang:1.16-buster
|
- image: circleci/golang:1.17-buster
|
||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "12"
|
llvm: "12"
|
||||||
@@ -118,4 +119,4 @@ workflows:
|
|||||||
test-all:
|
test-all:
|
||||||
jobs:
|
jobs:
|
||||||
- test-llvm11-go115
|
- test-llvm11-go115
|
||||||
- test-llvm12-go116
|
- test-llvm12-go117
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build-macos:
|
build-macos:
|
||||||
name: build-macos
|
name: build-macos
|
||||||
runs-on: macos-10.15
|
runs-on: macos-11
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: '1.17'
|
go-version: '1.18.1'
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -35,10 +35,11 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-13-macos-v1
|
key: llvm-source-14-macos-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
|
llvm-project/compiler-rt
|
||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Download LLVM source
|
- name: Download LLVM source
|
||||||
@@ -48,7 +49,7 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-13-macos-v2
|
key: llvm-build-14-macos-v1
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Build LLVM
|
- name: Build LLVM
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
@@ -66,7 +67,7 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-v1
|
key: wasi-libc-sysroot-v3
|
||||||
path: lib/wasi-libc/sysroot
|
path: lib/wasi-libc/sysroot
|
||||||
- name: Build wasi-libc
|
- name: Build wasi-libc
|
||||||
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||||
@@ -76,6 +77,8 @@ jobs:
|
|||||||
run: make test GOTESTFLAGS="-v -short"
|
run: make test GOTESTFLAGS="-v -short"
|
||||||
- name: Build TinyGo release tarball
|
- name: Build TinyGo release tarball
|
||||||
run: make release -j3
|
run: make release -j3
|
||||||
|
- name: Test stdlib packages
|
||||||
|
run: make tinygo-test
|
||||||
- name: Make release artifact
|
- name: Make release artifact
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cp -p build/release.tar.gz build/tinygo.darwin-amd64.tar.gz
|
run: cp -p build/release.tar.gz build/tinygo.darwin-amd64.tar.gz
|
||||||
|
|||||||
@@ -57,3 +57,27 @@ jobs:
|
|||||||
--header 'Content-Type: application/json' \
|
--header 'Content-Type: application/json' \
|
||||||
-d '{"branch": "dev"}' \
|
-d '{"branch": "dev"}' \
|
||||||
-u "${{ secrets.CIRCLECI_API_TOKEN }}"
|
-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
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: '1.17'
|
go-version: '1.18.1'
|
||||||
- name: Cache Go
|
- name: Cache Go
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
@@ -38,10 +38,11 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-13-linux-v1
|
key: llvm-source-14-linux-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
|
llvm-project/compiler-rt
|
||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Download LLVM source
|
- name: Download LLVM source
|
||||||
@@ -51,7 +52,7 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-13-linux-v1
|
key: llvm-build-14-linux-v1
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Build LLVM
|
- name: Build LLVM
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
@@ -76,14 +77,13 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-linux-asserts-v2
|
key: wasi-libc-sysroot-linux-asserts-v4
|
||||||
path: lib/wasi-libc/sysroot
|
path: lib/wasi-libc/sysroot
|
||||||
- name: Build wasi-libc
|
- name: Build wasi-libc
|
||||||
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||||
run: make wasi-libc
|
run: make wasi-libc
|
||||||
- name: Install fpm
|
- name: Install fpm
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install ruby ruby-dev
|
|
||||||
sudo gem install --no-document fpm
|
sudo gem install --no-document fpm
|
||||||
- name: Build TinyGo release
|
- name: Build TinyGo release
|
||||||
run: |
|
run: |
|
||||||
@@ -93,7 +93,7 @@ jobs:
|
|||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: release-double-zipped
|
name: linux-amd64-double-zipped
|
||||||
path: |
|
path: |
|
||||||
/tmp/tinygo.linux-amd64.tar.gz
|
/tmp/tinygo.linux-amd64.tar.gz
|
||||||
/tmp/tinygo_amd64.deb
|
/tmp/tinygo_amd64.deb
|
||||||
@@ -107,7 +107,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: '1.17'
|
go-version: '1.18.1'
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
run: |
|
run: |
|
||||||
curl https://wasmtime.dev/install.sh -sSf | bash
|
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||||
@@ -115,7 +115,7 @@ jobs:
|
|||||||
- name: Download release artifact
|
- name: Download release artifact
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: release-double-zipped
|
name: linux-amd64-double-zipped
|
||||||
- name: Extract release tarball
|
- name: Extract release tarball
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/lib
|
mkdir -p ~/lib
|
||||||
@@ -159,7 +159,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: '1.17'
|
go-version: '1.18.1'
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
@@ -179,10 +179,11 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-13-linux-asserts-v1
|
key: llvm-source-14-linux-asserts-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
|
llvm-project/compiler-rt
|
||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Download LLVM source
|
- name: Download LLVM source
|
||||||
@@ -192,7 +193,7 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-13-linux-asserts-v1
|
key: llvm-build-14-linux-asserts-v1
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Build LLVM
|
- name: Build LLVM
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
@@ -217,7 +218,7 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-linux-asserts-v2
|
key: wasi-libc-sysroot-linux-asserts-v4
|
||||||
path: lib/wasi-libc/sysroot
|
path: lib/wasi-libc/sysroot
|
||||||
- name: Build wasi-libc
|
- name: Build wasi-libc
|
||||||
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
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
|
rm xtensa-esp32-elf-gcc8_2_0-esp-2020r2-linux-amd64.tar.gz
|
||||||
- run: make smoketest
|
- run: make smoketest
|
||||||
- run: make wasmtest
|
- 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:
|
jobs:
|
||||||
build-windows:
|
build-windows:
|
||||||
runs-on: windows-2019
|
runs-on: windows-2022
|
||||||
steps:
|
steps:
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: '1.17'
|
go-version: '1.18.1'
|
||||||
- uses: MinoruSekine/setup-scoop@v1
|
- uses: brechtm/setup-scoop@v2
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -35,10 +35,11 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-13-windows-v1
|
key: llvm-source-14-windows-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
|
llvm-project/compiler-rt
|
||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Download LLVM source
|
- name: Download LLVM source
|
||||||
@@ -48,7 +49,7 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-13-windows-v1
|
key: llvm-build-14-windows-v1
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Build LLVM
|
- name: Build LLVM
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
@@ -65,11 +66,14 @@ jobs:
|
|||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-v1
|
key: wasi-libc-sysroot-v3
|
||||||
path: lib/wasi-libc/sysroot
|
path: lib/wasi-libc/sysroot
|
||||||
- name: Build wasi-libc
|
- name: Build wasi-libc
|
||||||
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||||
run: make wasi-libc
|
run: make wasi-libc
|
||||||
|
- name: Install wasmtime
|
||||||
|
run: |
|
||||||
|
scoop install wasmtime
|
||||||
- name: Test TinyGo
|
- name: Test TinyGo
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make test GOTESTFLAGS="-v -short"
|
run: make test GOTESTFLAGS="-v -short"
|
||||||
@@ -95,3 +99,5 @@ jobs:
|
|||||||
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0 XTENSA=0
|
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0 XTENSA=0
|
||||||
- name: Test stdlib packages
|
- name: Test stdlib packages
|
||||||
run: make tinygo-test
|
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"]
|
[submodule "lib/cmsis-svd"]
|
||||||
path = lib/cmsis-svd
|
path = lib/cmsis-svd
|
||||||
url = https://github.com/tinygo-org/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"]
|
[submodule "lib/wasi-libc"]
|
||||||
path = lib/wasi-libc
|
path = lib/wasi-libc
|
||||||
url = https://github.com/CraneStation/wasi-libc
|
url = https://github.com/CraneStation/wasi-libc
|
||||||
@@ -32,3 +28,6 @@
|
|||||||
[submodule "lib/mingw-w64"]
|
[submodule "lib/mingw-w64"]
|
||||||
path = lib/mingw-w64
|
path = lib/mingw-w64
|
||||||
url = https://github.com/mingw-w64/mingw-w64.git
|
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
|
0.22.0
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||||
FROM golang:1.17 AS tinygo-llvm
|
FROM golang:1.18 AS tinygo-llvm
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ LLD_SRC ?= $(LLVM_PROJECTDIR)/lld
|
|||||||
|
|
||||||
# Try to autodetect LLVM build tools.
|
# Try to autodetect LLVM build tools.
|
||||||
# Versions are listed here in descending priority order.
|
# 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)))
|
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)))
|
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)
|
toolSearchPathsVersion = $(1)-$(2)
|
||||||
@@ -50,6 +50,29 @@ else
|
|||||||
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
|
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
|
||||||
endif
|
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
|
.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
|
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)
|
else ifeq ($(shell uname -s),Darwin)
|
||||||
MD5SUM = md5
|
MD5SUM = md5
|
||||||
|
|
||||||
|
CGO_LDFLAGS += -lxar
|
||||||
|
|
||||||
USE_SYSTEM_BINARYEN ?= 1
|
USE_SYSTEM_BINARYEN ?= 1
|
||||||
|
|
||||||
else ifeq ($(shell uname -s),FreeBSD)
|
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++
|
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
|
||||||
|
|
||||||
# Libraries that should be linked in for the statically linked LLD.
|
# 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)
|
LLD_LIBS = $(START_GROUP) $(addprefix -l,$(LLD_LIB_NAMES)) $(END_GROUP)
|
||||||
|
|
||||||
# Other libraries that are needed to link TinyGo.
|
# 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).
|
# 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)
|
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.
|
# For static linking.
|
||||||
ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","")
|
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_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
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@@ -173,7 +198,7 @@ gen-device-rp: build/gen-device-svd
|
|||||||
|
|
||||||
# Get LLVM sources.
|
# Get LLVM sources.
|
||||||
$(LLVM_PROJECTDIR)/llvm:
|
$(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
|
llvm-source: $(LLVM_PROJECTDIR)/llvm
|
||||||
|
|
||||||
# Configure LLVM.
|
# Configure LLVM.
|
||||||
@@ -200,25 +225,24 @@ endif
|
|||||||
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
||||||
lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
|
lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
|
||||||
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
|
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
|
||||||
cd lib/wasi-libc && make -j4 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.
|
# Build the Go compiler.
|
||||||
tinygo:
|
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
|
@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
|
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 .
|
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 = \
|
TEST_PACKAGES_SLOW = \
|
||||||
compress/bzip2 \
|
compress/bzip2 \
|
||||||
compress/flate \
|
|
||||||
crypto/dsa \
|
crypto/dsa \
|
||||||
index/suffixarray \
|
index/suffixarray \
|
||||||
|
|
||||||
TEST_PACKAGES_BASE = \
|
# Standard library packages that pass tests quickly on darwin, linux, wasi, and windows
|
||||||
|
TEST_PACKAGES_FAST = \
|
||||||
compress/zlib \
|
compress/zlib \
|
||||||
container/heap \
|
container/heap \
|
||||||
container/list \
|
container/list \
|
||||||
@@ -247,6 +271,7 @@ TEST_PACKAGES_BASE = \
|
|||||||
internal/profile \
|
internal/profile \
|
||||||
math \
|
math \
|
||||||
math/cmplx \
|
math/cmplx \
|
||||||
|
net \
|
||||||
net/http/internal/ascii \
|
net/http/internal/ascii \
|
||||||
net/mail \
|
net/mail \
|
||||||
os \
|
os \
|
||||||
@@ -260,40 +285,70 @@ TEST_PACKAGES_BASE = \
|
|||||||
unicode/utf16 \
|
unicode/utf16 \
|
||||||
unicode/utf8 \
|
unicode/utf8 \
|
||||||
|
|
||||||
# Standard library packages that pass tests natively
|
# archive/zip requires os.ReadAt, which is not yet supported on windows
|
||||||
TEST_PACKAGES := \
|
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
|
||||||
$(TEST_PACKAGES_BASE)
|
# 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
|
# Additional standard library packages that pass tests on individual platforms
|
||||||
ifneq ($(OS),Windows_NT)
|
TEST_PACKAGES_LINUX := \
|
||||||
TEST_PACKAGES := \
|
archive/zip \
|
||||||
$(TEST_PACKAGES) \
|
compress/flate \
|
||||||
archive/zip
|
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
|
endif
|
||||||
|
|
||||||
# Standard library packages that pass tests on wasi
|
|
||||||
TEST_PACKAGES_WASI = \
|
|
||||||
$(TEST_PACKAGES_BASE)
|
|
||||||
|
|
||||||
# Test known-working standard library packages.
|
# Test known-working standard library packages.
|
||||||
# TODO: parallelize, and only show failing tests (no implied -v flag).
|
# TODO: parallelize, and only show failing tests (no implied -v flag).
|
||||||
.PHONY: tinygo-test
|
.PHONY: tinygo-test
|
||||||
tinygo-test:
|
tinygo-test:
|
||||||
$(TINYGO) test $(TEST_PACKAGES) $(TEST_PACKAGES_SLOW)
|
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||||
tinygo-test-fast:
|
tinygo-test-fast:
|
||||||
$(TINYGO) test $(TEST_PACKAGES)
|
$(TINYGO) test $(TEST_PACKAGES_HOST)
|
||||||
tinygo-bench:
|
tinygo-bench:
|
||||||
$(TINYGO) test -bench . $(TEST_PACKAGES) $(TEST_PACKAGES_SLOW)
|
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||||
tinygo-bench-fast:
|
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-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-wasi-fast:
|
||||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_WASI)
|
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST)
|
||||||
tinygo-bench-wasi:
|
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-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 external packages in a large corpus.
|
||||||
test-corpus:
|
test-corpus:
|
||||||
@@ -303,10 +358,16 @@ test-corpus-fast:
|
|||||||
test-corpus-wasi: wasi-libc
|
test-corpus-wasi: wasi-libc
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasi
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=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
|
.PHONY: smoketest
|
||||||
smoketest:
|
smoketest:
|
||||||
$(TINYGO) version
|
$(TINYGO) version
|
||||||
|
# compile-only platform-independent examples
|
||||||
|
cd tests/text/template/smoke && $(TINYGO) test -c && rm -f smoke.test
|
||||||
# regression test for #2563
|
# regression test for #2563
|
||||||
cd tests/os/smoke && $(TINYGO) test -c -target=pybadge && rm smoke.test
|
cd tests/os/smoke && $(TINYGO) test -c -target=pybadge && rm smoke.test
|
||||||
# test all examples (except pwm)
|
# test all examples (except pwm)
|
||||||
@@ -354,6 +415,8 @@ ifneq ($(WASM), 0)
|
|||||||
@$(MD5SUM) test.wasm
|
@$(MD5SUM) test.wasm
|
||||||
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_express examples/blinky1
|
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_express examples/blinky1
|
||||||
@$(MD5SUM) test.wasm
|
@$(MD5SUM) test.wasm
|
||||||
|
$(TINYGO) build -size short -o test.wasm -tags=circuitplay_bluefruit examples/blinky1
|
||||||
|
@$(MD5SUM) test.wasm
|
||||||
endif
|
endif
|
||||||
# test all targets/boards
|
# test all targets/boards
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
|
||||||
@@ -442,6 +505,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=qtpy examples/serial
|
$(TINYGO) build -size short -o test.hex -target=qtpy examples/serial
|
||||||
@$(MD5SUM) test.hex
|
@$(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
|
$(TINYGO) build -size short -o test.hex -target=teensy40 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=teensy36 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=teensy36 examples/blinky1
|
||||||
@@ -468,6 +533,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=macropad-rp2040 examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
# test pwm
|
# test pwm
|
||||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
@@ -566,6 +633,7 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
GOOS=linux GOARCH=arm $(TINYGO) build -size short -o test.elf ./testdata/cgo
|
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=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)
|
ifneq ($(OS),Windows_NT)
|
||||||
# TODO: this does not yet work on Windows. Somehow, unused functions are
|
# TODO: this does not yet work on Windows. Somehow, unused functions are
|
||||||
# not garbage collected.
|
# 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/bin
|
||||||
@mkdir -p build/release/tinygo/lib/clang/include
|
@mkdir -p build/release/tinygo/lib/clang/include
|
||||||
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
@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-crt/lib-common
|
||||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
||||||
@mkdir -p build/release/tinygo/lib/musl/arch
|
@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 -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/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
|
||||||
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/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/macos-minimal-sdk/* build/release/tinygo/lib/macos-minimal-sdk
|
||||||
@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/musl/arch/aarch64 build/release/tinygo/lib/musl/arch
|
@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/arm build/release/tinygo/lib/musl/arch
|
||||||
@cp -rp lib/musl/arch/generic 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/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
|
||||||
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
||||||
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
|
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
|
||||||
|
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
|
||||||
|
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
|
||||||
@cp -rp src build/release/tinygo/src
|
@cp -rp src build/release/tinygo/src
|
||||||
@cp -rp targets build/release/tinygo/targets
|
@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
|
./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-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
|
./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
|
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/bin
|
||||||
@mkdir -p build/release-deb/usr/local/lib
|
@mkdir -p build/release-deb/usr/local/lib
|
||||||
cp -ar build/release/tinygo build/release-deb/usr/local/lib/tinygo
|
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
|
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.
|
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 Bluefruit](https://www.adafruit.com/product/4333)
|
||||||
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
||||||
@@ -59,6 +59,7 @@ The following 80 microcontroller boards are currently supported:
|
|||||||
* [Adafruit ItsyBitsy M0](https://www.adafruit.com/product/3727)
|
* [Adafruit ItsyBitsy M0](https://www.adafruit.com/product/3727)
|
||||||
* [Adafruit ItsyBitsy M4](https://www.adafruit.com/product/3800)
|
* [Adafruit ItsyBitsy M4](https://www.adafruit.com/product/3800)
|
||||||
* [Adafruit ItsyBitsy nRF52840](https://www.adafruit.com/product/4481)
|
* [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 Matrix Portal M4](https://www.adafruit.com/product/4745)
|
||||||
* [Adafruit Metro M4 Express Airlift](https://www.adafruit.com/product/4000)
|
* [Adafruit Metro M4 Express Airlift](https://www.adafruit.com/product/4000)
|
||||||
* [Adafruit PyBadge](https://www.adafruit.com/product/4200)
|
* [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)
|
* [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 - Core board](https://www.espressif.com/en/products/socs/esp32)
|
||||||
* [ESP32 - mini32](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 - d1mini](https://www.espressif.com/en/products/socs/esp8266)
|
||||||
* [ESP8266 - NodeMCU](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)
|
* [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/)
|
* [PineTime DevKit](https://www.pine64.org/pinetime/)
|
||||||
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
||||||
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
|
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
|
||||||
|
* [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)
|
* [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/)
|
* [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/)
|
||||||
* [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199)
|
* [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199)
|
||||||
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
||||||
|
* [Seeed XIAO BLE](https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html)
|
||||||
* [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html)
|
* [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html)
|
||||||
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
|
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
|
||||||
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
||||||
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1)
|
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1)
|
||||||
|
* [Sparkfun Thing Plus RP2040](https://www.sparkfun.com/products/17745)
|
||||||
* [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
|
* [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
|
||||||
* [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
|
* [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
|
||||||
* [ST Micro "Nucleo" L031K6](https://www.st.com/ja/evaluation-tools/nucleo-l031k6.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
|
// BuildResult is the output of a build. This includes the binary itself and
|
||||||
// some other metadata that is obtained while building the binary.
|
// some other metadata that is obtained while building the binary.
|
||||||
type BuildResult struct {
|
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
|
// 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.
|
// 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
|
Binary string
|
||||||
|
|
||||||
// The directory of the main package. This is useful for testing as the test
|
// 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 {
|
if err != nil {
|
||||||
return err
|
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.
|
// Check for a libc dependency.
|
||||||
// As a side effect, this also creates the headers for the given libc, if
|
// 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")
|
root := goenv.Get("TINYGOROOT")
|
||||||
var libcDependencies []*compileJob
|
var libcDependencies []*compileJob
|
||||||
switch config.Target.Libc {
|
switch config.Target.Libc {
|
||||||
|
case "darwin-libSystem":
|
||||||
|
job := makeDarwinLibSystemJob(config, dir)
|
||||||
|
libcDependencies = append(libcDependencies, job)
|
||||||
case "musl":
|
case "musl":
|
||||||
job, unlock, err := Musl.load(config, dir)
|
job, unlock, err := Musl.load(config, dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -188,6 +210,21 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
var packageJobs []*compileJob
|
var packageJobs []*compileJob
|
||||||
packageBitcodePaths := make(map[string]string)
|
packageBitcodePaths := make(map[string]string)
|
||||||
packageActionIDs := 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() {
|
for _, pkg := range lprogram.Sorted() {
|
||||||
pkg := pkg // necessary to avoid a race condition
|
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
|
// Determine the path of the bitcode file (which is a serialized version
|
||||||
// of a LLVM module).
|
// 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")
|
bitcodePath := filepath.Join(cacheDir, "pkg-"+hex.EncodeToString(hash[:])+".bc")
|
||||||
packageBitcodePaths[pkg.ImportPath] = bitcodePath
|
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
|
// Load and link all the bitcode files. This does not yet optimize
|
||||||
// anything, it only links the bitcode files together.
|
// anything, it only links the bitcode files together.
|
||||||
ctx := llvm.NewContext()
|
ctx := llvm.NewContext()
|
||||||
mod = ctx.NewModule("")
|
mod = ctx.NewModule("main")
|
||||||
for _, pkg := range lprogram.Sorted() {
|
for _, pkg := range lprogram.Sorted() {
|
||||||
pkgMod, err := ctx.ParseBitcodeFile(packageBitcodePaths[pkg.ImportPath])
|
pkgMod, err := ctx.ParseBitcodeFile(packageBitcodePaths[pkg.ImportPath])
|
||||||
if err != nil {
|
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)
|
return ioutil.WriteFile(outpath, llvmBuf.Bytes(), 0666)
|
||||||
case ".bc":
|
case ".bc":
|
||||||
data := llvm.WriteBitcodeToMemoryBuffer(mod).Bytes()
|
var buf llvm.MemoryBuffer
|
||||||
return ioutil.WriteFile(outpath, data, 0666)
|
if config.UseThinLTO() {
|
||||||
|
buf = llvm.WriteThinLTOBitcodeToMemoryBuffer(mod)
|
||||||
|
} else {
|
||||||
|
buf = llvm.WriteBitcodeToMemoryBuffer(mod)
|
||||||
|
}
|
||||||
|
defer buf.Dispose()
|
||||||
|
return ioutil.WriteFile(outpath, buf.Bytes(), 0666)
|
||||||
case ".ll":
|
case ".ll":
|
||||||
data := []byte(mod.String())
|
data := []byte(mod.String())
|
||||||
return ioutil.WriteFile(outpath, data, 0666)
|
return ioutil.WriteFile(outpath, data, 0666)
|
||||||
@@ -526,10 +563,17 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
dependencies: []*compileJob{programJob},
|
dependencies: []*compileJob{programJob},
|
||||||
result: objfile,
|
result: objfile,
|
||||||
run: func(*compileJob) error {
|
run: func(*compileJob) error {
|
||||||
llvmBuf, err := machine.EmitToMemoryBuffer(mod, llvm.ObjectFile)
|
var llvmBuf llvm.MemoryBuffer
|
||||||
if err != nil {
|
if config.UseThinLTO() {
|
||||||
return err
|
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)
|
return ioutil.WriteFile(objfile, llvmBuf.Bytes(), 0666)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -562,7 +606,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
job := &compileJob{
|
job := &compileJob{
|
||||||
description: "compile extra file " + path,
|
description: "compile extra file " + path,
|
||||||
run: func(job *compileJob) error {
|
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
|
job.result = result
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
@@ -580,7 +624,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
job := &compileJob{
|
job := &compileJob{
|
||||||
description: "compile CGo file " + abspath,
|
description: "compile CGo file " + abspath,
|
||||||
run: func(job *compileJob) error {
|
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
|
job.result = result
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
@@ -649,6 +693,24 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
if config.Options.PrintCommands != nil {
|
if config.Options.PrintCommands != nil {
|
||||||
config.Options.PrintCommands(config.Target.Linker, ldflags...)
|
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...)
|
err = link(config.Target.Linker, ldflags...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &commandError{"failed to link", executable, err}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "esp32", "esp32c3", "esp8266":
|
case "esp32", "esp32-img", "esp32c3", "esp8266":
|
||||||
// Special format for the ESP family of chips (parsed by the ROM
|
// Special format for the ESP family of chips (parsed by the ROM
|
||||||
// bootloader).
|
// bootloader).
|
||||||
tmppath = filepath.Join(dir, "main"+outext)
|
tmppath = filepath.Join(dir, "main"+outext)
|
||||||
@@ -811,6 +873,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
|||||||
}
|
}
|
||||||
|
|
||||||
return action(BuildResult{
|
return action(BuildResult{
|
||||||
|
Executable: executable,
|
||||||
Binary: tmppath,
|
Binary: tmppath,
|
||||||
MainDir: lprogram.MainPkg().Dir,
|
MainDir: lprogram.MainPkg().Dir,
|
||||||
ModuleRoot: moduleroot,
|
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
|
transform.ApplyFunctionSections(mod) // -ffunction-sections
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -30,6 +30,7 @@ func ReadBuildID() ([]byte, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
var gnuID, goID []byte
|
||||||
for _, section := range file.Sections {
|
for _, section := range file.Sections {
|
||||||
if section.Type != elf.SHT_NOTE ||
|
if section.Type != elf.SHT_NOTE ||
|
||||||
(section.Name != ".note.gnu.build-id" && section.Name != ".note.go.buildid") {
|
(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 {
|
if uint64(n) != section.Size || err != nil {
|
||||||
return nil, fmt.Errorf("could not read build id: %w", err)
|
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":
|
case "darwin":
|
||||||
// Read the LC_UUID load command, which contains the equivalent of a
|
// Read the LC_UUID load command, which contains the equivalent of a
|
||||||
|
|||||||
+14
-1
@@ -1,7 +1,11 @@
|
|||||||
package builder
|
package builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// These are the GENERIC_SOURCES according to CMakeList.txt.
|
// These are the GENERIC_SOURCES according to CMakeList.txt.
|
||||||
@@ -72,6 +76,7 @@ var genericBuiltins = []string{
|
|||||||
"floatunsisf.c",
|
"floatunsisf.c",
|
||||||
"floatuntidf.c",
|
"floatuntidf.c",
|
||||||
"floatuntisf.c",
|
"floatuntisf.c",
|
||||||
|
"fp_mode.c",
|
||||||
//"int_util.c",
|
//"int_util.c",
|
||||||
"lshrdi3.c",
|
"lshrdi3.c",
|
||||||
"lshrti3.c",
|
"lshrti3.c",
|
||||||
@@ -161,7 +166,15 @@ var CompilerRT = Library{
|
|||||||
cflags: func(target, headerPath string) []string {
|
cflags: func(target, headerPath string) []string {
|
||||||
return []string{"-Werror", "-Wall", "-std=c11", "-nostdlibinc"}
|
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 {
|
librarySources: func(target string) []string {
|
||||||
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
|
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
|
||||||
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
|
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
|
// depfile but without invalidating its name. For this reason, the depfile is
|
||||||
// written on each new compilation (even when it seems unnecessary). However, it
|
// written on each new compilation (even when it seems unnecessary). However, it
|
||||||
// could in rare cases lead to a stale file fetched from the cache.
|
// could in rare cases lead to a stale file fetched from the cache.
|
||||||
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands func(string, ...string)) (string, error) {
|
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool, printCommands func(string, ...string)) (string, error) {
|
||||||
// Hash input file.
|
// Hash input file.
|
||||||
fileHash, err := hashFile(abspath)
|
fileHash, err := hashFile(abspath)
|
||||||
if err != nil {
|
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"))
|
unlock := lock(filepath.Join(goenv.Get("GOCACHE"), fileHash+".c.lock"))
|
||||||
defer unlock()
|
defer unlock()
|
||||||
|
|
||||||
|
ext := ".o"
|
||||||
|
if thinlto {
|
||||||
|
ext = ".bc"
|
||||||
|
}
|
||||||
|
|
||||||
// Create cache key for the dependencies file.
|
// Create cache key for the dependencies file.
|
||||||
buf, err := json.Marshal(struct {
|
buf, err := json.Marshal(struct {
|
||||||
Path string
|
Path string
|
||||||
@@ -99,7 +104,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtain hashes of all the files listed as a dependency.
|
// 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 == nil {
|
||||||
if _, err := os.Stat(outpath); err == nil {
|
if _, err := os.Stat(outpath); err == nil {
|
||||||
return outpath, nil
|
return outpath, nil
|
||||||
@@ -112,7 +117,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
objTmpFile, err := ioutil.TempFile(goenv.Get("GOCACHE"), "tmp-*.o")
|
objTmpFile, err := ioutil.TempFile(goenv.Get("GOCACHE"), "tmp-*"+ext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -124,6 +129,9 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands
|
|||||||
depTmpFile.Close()
|
depTmpFile.Close()
|
||||||
flags := append([]string{}, cflags...) // copy cflags
|
flags := append([]string{}, cflags...) // copy cflags
|
||||||
flags = append(flags, "-MD", "-MV", "-MTdeps", "-MF", depTmpFile.Name()) // autogenerate dependencies
|
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)
|
flags = append(flags, "-c", "-o", objTmpFile.Name(), abspath)
|
||||||
if strings.ToLower(filepath.Ext(abspath)) == ".s" {
|
if strings.ToLower(filepath.Ext(abspath)) == ".s" {
|
||||||
// If this is an assembly file (.s or .S, lowercase or uppercase), then
|
// 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.
|
// Move temporary object file to final location.
|
||||||
outpath, err := makeCFileCachePath(dependencySlice, depfileNameHash)
|
outpath, err := makeCFileCachePath(dependencySlice, depfileNameHash, ext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
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
|
// 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
|
// 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.
|
// 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.
|
// Hash all input files.
|
||||||
fileHashes := make(map[string]string, len(paths))
|
fileHashes := make(map[string]string, len(paths))
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
@@ -221,7 +229,7 @@ func makeCFileCachePath(paths []string, depfileNameHash string) (string, error)
|
|||||||
outFileNameBuf := sha512.Sum512_224(buf)
|
outFileNameBuf := sha512.Sum512_224(buf)
|
||||||
cacheKey := hex.EncodeToString(outFileNameBuf[:])
|
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
|
return outpath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -38,6 +38,7 @@
|
|||||||
#include "llvm/MC/MCStreamer.h"
|
#include "llvm/MC/MCStreamer.h"
|
||||||
#include "llvm/MC/MCSubtargetInfo.h"
|
#include "llvm/MC/MCSubtargetInfo.h"
|
||||||
#include "llvm/MC/MCTargetOptions.h"
|
#include "llvm/MC/MCTargetOptions.h"
|
||||||
|
#include "llvm/MC/TargetRegistry.h"
|
||||||
#include "llvm/Option/Arg.h"
|
#include "llvm/Option/Arg.h"
|
||||||
#include "llvm/Option/ArgList.h"
|
#include "llvm/Option/ArgList.h"
|
||||||
#include "llvm/Option/OptTable.h"
|
#include "llvm/Option/OptTable.h"
|
||||||
@@ -51,7 +52,6 @@
|
|||||||
#include "llvm/Support/Process.h"
|
#include "llvm/Support/Process.h"
|
||||||
#include "llvm/Support/Signals.h"
|
#include "llvm/Support/Signals.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/Support/TargetRegistry.h"
|
|
||||||
#include "llvm/Support/TargetSelect.h"
|
#include "llvm/Support/TargetSelect.h"
|
||||||
#include "llvm/Support/Timer.h"
|
#include "llvm/Support/Timer.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
@@ -120,7 +120,6 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
|
|||||||
llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
|
llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
|
||||||
.Case("none", llvm::DebugCompressionType::None)
|
.Case("none", llvm::DebugCompressionType::None)
|
||||||
.Case("zlib", llvm::DebugCompressionType::Z)
|
.Case("zlib", llvm::DebugCompressionType::Z)
|
||||||
.Case("zlib-gnu", llvm::DebugCompressionType::GNU)
|
|
||||||
.Default(llvm::DebugCompressionType::None);
|
.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,
|
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
|
||||||
Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
|
Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
|
||||||
/*DWARFMustBeAtTheEnd*/ true));
|
/*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
|
// When -fembed-bitcode is passed to clang_as, a 1-byte marker
|
||||||
@@ -442,7 +441,7 @@ bool ExecuteAssembler(AssemblerInvocation &Opts,
|
|||||||
return Failed;
|
return Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LLVMErrorHandler(void *UserData, const std::string &Message,
|
static void LLVMErrorHandler(void *UserData, const char *Message,
|
||||||
bool GenCrashDiag) {
|
bool GenCrashDiag) {
|
||||||
DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
|
DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -33,8 +33,8 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
|
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
|
||||||
}
|
}
|
||||||
if major != 1 || minor < 15 || minor > 17 {
|
if major != 1 || minor < 15 || minor > 18 {
|
||||||
return nil, fmt.Errorf("requires go version 1.15 through 1.17, got go%d.%d", major, minor)
|
return nil, fmt.Errorf("requires go version 1.15 through 1.18, got go%d.%d", major, minor)
|
||||||
}
|
}
|
||||||
|
|
||||||
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
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"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type espImageSegment struct {
|
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.
|
// An added benefit is that we don't need to check for errors all the time.
|
||||||
outf := &bytes.Buffer{}
|
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:
|
// Chip IDs. Source:
|
||||||
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L22
|
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L22
|
||||||
chip_id := map[string]uint16{
|
chip_id := map[string]uint16{
|
||||||
"esp32": 0x0000,
|
"esp32": 0x0000,
|
||||||
"esp32c3": 0x0005,
|
"esp32c3": 0x0005,
|
||||||
}[format]
|
}[chip]
|
||||||
|
|
||||||
// Image header.
|
// Image header.
|
||||||
switch format {
|
switch chip {
|
||||||
case "esp32", "esp32c3":
|
case "esp32", "esp32c3":
|
||||||
// Header format:
|
// Header format:
|
||||||
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71
|
// 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.Write(make([]byte, 15-outf.Len()%16))
|
||||||
outf.WriteByte(checksum)
|
outf.WriteByte(checksum)
|
||||||
|
|
||||||
if format != "esp8266" {
|
if chip != "esp8266" {
|
||||||
// SHA256 hash (to protect against image corruption, not for security).
|
// SHA256 hash (to protect against image corruption, not for security).
|
||||||
hash := sha256.Sum256(outf.Bytes())
|
hash := sha256.Sum256(outf.Bytes())
|
||||||
outf.Write(hash[:])
|
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.
|
// Write the image to the output file.
|
||||||
return ioutil.WriteFile(outfile, outf.Bytes(), 0666)
|
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 returns the C flags specific to this library
|
||||||
cflags func(target, headerPath string) []string
|
cflags func(target, headerPath string) []string
|
||||||
|
|
||||||
// The source directory, relative to TINYGOROOT.
|
// The source directory.
|
||||||
sourceDir string
|
sourceDir func() string
|
||||||
|
|
||||||
// The source files, relative to sourceDir.
|
// The source files, relative to sourceDir.
|
||||||
librarySources func(target string) []string
|
librarySources func(target string) []string
|
||||||
@@ -103,6 +103,10 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
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)
|
err = os.Rename(temporaryHeaderPath, headerPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch {
|
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") {
|
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-") {
|
if strings.HasPrefix(target, "riscv32-") {
|
||||||
args = append(args, "-march=rv32imac", "-mabi=ilp32", "-fforce-enable-int128")
|
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-") {
|
if strings.HasPrefix(target, "riscv64-") {
|
||||||
args = append(args, "-march=rv64gc", "-mabi=lp64")
|
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
|
var once sync.Once
|
||||||
|
|
||||||
@@ -182,11 +192,17 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = os.Chmod(f.Name(), 0o644) // TempFile uses 0o600 by default
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// Store this archive in the cache.
|
// Store this archive in the cache.
|
||||||
return os.Rename(f.Name(), archiveFilePath)
|
return os.Rename(f.Name(), archiveFilePath)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceDir := l.sourceDir()
|
||||||
|
|
||||||
// Create jobs to compile all sources. These jobs are depended upon by the
|
// Create jobs to compile all sources. These jobs are depended upon by the
|
||||||
// archive job above, so must be run first.
|
// archive job above, so must be run first.
|
||||||
for _, path := range l.librarySources(target) {
|
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, "../") {
|
for strings.HasPrefix(cleanpath, "../") {
|
||||||
cleanpath = cleanpath[3:]
|
cleanpath = cleanpath[3:]
|
||||||
}
|
}
|
||||||
srcpath := filepath.Join(goenv.Get("TINYGOROOT"), l.sourceDir, path)
|
srcpath := filepath.Join(sourceDir, path)
|
||||||
objpath := filepath.Join(dir, cleanpath+".o")
|
objpath := filepath.Join(dir, cleanpath+".o")
|
||||||
os.MkdirAll(filepath.Dir(objpath), 0o777)
|
os.MkdirAll(filepath.Dir(objpath), 0o777)
|
||||||
objs = append(objs, objpath)
|
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
|
// (It could be done in parallel with creating the ar file, but it probably
|
||||||
// won't make much of a difference in speed).
|
// won't make much of a difference in speed).
|
||||||
if l.crt1Source != "" {
|
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{
|
job.dependencies = append(job.dependencies, &compileJob{
|
||||||
description: "compile " + srcpath,
|
description: "compile " + srcpath,
|
||||||
run: func(*compileJob) error {
|
run: func(*compileJob) error {
|
||||||
|
|||||||
+8
-3
@@ -8,17 +8,22 @@ extern "C" {
|
|||||||
|
|
||||||
bool tinygo_link_elf(int argc, char **argv) {
|
bool tinygo_link_elf(int argc, char **argv) {
|
||||||
std::vector<const char*> args(argv, argv + argc);
|
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) {
|
bool tinygo_link_mingw(int argc, char **argv) {
|
||||||
std::vector<const char*> args(argv, argv + argc);
|
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) {
|
bool tinygo_link_wasm(int argc, char **argv) {
|
||||||
std::vector<const char*> args(argv, argv + argc);
|
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"
|
} // external "C"
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ var MinGW = Library{
|
|||||||
_, err = io.Copy(outf, inf)
|
_, err = io.Copy(outf, inf)
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
|
sourceDir: func() string { return "" }, // unused
|
||||||
cflags: func(target, headerPath string) []string {
|
cflags: func(target, headerPath string) []string {
|
||||||
// No flags necessary because there are no files to compile.
|
// No flags necessary because there are no files to compile.
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
+1
-1
@@ -104,7 +104,7 @@ var Musl = Library{
|
|||||||
"-fno-stack-protector",
|
"-fno-stack-protector",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sourceDir: "lib/musl/src",
|
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl/src") },
|
||||||
librarySources: func(target string) []string {
|
librarySources: func(target string) []string {
|
||||||
arch := compileopts.MuslArchitecture(target)
|
arch := compileopts.MuslArchitecture(target)
|
||||||
globs := []string{
|
globs := []string{
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ var Picolibc = Library{
|
|||||||
"-I" + headerPath,
|
"-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 {
|
librarySources: func(target string) []string {
|
||||||
return picolibcSources
|
return picolibcSources
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build byollvm
|
||||||
// +build byollvm
|
// +build byollvm
|
||||||
|
|
||||||
package builder
|
package builder
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
bool tinygo_clang_driver(int argc, char **argv);
|
bool tinygo_clang_driver(int argc, char **argv);
|
||||||
bool tinygo_link_elf(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_mingw(int argc, char **argv);
|
||||||
bool tinygo_link_wasm(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).
|
// linking statically with LLVM (with the byollvm build tag).
|
||||||
func RunTool(tool string, args ...string) error {
|
func RunTool(tool string, args ...string) error {
|
||||||
linker := "elf"
|
linker := "elf"
|
||||||
if tool == "ld.lld" && len(args) >= 2 && args[0] == "-m" && args[1] == "i386pep" {
|
if tool == "ld.lld" && len(args) >= 2 {
|
||||||
linker = "mingw"
|
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...)
|
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))
|
ok = C.tinygo_clang_driver(C.int(len(args)), (**C.char)(buf))
|
||||||
case "ld.lld":
|
case "ld.lld":
|
||||||
switch linker {
|
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":
|
case "elf":
|
||||||
ok = C.tinygo_link_elf(C.int(len(args)), (**C.char)(buf))
|
ok = C.tinygo_link_elf(C.int(len(args)), (**C.char)(buf))
|
||||||
case "mingw":
|
case "mingw":
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !byollvm
|
||||||
// +build !byollvm
|
// +build !byollvm
|
||||||
|
|
||||||
package builder
|
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
|
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
|
||||||
// hashes of the accessed C header files. If there is one or more error, it
|
// hashes of the accessed C header files. If there is one or more error, it
|
||||||
// returns these in the []error slice but still modifies the AST.
|
// returns these in the []error slice but still modifies the AST.
|
||||||
func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string) (*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{
|
p := &cgoPackage{
|
||||||
currentDir: dir,
|
currentDir: dir,
|
||||||
fset: fset,
|
fset: fset,
|
||||||
@@ -333,6 +333,9 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
|
|||||||
// have better alternatives anyway.
|
// have better alternatives anyway.
|
||||||
cflagsForCGo := append([]string{"-D_FORTIFY_SOURCE=0"}, cflags...)
|
cflagsForCGo := append([]string{"-D_FORTIFY_SOURCE=0"}, cflags...)
|
||||||
cflagsForCGo = append(cflagsForCGo, p.cflags...)
|
cflagsForCGo = append(cflagsForCGo, p.cflags...)
|
||||||
|
if clangHeaders != "" {
|
||||||
|
cflagsForCGo = append(cflagsForCGo, "-isystem", clangHeaders)
|
||||||
|
}
|
||||||
|
|
||||||
// Process CGo imports for each file.
|
// Process CGo imports for each file.
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ func TestCGo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process the AST with CGo.
|
// Process the AST with CGo.
|
||||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags)
|
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags, "")
|
||||||
|
|
||||||
// Check the AST for type errors.
|
// Check the AST for type errors.
|
||||||
var typecheckErrors []error
|
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 <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ package cgo
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo linux CFLAGS: -I/usr/lib/llvm-11/include
|
#cgo linux CFLAGS: -I/usr/lib/llvm-11/include
|
||||||
#cgo darwin amd64 CFLAGS: -I/usr/local/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 darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@11/include
|
||||||
#cgo freebsd CFLAGS: -I/usr/local/llvm11/include
|
#cgo freebsd CFLAGS: -I/usr/local/llvm11/include
|
||||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-11/lib -lclang
|
#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,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,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@11/lib -lclang -lffi
|
||||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm11/lib -lclang
|
#cgo freebsd LDFLAGS: -L/usr/local/llvm11/lib -lclang
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ package cgo
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo linux CFLAGS: -I/usr/lib/llvm-12/include
|
#cgo linux CFLAGS: -I/usr/lib/llvm-12/include
|
||||||
#cgo darwin amd64 CFLAGS: -I/usr/local/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 darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@12/include
|
||||||
#cgo freebsd CFLAGS: -I/usr/local/llvm12/include
|
#cgo freebsd CFLAGS: -I/usr/local/llvm12/include
|
||||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-12/lib -lclang
|
#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,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,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@12/lib -lclang -lffi
|
||||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm12/lib -lclang
|
#cgo freebsd LDFLAGS: -L/usr/local/llvm12/lib -lclang
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
//go:build !byollvm && !llvm11 && !llvm12
|
//go:build !byollvm && !llvm11 && !llvm12 && !llvm14
|
||||||
// +build !byollvm,!llvm11,!llvm12
|
// +build !byollvm,!llvm11,!llvm12,!llvm14
|
||||||
|
|
||||||
package cgo
|
package cgo
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo linux CFLAGS: -I/usr/lib/llvm-13/include
|
#cgo linux CFLAGS: -I/usr/lib/llvm-13/include
|
||||||
#cgo darwin amd64 CFLAGS: -I/usr/local/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 darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@13/include
|
||||||
#cgo freebsd CFLAGS: -I/usr/local/llvm13/include
|
#cgo freebsd CFLAGS: -I/usr/local/llvm13/include
|
||||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-13/lib -lclang
|
#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,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,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@13/lib -lclang -lffi
|
||||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm13/lib -lclang
|
#cgo freebsd LDFLAGS: -L/usr/local/llvm13/lib -lclang
|
||||||
*/
|
*/
|
||||||
import "C"
|
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
|
// are slightly different from the ones defined in libclang.go, but they
|
||||||
// should be ABI compatible.
|
// 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) {
|
CXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu) {
|
||||||
return clang_getTranslationUnitCursor(tu);
|
return clang_getTranslationUnitCursor(tu);
|
||||||
|
|||||||
+101
-6
@@ -10,6 +10,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/shlex"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -176,6 +177,34 @@ func (c *Config) AutomaticStackSize() bool {
|
|||||||
return false
|
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
|
// RP2040BootPatch returns whether the RP2040 boot patch should be applied that
|
||||||
// calculates and patches in the checksum for the 2nd stage bootloader.
|
// calculates and patches in the checksum for the 2nd stage bootloader.
|
||||||
func (c *Config) RP2040BootPatch() bool {
|
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
|
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
|
// CFlags returns the flags to pass to the C compiler. This is necessary for CGo
|
||||||
// preprocessing.
|
// preprocessing.
|
||||||
func (c *Config) CFlags() []string {
|
func (c *Config) CFlags() []string {
|
||||||
@@ -225,12 +277,18 @@ func (c *Config) CFlags() []string {
|
|||||||
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
|
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
|
||||||
}
|
}
|
||||||
switch c.Target.Libc {
|
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":
|
case "picolibc":
|
||||||
root := goenv.Get("TINYGOROOT")
|
root := goenv.Get("TINYGOROOT")
|
||||||
picolibcDir := filepath.Join(root, "lib", "picolibc", "newlib", "libc")
|
picolibcDir := filepath.Join(root, "lib", "picolibc", "newlib", "libc")
|
||||||
path, _ := c.LibcPath("picolibc")
|
path, _ := c.LibcPath("picolibc")
|
||||||
cflags = append(cflags,
|
cflags = append(cflags,
|
||||||
"--sysroot="+path,
|
"--sysroot="+path,
|
||||||
|
"-isystem", filepath.Join(path, "include"), // necessary for Xtensa
|
||||||
"-isystem", filepath.Join(picolibcDir, "include"),
|
"-isystem", filepath.Join(picolibcDir, "include"),
|
||||||
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
|
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
|
||||||
)
|
)
|
||||||
@@ -337,6 +395,13 @@ func (c *Config) BinaryFormat(ext string) string {
|
|||||||
return c.Target.BinaryFormat
|
return c.Target.BinaryFormat
|
||||||
}
|
}
|
||||||
return "bin"
|
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":
|
case ".hex":
|
||||||
// Similar to bin, but includes the start address and is thus usually a
|
// Similar to bin, but includes the start address and is thus usually a
|
||||||
// better format.
|
// better format.
|
||||||
@@ -437,13 +502,43 @@ func (c *Config) WasmAbi() string {
|
|||||||
return c.Target.WasmAbi
|
return c.Target.WasmAbi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emulator returns the emulator target config
|
// EmulatorName is a shorthand to get the command for this emulator, something
|
||||||
func (c *Config) Emulator() []string {
|
// like qemu-system-arm or simavr.
|
||||||
var emulator []string
|
func (c *Config) EmulatorName() string {
|
||||||
for _, s := range c.Target.Emulator {
|
parts := strings.SplitN(c.Target.Emulator, " ", 2)
|
||||||
emulator = append(emulator, strings.ReplaceAll(s, "{root}", goenv.Get("TINYGOROOT")))
|
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 {
|
type TestConfig struct {
|
||||||
|
|||||||
@@ -28,11 +28,12 @@ type Options struct {
|
|||||||
PanicStrategy string
|
PanicStrategy string
|
||||||
Scheduler string
|
Scheduler string
|
||||||
Serial string
|
Serial string
|
||||||
|
Work bool // -work flag to print temporary build directory
|
||||||
PrintIR bool
|
PrintIR bool
|
||||||
DumpSSA bool
|
DumpSSA bool
|
||||||
VerifyIR bool
|
VerifyIR bool
|
||||||
PrintCommands func(cmd string, args ...string)
|
PrintCommands func(cmd string, args ...string) `json:"-"`
|
||||||
Semaphore chan struct{} // -p flag controls cap
|
Semaphore chan struct{} `json:"-"` // -p flag controls cap
|
||||||
Debug bool
|
Debug bool
|
||||||
PrintSizes string
|
PrintSizes string
|
||||||
PrintAllocs *regexp.Regexp // regexp string
|
PrintAllocs *regexp.Regexp // regexp string
|
||||||
@@ -45,6 +46,7 @@ type Options struct {
|
|||||||
OpenOCDCommands []string
|
OpenOCDCommands []string
|
||||||
LLVMFeatures string
|
LLVMFeatures string
|
||||||
Directory string
|
Directory string
|
||||||
|
PrintJSON bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify performs a validation on the given options, raising an error if options are not valid.
|
// Verify performs a validation on the given options, raising an error if options are not valid.
|
||||||
|
|||||||
+35
-24
@@ -44,8 +44,8 @@ type TargetSpec struct {
|
|||||||
LDFlags []string `json:"ldflags"`
|
LDFlags []string `json:"ldflags"`
|
||||||
LinkerScript string `json:"linkerscript"`
|
LinkerScript string `json:"linkerscript"`
|
||||||
ExtraFiles []string `json:"extra-files"`
|
ExtraFiles []string `json:"extra-files"`
|
||||||
RP2040BootPatch *bool `json:"rp2040-boot-patch"` // Patch RP2040 2nd stage bootloader checksum
|
RP2040BootPatch *bool `json:"rp2040-boot-patch"` // Patch RP2040 2nd stage bootloader checksum
|
||||||
Emulator []string `json:"emulator" override:"copy"` // inherited Emulator must not be append
|
Emulator string `json:"emulator"`
|
||||||
FlashCommand string `json:"flash-command"`
|
FlashCommand string `json:"flash-command"`
|
||||||
GDB []string `json:"gdb"`
|
GDB []string `json:"gdb"`
|
||||||
PortReset string `json:"flash-1200-bps-reset"`
|
PortReset string `json:"flash-1200-bps-reset"`
|
||||||
@@ -59,6 +59,7 @@ type TargetSpec struct {
|
|||||||
OpenOCDTarget string `json:"openocd-target"`
|
OpenOCDTarget string `json:"openocd-target"`
|
||||||
OpenOCDTransport string `json:"openocd-transport"`
|
OpenOCDTransport string `json:"openocd-transport"`
|
||||||
OpenOCDCommands []string `json:"openocd-commands"`
|
OpenOCDCommands []string `json:"openocd-commands"`
|
||||||
|
OpenOCDVerify *bool `json:"openocd-verify"` // enable verify when flashing with openocd
|
||||||
JLinkDevice string `json:"jlink-device"`
|
JLinkDevice string `json:"jlink-device"`
|
||||||
CodeModel string `json:"code-model"`
|
CodeModel string `json:"code-model"`
|
||||||
RelocationModel string `json:"relocation-model"`
|
RelocationModel string `json:"relocation-model"`
|
||||||
@@ -89,19 +90,8 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
|
|||||||
if !src.IsNil() {
|
if !src.IsNil() {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
}
|
}
|
||||||
case reflect.Slice: // for slices...
|
case reflect.Slice: // for slices, append the field
|
||||||
if src.Len() > 0 { // ... if not empty ...
|
dst.Set(reflect.AppendSlice(dst, src))
|
||||||
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 + "'.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
panic("unknown field type : " + kind.String())
|
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"
|
spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
||||||
case "arm":
|
case "arm":
|
||||||
spec.CPU = "generic"
|
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] {
|
switch strings.Split(triple, "-")[0] {
|
||||||
case "armv5":
|
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"
|
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"
|
spec.Features = "+neon"
|
||||||
}
|
}
|
||||||
if goos == "darwin" {
|
if goos == "darwin" {
|
||||||
spec.CFlags = append(spec.CFlags, "-isysroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk")
|
spec.Linker = "ld.lld"
|
||||||
spec.LDFlags = append(spec.LDFlags, "-Wl,-dead_strip")
|
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" {
|
} else if goos == "linux" {
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.RTLib = "compiler-rt"
|
spec.RTLib = "compiler-rt"
|
||||||
@@ -317,16 +319,25 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
|||||||
if goarch != runtime.GOARCH {
|
if goarch != runtime.GOARCH {
|
||||||
// Some educated guesses as to how to invoke helper programs.
|
// Some educated guesses as to how to invoke helper programs.
|
||||||
spec.GDB = []string{"gdb-multiarch"}
|
spec.GDB = []string{"gdb-multiarch"}
|
||||||
if goarch == "arm" && goos == "linux" {
|
if goos == "linux" {
|
||||||
spec.Emulator = []string{"qemu-arm"}
|
switch goarch {
|
||||||
}
|
case "386":
|
||||||
if goarch == "arm64" && goos == "linux" {
|
// amd64 can _usually_ run 32-bit programs, so skip the emulator in that case.
|
||||||
spec.Emulator = []string{"qemu-aarch64"}
|
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 != runtime.GOOS {
|
||||||
if goos == "windows" {
|
if goos == "windows" {
|
||||||
spec.Emulator = []string{"wine"}
|
spec.Emulator = "wine {}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &spec, nil
|
return &spec, nil
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ func TestOverrideProperties(t *testing.T) {
|
|||||||
CPU: "baseCpu",
|
CPU: "baseCpu",
|
||||||
CFlags: []string{"-base-foo", "-base-bar"},
|
CFlags: []string{"-base-foo", "-base-bar"},
|
||||||
BuildTags: []string{"bt1", "bt2"},
|
BuildTags: []string{"bt1", "bt2"},
|
||||||
Emulator: []string{"be1", "be2"},
|
|
||||||
DefaultStackSize: 42,
|
DefaultStackSize: 42,
|
||||||
AutoStackSize: &baseAutoStackSize,
|
AutoStackSize: &baseAutoStackSize,
|
||||||
}
|
}
|
||||||
@@ -38,7 +37,6 @@ func TestOverrideProperties(t *testing.T) {
|
|||||||
GOOS: "",
|
GOOS: "",
|
||||||
CPU: "chlidCpu",
|
CPU: "chlidCpu",
|
||||||
CFlags: []string{"-child-foo", "-child-bar"},
|
CFlags: []string{"-child-foo", "-child-bar"},
|
||||||
Emulator: []string{"ce1", "ce2"},
|
|
||||||
AutoStackSize: &childAutoStackSize,
|
AutoStackSize: &childAutoStackSize,
|
||||||
DefaultStackSize: 64,
|
DefaultStackSize: 64,
|
||||||
}
|
}
|
||||||
@@ -57,9 +55,6 @@ func TestOverrideProperties(t *testing.T) {
|
|||||||
if !reflect.DeepEqual(base.BuildTags, []string{"bt1", "bt2"}) {
|
if !reflect.DeepEqual(base.BuildTags, []string{"bt1", "bt2"}) {
|
||||||
t.Errorf("Overriding failed : got %v", base.BuildTags)
|
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 {
|
if *base.AutoStackSize != false {
|
||||||
t.Errorf("Overriding failed : got %v", base.AutoStackSize)
|
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")
|
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{
|
return &stdSizes{
|
||||||
IntSize: int64(intWidth / 8),
|
IntSize: int64(intWidth / 8),
|
||||||
PtrSize: int64(targetData.PointerSize()),
|
PtrSize: int64(targetData.PointerSize()),
|
||||||
MaxAlign: int64(targetData.PrefTypeAlignment(targetData.IntPtrType())),
|
MaxAlign: int64(targetData.ABITypeAlignment(complex128Type)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,10 +957,10 @@ func (b *builder) createFunction() {
|
|||||||
} else {
|
} else {
|
||||||
fieldOffsets := b.expandFormalParamOffsets(llvmType)
|
fieldOffsets := b.expandFormalParamOffsets(llvmType)
|
||||||
for i, field := range fields {
|
for i, field := range fields {
|
||||||
expr := b.dibuilder.CreateExpression([]int64{
|
expr := b.dibuilder.CreateExpression([]uint64{
|
||||||
0x1000, // DW_OP_LLVM_fragment
|
0x1000, // DW_OP_LLVM_fragment
|
||||||
int64(fieldOffsets[i]) * 8, // offset in bits
|
fieldOffsets[i] * 8, // offset in bits
|
||||||
int64(b.targetData.TypeAllocSize(field.Type())) * 8, // size in bits
|
b.targetData.TypeAllocSize(field.Type()) * 8, // size in bits
|
||||||
})
|
})
|
||||||
b.dibuilder.InsertValueAtEnd(field, dbgParam, expr, loc, entryBlock)
|
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":
|
case "cap":
|
||||||
value := argValues[0]
|
value := argValues[0]
|
||||||
var llvmCap llvm.Value
|
var llvmCap llvm.Value
|
||||||
switch argTypes[0].(type) {
|
switch argTypes[0].Underlying().(type) {
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
llvmCap = b.createRuntimeCall("chanCap", []llvm.Value{value}, "cap")
|
llvmCap = b.createRuntimeCall("chanCap", []llvm.Value{value}, "cap")
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
@@ -1435,7 +1440,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
return b.emitSV64Call(instr.Args)
|
return b.emitSV64Call(instr.Args)
|
||||||
case strings.HasPrefix(name, "(device/riscv.CSR)."):
|
case strings.HasPrefix(name, "(device/riscv.CSR)."):
|
||||||
return b.emitCSROperation(instr)
|
return b.emitCSROperation(instr)
|
||||||
case strings.HasPrefix(name, "syscall.Syscall"):
|
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall"):
|
||||||
return b.createSyscall(instr)
|
return b.createSyscall(instr)
|
||||||
case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
|
case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
|
||||||
return b.createRawSyscallNoError(instr)
|
return b.createRawSyscallNoError(instr)
|
||||||
@@ -1464,6 +1469,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
case *ssa.Function:
|
case *ssa.Function:
|
||||||
// Regular function call. No context is necessary.
|
// Regular function call. No context is necessary.
|
||||||
context = llvm.Undef(b.i8ptrType)
|
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:
|
case *ssa.MakeClosure:
|
||||||
// A call on a func value, but the callee is trivial to find. For
|
// A call on a func value, but the callee is trivial to find. For
|
||||||
// example: immediately applied functions.
|
// 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
|
// Determine the maximum allowed size for a slice. The biggest possible
|
||||||
// pointer (starting from 0) would be maxPointerValue*sizeof(elementType) so
|
// pointer (starting from 0) would be maxPointerValue*sizeof(elementType) so
|
||||||
// divide by the element type to get the real maximum size.
|
// 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
|
// len(slice) is an int. Make sure the length remains small enough to fit in
|
||||||
// an int.
|
// an int.
|
||||||
@@ -1571,8 +1588,9 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
|
|||||||
switch expr := expr.(type) {
|
switch expr := expr.(type) {
|
||||||
case *ssa.Alloc:
|
case *ssa.Alloc:
|
||||||
typ := b.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
|
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)
|
// Calculate ^uintptr(0)
|
||||||
maxSize := llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)).ZExtValue()
|
maxSize := llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)).ZExtValue()
|
||||||
if size > maxSize {
|
if size > maxSize {
|
||||||
|
|||||||
@@ -226,9 +226,9 @@ func filterIrrelevantIRLines(lines []string) []string {
|
|||||||
// Right now test outputs are for LLVM 12 and higher.
|
// Right now test outputs are for LLVM 12 and higher.
|
||||||
continue
|
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.
|
// 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
|
continue
|
||||||
}
|
}
|
||||||
out = append(out, line)
|
out = append(out, line)
|
||||||
|
|||||||
@@ -98,7 +98,10 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
case llvm.IntegerTypeKind:
|
case llvm.IntegerTypeKind:
|
||||||
constraints = append(constraints, "r")
|
constraints = append(constraints, "r")
|
||||||
case llvm.PointerTypeKind:
|
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:
|
default:
|
||||||
err = b.makeError(instr.Pos(), "unknown type in inline assembly for value: "+name)
|
err = b.makeError(instr.Pos(), "unknown type in inline assembly for value: "+name)
|
||||||
return s
|
return s
|
||||||
|
|||||||
+79
-45
@@ -152,6 +152,27 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value {
|
|||||||
return structGlobal
|
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
|
// 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
|
// interface lowering pass to assign type codes as expected by the reflect
|
||||||
// package. See getTypeCodeNum.
|
// package. See getTypeCodeNum.
|
||||||
@@ -162,48 +183,7 @@ func getTypeCodeName(t types.Type) string {
|
|||||||
case *types.Array:
|
case *types.Array:
|
||||||
return "array:" + strconv.FormatInt(t.Len(), 10) + ":" + getTypeCodeName(t.Elem())
|
return "array:" + strconv.FormatInt(t.Len(), 10) + ":" + getTypeCodeName(t.Elem())
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
var kind string
|
return "basic:" + basicTypes[t.Kind()]
|
||||||
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
|
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
return "chan:" + getTypeCodeName(t.Elem())
|
return "chan:" + getTypeCodeName(t.Elem())
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
@@ -591,23 +571,77 @@ func signature(sig *types.Signature) string {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
s += ", "
|
s += ", "
|
||||||
}
|
}
|
||||||
s += sig.Params().At(i).Type().String()
|
s += typestring(sig.Params().At(i).Type())
|
||||||
}
|
}
|
||||||
s += ")"
|
s += ")"
|
||||||
}
|
}
|
||||||
if sig.Results().Len() == 0 {
|
if sig.Results().Len() == 0 {
|
||||||
// keep as-is
|
// keep as-is
|
||||||
} else if sig.Results().Len() == 1 {
|
} else if sig.Results().Len() == 1 {
|
||||||
s += " " + sig.Results().At(0).Type().String()
|
s += " " + typestring(sig.Results().At(0).Type())
|
||||||
} else {
|
} else {
|
||||||
s += " ("
|
s += " ("
|
||||||
for i := 0; i < sig.Results().Len(); i++ {
|
for i := 0; i < sig.Results().Len(); i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
s += ", "
|
s += ", "
|
||||||
}
|
}
|
||||||
s += sig.Results().At(i).Type().String()
|
s += typestring(sig.Results().At(i).Type())
|
||||||
}
|
}
|
||||||
s += ")"
|
s += ")"
|
||||||
}
|
}
|
||||||
return 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())
|
return fmt.Errorf("type %q uses global context", t.String())
|
||||||
default:
|
default:
|
||||||
// we used some other context by accident
|
// 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
|
// if this is a composite type, check the components of the type
|
||||||
|
|||||||
+13
-1
@@ -10,6 +10,13 @@ import (
|
|||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// constants for hashmap algorithms; must match src/runtime/hashmap.go
|
||||||
|
const (
|
||||||
|
hashmapAlgorithmBinary = iota
|
||||||
|
hashmapAlgorithmString
|
||||||
|
hashmapAlgorithmInterface
|
||||||
|
)
|
||||||
|
|
||||||
// createMakeMap creates a new map object (runtime.hashmap) by allocating and
|
// createMakeMap creates a new map object (runtime.hashmap) by allocating and
|
||||||
// initializing an appropriately sized object.
|
// initializing an appropriately sized object.
|
||||||
func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
||||||
@@ -17,22 +24,27 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
|||||||
keyType := mapType.Key().Underlying()
|
keyType := mapType.Key().Underlying()
|
||||||
llvmValueType := b.getLLVMType(mapType.Elem().Underlying())
|
llvmValueType := b.getLLVMType(mapType.Elem().Underlying())
|
||||||
var llvmKeyType llvm.Type
|
var llvmKeyType llvm.Type
|
||||||
|
var alg uint64 // must match values in src/runtime/hashmap.go
|
||||||
if t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {
|
if t, ok := keyType.(*types.Basic); ok && t.Info()&types.IsString != 0 {
|
||||||
// String keys.
|
// String keys.
|
||||||
llvmKeyType = b.getLLVMType(keyType)
|
llvmKeyType = b.getLLVMType(keyType)
|
||||||
|
alg = hashmapAlgorithmString
|
||||||
} else if hashmapIsBinaryKey(keyType) {
|
} else if hashmapIsBinaryKey(keyType) {
|
||||||
// Trivially comparable keys.
|
// Trivially comparable keys.
|
||||||
llvmKeyType = b.getLLVMType(keyType)
|
llvmKeyType = b.getLLVMType(keyType)
|
||||||
|
alg = hashmapAlgorithmBinary
|
||||||
} else {
|
} else {
|
||||||
// All other keys. Implemented as map[interface{}]valueType for ease of
|
// All other keys. Implemented as map[interface{}]valueType for ease of
|
||||||
// implementation.
|
// implementation.
|
||||||
llvmKeyType = b.getLLVMRuntimeType("_interface")
|
llvmKeyType = b.getLLVMRuntimeType("_interface")
|
||||||
|
alg = hashmapAlgorithmInterface
|
||||||
}
|
}
|
||||||
keySize := b.targetData.TypeAllocSize(llvmKeyType)
|
keySize := b.targetData.TypeAllocSize(llvmKeyType)
|
||||||
valueSize := b.targetData.TypeAllocSize(llvmValueType)
|
valueSize := b.targetData.TypeAllocSize(llvmValueType)
|
||||||
llvmKeySize := llvm.ConstInt(b.ctx.Int8Type(), keySize, false)
|
llvmKeySize := llvm.ConstInt(b.ctx.Int8Type(), keySize, false)
|
||||||
llvmValueSize := llvm.ConstInt(b.ctx.Int8Type(), valueSize, false)
|
llvmValueSize := llvm.ConstInt(b.ctx.Int8Type(), valueSize, false)
|
||||||
sizeHint := llvm.ConstInt(b.uintptrType, 8, false)
|
sizeHint := llvm.ConstInt(b.uintptrType, 8, false)
|
||||||
|
algEnum := llvm.ConstInt(b.ctx.Int8Type(), alg, false)
|
||||||
if expr.Reserve != nil {
|
if expr.Reserve != nil {
|
||||||
sizeHint = b.getValue(expr.Reserve)
|
sizeHint = b.getValue(expr.Reserve)
|
||||||
var err error
|
var err error
|
||||||
@@ -41,7 +53,7 @@ func (b *builder) createMakeMap(expr *ssa.MakeMap) (llvm.Value, error) {
|
|||||||
return llvm.Value{}, err
|
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
|
return hashmap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'basic.go'
|
; ModuleID = 'basic.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
%main.kv = type { float }
|
%main.kv = type { float }
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'channel.go'
|
; ModuleID = 'channel.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'float.go'
|
; ModuleID = 'float.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'func.go'
|
; ModuleID = 'func.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'gc.go'
|
; ModuleID = 'gc.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 }
|
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 }
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'go1.17.go'
|
; ModuleID = 'go1.17.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'goroutine.go'
|
; ModuleID = 'goroutine.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
%runtime.channel = type { i32, i32, i8, %runtime.channelBlockedList*, i32, i32, i32, i8* }
|
||||||
|
|||||||
Vendored
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'interface.go'
|
; ModuleID = 'interface.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo*, %runtime.typecodeID*, i32 }
|
%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 #0 = { nounwind }
|
||||||
attributes #1 = { "tinygo-methods"="reflect/methods.Error() string" }
|
attributes #1 = { "tinygo-methods"="reflect/methods.Error() string" }
|
||||||
attributes #2 = { "tinygo-methods"="reflect/methods.String() 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" }
|
attributes #4 = { "tinygo-invoke"="reflect/methods.Error() string" "tinygo-methods"="reflect/methods.Error() string" }
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'intrinsics.go'
|
; ModuleID = 'intrinsics.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'pointer.go'
|
; ModuleID = 'pointer.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'pragma.go'
|
; ModuleID = 'pragma.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
@extern_global = external global [0 x i8], align 1
|
@extern_global = external global [0 x i8], align 1
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'slice.go'
|
; ModuleID = 'slice.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
; ModuleID = 'string.go'
|
; ModuleID = 'string.go'
|
||||||
source_filename = "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"
|
target triple = "wasm32-unknown-wasi"
|
||||||
|
|
||||||
%runtime._string = type { i8*, i32 }
|
%runtime._string = type { i8*, i32 }
|
||||||
|
|||||||
@@ -15,5 +15,5 @@ require (
|
|||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
||||||
golang.org/x/tools v0.1.6-0.20210813165731-45389f592fe9
|
golang.org/x/tools v0.1.6-0.20210813165731-45389f592fe9
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
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.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20220121152956-4fa2ab2718f3 h1:vQSFy0kNQegAfL/F6iyWQa4bF941Xc1gyJUkGy2m448=
|
tinygo.org/x/go-llvm v0.0.0-20220420140351-512c94c1e71f h1:9/J+NpFTpAhYcbh1mC4dr9W/aAPnwrUh8dmq21xWdSM=
|
||||||
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/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||||
|
|||||||
+9
-3
@@ -12,7 +12,13 @@ import (
|
|||||||
|
|
||||||
// Version of TinyGo.
|
// Version of TinyGo.
|
||||||
// Update this value before release of new version of software.
|
// Update this value before release of new version of software.
|
||||||
const Version = "0.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.
|
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||||
// If the goroot cannot be determined, (0, 0) is returned.
|
// If the goroot cannot be determined, (0, 0) is returned.
|
||||||
@@ -52,9 +58,9 @@ func GorootVersionString(goroot string) (string, error) {
|
|||||||
return string(data), nil
|
return string(data), nil
|
||||||
|
|
||||||
} else if data, err := ioutil.ReadFile(filepath.Join(
|
} 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)
|
matches := r.FindSubmatch(data)
|
||||||
if len(matches) != 2 {
|
if len(matches) != 2 {
|
||||||
return "", errors.New("Invalid go version output:\n" + string(data))
|
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,
|
// Call a function with a definition available. Run it as usual,
|
||||||
// possibly trying to recover from it if it failed to execute.
|
// possibly trying to recover from it if it failed to execute.
|
||||||
if r.debug {
|
if r.debug {
|
||||||
argStrings := make([]string, len(operands))
|
argStrings := make([]string, len(operands)-1)
|
||||||
for i := range argStrings {
|
for i, v := range operands[1:] {
|
||||||
argStrings[i] = operands[i+1].String()
|
argStrings[i] = v.String()
|
||||||
}
|
}
|
||||||
fmt.Fprintln(os.Stderr, indent+"call:", callFn.name+"("+strings.Join(argStrings, ", ")+")")
|
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 datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
target triple = "x86_64--linux"
|
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.printuint8(i8) local_unnamed_addr
|
||||||
|
|
||||||
declare void @runtime.printint16(i16) 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.printuint8(i8 3)
|
call void @runtime.printuint8(i8 3)
|
||||||
call void @runtime.printint16(i16 5)
|
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 5)
|
||||||
call void @runtime.printint16(i16 %int16SliceDst.val)
|
|
||||||
ret void
|
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,
|
"device/": false,
|
||||||
"examples/": false,
|
"examples/": false,
|
||||||
"internal/": true,
|
"internal/": true,
|
||||||
|
"internal/fuzz/": false,
|
||||||
"internal/bytealg/": false,
|
"internal/bytealg/": false,
|
||||||
"internal/reflectlite/": false,
|
"internal/reflectlite/": false,
|
||||||
"internal/task/": false,
|
"internal/task/": false,
|
||||||
|
|||||||
+1
-4
@@ -418,10 +418,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
|||||||
var initialCFlags []string
|
var initialCFlags []string
|
||||||
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
||||||
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
||||||
if p.program.clangHeaders != "" {
|
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.program.fset, initialCFlags, 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)
|
|
||||||
p.CFlags = append(initialCFlags, cflags...)
|
p.CFlags = append(initialCFlags, cflags...)
|
||||||
p.CGoHeaders = headerCode
|
p.CGoHeaders = headerCode
|
||||||
for path, hash := range accessedFiles {
|
for path, hash := range accessedFiles {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
@@ -36,12 +37,6 @@ import (
|
|||||||
"go.bug.st/serial/enumerator"
|
"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
|
// commandError is an error type to wrap os/exec.Command errors. This provides
|
||||||
// some more information regarding what went wrong while running a command.
|
// some more information regarding what went wrong while running a command.
|
||||||
type commandError struct {
|
type commandError struct {
|
||||||
@@ -148,7 +143,27 @@ func Build(pkgName, outpath string, options *compileopts.Options) error {
|
|||||||
return err
|
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 {
|
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 {
|
if err := os.Rename(result.Binary, outpath); err != nil {
|
||||||
// Moving failed. Do a file copy.
|
// Moving failed. Do a file copy.
|
||||||
inf, err := os.Open(result.Binary)
|
inf, err := os.Open(result.Binary)
|
||||||
@@ -185,8 +200,26 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
|||||||
return false, err
|
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
|
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 != "" {
|
if testCompileOnly || outpath != "" {
|
||||||
// Write test binary to the specified file name.
|
// Write test binary to the specified file name.
|
||||||
if outpath == "" {
|
if outpath == "" {
|
||||||
@@ -202,27 +235,52 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the test.
|
// Tests are always run in the package directory.
|
||||||
config.Options.Semaphore <- struct{}{}
|
cmd.Dir = result.MainDir
|
||||||
defer func() {
|
|
||||||
<-config.Options.Semaphore
|
// Wasmtime needs a few extra flags to work.
|
||||||
}()
|
if config.EmulatorName() == "wasmtime" {
|
||||||
start := time.Now()
|
// Add directories to the module root, but skip the current working
|
||||||
var err error
|
// directory which is already added by buildAndRun.
|
||||||
passed, err = runPackageTest(config, stdout, stderr, result, testVerbose, testShort, testRunRegexp, testBenchRegexp, testBenchTime)
|
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
|
||||||
if err != nil {
|
var args []string
|
||||||
return err
|
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)
|
duration := time.Since(start)
|
||||||
|
|
||||||
// Print the result.
|
// Print the result.
|
||||||
importPath := strings.TrimSuffix(result.ImportPath, ".test")
|
importPath := strings.TrimSuffix(result.ImportPath, ".test")
|
||||||
|
passed = err == nil
|
||||||
if passed {
|
if passed {
|
||||||
fmt.Fprintf(stdout, "ok \t%s\t%.3fs\n", importPath, duration.Seconds())
|
fmt.Fprintf(stdout, "ok \t%s\t%.3fs\n", importPath, duration.Seconds())
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(stdout, "FAIL\t%s\t%.3fs\n", importPath, duration.Seconds())
|
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 {
|
if err, ok := err.(loader.NoTestFilesError); ok {
|
||||||
fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", err.ImportPath)
|
fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", err.ImportPath)
|
||||||
@@ -245,81 +303,6 @@ func dirsToModuleRoot(maindir, modroot string) []string {
|
|||||||
return dirs
|
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.
|
// Flash builds and flashes the built binary to the given serial port.
|
||||||
func Flash(pkgName, port string, options *compileopts.Options) error {
|
func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||||
config, err := builder.NewConfig(options)
|
config, err := builder.NewConfig(options)
|
||||||
@@ -439,7 +422,11 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 := executeCommand(config.Options, "openocd", args...)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
@@ -496,18 +483,19 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
|||||||
return err
|
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.
|
// Find a good way to run GDB.
|
||||||
gdbInterface, openocdInterface := config.Programmer()
|
gdbInterface, openocdInterface := config.Programmer()
|
||||||
switch gdbInterface {
|
switch gdbInterface {
|
||||||
case "msd", "command", "":
|
case "msd", "command", "":
|
||||||
emulator := config.Emulator()
|
emulator := config.EmulatorName()
|
||||||
if len(emulator) != 0 {
|
if emulator != "" {
|
||||||
if emulator[0] == "mgba" {
|
if emulator == "mgba" {
|
||||||
gdbInterface = "mgba"
|
gdbInterface = "mgba"
|
||||||
} else if emulator[0] == "simavr" {
|
} else if emulator == "simavr" {
|
||||||
gdbInterface = "simavr"
|
gdbInterface = "simavr"
|
||||||
} else if strings.HasPrefix(emulator[0], "qemu-system-") {
|
} else if strings.HasPrefix(emulator, "qemu-system-") {
|
||||||
gdbInterface = "qemu"
|
gdbInterface = "qemu"
|
||||||
} else {
|
} else {
|
||||||
// Assume QEMU as an emulator.
|
// Assume QEMU as an emulator.
|
||||||
@@ -526,6 +514,10 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
|||||||
port := ""
|
port := ""
|
||||||
var gdbCommands []string
|
var gdbCommands []string
|
||||||
var daemon *exec.Cmd
|
var daemon *exec.Cmd
|
||||||
|
emulator, err := config.Emulator(format, result.Binary)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
switch gdbInterface {
|
switch gdbInterface {
|
||||||
case "native":
|
case "native":
|
||||||
// Run GDB directly.
|
// Run GDB directly.
|
||||||
@@ -575,33 +567,29 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
|||||||
}
|
}
|
||||||
case "qemu":
|
case "qemu":
|
||||||
port = ":1234"
|
port = ":1234"
|
||||||
emulator := config.Emulator()
|
|
||||||
// Run in an 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 = executeCommand(config.Options, emulator[0], args...)
|
||||||
daemon.Stdout = os.Stdout
|
daemon.Stdout = os.Stdout
|
||||||
daemon.Stderr = os.Stderr
|
daemon.Stderr = os.Stderr
|
||||||
case "qemu-user":
|
case "qemu-user":
|
||||||
port = ":1234"
|
port = ":1234"
|
||||||
emulator := config.Emulator()
|
|
||||||
// Run in an 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 = executeCommand(config.Options, emulator[0], args...)
|
||||||
daemon.Stdout = os.Stdout
|
daemon.Stdout = os.Stdout
|
||||||
daemon.Stderr = os.Stderr
|
daemon.Stderr = os.Stderr
|
||||||
case "mgba":
|
case "mgba":
|
||||||
port = ":2345"
|
port = ":2345"
|
||||||
emulator := config.Emulator()
|
|
||||||
// Run in an 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 = executeCommand(config.Options, emulator[0], args...)
|
||||||
daemon.Stdout = os.Stdout
|
daemon.Stdout = os.Stdout
|
||||||
daemon.Stderr = os.Stderr
|
daemon.Stderr = os.Stderr
|
||||||
case "simavr":
|
case "simavr":
|
||||||
port = ":1234"
|
port = ":1234"
|
||||||
emulator := config.Emulator()
|
|
||||||
// Run in an 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 = executeCommand(config.Options, emulator[0], args...)
|
||||||
daemon.Stdout = os.Stdout
|
daemon.Stdout = os.Stdout
|
||||||
daemon.Stderr = os.Stderr
|
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.
|
// Construct and execute a gdb or lldb command.
|
||||||
// By default: gdb -ex run <binary>
|
// By default: gdb -ex run <binary>
|
||||||
// Exit the debugger with Ctrl-D.
|
// Exit the debugger with Ctrl-D.
|
||||||
params := []string{result.Binary}
|
params := []string{result.Executable}
|
||||||
switch debugger {
|
switch debugger {
|
||||||
case "gdb":
|
case "gdb":
|
||||||
if port != "" {
|
if port != "" {
|
||||||
@@ -678,9 +666,9 @@ func Debug(debugger, pkgName string, ocdOutput bool, options *compileopts.Option
|
|||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
err := cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
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
|
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
|
// 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
|
// an emulator. For example, -target=wasm will cause the binary to be run inside
|
||||||
// of a WebAssembly VM.
|
// 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)
|
config, err := builder.NewConfig(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.Build(pkgName, ".elf", config, func(result builder.BuildResult) error {
|
return buildAndRun(pkgName, config, os.Stdout, cmdArgs, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||||
emulator := config.Emulator()
|
return cmd.Run()
|
||||||
if len(emulator) == 0 {
|
})
|
||||||
// Run directly.
|
}
|
||||||
cmd := executeCommand(config.Options, result.Binary)
|
|
||||||
cmd.Stdout = os.Stdout
|
// buildAndRun builds and runs the given program, writing output to stdout and
|
||||||
cmd.Stderr = os.Stderr
|
// errors to os.Stderr. It takes care of emulators (qemu, wasmtime, etc) and
|
||||||
err := cmd.Run()
|
// passes command line arguments and evironment variables in a way appropriate
|
||||||
if err != nil {
|
// for the given emulator.
|
||||||
if err, ok := err.(*exec.ExitError); ok && err.Exited() {
|
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 {
|
||||||
// Workaround for QEMU which always exits with an error.
|
// Determine whether we're on a system that supports environment variables
|
||||||
return nil
|
// and command line parameters (operating systems, WASI) or not (baremetal,
|
||||||
}
|
// WebAssembly in the browser). If we're on a system without an environment,
|
||||||
return &commandError{"failed to run compiled binary", result.Binary, err}
|
// we need to pass command line arguments and environment variables through
|
||||||
}
|
// global variables (built into the binary directly) instead of the
|
||||||
return nil
|
// conventional way.
|
||||||
} else {
|
needsEnvInVars := config.GOOS() == "js"
|
||||||
// Run in an emulator.
|
for _, tag := range config.BuildTags() {
|
||||||
args := append(emulator[1:], result.Binary)
|
if tag == "baremetal" {
|
||||||
cmd := executeCommand(config.Options, emulator[0], args...)
|
needsEnvInVars = true
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
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) {
|
func usage(command string) {
|
||||||
version := goenv.Version
|
version := goenv.Version
|
||||||
if strings.HasSuffix(version, "-dev") && gitSha1 != "" {
|
if strings.HasSuffix(version, "-dev") && goenv.GitSha1 != "" {
|
||||||
version += "-" + gitSha1
|
version += "-" + goenv.GitSha1
|
||||||
}
|
}
|
||||||
|
|
||||||
switch command {
|
switch command {
|
||||||
@@ -1187,6 +1265,7 @@ func main() {
|
|||||||
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
||||||
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
|
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
|
||||||
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
|
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
|
||||||
|
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
|
||||||
printIR := flag.Bool("printir", false, "print LLVM IR")
|
printIR := flag.Bool("printir", false, "print LLVM IR")
|
||||||
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
||||||
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
||||||
@@ -1207,13 +1286,13 @@ func main() {
|
|||||||
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
||||||
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
||||||
|
|
||||||
var flagJSON, flagDeps, flagTest *bool
|
var flagJSON, flagDeps, flagTest bool
|
||||||
if command == "help" || command == "list" || command == "info" {
|
if command == "help" || command == "list" || command == "info" || command == "build" {
|
||||||
flagJSON = flag.Bool("json", false, "print data in JSON format")
|
flag.BoolVar(&flagJSON, "json", false, "print data in JSON format")
|
||||||
}
|
}
|
||||||
if command == "help" || command == "list" {
|
if command == "help" || command == "list" {
|
||||||
flagDeps = flag.Bool("deps", false, "supply -deps flag to go list")
|
flag.BoolVar(&flagDeps, "deps", false, "supply -deps flag to go list")
|
||||||
flagTest = flag.Bool("test", false, "supply -test flag to go list")
|
flag.BoolVar(&flagTest, "test", false, "supply -test flag to go list")
|
||||||
}
|
}
|
||||||
var outpath string
|
var outpath string
|
||||||
if command == "help" || command == "build" || command == "build-library" || command == "test" {
|
if command == "help" || command == "build" || command == "build-library" || command == "test" {
|
||||||
@@ -1275,6 +1354,7 @@ func main() {
|
|||||||
PanicStrategy: *panicStrategy,
|
PanicStrategy: *panicStrategy,
|
||||||
Scheduler: *scheduler,
|
Scheduler: *scheduler,
|
||||||
Serial: *serial,
|
Serial: *serial,
|
||||||
|
Work: *work,
|
||||||
PrintIR: *printIR,
|
PrintIR: *printIR,
|
||||||
DumpSSA: *dumpSSA,
|
DumpSSA: *dumpSSA,
|
||||||
VerifyIR: *verifyIR,
|
VerifyIR: *verifyIR,
|
||||||
@@ -1289,6 +1369,7 @@ func main() {
|
|||||||
Programmer: *programmer,
|
Programmer: *programmer,
|
||||||
OpenOCDCommands: ocdCommands,
|
OpenOCDCommands: ocdCommands,
|
||||||
LLVMFeatures: *llvmFeatures,
|
LLVMFeatures: *llvmFeatures,
|
||||||
|
PrintJSON: flagJSON,
|
||||||
}
|
}
|
||||||
if *printCommands {
|
if *printCommands {
|
||||||
options.PrintCommands = printCommand
|
options.PrintCommands = printCommand
|
||||||
@@ -1317,11 +1398,6 @@ func main() {
|
|||||||
|
|
||||||
switch command {
|
switch command {
|
||||||
case "build":
|
case "build":
|
||||||
if outpath == "" {
|
|
||||||
fmt.Fprintln(os.Stderr, "No output filename supplied (-o).")
|
|
||||||
usage(command)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
pkgName := "."
|
pkgName := "."
|
||||||
if flag.NArg() == 1 {
|
if flag.NArg() == 1 {
|
||||||
pkgName = filepath.ToSlash(flag.Arg(0))
|
pkgName = filepath.ToSlash(flag.Arg(0))
|
||||||
@@ -1395,13 +1471,13 @@ func main() {
|
|||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
}
|
}
|
||||||
case "run":
|
case "run":
|
||||||
if flag.NArg() != 1 {
|
if flag.NArg() < 1 {
|
||||||
fmt.Fprintln(os.Stderr, "No package specified.")
|
fmt.Fprintln(os.Stderr, "No package specified.")
|
||||||
usage(command)
|
usage(command)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
pkgName := filepath.ToSlash(flag.Arg(0))
|
pkgName := filepath.ToSlash(flag.Arg(0))
|
||||||
err := Run(pkgName, options)
|
err := Run(pkgName, options, flag.Args()[1:])
|
||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
case "test":
|
case "test":
|
||||||
var pkgNames []string
|
var pkgNames []string
|
||||||
@@ -1411,8 +1487,8 @@ func main() {
|
|||||||
if len(pkgNames) == 0 {
|
if len(pkgNames) == 0 {
|
||||||
pkgNames = []string{"."}
|
pkgNames = []string{"."}
|
||||||
}
|
}
|
||||||
if *testCompileOnlyFlag && len(pkgNames) > 1 {
|
if outpath != "" && len(pkgNames) > 1 {
|
||||||
fmt.Println("cannot use -c flag with multiple packages")
|
fmt.Println("cannot use -o flag with multiple packages")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1497,7 +1573,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
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
|
// This doesn't look like a regular target file, but rather like
|
||||||
// a parent target (such as targets/cortex-m.json).
|
// a parent target (such as targets/cortex-m.json).
|
||||||
continue
|
continue
|
||||||
@@ -1530,7 +1606,7 @@ func main() {
|
|||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if *flagJSON {
|
if flagJSON {
|
||||||
json, _ := json.MarshalIndent(struct {
|
json, _ := json.MarshalIndent(struct {
|
||||||
GOROOT string `json:"goroot"`
|
GOROOT string `json:"goroot"`
|
||||||
GOOS string `json:"goos"`
|
GOOS string `json:"goos"`
|
||||||
@@ -1569,13 +1645,13 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
var extraArgs []string
|
var extraArgs []string
|
||||||
if *flagJSON {
|
if flagJSON {
|
||||||
extraArgs = append(extraArgs, "-json")
|
extraArgs = append(extraArgs, "-json")
|
||||||
}
|
}
|
||||||
if *flagDeps {
|
if flagDeps {
|
||||||
extraArgs = append(extraArgs, "-deps")
|
extraArgs = append(extraArgs, "-deps")
|
||||||
}
|
}
|
||||||
if *flagTest {
|
if flagTest {
|
||||||
extraArgs = append(extraArgs, "-test")
|
extraArgs = append(extraArgs, "-test")
|
||||||
}
|
}
|
||||||
cmd, err := loader.List(config, extraArgs, flag.Args())
|
cmd, err := loader.List(config, extraArgs, flag.Args())
|
||||||
@@ -1612,8 +1688,8 @@ func main() {
|
|||||||
goversion = s
|
goversion = s
|
||||||
}
|
}
|
||||||
version := goenv.Version
|
version := goenv.Version
|
||||||
if strings.HasSuffix(goenv.Version, "-dev") && gitSha1 != "" {
|
if strings.HasSuffix(goenv.Version, "-dev") && goenv.GitSha1 != "" {
|
||||||
version += "-" + 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)
|
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":
|
case "env":
|
||||||
|
|||||||
+36
-121
@@ -6,7 +6,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -14,7 +13,6 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -31,6 +29,13 @@ const TESTDATA = "testdata"
|
|||||||
|
|
||||||
var testTarget = flag.String("target", "", "override test target")
|
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())
|
var sema = make(chan struct{}, runtime.NumCPU())
|
||||||
|
|
||||||
func TestBuild(t *testing.T) {
|
func TestBuild(t *testing.T) {
|
||||||
@@ -59,7 +64,6 @@ func TestBuild(t *testing.T) {
|
|||||||
"stdlib.go",
|
"stdlib.go",
|
||||||
"string.go",
|
"string.go",
|
||||||
"structs.go",
|
"structs.go",
|
||||||
"testing.go",
|
|
||||||
"zeroalloc.go",
|
"zeroalloc.go",
|
||||||
}
|
}
|
||||||
_, minor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
|
_, minor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
|
||||||
@@ -69,6 +73,11 @@ func TestBuild(t *testing.T) {
|
|||||||
if minor >= 17 {
|
if minor >= 17 {
|
||||||
tests = append(tests, "go1.17.go")
|
tests = append(tests, "go1.17.go")
|
||||||
}
|
}
|
||||||
|
if minor >= 18 {
|
||||||
|
tests = append(tests, "testing_go118.go")
|
||||||
|
} else {
|
||||||
|
tests = append(tests, "testing.go")
|
||||||
|
}
|
||||||
|
|
||||||
if *testTarget != "" {
|
if *testTarget != "" {
|
||||||
// This makes it possible to run one specific test (instead of all),
|
// This makes it possible to run one specific test (instead of all),
|
||||||
@@ -180,18 +189,14 @@ func TestBuild(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
t.Run("X86Linux", func(t *testing.T) {
|
for name, osArch := range supportedLinuxArches {
|
||||||
t.Parallel()
|
options := optionsFromOSARCH(osArch, sema)
|
||||||
runPlatTests(optionsFromOSARCH("linux/386", sema), tests, t)
|
if options.GOARCH != runtime.GOARCH { // Native architecture already run above.
|
||||||
})
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Run("ARMLinux", func(t *testing.T) {
|
runPlatTests(options, tests, 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)
|
|
||||||
})
|
|
||||||
t.Run("WebAssembly", func(t *testing.T) {
|
t.Run("WebAssembly", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runPlatTests(optionsFromTarget("wasm", sema), tests, t)
|
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)
|
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.Run("env.go", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runTest("env.go", options, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"})
|
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 {
|
if err != nil {
|
||||||
t.Fatal("failed to load target spec:", err)
|
t.Fatal("failed to load target spec:", err)
|
||||||
}
|
}
|
||||||
if len(spec.Emulator) != 0 {
|
if spec.Emulator != "" {
|
||||||
_, err := exec.LookPath(spec.Emulator[0])
|
_, err := exec.LookPath(strings.SplitN(spec.Emulator, " ", 2)[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, exec.ErrNotFound) {
|
if errors.Is(err, exec.ErrNotFound) {
|
||||||
t.Skipf("emulator not installed: %q", spec.Emulator[0])
|
t.Skipf("emulator not installed: %q", 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)
|
t.Fatal("could not read expected output file:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a temporary directory for test output files.
|
config, err := builder.NewConfig(&options)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("failed to load target spec:", err)
|
t.Fatal(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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the test binary.
|
// Build the test binary.
|
||||||
binary := filepath.Join(tmpdir, "test")
|
stdout := &bytes.Buffer{}
|
||||||
if spec.GOOS == "windows" {
|
err = buildAndRun("./"+path, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||||
binary += ".exe"
|
return cmd.Run()
|
||||||
}
|
})
|
||||||
err = Build("./"+path, binary, &options)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printCompilerError(t.Log, err)
|
printCompilerError(t.Log, err)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
return
|
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.
|
// putchar() prints CRLF, convert it to LF.
|
||||||
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
|
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
|
||||||
expected = bytes.Replace(expected, []byte{'\r', '\n'}, []byte{'\n'}, -1) // for Windows
|
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.
|
// Strip simavr log formatting.
|
||||||
actual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)
|
actual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)
|
||||||
actual = bytes.Replace(actual, []byte{0x1b, '[', '0', '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 !testing.Short() {
|
||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
targs = append(targs,
|
for name, osArch := range supportedLinuxArches {
|
||||||
// Linux
|
options := optionsFromOSARCH(osArch, sema)
|
||||||
targ{"X86Linux", optionsFromOSARCH("linux/386", sema)},
|
if options.GOARCH != runtime.GOARCH { // Native architecture already run above.
|
||||||
targ{"ARMLinux", optionsFromOSARCH("linux/arm/6", sema)},
|
targs = append(targs, targ{name, options})
|
||||||
targ{"ARM64Linux", optionsFromOSARCH("linux/arm64", sema)},
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
targs = append(targs,
|
targs = append(targs,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Hand created file. DO NOT DELETE.
|
// Hand created file. DO NOT DELETE.
|
||||||
// Cortex-M System Control Block-related definitions.
|
// Cortex-M System Control Block-related definitions.
|
||||||
|
|
||||||
|
//go:build cortexm
|
||||||
// +build cortexm
|
// +build cortexm
|
||||||
|
|
||||||
package arm
|
package arm
|
||||||
|
|||||||
@@ -142,18 +142,14 @@ func (mpu *MPU_Type) Enable(enable bool) {
|
|||||||
if enable {
|
if enable {
|
||||||
mpu.CTRL.Set(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk)
|
mpu.CTRL.Set(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk)
|
||||||
SystemControl.SHCSR.SetBits(SCB_SHCSR_MEMFAULTENA_Msk)
|
SystemControl.SHCSR.SetBits(SCB_SHCSR_MEMFAULTENA_Msk)
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
arm.Asm("isb 0xF")
|
||||||
isb 0xF
|
|
||||||
`, nil)
|
|
||||||
enableDcache(true)
|
enableDcache(true)
|
||||||
enableIcache(true)
|
enableIcache(true)
|
||||||
} else {
|
} else {
|
||||||
enableIcache(false)
|
enableIcache(false)
|
||||||
enableDcache(false)
|
enableDcache(false)
|
||||||
arm.AsmFull(`
|
arm.Asm("dmb 0xF")
|
||||||
dmb 0xF
|
|
||||||
`, nil)
|
|
||||||
SystemControl.SHCSR.ClearBits(SCB_SHCSR_MEMFAULTENA_Msk)
|
SystemControl.SHCSR.ClearBits(SCB_SHCSR_MEMFAULTENA_Msk)
|
||||||
mpu.CTRL.ClearBits(MPU_CTRL_ENABLE_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) {
|
func enableIcache(enable bool) {
|
||||||
if enable != SystemControl.CCR.HasBits(SCB_CCR_IC_Msk) {
|
if enable != SystemControl.CCR.HasBits(SCB_CCR_IC_Msk) {
|
||||||
if enable {
|
if enable {
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
arm.Asm("isb 0xF")
|
||||||
isb 0xF
|
|
||||||
`, nil)
|
|
||||||
SystemControl.ICIALLU.Set(0)
|
SystemControl.ICIALLU.Set(0)
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
arm.Asm("isb 0xF")
|
||||||
isb 0xF
|
|
||||||
`, nil)
|
|
||||||
SystemControl.CCR.SetBits(SCB_CCR_IC_Msk)
|
SystemControl.CCR.SetBits(SCB_CCR_IC_Msk)
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
arm.Asm("isb 0xF")
|
||||||
isb 0xF
|
|
||||||
`, nil)
|
|
||||||
} else {
|
} else {
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
arm.Asm("isb 0xF")
|
||||||
isb 0xF
|
|
||||||
`, nil)
|
|
||||||
SystemControl.CCR.ClearBits(SCB_CCR_IC_Msk)
|
SystemControl.CCR.ClearBits(SCB_CCR_IC_Msk)
|
||||||
SystemControl.ICIALLU.Set(0)
|
SystemControl.ICIALLU.Set(0)
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
arm.Asm("isb 0xF")
|
||||||
isb 0xF
|
|
||||||
`, nil)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,9 +213,7 @@ func enableDcache(enable bool) {
|
|||||||
if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) {
|
if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) {
|
||||||
if enable {
|
if enable {
|
||||||
SystemControl.CSSELR.Set(0)
|
SystemControl.CSSELR.Set(0)
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
|
||||||
`, nil)
|
|
||||||
ccsidr := SystemControl.CCSIDR.Get()
|
ccsidr := SystemControl.CCSIDR.Get()
|
||||||
sets := (ccsidr & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos
|
sets := (ccsidr & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos
|
||||||
for sets != 0 {
|
for sets != 0 {
|
||||||
@@ -242,23 +226,15 @@ func enableDcache(enable bool) {
|
|||||||
}
|
}
|
||||||
sets--
|
sets--
|
||||||
}
|
}
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
|
||||||
`, nil)
|
|
||||||
SystemControl.CCR.SetBits(SCB_CCR_DC_Msk)
|
SystemControl.CCR.SetBits(SCB_CCR_DC_Msk)
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
arm.Asm("isb 0xF")
|
||||||
isb 0xF
|
|
||||||
`, nil)
|
|
||||||
} else {
|
} else {
|
||||||
SystemControl.CSSELR.Set(0)
|
SystemControl.CSSELR.Set(0)
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
|
||||||
`, nil)
|
|
||||||
SystemControl.CCR.ClearBits(SCB_CCR_DC_Msk)
|
SystemControl.CCR.ClearBits(SCB_CCR_DC_Msk)
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
|
||||||
`, nil)
|
|
||||||
dcacheCcsidr.Set(SystemControl.CCSIDR.Get())
|
dcacheCcsidr.Set(SystemControl.CCSIDR.Get())
|
||||||
dcacheSets.Set((dcacheCcsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
|
dcacheSets.Set((dcacheCcsidr.Get() & SCB_CCSIDR_NUMSETS_Msk) >> SCB_CCSIDR_NUMSETS_Pos)
|
||||||
for dcacheSets.Get() != 0 {
|
for dcacheSets.Get() != 0 {
|
||||||
@@ -271,10 +247,8 @@ func enableDcache(enable bool) {
|
|||||||
}
|
}
|
||||||
dcacheSets.Set(dcacheSets.Get() - 1)
|
dcacheSets.Set(dcacheSets.Get() - 1)
|
||||||
}
|
}
|
||||||
arm.AsmFull(`
|
arm.Asm("dsb 0xF")
|
||||||
dsb 0xF
|
arm.Asm("isb 0xF")
|
||||||
isb 0xF
|
|
||||||
`, nil)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
// +build feather_m4_can
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build feather_m4_can
|
||||||
// +build feather_m4_can
|
// +build feather_m4_can
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build circuitplay_express
|
||||||
// +build circuitplay_express
|
// +build circuitplay_express
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build pyportal
|
||||||
// +build pyportal
|
// +build pyportal
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build circuitplay_express
|
||||||
// +build circuitplay_express
|
// +build circuitplay_express
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build pca10040
|
||||||
// +build pca10040
|
// +build pca10040
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build stm32
|
||||||
// +build stm32
|
// +build stm32
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build wioterminal
|
||||||
// +build wioterminal
|
// +build wioterminal
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build arduino_mega1280
|
||||||
// +build arduino_mega1280
|
// +build arduino_mega1280
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build arduino
|
||||||
// +build arduino
|
// +build arduino
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build bluepill
|
||||||
// +build bluepill
|
// +build bluepill
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build feather_m4
|
||||||
// +build feather_m4
|
// +build feather_m4
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build itsybitsy_m0
|
||||||
// +build itsybitsy_m0
|
// +build itsybitsy_m0
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build itsybitsy_m4
|
||||||
// +build itsybitsy_m4
|
// +build itsybitsy_m4
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build stm32f7
|
||||||
// +build stm32f7
|
// +build stm32f7
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build stm32l0
|
||||||
// +build stm32l0
|
// +build stm32l0
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build stm32l4
|
||||||
// +build stm32l4
|
// +build stm32l4
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build stm32l5
|
||||||
// +build stm32l5
|
// +build stm32l5
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build pico
|
||||||
// +build pico
|
// +build pico
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build stm32f4disco
|
||||||
// +build stm32f4disco
|
// +build stm32f4disco
|
||||||
|
|
||||||
package main
|
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
|
// +build arduino
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build arduino_mega1280
|
||||||
// +build arduino_mega1280
|
// +build arduino_mega1280
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build arduino_mega2560
|
||||||
// +build arduino_mega2560
|
// +build arduino_mega2560
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build arduino_mkr1000
|
||||||
// +build arduino_mkr1000
|
// +build arduino_mkr1000
|
||||||
|
|
||||||
// This contains the pin mappings for the Arduino MKR1000 board.
|
// This contains the pin mappings for the Arduino MKR1000 board.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build arduino_mkrwifi1010
|
||||||
// +build arduino_mkrwifi1010
|
// +build arduino_mkrwifi1010
|
||||||
|
|
||||||
// This contains the pin mappings for the Arduino MKR WiFi 1010 board.
|
// This contains the pin mappings for the Arduino MKR WiFi 1010 board.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build arduino_nano
|
||||||
// +build arduino_nano
|
// +build arduino_nano
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build arduino_nano33
|
||||||
// +build arduino_nano33
|
// +build arduino_nano33
|
||||||
|
|
||||||
// This contains the pin mappings for the Arduino Nano33 IoT board.
|
// 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
|
// +build sam,atsamd21,arduino_zero
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build (avr && atmega328p) || arduino || arduino_nano
|
||||||
// +build avr,atmega328p arduino arduino_nano
|
// +build avr,atmega328p arduino arduino_nano
|
||||||
|
|
||||||
package machine
|
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