mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-05 03:27:48 +00:00
Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8eaa9bd8d0 | |||
| 6061f3db92 | |||
| 410aa0e0d8 | |||
| c66836cf3a | |||
| ca9211b582 | |||
| cb7d470ba4 | |||
| 5baee9a8ee | |||
| c47f52b546 | |||
| a2588d8db3 | |||
| f529b6071d | |||
| 5557e97888 | |||
| d04b07fa8b | |||
| 7486277012 | |||
| 36d60b8349 | |||
| c55191283b | |||
| ad30085b93 | |||
| e9ca41735a | |||
| df1f83f4e1 | |||
| 5879d785a9 | |||
| 186018abeb | |||
| 828b9614c2 | |||
| f5e933cd4d | |||
| 0952b1b984 | |||
| ed55f56d85 | |||
| edb8766aab | |||
| 413bb55e2c | |||
| 0db1a4bec1 | |||
| 2867da164d | |||
| 7b8ae2d6b6 | |||
| 5b8127fd4e | |||
| cc3e785692 | |||
| 0ea5cfc8fe | |||
| 70f1a5429a | |||
| 2fb2113168 | |||
| cb39611389 | |||
| 45764325b4 | |||
| bb66232164 | |||
| 9679e7f1cc | |||
| 6cdfc298cf | |||
| 9a4bfd0e96 | |||
| ee3106be98 | |||
| 57f49af726 | |||
| 38a80b45d3 | |||
| e9003e2deb | |||
| 204659bdcd | |||
| 08ca1d13d0 | |||
| 53db436a7d | |||
| 0ad15551c8 | |||
| afd65e224a | |||
| 5f50c3b60b | |||
| 8858d49989 | |||
| cf39d8b2c8 | |||
| d92a31b440 | |||
| 9c77a38358 | |||
| d0445d6f83 | |||
| a40b11f535 | |||
| 8c90f4facf | |||
| c7c9a76af5 | |||
| 6984af43a0 | |||
| 81c56c3ab8 | |||
| 3d9a1ca22a | |||
| c2083014b3 | |||
| 603a81f194 | |||
| cfc32794a7 | |||
| 1d9c53d00e | |||
| 8d2a07b927 | |||
| ffe6dfd21b | |||
| cf21380264 | |||
| 534b3b0c0b | |||
| ceeb233ff6 | |||
| de3f0af829 | |||
| a511f18c64 | |||
| 731bd5cd1b | |||
| 4acf59546e | |||
| 2ee4d9aaa1 | |||
| b58b7c59ae | |||
| e14b6a7009 | |||
| a1a2d1ab81 | |||
| 07591178cd | |||
| 43bdc888dd | |||
| 4229e670ce | |||
| 76a7ad2a3e | |||
| e4f551ac7f | |||
| 338590cc75 | |||
| 22d70604d8 | |||
| c6add1e769 | |||
| c6609a02fa | |||
| a449c4813a | |||
| 19fb1bfafc | |||
| f91b6ad0df | |||
| 94459cefe5 | |||
| 803ba4f54d | |||
| 2919fa8b14 | |||
| 6420e90124 | |||
| 2d289addb7 | |||
| 4df145dcb4 | |||
| e065da20cb | |||
| d7c77b6761 | |||
| f51029484a | |||
| 03cfcbc17c | |||
| 649f49e000 | |||
| 3bcd4dc3e0 | |||
| 772c71ec27 | |||
| 9b896dc981 | |||
| d4189feca6 | |||
| 777048cfa9 | |||
| 2b215955ca | |||
| ce25f00769 | |||
| 1a59aecb63 | |||
| cca32e67a9 | |||
| 174d492355 | |||
| 5355473dce | |||
| a531ed614a | |||
| 24ae6fdf29 | |||
| 938ce22307 | |||
| 9fb5a5b9a4 | |||
| 9fd9d9c05a | |||
| fd50227a3d | |||
| a90295430c | |||
| fa4ca63ff2 | |||
| 7019c4e8fc | |||
| b79e0e8528 | |||
| 51bed3afae | |||
| 4d4ccddad8 | |||
| f55f5315cc | |||
| 7468a00ef4 | |||
| 8d77278c6b | |||
| dde9b5ad3a | |||
| 2d4307647e | |||
| 935a293106 | |||
| 72b715fa99 | |||
| d801d0cd53 | |||
| c2f1965e03 | |||
| 75bba42b60 | |||
| 18b50db0dc | |||
| 499fce9cee | |||
| 88b29589d6 | |||
| 8cbfbcae5a | |||
| 5cd8ba2421 |
+19
-10
@@ -5,17 +5,17 @@ commands:
|
|||||||
steps:
|
steps:
|
||||||
- run:
|
- run:
|
||||||
name: "Pull submodules"
|
name: "Pull submodules"
|
||||||
command: git submodule update --init
|
command: git submodule update --init --recursive
|
||||||
llvm-source-linux:
|
llvm-source-linux:
|
||||||
steps:
|
steps:
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- llvm-source-16-v3
|
- llvm-source-17-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-16-v3
|
key: llvm-source-17-v1
|
||||||
paths:
|
paths:
|
||||||
- llvm-project/clang/lib/Headers
|
- llvm-project/clang/lib/Headers
|
||||||
- llvm-project/clang/include
|
- llvm-project/clang/include
|
||||||
@@ -55,7 +55,7 @@ commands:
|
|||||||
- run:
|
- run:
|
||||||
name: "Install apt dependencies"
|
name: "Install apt dependencies"
|
||||||
command: |
|
command: |
|
||||||
echo 'deb https://apt.llvm.org/buster/ llvm-toolchain-buster-<<parameters.llvm>> main' > /etc/apt/sources.list.d/llvm.list
|
echo 'deb https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-<<parameters.llvm>> main' > /etc/apt/sources.list.d/llvm.list
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install --no-install-recommends -y \
|
apt-get install --no-install-recommends -y \
|
||||||
@@ -69,16 +69,16 @@ commands:
|
|||||||
- build-binaryen-linux
|
- build-binaryen-linux
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- go-cache-v3-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
|
- go-cache-v4-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
|
||||||
- go-cache-v3-{{ checksum "go.mod" }}
|
- go-cache-v4-{{ checksum "go.mod" }}
|
||||||
- llvm-source-linux
|
- llvm-source-linux
|
||||||
- run: go install -tags=llvm<<parameters.llvm>> .
|
- run: go install -tags=llvm<<parameters.llvm>> .
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- wasi-libc-sysroot-systemclang-v6
|
- wasi-libc-sysroot-systemclang-v7
|
||||||
- run: make wasi-libc
|
- run: make wasi-libc
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: wasi-libc-sysroot-systemclang-v6
|
key: wasi-libc-sysroot-systemclang-v7
|
||||||
paths:
|
paths:
|
||||||
- lib/wasi-libc/sysroot
|
- lib/wasi-libc/sysroot
|
||||||
- when:
|
- when:
|
||||||
@@ -92,7 +92,7 @@ commands:
|
|||||||
- run: make gen-device -j4
|
- run: make gen-device -j4
|
||||||
- run: make smoketest XTENSA=0
|
- run: make smoketest XTENSA=0
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: go-cache-v3-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
key: go-cache-v4-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
|
||||||
paths:
|
paths:
|
||||||
- ~/.cache/go-build
|
- ~/.cache/go-build
|
||||||
- /go/pkg/mod
|
- /go/pkg/mod
|
||||||
@@ -100,11 +100,18 @@ commands:
|
|||||||
jobs:
|
jobs:
|
||||||
test-llvm15-go118:
|
test-llvm15-go118:
|
||||||
docker:
|
docker:
|
||||||
- image: golang:1.18-buster
|
- image: golang:1.18-bullseye
|
||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "15"
|
llvm: "15"
|
||||||
resource_class: large
|
resource_class: large
|
||||||
|
test-llvm17-go122:
|
||||||
|
docker:
|
||||||
|
- image: golang:1.22-bullseye
|
||||||
|
steps:
|
||||||
|
- test-linux:
|
||||||
|
llvm: "17"
|
||||||
|
resource_class: large
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
test-all:
|
test-all:
|
||||||
@@ -112,3 +119,5 @@ workflows:
|
|||||||
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
||||||
# least the smoke tests still pass.
|
# least the smoke tests still pass.
|
||||||
- test-llvm15-go118
|
- test-llvm15-go118
|
||||||
|
# This tests LLVM 17 support when linking against system libraries.
|
||||||
|
- test-llvm17-go122
|
||||||
|
|||||||
@@ -14,26 +14,36 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
build-macos:
|
build-macos:
|
||||||
name: build-macos
|
name: build-macos
|
||||||
runs-on: macos-11
|
strategy:
|
||||||
|
matrix:
|
||||||
|
# macos-12: amd64 (oldest supported version as of 05-02-2024)
|
||||||
|
# macos-14: arm64 (oldest arm64 version)
|
||||||
|
os: [macos-12, macos-14]
|
||||||
|
include:
|
||||||
|
- os: macos-12
|
||||||
|
goarch: amd64
|
||||||
|
- os: macos-14
|
||||||
|
goarch: arm64
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu binaryen
|
HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu binaryen
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-16-macos-v1
|
key: llvm-source-17-${{ matrix.os }}-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
@@ -44,7 +54,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -55,10 +65,10 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore LLVM build cache
|
- name: Restore LLVM build cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-16-macos-v1
|
key: llvm-build-17-${{ matrix.os }}-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'
|
||||||
@@ -73,16 +83,16 @@ jobs:
|
|||||||
make llvm-build
|
make llvm-build
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save LLVM build cache
|
- name: Save LLVM build cache
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Cache wasi-libc sysroot
|
- name: Cache wasi-libc sysroot
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-v4
|
key: wasi-libc-sysroot-${{ matrix.os }}-v1
|
||||||
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'
|
||||||
@@ -98,7 +108,7 @@ jobs:
|
|||||||
run: make tinygo-test
|
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-${{ matrix.goarch }}.tar.gz
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
# Note: this release artifact is double-zipped, see:
|
# Note: this release artifact is double-zipped, see:
|
||||||
# https://github.com/actions/upload-artifact/issues/39
|
# https://github.com/actions/upload-artifact/issues/39
|
||||||
@@ -106,29 +116,44 @@ jobs:
|
|||||||
# - have a double-zipped artifact when downloaded from the UI
|
# - have a double-zipped artifact when downloaded from the UI
|
||||||
# - have a very slow artifact upload
|
# - have a very slow artifact upload
|
||||||
# We're doing the former here, to keep artifact uploads fast.
|
# We're doing the former here, to keep artifact uploads fast.
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: darwin-amd64-double-zipped
|
name: darwin-${{ matrix.goarch }}-double-zipped
|
||||||
path: build/tinygo.darwin-amd64.tar.gz
|
path: build/tinygo.darwin-${{ matrix.goarch }}.tar.gz
|
||||||
- name: Smoke tests
|
- name: Smoke tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make smoketest TINYGO=$(PWD)/build/tinygo
|
run: make smoketest TINYGO=$(PWD)/build/tinygo
|
||||||
test-macos-homebrew:
|
test-macos-homebrew:
|
||||||
name: homebrew-install
|
name: homebrew-install
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
version: [16, 17]
|
||||||
steps:
|
steps:
|
||||||
- name: Install LLVM
|
- name: Set up Homebrew
|
||||||
shell: bash
|
uses: Homebrew/actions/setup-homebrew@master
|
||||||
|
- name: Fix Python symlinks
|
||||||
run: |
|
run: |
|
||||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@16
|
# Github runners have broken symlinks, so relink
|
||||||
|
# see: https://github.com/actions/setup-python/issues/577
|
||||||
|
brew list -1 | grep python | while read formula; do brew unlink $formula; brew link --overwrite $formula; done
|
||||||
|
- name: Install LLVM
|
||||||
|
run: |
|
||||||
|
brew install llvm@${{ matrix.version }}
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Build TinyGo
|
- name: Build TinyGo (LLVM ${{ matrix.version }})
|
||||||
run: go install
|
run: go install -tags=llvm${{ matrix.version }}
|
||||||
- name: Check binary
|
- name: Check binary
|
||||||
run: tinygo version
|
run: tinygo version
|
||||||
|
- name: Build TinyGo (default LLVM)
|
||||||
|
if: matrix.version == 17
|
||||||
|
run: go install
|
||||||
|
- name: Check binary
|
||||||
|
if: matrix.version == 17
|
||||||
|
run: tinygo version
|
||||||
|
|||||||
@@ -19,15 +19,26 @@ jobs:
|
|||||||
packages: write
|
packages: write
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
|
- name: Free Disk space
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
df -h
|
||||||
|
sudo rm -rf /opt/hostedtoolcache
|
||||||
|
sudo rm -rf /usr/local/lib/android
|
||||||
|
sudo rm -rf /usr/share/dotnet
|
||||||
|
sudo rm -rf /opt/ghc
|
||||||
|
sudo rm -rf /usr/local/graalvm
|
||||||
|
sudo rm -rf /usr/local/share/boost
|
||||||
|
df -h
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
tinygo/tinygo-dev
|
tinygo/tinygo-dev
|
||||||
@@ -36,24 +47,24 @@ jobs:
|
|||||||
type=sha,format=long
|
type=sha,format=long
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
- name: Log in to Github Container Registry
|
- name: Log in to Github Container Registry
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
build-contexts: tinygo-llvm-build=docker-image://tinygo/llvm-16
|
build-contexts: tinygo-llvm-build=docker-image://tinygo/llvm-17
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
- name: Trigger Drivers repo build on Github Actions
|
- name: Trigger Drivers repo build on Github Actions
|
||||||
|
|||||||
+50
-50
@@ -18,10 +18,10 @@ jobs:
|
|||||||
# statically linked binary.
|
# statically linked binary.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: golang:1.21-alpine
|
image: golang:1.22-alpine
|
||||||
steps:
|
steps:
|
||||||
- name: Install apk dependencies
|
- name: Install apk dependencies
|
||||||
# tar: needed for actions/cache@v3
|
# tar: needed for actions/cache@v4
|
||||||
# git+openssh: needed for checkout (I think?)
|
# git+openssh: needed for checkout (I think?)
|
||||||
# ruby: needed to install fpm
|
# ruby: needed to install fpm
|
||||||
run: apk add tar git openssh make g++ ruby
|
run: apk add tar git openssh make g++ ruby
|
||||||
@@ -29,21 +29,21 @@ jobs:
|
|||||||
# We're not on a multi-user machine, so this is safe.
|
# We're not on a multi-user machine, so this is safe.
|
||||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Cache Go
|
- name: Cache Go
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
|
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
~/go/pkg/mod
|
~/go/pkg/mod
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-16-linux-alpine-v1
|
key: llvm-source-17-linux-alpine-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -65,10 +65,10 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore LLVM build cache
|
- name: Restore LLVM build cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-16-linux-alpine-v1
|
key: llvm-build-17-linux-alpine-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'
|
||||||
@@ -83,13 +83,13 @@ jobs:
|
|||||||
# Remove unnecessary object files (to reduce cache size).
|
# Remove unnecessary object files (to reduce cache size).
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save LLVM build cache
|
- name: Save LLVM build cache
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-alpine-v1
|
key: binaryen-linux-alpine-v1
|
||||||
@@ -100,10 +100,10 @@ jobs:
|
|||||||
apk add cmake samurai python3
|
apk add cmake samurai python3
|
||||||
make binaryen STATIC=1
|
make binaryen STATIC=1
|
||||||
- name: Cache wasi-libc
|
- name: Cache wasi-libc
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-linux-alpine-v1
|
key: wasi-libc-sysroot-linux-alpine-v2
|
||||||
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'
|
||||||
@@ -119,7 +119,7 @@ jobs:
|
|||||||
cp -p build/release.tar.gz /tmp/tinygo.linux-amd64.tar.gz
|
cp -p build/release.tar.gz /tmp/tinygo.linux-amd64.tar.gz
|
||||||
cp -p build/release.deb /tmp/tinygo_amd64.deb
|
cp -p build/release.deb /tmp/tinygo_amd64.deb
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped
|
name: linux-amd64-double-zipped
|
||||||
path: |
|
path: |
|
||||||
@@ -131,20 +131,20 @@ jobs:
|
|||||||
needs: build-linux
|
needs: build-linux
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
run: |
|
run: |
|
||||||
mkdir -p $HOME/.wasmtime $HOME/.wasmtime/bin
|
mkdir -p $HOME/.wasmtime $HOME/.wasmtime/bin
|
||||||
curl https://github.com/bytecodealliance/wasmtime/releases/download/v5.0.0/wasmtime-v5.0.0-x86_64-linux.tar.xz -o wasmtime-v5.0.0-x86_64-linux.tar.xz -SfL
|
curl https://github.com/bytecodealliance/wasmtime/releases/download/v14.0.4/wasmtime-v14.0.4-x86_64-linux.tar.xz -o wasmtime-v14.0.4-x86_64-linux.tar.xz -SfL
|
||||||
tar -C $HOME/.wasmtime/bin --wildcards -xf wasmtime-v5.0.0-x86_64-linux.tar.xz --strip-components=1 wasmtime-v5.0.0-x86_64-linux/*
|
tar -C $HOME/.wasmtime/bin --wildcards -xf wasmtime-v14.0.4-x86_64-linux.tar.xz --strip-components=1 wasmtime-v14.0.4-x86_64-linux/*
|
||||||
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
|
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
|
||||||
- name: Download release artifact
|
- name: Download release artifact
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped
|
name: linux-amd64-double-zipped
|
||||||
- name: Extract release tarball
|
- name: Extract release tarball
|
||||||
@@ -161,7 +161,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install apt dependencies
|
- name: Install apt dependencies
|
||||||
@@ -176,25 +176,25 @@ jobs:
|
|||||||
simavr \
|
simavr \
|
||||||
ninja-build
|
ninja-build
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '16'
|
node-version: '18'
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
run: |
|
run: |
|
||||||
mkdir -p $HOME/.wasmtime $HOME/.wasmtime/bin
|
mkdir -p $HOME/.wasmtime $HOME/.wasmtime/bin
|
||||||
curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v5.0.0/wasmtime-v5.0.0-x86_64-linux.tar.xz -o wasmtime-v5.0.0-x86_64-linux.tar.xz -SfL
|
curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v14.0.4/wasmtime-v14.0.4-x86_64-linux.tar.xz -o wasmtime-v14.0.4-x86_64-linux.tar.xz -SfL
|
||||||
tar -C $HOME/.wasmtime/bin --wildcards -xf wasmtime-v5.0.0-x86_64-linux.tar.xz --strip-components=1 wasmtime-v5.0.0-x86_64-linux/*
|
tar -C $HOME/.wasmtime/bin --wildcards -xf wasmtime-v14.0.4-x86_64-linux.tar.xz --strip-components=1 wasmtime-v14.0.4-x86_64-linux/*
|
||||||
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
|
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-16-linux-asserts-v1
|
key: llvm-source-17-linux-asserts-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
@@ -205,7 +205,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -216,10 +216,10 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore LLVM build cache
|
- name: Restore LLVM build cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-16-linux-asserts-v1
|
key: llvm-build-17-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'
|
||||||
@@ -232,13 +232,13 @@ jobs:
|
|||||||
# Remove unnecessary object files (to reduce cache size).
|
# Remove unnecessary object files (to reduce cache size).
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save LLVM build cache
|
- name: Save LLVM build cache
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-asserts-v1
|
key: binaryen-linux-asserts-v1
|
||||||
@@ -247,10 +247,10 @@ jobs:
|
|||||||
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
||||||
run: make binaryen
|
run: make binaryen
|
||||||
- name: Cache wasi-libc
|
- name: Cache wasi-libc
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-linux-asserts-v5
|
key: wasi-libc-sysroot-linux-asserts-v6
|
||||||
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'
|
||||||
@@ -290,7 +290,7 @@ jobs:
|
|||||||
needs: build-linux
|
needs: build-linux
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Install apt dependencies
|
- name: Install apt dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
@@ -299,15 +299,15 @@ jobs:
|
|||||||
g++-${{ matrix.toolchain }} \
|
g++-${{ matrix.toolchain }} \
|
||||||
libc6-dev-${{ matrix.libc }}-cross
|
libc6-dev-${{ matrix.libc }}-cross
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-16-linux-v1
|
key: llvm-source-17-linux-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
@@ -318,7 +318,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save LLVM source cache
|
- name: Save LLVM source cache
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -329,10 +329,10 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore LLVM build cache
|
- name: Restore LLVM build cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-16-linux-${{ matrix.goarch }}-v1
|
key: llvm-build-17-linux-${{ matrix.goarch }}-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'
|
||||||
@@ -347,22 +347,22 @@ jobs:
|
|||||||
# Remove unnecessary object files (to reduce cache size).
|
# Remove unnecessary object files (to reduce cache size).
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save LLVM build cache
|
- name: Save LLVM build cache
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Cache Binaryen
|
- name: Cache Binaryen
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: cache-binaryen
|
id: cache-binaryen
|
||||||
with:
|
with:
|
||||||
key: binaryen-linux-${{ matrix.goarch }}-v1
|
key: binaryen-linux-${{ matrix.goarch }}-v3
|
||||||
path: build/wasm-opt
|
path: build/wasm-opt
|
||||||
- name: Build Binaryen
|
- name: Build Binaryen
|
||||||
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install --no-install-recommends ninja-build
|
sudo apt-get install --no-install-recommends ninja-build
|
||||||
git submodule update --init lib/binaryen
|
git submodule update --init --recursive lib/binaryen
|
||||||
make CROSS=${{ matrix.toolchain }} binaryen
|
make CROSS=${{ matrix.toolchain }} binaryen
|
||||||
- name: Install fpm
|
- name: Install fpm
|
||||||
run: |
|
run: |
|
||||||
@@ -373,7 +373,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make CROSS=${{ matrix.toolchain }}
|
make CROSS=${{ matrix.toolchain }}
|
||||||
- name: Download amd64 release
|
- name: Download amd64 release
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-amd64-double-zipped
|
name: linux-amd64-double-zipped
|
||||||
- name: Extract amd64 release
|
- name: Extract amd64 release
|
||||||
@@ -390,7 +390,7 @@ jobs:
|
|||||||
cp -p build/release.tar.gz /tmp/tinygo.linux-${{ matrix.goarch }}.tar.gz
|
cp -p build/release.tar.gz /tmp/tinygo.linux-${{ matrix.goarch }}.tar.gz
|
||||||
cp -p build/release.deb /tmp/tinygo_${{ matrix.libc }}.deb
|
cp -p build/release.deb /tmp/tinygo_${{ matrix.libc }}.deb
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: linux-${{ matrix.goarch }}-double-zipped
|
name: linux-${{ matrix.goarch }}-double-zipped
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -25,18 +25,18 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
tinygo/llvm-16
|
tinygo/llvm-17
|
||||||
ghcr.io/${{ github.repository_owner }}/llvm-16
|
ghcr.io/${{ github.repository_owner }}/llvm-17
|
||||||
tags: |
|
tags: |
|
||||||
type=sha,format=long
|
type=sha,format=long
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
@@ -46,13 +46,13 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
- name: Log in to Github Container Registry
|
- name: Log in to Github Container Registry
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
target: tinygo-llvm-build
|
target: tinygo-llvm-build
|
||||||
context: .
|
context: .
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
name: Nix
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
- release
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
nix-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Pull musl
|
||||||
|
run: |
|
||||||
|
git submodule update --init lib/musl
|
||||||
|
- name: Restore LLVM source cache
|
||||||
|
uses: actions/cache/restore@v4
|
||||||
|
id: cache-llvm-source
|
||||||
|
with:
|
||||||
|
key: llvm-source-17-linux-nix-v1
|
||||||
|
path: |
|
||||||
|
llvm-project/compiler-rt
|
||||||
|
- name: Download LLVM source
|
||||||
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
|
run: make llvm-source
|
||||||
|
- name: Save LLVM source cache
|
||||||
|
uses: actions/cache/save@v4
|
||||||
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
|
with:
|
||||||
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
|
path: |
|
||||||
|
llvm-project/compiler-rt
|
||||||
|
- uses: cachix/install-nix-action@v22
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
nix develop --ignore-environment --keep HOME --command bash -c "go install && ~/go/bin/tinygo version && ~/go/bin/tinygo build -o test ./testdata/cgo"
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
# Command that's part of sizediff.yml. This is put in a separate file so that it
|
||||||
|
# still works after checking out the dev branch (that is, when going from LLVM
|
||||||
|
# 16 to LLVM 17 for example, both Clang 16 and Clang 17 are installed).
|
||||||
|
|
||||||
|
echo 'deb https://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main' | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||||
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install --no-install-recommends -y \
|
||||||
|
llvm-17-dev \
|
||||||
|
clang-17 \
|
||||||
|
libclang-17-dev \
|
||||||
|
lld-17
|
||||||
@@ -18,32 +18,24 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "$HOME/go/bin" >> $GITHUB_PATH
|
echo "$HOME/go/bin" >> $GITHUB_PATH
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # fetch all history (no sparse checkout)
|
fetch-depth: 0 # fetch all history (no sparse checkout)
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install apt dependencies
|
- name: Install apt dependencies
|
||||||
run: |
|
run: ./.github/workflows/sizediff-install-pkgs.sh
|
||||||
echo 'deb https://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main' | sudo tee /etc/apt/sources.list.d/llvm.list
|
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install --no-install-recommends -y \
|
|
||||||
llvm-16-dev \
|
|
||||||
clang-16 \
|
|
||||||
libclang-16-dev \
|
|
||||||
lld-16
|
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-16-sizediff-v1
|
key: llvm-source-17-sizediff-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/compiler-rt
|
llvm-project/compiler-rt
|
||||||
- name: Download LLVM source
|
- name: Download LLVM source
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Cache Go
|
- name: Cache Go
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
key: go-cache-linux-sizediff-v1-${{ hashFiles('go.mod') }}
|
key: go-cache-linux-sizediff-v1-${{ hashFiles('go.mod') }}
|
||||||
path: |
|
path: |
|
||||||
@@ -55,22 +47,25 @@ jobs:
|
|||||||
- name: Save HEAD
|
- name: Save HEAD
|
||||||
run: git branch github-actions-saved-HEAD HEAD
|
run: git branch github-actions-saved-HEAD HEAD
|
||||||
|
|
||||||
# Compute sizes for the dev branch
|
|
||||||
- name: Checkout dev branch
|
|
||||||
run: git checkout --no-recurse-submodules `git merge-base HEAD origin/dev`
|
|
||||||
- name: Build tinygo binary for the dev branch
|
|
||||||
run: go install
|
|
||||||
- name: Determine binary sizes on the dev branch
|
|
||||||
run: (cd drivers; make smoke-test XTENSA=0 | tee sizes-dev.txt)
|
|
||||||
|
|
||||||
# Compute sizes for the PR branch
|
# Compute sizes for the PR branch
|
||||||
- name: Checkout PR branch
|
|
||||||
run: git checkout --no-recurse-submodules github-actions-saved-HEAD
|
|
||||||
- name: Build tinygo binary for the PR branch
|
- name: Build tinygo binary for the PR branch
|
||||||
run: go install
|
run: go install
|
||||||
- name: Determine binary sizes on the PR branch
|
- name: Determine binary sizes on the PR branch
|
||||||
run: (cd drivers; make smoke-test XTENSA=0 | tee sizes-pr.txt)
|
run: (cd drivers; make smoke-test XTENSA=0 | tee sizes-pr.txt)
|
||||||
|
|
||||||
|
# Compute sizes for the dev branch
|
||||||
|
- name: Checkout dev branch
|
||||||
|
run: |
|
||||||
|
git reset --hard origin/dev
|
||||||
|
git checkout --no-recurse-submodules `git merge-base HEAD origin/dev`
|
||||||
|
- name: Install apt dependencies on the dev branch
|
||||||
|
# this is only needed on a PR that changes the LLVM version
|
||||||
|
run: ./.github/workflows/sizediff-install-pkgs.sh
|
||||||
|
- name: Build tinygo binary for the dev branch
|
||||||
|
run: go install
|
||||||
|
- name: Determine binary sizes on the dev branch
|
||||||
|
run: (cd drivers; make smoke-test XTENSA=0 | tee sizes-dev.txt)
|
||||||
|
|
||||||
# Create comment
|
# Create comment
|
||||||
# TODO: add a summary, something like:
|
# TODO: add a summary, something like:
|
||||||
# - overall size difference (percent)
|
# - overall size difference (percent)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
steps:
|
steps:
|
||||||
- name: Configure pagefile
|
- name: Configure pagefile
|
||||||
uses: al-cheb/configure-pagefile-action@v1.3
|
uses: al-cheb/configure-pagefile-action@v1.4
|
||||||
with:
|
with:
|
||||||
minimum-size: 8GB
|
minimum-size: 8GB
|
||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
@@ -29,19 +29,19 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
scoop install ninja binaryen
|
scoop install ninja binaryen
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore cached LLVM source
|
- name: Restore cached LLVM source
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
with:
|
with:
|
||||||
key: llvm-source-16-windows-v1
|
key: llvm-source-17-windows-v1
|
||||||
path: |
|
path: |
|
||||||
llvm-project/clang/lib/Headers
|
llvm-project/clang/lib/Headers
|
||||||
llvm-project/clang/include
|
llvm-project/clang/include
|
||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
run: make llvm-source
|
run: make llvm-source
|
||||||
- name: Save cached LLVM source
|
- name: Save cached LLVM source
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
|
||||||
@@ -63,10 +63,10 @@ jobs:
|
|||||||
llvm-project/lld/include
|
llvm-project/lld/include
|
||||||
llvm-project/llvm/include
|
llvm-project/llvm/include
|
||||||
- name: Restore cached LLVM build
|
- name: Restore cached LLVM build
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-16-windows-v2
|
key: llvm-build-17-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'
|
||||||
@@ -80,23 +80,23 @@ jobs:
|
|||||||
# Remove unnecessary object files (to reduce cache size).
|
# Remove unnecessary object files (to reduce cache size).
|
||||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||||
- name: Save cached LLVM build
|
- name: Save cached LLVM build
|
||||||
uses: actions/cache/save@v3
|
uses: actions/cache/save@v4
|
||||||
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
|
||||||
path: llvm-build
|
path: llvm-build
|
||||||
- name: Cache wasi-libc sysroot
|
- name: Cache wasi-libc sysroot
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: cache-wasi-libc
|
id: cache-wasi-libc
|
||||||
with:
|
with:
|
||||||
key: wasi-libc-sysroot-v4
|
key: wasi-libc-sysroot-v5
|
||||||
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
|
- name: Install wasmtime
|
||||||
run: |
|
run: |
|
||||||
scoop install wasmtime
|
scoop install wasmtime@14.0.4
|
||||||
- name: make gen-device
|
- name: make gen-device
|
||||||
run: make -j3 gen-device
|
run: make -j3 gen-device
|
||||||
- name: Test TinyGo
|
- name: Test TinyGo
|
||||||
@@ -116,7 +116,7 @@ jobs:
|
|||||||
# - have a dobule-zipped artifact when downloaded from the UI
|
# - have a dobule-zipped artifact when downloaded from the UI
|
||||||
# - have a very slow artifact upload
|
# - have a very slow artifact upload
|
||||||
# We're doing the former here, to keep artifact uploads fast.
|
# We're doing the former here, to keep artifact uploads fast.
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped
|
name: windows-amd64-double-zipped
|
||||||
path: build/release/release.zip
|
path: build/release/release.zip
|
||||||
@@ -126,7 +126,7 @@ jobs:
|
|||||||
needs: build-windows
|
needs: build-windows
|
||||||
steps:
|
steps:
|
||||||
- name: Configure pagefile
|
- name: Configure pagefile
|
||||||
uses: al-cheb/configure-pagefile-action@v1.3
|
uses: al-cheb/configure-pagefile-action@v1.4
|
||||||
with:
|
with:
|
||||||
minimum-size: 8GB
|
minimum-size: 8GB
|
||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
@@ -139,14 +139,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
scoop install binaryen
|
scoop install binaryen
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped
|
name: windows-amd64-double-zipped
|
||||||
path: build/
|
path: build/
|
||||||
@@ -163,20 +163,20 @@ jobs:
|
|||||||
needs: build-windows
|
needs: build-windows
|
||||||
steps:
|
steps:
|
||||||
- name: Configure pagefile
|
- name: Configure pagefile
|
||||||
uses: al-cheb/configure-pagefile-action@v1.3
|
uses: al-cheb/configure-pagefile-action@v1.4
|
||||||
with:
|
with:
|
||||||
minimum-size: 8GB
|
minimum-size: 8GB
|
||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped
|
name: windows-amd64-double-zipped
|
||||||
path: build/
|
path: build/
|
||||||
@@ -192,7 +192,7 @@ jobs:
|
|||||||
needs: build-windows
|
needs: build-windows
|
||||||
steps:
|
steps:
|
||||||
- name: Configure pagefile
|
- name: Configure pagefile
|
||||||
uses: al-cheb/configure-pagefile-action@v1.3
|
uses: al-cheb/configure-pagefile-action@v1.4
|
||||||
with:
|
with:
|
||||||
minimum-size: 8GB
|
minimum-size: 8GB
|
||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
@@ -203,16 +203,16 @@ jobs:
|
|||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
scoop install binaryen wasmtime
|
scoop install binaryen && scoop install wasmtime@14.0.4
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.21'
|
go-version: '1.22'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-amd64-double-zipped
|
name: windows-amd64-double-zipped
|
||||||
path: build/
|
path: build/
|
||||||
|
|||||||
+7
-2
@@ -9,10 +9,11 @@
|
|||||||
url = https://github.com/avr-rust/avr-mcu.git
|
url = https://github.com/avr-rust/avr-mcu.git
|
||||||
[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/cmsis-svd/cmsis-svd-data.git
|
||||||
|
branch = main
|
||||||
[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/WebAssembly/wasi-libc
|
||||||
[submodule "lib/picolibc"]
|
[submodule "lib/picolibc"]
|
||||||
path = lib/picolibc
|
path = lib/picolibc
|
||||||
url = https://github.com/keith-packard/picolibc.git
|
url = https://github.com/keith-packard/picolibc.git
|
||||||
@@ -34,3 +35,7 @@
|
|||||||
[submodule "lib/renesas-svd"]
|
[submodule "lib/renesas-svd"]
|
||||||
path = lib/renesas-svd
|
path = lib/renesas-svd
|
||||||
url = https://github.com/tinygo-org/renesas-svd.git
|
url = https://github.com/tinygo-org/renesas-svd.git
|
||||||
|
[submodule "src/net"]
|
||||||
|
path = src/net
|
||||||
|
url = https://github.com/tinygo-org/net.git
|
||||||
|
branch = dev
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ Now that we have a working static build, it's time to make a release tarball:
|
|||||||
|
|
||||||
If you did not clone the repository with the `--recursive` option, you will get errors until you initialize the project submodules:
|
If you did not clone the repository with the `--recursive` option, you will get errors until you initialize the project submodules:
|
||||||
|
|
||||||
git submodule update --init
|
git submodule update --init --recursive
|
||||||
|
|
||||||
The release tarball is stored in build/release.tar.gz, and can be extracted with
|
The release tarball is stored in build/release.tar.gz, and can be extracted with
|
||||||
the following command (for example in ~/lib):
|
the following command (for example in ~/lib):
|
||||||
|
|||||||
@@ -1,3 +1,78 @@
|
|||||||
|
0.31.0
|
||||||
|
---
|
||||||
|
|
||||||
|
* **general**
|
||||||
|
* remove LLVM 14 support
|
||||||
|
* add LLVM 17 support, and use it by default
|
||||||
|
* add Nix flake support
|
||||||
|
* update bundled Binaryen to version 116
|
||||||
|
* add `ports` subcommand that lists available serial ports for `-port` and `-monitor`
|
||||||
|
* support wasmtime version 14
|
||||||
|
* add `-serial=rtt` for serial output over SWD
|
||||||
|
* add Go 1.22 support and use it by default
|
||||||
|
* change minimum Node.js version from 16 to 18
|
||||||
|
* **compiler**
|
||||||
|
* use the new LLVM pass manager
|
||||||
|
* allow systems with more stack space to allocate larger values on the stack
|
||||||
|
* `build`: fix a crash due to sharing GlobalValues between build instances
|
||||||
|
* `cgo`: add `C._Bool` type
|
||||||
|
* `cgo`: fix calling CGo callback inside generic function
|
||||||
|
* `compileopts`: set `purego` build tag by default so that more packages can be built
|
||||||
|
* `compileopts`: force-enable CGo to avoid build issues
|
||||||
|
* `compiler`: fix crash on type assert on interfaces with no methods
|
||||||
|
* `interp`: print LLVM instruction in traceback
|
||||||
|
* `interp`: support runtime times by running them at runtime
|
||||||
|
* `loader`: enforce Go language version in the type checker (this may break existing programs with an incorrect Go version in go.mod)
|
||||||
|
* `transform`: fix bug in StringToBytes optimization pass
|
||||||
|
* **standard library**
|
||||||
|
* `crypto/tls`: stub out a lot of functions
|
||||||
|
* `internal/task`, `machine`: make TinyGo code usable with "big Go" CGo
|
||||||
|
* `machine`: implement `I2C.SetBaudRate` consistently across chips
|
||||||
|
* `machine`: implement `SPI.Configure` consistently across chips
|
||||||
|
* `machine`: add `DeviceID` for nrf, rp2040, sam, stm32
|
||||||
|
* `machine`: use smaller UART buffer size on atmega chips
|
||||||
|
* `machine/usb`: allow setting a serial number using a linker flag
|
||||||
|
* `math`: support more math functions on baremetal (picolibc) systems
|
||||||
|
* `net`: replace entire net package with a new one based on the netdev driver
|
||||||
|
* `os/user`: add bare-bones implementation of this package
|
||||||
|
* `reflect`: stub `CallSlice` and `FuncOf`
|
||||||
|
* `reflect`: add `TypeFor[T]`
|
||||||
|
* `reflect`: update `IsZero` to Go 1.22 semantics
|
||||||
|
* `reflect`: move indirect values into interface when setting interfaces
|
||||||
|
* `runtime`: stub `Breakpoint`
|
||||||
|
* `sync`: implement trylock
|
||||||
|
* **targets**
|
||||||
|
* `atmega`: use UART double speed mode for fewer errors and higher throughput
|
||||||
|
* `atmega328pb`: refactor to enable extra uart
|
||||||
|
* `avr`: don't compile large parts of picolibc (math, stdio) for LLVM 17 support
|
||||||
|
* `esp32`: switch over to the official SVD file
|
||||||
|
* `esp32c3`: implement USB_SERIAL for USBCDC communication
|
||||||
|
* `esp32c3`: implement I2C
|
||||||
|
* `esp32c3`: implement RNG
|
||||||
|
* `esp32c3`: add more ROM functions and update linker script for the in-progress wifi support
|
||||||
|
* `esp32c3`: update to newer SVD files
|
||||||
|
* `rp2040`: add support for UART hardware flow control
|
||||||
|
* `rp2040`: add definition for `machine.PinToggle`
|
||||||
|
* `rp2040`: set XOSC startup delay multiplier
|
||||||
|
* `samd21`: add support for UART hardware flow control
|
||||||
|
* `samd51`: add support for UART hardware flow control
|
||||||
|
* `wasm`: increase default stack size to 64k for wasi/wasm targets
|
||||||
|
* `wasm`: bump wasi-libc version to SDK 20
|
||||||
|
* `wasm`: remove line of dead code in wasm_exec.js
|
||||||
|
* **new targets/boards**
|
||||||
|
* `qtpy-esp32c3`: add Adafruit QT Py ESP32-C3 board
|
||||||
|
* `mksnanov3`: add support for the MKS Robin Nano V3.x
|
||||||
|
* `nrf52840-generic`: add generic nrf52840 chip support
|
||||||
|
* `thumby`: add support for Thumby
|
||||||
|
* `wasm`: add new `wasm-generic` target that doesn't depend on WASI or a browser
|
||||||
|
* **boards**
|
||||||
|
* `arduino-mkrwifi1010`, `arduino-nano33`, `nano-rp2040`, `matrixportal-m4`, `metro-m4-airlift`, `pybadge`, `pyportal`: add `ninafw` build tag and some constants for BLE support
|
||||||
|
* `gopher-badge`: fix typo in USB product name
|
||||||
|
* `nano-rp2040`: add UART1 and correct mappings for NINA via UART
|
||||||
|
* `pico`: bump default stack size from 2kB to 8kB
|
||||||
|
* `wioterminal`: expose UART4
|
||||||
|
|
||||||
|
|
||||||
0.30.0
|
0.30.0
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+22
-19
@@ -1,10 +1,15 @@
|
|||||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||||
FROM golang:1.21 AS tinygo-llvm
|
FROM golang:1.22 AS tinygo-llvm
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y apt-utils make cmake clang-15 ninja-build
|
apt-get install -y apt-utils make cmake clang-15 ninja-build && \
|
||||||
|
rm -rf \
|
||||||
|
/var/lib/apt/lists/* \
|
||||||
|
/var/log/* \
|
||||||
|
/var/tmp/* \
|
||||||
|
/tmp/*
|
||||||
|
|
||||||
COPY ./Makefile /tinygo/Makefile
|
COPY ./GNUmakefile /tinygo/GNUmakefile
|
||||||
|
|
||||||
RUN cd /tinygo/ && \
|
RUN cd /tinygo/ && \
|
||||||
make llvm-source
|
make llvm-source
|
||||||
@@ -15,26 +20,24 @@ FROM tinygo-llvm AS tinygo-llvm-build
|
|||||||
RUN cd /tinygo/ && \
|
RUN cd /tinygo/ && \
|
||||||
make llvm-build
|
make llvm-build
|
||||||
|
|
||||||
# tinygo-compiler stage builds the compiler itself
|
# tinygo-compiler-build stage builds the compiler itself
|
||||||
FROM tinygo-llvm-build AS tinygo-compiler
|
FROM tinygo-llvm-build AS tinygo-compiler-build
|
||||||
|
|
||||||
COPY . /tinygo
|
COPY . /tinygo
|
||||||
|
|
||||||
# update submodules
|
# build the compiler and tools
|
||||||
RUN cd /tinygo/ && \
|
RUN cd /tinygo/ && \
|
||||||
rm -rf ./lib/*/ && \
|
git submodule update --init --recursive && \
|
||||||
git submodule sync && \
|
|
||||||
git submodule update --init --recursive --force
|
|
||||||
|
|
||||||
RUN cd /tinygo/ && \
|
|
||||||
make
|
|
||||||
|
|
||||||
# tinygo-tools stage installs the needed dependencies to compile TinyGo programs for all platforms.
|
|
||||||
FROM tinygo-compiler AS tinygo-tools
|
|
||||||
|
|
||||||
RUN cd /tinygo/ && \
|
|
||||||
make wasi-libc binaryen && \
|
|
||||||
make gen-device -j4 && \
|
make gen-device -j4 && \
|
||||||
cp build/* $GOPATH/bin/
|
make build/release
|
||||||
|
|
||||||
|
# tinygo-compiler copies the compiler build over to a base Go container (without
|
||||||
|
# all the build tools etc).
|
||||||
|
FROM golang:1.21 AS tinygo-compiler
|
||||||
|
|
||||||
|
# Copy tinygo build.
|
||||||
|
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
|
||||||
|
|
||||||
|
# Configure the container.
|
||||||
|
ENV PATH="${PATH}:/tinygo/bin"
|
||||||
CMD ["tinygo"]
|
CMD ["tinygo"]
|
||||||
|
|||||||
+30
-18
@@ -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 = 16 15
|
LLVM_VERSIONS = 17 16 15
|
||||||
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)
|
||||||
@@ -32,9 +32,6 @@ export GOROOT = $(shell $(GO) env GOROOT)
|
|||||||
# Flags to pass to go test.
|
# Flags to pass to go test.
|
||||||
GOTESTFLAGS ?=
|
GOTESTFLAGS ?=
|
||||||
|
|
||||||
# md5sum binary
|
|
||||||
MD5SUM = md5sum
|
|
||||||
|
|
||||||
# tinygo binary for tests
|
# tinygo binary for tests
|
||||||
TINYGO ?= $(call detect,tinygo,tinygo $(CURDIR)/build/tinygo)
|
TINYGO ?= $(call detect,tinygo,tinygo $(CURDIR)/build/tinygo)
|
||||||
|
|
||||||
@@ -130,14 +127,14 @@ ifeq ($(OS),Windows_NT)
|
|||||||
USE_SYSTEM_BINARYEN ?= 1
|
USE_SYSTEM_BINARYEN ?= 1
|
||||||
|
|
||||||
else ifeq ($(shell uname -s),Darwin)
|
else ifeq ($(shell uname -s),Darwin)
|
||||||
MD5SUM = md5
|
MD5SUM ?= md5
|
||||||
|
|
||||||
CGO_LDFLAGS += -lxar
|
CGO_LDFLAGS += -lxar
|
||||||
|
|
||||||
USE_SYSTEM_BINARYEN ?= 1
|
USE_SYSTEM_BINARYEN ?= 1
|
||||||
|
|
||||||
else ifeq ($(shell uname -s),FreeBSD)
|
else ifeq ($(shell uname -s),FreeBSD)
|
||||||
MD5SUM = md5
|
MD5SUM ?= md5
|
||||||
START_GROUP = -Wl,--start-group
|
START_GROUP = -Wl,--start-group
|
||||||
END_GROUP = -Wl,--end-group
|
END_GROUP = -Wl,--end-group
|
||||||
else
|
else
|
||||||
@@ -145,6 +142,9 @@ else
|
|||||||
END_GROUP = -Wl,--end-group
|
END_GROUP = -Wl,--end-group
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# md5sum binary default, can be overridden by an environment variable
|
||||||
|
MD5SUM ?= md5sum
|
||||||
|
|
||||||
# Libraries that should be linked in for the statically linked Clang.
|
# Libraries that should be linked in for the statically linked Clang.
|
||||||
CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGen clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangExtractAPI clangFormat clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangSupport clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions
|
CLANG_LIB_NAMES = clangAnalysis clangAST clangASTMatchers clangBasic clangCodeGen clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangExtractAPI clangFormat clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangSupport clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions
|
||||||
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
|
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
|
||||||
@@ -190,7 +190,7 @@ gen-device: gen-device-stm32
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
gen-device-avr:
|
gen-device-avr:
|
||||||
@if [ ! -e lib/avr/README.md ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
|
@if [ ! -e lib/avr/README.md ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init --recursive"; exit 1; fi
|
||||||
$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/
|
$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/
|
||||||
./build/gen-device-avr lib/avr/packs/atmega src/device/avr/
|
./build/gen-device-avr lib/avr/packs/atmega src/device/avr/
|
||||||
./build/gen-device-avr lib/avr/packs/tiny src/device/avr/
|
./build/gen-device-avr lib/avr/packs/tiny src/device/avr/
|
||||||
@@ -238,7 +238,7 @@ gen-device-renesas: build/gen-device-svd
|
|||||||
|
|
||||||
# Get LLVM sources.
|
# Get LLVM sources.
|
||||||
$(LLVM_PROJECTDIR)/llvm:
|
$(LLVM_PROJECTDIR)/llvm:
|
||||||
git clone -b xtensa_release_16.x --depth=1 https://github.com/espressif/llvm-project $(LLVM_PROJECTDIR)
|
git clone -b xtensa_release_17.0.1 --depth=1 https://github.com/espressif/llvm-project $(LLVM_PROJECTDIR)
|
||||||
llvm-source: $(LLVM_PROJECTDIR)/llvm
|
llvm-source: $(LLVM_PROJECTDIR)/llvm
|
||||||
|
|
||||||
# Configure LLVM.
|
# Configure LLVM.
|
||||||
@@ -256,7 +256,7 @@ ifneq ($(USE_SYSTEM_BINARYEN),1)
|
|||||||
binaryen: build/wasm-opt$(EXE)
|
binaryen: build/wasm-opt$(EXE)
|
||||||
build/wasm-opt$(EXE):
|
build/wasm-opt$(EXE):
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd lib/binaryen && cmake -G Ninja . -DBUILD_STATIC_LIB=ON $(BINARYEN_OPTION) && ninja bin/wasm-opt$(EXE)
|
cd lib/binaryen && cmake -G Ninja . -DBUILD_STATIC_LIB=ON -DBUILD_TESTS=OFF $(BINARYEN_OPTION) && ninja bin/wasm-opt$(EXE)
|
||||||
cp lib/binaryen/bin/wasm-opt$(EXE) build/wasm-opt$(EXE)
|
cp lib/binaryen/bin/wasm-opt$(EXE) build/wasm-opt$(EXE)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -264,19 +264,19 @@ endif
|
|||||||
.PHONY: wasi-libc
|
.PHONY: wasi-libc
|
||||||
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
||||||
lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
|
lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
|
||||||
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
|
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init --recursive"; exit 1; fi
|
||||||
cd lib/wasi-libc && $(MAKE) -j4 EXTRA_CFLAGS="-O2 -g -DNDEBUG -mnontrapping-fptoint -msign-ext" MALLOC_IMPL=none CC=$(CLANG) AR=$(LLVM_AR) NM=$(LLVM_NM)
|
cd lib/wasi-libc && $(MAKE) -j4 EXTRA_CFLAGS="-O2 -g -DNDEBUG -mnontrapping-fptoint -msign-ext" MALLOC_IMPL=none CC="$(CLANG)" AR=$(LLVM_AR) NM=$(LLVM_NM)
|
||||||
|
|
||||||
# Check for Node.js used during WASM tests.
|
# Check for Node.js used during WASM tests.
|
||||||
NODEJS_VERSION := $(word 1,$(subst ., ,$(shell node -v | cut -c 2-)))
|
NODEJS_VERSION := $(word 1,$(subst ., ,$(shell node -v | cut -c 2-)))
|
||||||
MIN_NODEJS_VERSION=16
|
MIN_NODEJS_VERSION=18
|
||||||
|
|
||||||
.PHONY: check-nodejs-version
|
.PHONY: check-nodejs-version
|
||||||
check-nodejs-version:
|
check-nodejs-version:
|
||||||
ifeq (, $(shell which node))
|
ifeq (, $(shell which node))
|
||||||
@echo "Install NodeJS version 16+ to run tests."; exit 1;
|
@echo "Install NodeJS version 18+ to run tests."; exit 1;
|
||||||
endif
|
endif
|
||||||
@if [ $(NODEJS_VERSION) -lt $(MIN_NODEJS_VERSION) ]; then echo "Install NodeJS version 16+ to run tests."; exit 1; fi
|
@if [ $(NODEJS_VERSION) -lt $(MIN_NODEJS_VERSION) ]; then echo "Install NodeJS version 18+ to run tests."; exit 1; fi
|
||||||
|
|
||||||
# Build the Go compiler.
|
# Build the Go compiler.
|
||||||
tinygo:
|
tinygo:
|
||||||
@@ -506,6 +506,8 @@ smoketest:
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/watchdog
|
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/watchdog
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/device-id
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
# test simulated boards on play.tinygo.org
|
# test simulated boards on play.tinygo.org
|
||||||
ifneq ($(WASM), 0)
|
ifneq ($(WASM), 0)
|
||||||
$(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1
|
$(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1
|
||||||
@@ -668,6 +670,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=ae-rp2040 examples/echo
|
$(TINYGO) build -size short -o test.hex -target=ae-rp2040 examples/echo
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=thumby examples/echo
|
||||||
|
@$(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
|
||||||
@@ -682,6 +686,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840 examples/usb-midi
|
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840 examples/usb-midi
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=nrf52840-s140v6-uf2-generic examples/serial
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
ifneq ($(STM32), 0)
|
ifneq ($(STM32), 0)
|
||||||
$(TINYGO) build -size short -o test.hex -target=bluepill examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=bluepill examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
@@ -715,7 +721,11 @@ ifneq ($(STM32), 0)
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=swan examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=swan examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=mksnanov3 examples/blinky1
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
endif
|
endif
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=atmega328pb examples/blinkm
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/serial
|
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/serial
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=arduino examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=arduino examples/blinky1
|
||||||
@@ -752,9 +762,7 @@ ifneq ($(XTENSA), 0)
|
|||||||
$(TINYGO) build -size short -o test.bin -target mch2022 examples/serial
|
$(TINYGO) build -size short -o test.bin -target mch2022 examples/serial
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
endif
|
endif
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
|
$(TINYGO) build -size short -o test.bin -target=qtpy-esp32c3 examples/serial
|
||||||
@$(MD5SUM) test.bin
|
|
||||||
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/serial
|
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
|
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
|
||||||
@$(MD5SUM) test.bin
|
@$(MD5SUM) test.bin
|
||||||
@@ -767,6 +775,7 @@ endif
|
|||||||
ifneq ($(WASM), 0)
|
ifneq ($(WASM), 0)
|
||||||
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/export
|
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/export
|
||||||
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/main
|
$(TINYGO) build -size short -o wasm.wasm -target=wasm examples/wasm/main
|
||||||
|
$(TINYGO) build -size short -o wasm.wasm -target=wasm-unknown examples/hello-wasm-unknown
|
||||||
endif
|
endif
|
||||||
# test various compiler flags
|
# test various compiler flags
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040 -gc=none -scheduler=none examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pca10040 -gc=none -scheduler=none examples/blinky1
|
||||||
@@ -775,6 +784,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040 -serial=none examples/echo
|
$(TINYGO) build -size short -o test.hex -target=pca10040 -serial=none examples/echo
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
|
$(TINYGO) build -size short -o test.hex -target=pca10040 -serial=rtt examples/echo
|
||||||
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -o test.nro -target=nintendoswitch examples/serial
|
$(TINYGO) build -o test.nro -target=nintendoswitch examples/serial
|
||||||
@$(MD5SUM) test.nro
|
@$(MD5SUM) test.nro
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=0 ./testdata/stdlib.go
|
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=0 ./testdata/stdlib.go
|
||||||
@@ -834,6 +845,7 @@ endif
|
|||||||
@cp -rp lib/musl/src/include build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/include build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/legacy build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/legacy build/release/tinygo/lib/musl/src
|
||||||
|
@cp -rp lib/musl/src/linux build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
|
||||||
@@ -878,7 +890,7 @@ deb:
|
|||||||
@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 -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
|
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)
|
ifneq ($(RELEASEONLY), 1)
|
||||||
release: build/release
|
release: build/release
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# TinyGo - Go compiler for small places
|
# TinyGo - Go compiler for small places
|
||||||
|
|
||||||
[](https://github.com/tinygo-org/tinygo/actions/workflows/linux.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/build-macos.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/windows.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/docker.yml) [](https://circleci.com/gh/tinygo-org/tinygo/tree/dev)
|
[](https://github.com/tinygo-org/tinygo/actions/workflows/linux.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/build-macos.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/windows.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/docker.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/nix.yml) [](https://circleci.com/gh/tinygo-org/tinygo/tree/dev)
|
||||||
|
|
||||||
TinyGo is a Go compiler intended for use in small places such as microcontrollers, WebAssembly (wasm/wasi), and command-line tools.
|
TinyGo is a Go compiler intended for use in small places such as microcontrollers, WebAssembly (wasm/wasi), and command-line tools.
|
||||||
|
|
||||||
|
|||||||
+34
-44
@@ -114,6 +114,30 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
cacheDir = tmpdir
|
cacheDir = tmpdir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create default global values.
|
||||||
|
globalValues := map[string]map[string]string{
|
||||||
|
"runtime": {
|
||||||
|
"buildVersion": goenv.Version(),
|
||||||
|
},
|
||||||
|
"testing": {},
|
||||||
|
}
|
||||||
|
if config.TestConfig.CompileTestBinary {
|
||||||
|
// The testing.testBinary is set to "1" when in a test.
|
||||||
|
// This is needed for testing.Testing() to work correctly.
|
||||||
|
globalValues["testing"]["testBinary"] = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over explicitly set global values, like
|
||||||
|
// -ldflags="-X main.Version="1.0"
|
||||||
|
for pkgPath, vals := range config.Options.GlobalValues {
|
||||||
|
if _, ok := globalValues[pkgPath]; !ok {
|
||||||
|
globalValues[pkgPath] = map[string]string{}
|
||||||
|
}
|
||||||
|
for k, v := range vals {
|
||||||
|
globalValues[pkgPath][k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
// the libc needs them.
|
// the libc needs them.
|
||||||
@@ -168,11 +192,12 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
CodeModel: config.CodeModel(),
|
CodeModel: config.CodeModel(),
|
||||||
RelocationModel: config.RelocationModel(),
|
RelocationModel: config.RelocationModel(),
|
||||||
SizeLevel: sizeLevel,
|
SizeLevel: sizeLevel,
|
||||||
TinyGoVersion: goenv.Version,
|
TinyGoVersion: goenv.Version(),
|
||||||
|
|
||||||
Scheduler: config.Scheduler(),
|
Scheduler: config.Scheduler(),
|
||||||
AutomaticStackSize: config.AutomaticStackSize(),
|
AutomaticStackSize: config.AutomaticStackSize(),
|
||||||
DefaultStackSize: config.StackSize(),
|
DefaultStackSize: config.StackSize(),
|
||||||
|
MaxStackAlloc: config.MaxStackAlloc(),
|
||||||
NeedsStackObjects: config.NeedsStackObjects(),
|
NeedsStackObjects: config.NeedsStackObjects(),
|
||||||
Debug: !config.Options.SkipDWARF, // emit DWARF except when -internal-nodwarf is passed
|
Debug: !config.Options.SkipDWARF, // emit DWARF except when -internal-nodwarf is passed
|
||||||
}
|
}
|
||||||
@@ -187,7 +212,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
defer machine.Dispose()
|
defer machine.Dispose()
|
||||||
|
|
||||||
// Load entire program AST into memory.
|
// Load entire program AST into memory.
|
||||||
lprogram, err := loader.Load(config, pkgName, config.ClangHeaders, types.Config{
|
lprogram, err := loader.Load(config, pkgName, types.Config{
|
||||||
Sizes: compiler.Sizes(machine),
|
Sizes: compiler.Sizes(machine),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -216,34 +241,12 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
var packageJobs []*compileJob
|
var packageJobs []*compileJob
|
||||||
packageActionIDJobs := make(map[string]*compileJob)
|
packageActionIDJobs := make(map[string]*compileJob)
|
||||||
|
|
||||||
if config.Options.GlobalValues == nil {
|
|
||||||
config.Options.GlobalValues = make(map[string]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["runtime"] == nil {
|
|
||||||
config.Options.GlobalValues["runtime"] = make(map[string]string)
|
|
||||||
}
|
|
||||||
config.Options.GlobalValues["runtime"]["buildVersion"] = version
|
|
||||||
}
|
|
||||||
if config.TestConfig.CompileTestBinary {
|
|
||||||
// The testing.testBinary is set to "1" when in a test.
|
|
||||||
// This is needed for testing.Testing() to work correctly.
|
|
||||||
if config.Options.GlobalValues["testing"] == nil {
|
|
||||||
config.Options.GlobalValues["testing"] = make(map[string]string)
|
|
||||||
}
|
|
||||||
config.Options.GlobalValues["testing"]["testBinary"] = "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
var embedFileObjects []*compileJob
|
var embedFileObjects []*compileJob
|
||||||
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
|
||||||
|
|
||||||
var undefinedGlobals []string
|
var undefinedGlobals []string
|
||||||
for name := range config.Options.GlobalValues[pkg.Pkg.Path()] {
|
for name := range globalValues[pkg.Pkg.Path()] {
|
||||||
undefinedGlobals = append(undefinedGlobals, name)
|
undefinedGlobals = append(undefinedGlobals, name)
|
||||||
}
|
}
|
||||||
sort.Strings(undefinedGlobals)
|
sort.Strings(undefinedGlobals)
|
||||||
@@ -571,7 +574,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
|
|
||||||
// Run all optimization passes, which are much more effective now
|
// Run all optimization passes, which are much more effective now
|
||||||
// that the optimizer can see the whole program at once.
|
// that the optimizer can see the whole program at once.
|
||||||
err := optimizeProgram(mod, config)
|
err := optimizeProgram(mod, config, globalValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -660,7 +663,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
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, tmpdir, config.CFlags(), config.Options.PrintCommands)
|
result, err := compileAndCacheCFile(abspath, tmpdir, config.CFlags(false), config.Options.PrintCommands)
|
||||||
job.result = result
|
job.result = result
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
@@ -805,21 +808,8 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
|
|
||||||
// Run wasm-opt for wasm binaries
|
// Run wasm-opt for wasm binaries
|
||||||
if arch := strings.Split(config.Triple(), "-")[0]; arch == "wasm32" {
|
if arch := strings.Split(config.Triple(), "-")[0]; arch == "wasm32" {
|
||||||
var opt string
|
optLevel, _, _ := config.OptLevel()
|
||||||
switch config.Options.Opt {
|
opt := "-" + optLevel
|
||||||
case "none", "0":
|
|
||||||
opt = "-O0"
|
|
||||||
case "1":
|
|
||||||
opt = "-O1"
|
|
||||||
case "2":
|
|
||||||
opt = "-O2"
|
|
||||||
case "s":
|
|
||||||
opt = "-Os"
|
|
||||||
case "z":
|
|
||||||
opt = "-Oz"
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unknown opt level: %q", config.Options.Opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
var args []string
|
var args []string
|
||||||
|
|
||||||
@@ -1040,7 +1030,7 @@ func createEmbedObjectFile(data, hexSum, sourceFile, sourceDir, tmpdir string, c
|
|||||||
// optimizeProgram runs a series of optimizations and transformations that are
|
// optimizeProgram runs a series of optimizations and transformations that are
|
||||||
// needed to convert a program to its final form. Some transformations are not
|
// needed to convert a program to its final form. Some transformations are not
|
||||||
// optional and must be run as the compiler expects them to run.
|
// optional and must be run as the compiler expects them to run.
|
||||||
func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
func optimizeProgram(mod llvm.Module, config *compileopts.Config, globalValues map[string]map[string]string) error {
|
||||||
err := interp.Run(mod, config.Options.InterpTimeout, config.DumpSSA())
|
err := interp.Run(mod, config.Options.InterpTimeout, config.DumpSSA())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1059,7 +1049,7 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert values from -ldflags="-X ..." into the IR.
|
// Insert values from -ldflags="-X ..." into the IR.
|
||||||
err = setGlobalValues(mod, config.Options.GlobalValues)
|
err = setGlobalValues(mod, globalValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,6 +35,7 @@ func TestClangAttributes(t *testing.T) {
|
|||||||
"riscv-qemu",
|
"riscv-qemu",
|
||||||
"wasi",
|
"wasi",
|
||||||
"wasm",
|
"wasm",
|
||||||
|
"wasm-unknown",
|
||||||
}
|
}
|
||||||
if hasBuiltinTools {
|
if hasBuiltinTools {
|
||||||
// hasBuiltinTools is set when TinyGo is statically linked with LLVM,
|
// hasBuiltinTools is set when TinyGo is statically linked with LLVM,
|
||||||
@@ -74,7 +74,6 @@ func TestClangAttributes(t *testing.T) {
|
|||||||
|
|
||||||
func testClangAttributes(t *testing.T, options *compileopts.Options) {
|
func testClangAttributes(t *testing.T, options *compileopts.Options) {
|
||||||
testDir := t.TempDir()
|
testDir := t.TempDir()
|
||||||
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
|
||||||
|
|
||||||
ctx := llvm.NewContext()
|
ctx := llvm.NewContext()
|
||||||
defer ctx.Dispose()
|
defer ctx.Dispose()
|
||||||
@@ -84,9 +83,8 @@ func testClangAttributes(t *testing.T, options *compileopts.Options) {
|
|||||||
t.Fatalf("could not load target: %s", err)
|
t.Fatalf("could not load target: %s", err)
|
||||||
}
|
}
|
||||||
config := compileopts.Config{
|
config := compileopts.Config{
|
||||||
Options: options,
|
Options: options,
|
||||||
Target: target,
|
Target: target,
|
||||||
ClangHeaders: clangHeaderPath,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a very simple C input file.
|
// Create a very simple C input file.
|
||||||
@@ -98,7 +96,7 @@ func testClangAttributes(t *testing.T, options *compileopts.Options) {
|
|||||||
|
|
||||||
// Compile this file using Clang.
|
// Compile this file using Clang.
|
||||||
outpath := filepath.Join(testDir, "test.bc")
|
outpath := filepath.Join(testDir, "test.bc")
|
||||||
flags := append([]string{"-c", "-emit-llvm", "-o", outpath, srcpath}, config.CFlags()...)
|
flags := append([]string{"-c", "-emit-llvm", "-o", outpath, srcpath}, config.CFlags(false)...)
|
||||||
if config.GOOS() == "darwin" {
|
if config.GOOS() == "darwin" {
|
||||||
// Silence some warnings that happen when testing GOOS=darwin on
|
// Silence some warnings that happen when testing GOOS=darwin on
|
||||||
// something other than MacOS.
|
// something other than MacOS.
|
||||||
|
|||||||
+34
-10
@@ -77,6 +77,15 @@ func ReadBuildID() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
return raw[4:], nil
|
return raw[4:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normally we would have found a build ID by now. But not on Nix,
|
||||||
|
// unfortunately, because Nix adds -no_uuid for some reason:
|
||||||
|
// https://github.com/NixOS/nixpkgs/issues/178366
|
||||||
|
// Fall back to the same implementation that we use for Windows.
|
||||||
|
id, err := readRawGoBuildID(f, 32*1024)
|
||||||
|
if len(id) != 0 || err != nil {
|
||||||
|
return id, err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// On other platforms (such as Windows) there isn't such a convenient
|
// On other platforms (such as Windows) there isn't such a convenient
|
||||||
// build ID. Luckily, Go does have an equivalent of the build ID, which
|
// build ID. Luckily, Go does have an equivalent of the build ID, which
|
||||||
@@ -88,16 +97,31 @@ func ReadBuildID() ([]byte, error) {
|
|||||||
// directly. Luckily the build ID is always at the start of the file.
|
// directly. Luckily the build ID is always at the start of the file.
|
||||||
// For details, see:
|
// For details, see:
|
||||||
// https://github.com/golang/go/blob/master/src/cmd/internal/buildid/buildid.go
|
// https://github.com/golang/go/blob/master/src/cmd/internal/buildid/buildid.go
|
||||||
fileStart := make([]byte, 4096)
|
id, err := readRawGoBuildID(f, 4096)
|
||||||
_, err := io.ReadFull(f, fileStart)
|
if len(id) != 0 || err != nil {
|
||||||
index := bytes.Index(fileStart, []byte("\xff Go build ID: \""))
|
return id, err
|
||||||
if index < 0 || index > len(fileStart)-103 {
|
|
||||||
return nil, fmt.Errorf("could not find build id in %s", err)
|
|
||||||
}
|
|
||||||
buf := fileStart[index : index+103]
|
|
||||||
if bytes.HasPrefix(buf, []byte("\xff Go build ID: \"")) && bytes.HasSuffix(buf, []byte("\"\n \xff")) {
|
|
||||||
return buf[len("\xff Go build ID: \"") : len(buf)-1], nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("could not find build ID in %s", executable)
|
return nil, fmt.Errorf("could not find build ID in %v", executable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Go toolchain stores a build ID in the binary that we can use, as a
|
||||||
|
// fallback if binary file specific build IDs can't be obtained.
|
||||||
|
// This function reads that build ID from the binary.
|
||||||
|
func readRawGoBuildID(f *os.File, prefixSize int) ([]byte, error) {
|
||||||
|
fileStart := make([]byte, prefixSize)
|
||||||
|
_, err := io.ReadFull(f, fileStart)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read build id from %s: %v", f.Name(), err)
|
||||||
|
}
|
||||||
|
index := bytes.Index(fileStart, []byte("\xff Go build ID: \""))
|
||||||
|
if index < 0 || index > len(fileStart)-103 {
|
||||||
|
return nil, fmt.Errorf("could not find build id in %s", f.Name())
|
||||||
|
}
|
||||||
|
buf := fileStart[index : index+103]
|
||||||
|
if bytes.HasPrefix(buf, []byte("\xff Go build ID: \"")) && bytes.HasSuffix(buf, []byte("\"\n \xff")) {
|
||||||
|
return buf[len("\xff Go build ID: \"") : len(buf)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-6
@@ -1,5 +1,12 @@
|
|||||||
//go:build byollvm
|
//go:build byollvm
|
||||||
|
|
||||||
|
// Source: https://github.com/llvm/llvm-project/blob/main/clang/tools/driver/cc1as_main.cpp
|
||||||
|
// This file needs to be updated each LLVM release.
|
||||||
|
// There are a few small modifications to make, like:
|
||||||
|
// * ExecuteAssembler is made non-static.
|
||||||
|
// * The struct AssemblerImplementation is moved to cc1as.h so it can be
|
||||||
|
// included elsewhere.
|
||||||
|
|
||||||
//===-- cc1as.cpp - Clang Assembler --------------------------------------===//
|
//===-- cc1as.cpp - Clang Assembler --------------------------------------===//
|
||||||
//
|
//
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
@@ -21,8 +28,8 @@
|
|||||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||||
#include "clang/Frontend/Utils.h"
|
#include "clang/Frontend/Utils.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/MC/MCAsmBackend.h"
|
#include "llvm/MC/MCAsmBackend.h"
|
||||||
#include "llvm/MC/MCAsmInfo.h"
|
#include "llvm/MC/MCAsmInfo.h"
|
||||||
@@ -46,7 +53,6 @@
|
|||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/FormattedStream.h"
|
#include "llvm/Support/FormattedStream.h"
|
||||||
#include "llvm/Support/Host.h"
|
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/Support/Process.h"
|
#include "llvm/Support/Process.h"
|
||||||
@@ -55,6 +61,8 @@
|
|||||||
#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"
|
||||||
|
#include "llvm/TargetParser/Host.h"
|
||||||
|
#include "llvm/TargetParser/Triple.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
@@ -151,8 +159,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
|
|||||||
|
|
||||||
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
|
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
|
||||||
auto Split = StringRef(Arg).split('=');
|
auto Split = StringRef(Arg).split('=');
|
||||||
Opts.DebugPrefixMap.insert(
|
Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);
|
||||||
{std::string(Split.first), std::string(Split.second)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Frontend Options
|
// Frontend Options
|
||||||
@@ -225,6 +232,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
|
|||||||
.Case("default", EmitDwarfUnwindType::Default);
|
.Case("default", EmitDwarfUnwindType::Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Opts.EmitCompactUnwindNonCanonical =
|
||||||
|
Args.hasArg(OPT_femit_compact_unwind_non_canonical);
|
||||||
|
|
||||||
Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);
|
Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
@@ -260,8 +270,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
|
|||||||
MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
|
MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
|
||||||
|
|
||||||
if (std::error_code EC = Buffer.getError()) {
|
if (std::error_code EC = Buffer.getError()) {
|
||||||
Error = EC.message();
|
return Diags.Report(diag::err_fe_error_reading)
|
||||||
return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
|
<< Opts.InputFile << EC.message();
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceMgr SrcMgr;
|
SourceMgr SrcMgr;
|
||||||
@@ -278,6 +288,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
|
|||||||
|
|
||||||
MCTargetOptions MCOptions;
|
MCTargetOptions MCOptions;
|
||||||
MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
|
MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
|
||||||
|
MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical;
|
||||||
MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
|
MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
|
||||||
|
|
||||||
std::unique_ptr<MCAsmInfo> MAI(
|
std::unique_ptr<MCAsmInfo> MAI(
|
||||||
|
|||||||
+9
-1
@@ -1,3 +1,6 @@
|
|||||||
|
// Source: https://github.com/llvm/llvm-project/blob/main/clang/tools/driver/cc1as_main.cpp
|
||||||
|
// See cc1as.cpp for details.
|
||||||
|
|
||||||
//===-- cc1as.h - Clang Assembler ----------------------------------------===//
|
//===-- cc1as.h - Clang Assembler ----------------------------------------===//
|
||||||
//
|
//
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
@@ -44,7 +47,7 @@ struct AssemblerInvocation {
|
|||||||
std::string DwarfDebugFlags;
|
std::string DwarfDebugFlags;
|
||||||
std::string DwarfDebugProducer;
|
std::string DwarfDebugProducer;
|
||||||
std::string DebugCompilationDir;
|
std::string DebugCompilationDir;
|
||||||
std::map<const std::string, const std::string> DebugPrefixMap;
|
llvm::SmallVector<std::pair<std::string, std::string>, 0> DebugPrefixMap;
|
||||||
llvm::DebugCompressionType CompressDebugSections =
|
llvm::DebugCompressionType CompressDebugSections =
|
||||||
llvm::DebugCompressionType::None;
|
llvm::DebugCompressionType::None;
|
||||||
std::string MainFileName;
|
std::string MainFileName;
|
||||||
@@ -89,6 +92,10 @@ struct AssemblerInvocation {
|
|||||||
/// Whether to emit DWARF unwind info.
|
/// Whether to emit DWARF unwind info.
|
||||||
EmitDwarfUnwindType EmitDwarfUnwind;
|
EmitDwarfUnwindType EmitDwarfUnwind;
|
||||||
|
|
||||||
|
// Whether to emit compact-unwind for non-canonical entries.
|
||||||
|
// Note: maybe overriden by other constraints.
|
||||||
|
unsigned EmitCompactUnwindNonCanonical : 1;
|
||||||
|
|
||||||
/// The name of the relocation model to use.
|
/// The name of the relocation model to use.
|
||||||
std::string RelocationModel;
|
std::string RelocationModel;
|
||||||
|
|
||||||
@@ -128,6 +135,7 @@ public:
|
|||||||
DwarfVersion = 0;
|
DwarfVersion = 0;
|
||||||
EmbedBitcode = 0;
|
EmbedBitcode = 0;
|
||||||
EmitDwarfUnwind = EmitDwarfUnwindType::Default;
|
EmitDwarfUnwind = EmitDwarfUnwindType::Default;
|
||||||
|
EmitCompactUnwindNonCanonical = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CreateFromArgs(AssemblerInvocation &Res,
|
static bool CreateFromArgs(AssemblerInvocation &Res,
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
#include <clang/FrontendTool/Utils.h>
|
#include <clang/FrontendTool/Utils.h>
|
||||||
#include <llvm/ADT/IntrusiveRefCntPtr.h>
|
#include <llvm/ADT/IntrusiveRefCntPtr.h>
|
||||||
#include <llvm/Option/Option.h>
|
#include <llvm/Option/Option.h>
|
||||||
#include <llvm/Support/Host.h>
|
#include <llvm/TargetParser/Host.h>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|||||||
+2
-5
@@ -27,19 +27,16 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if major != 1 || minor < 18 || minor > 21 {
|
if major != 1 || minor < 18 || minor > 22 {
|
||||||
// Note: when this gets updated, also update the Go compatibility matrix:
|
// Note: when this gets updated, also update the Go compatibility matrix:
|
||||||
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
|
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
|
||||||
return nil, fmt.Errorf("requires go version 1.18 through 1.21, got go%d.%d", major, minor)
|
return nil, fmt.Errorf("requires go version 1.18 through 1.22, got go%d.%d", major, minor)
|
||||||
}
|
}
|
||||||
|
|
||||||
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
|
||||||
|
|
||||||
return &compileopts.Config{
|
return &compileopts.Config{
|
||||||
Options: options,
|
Options: options,
|
||||||
Target: spec,
|
Target: spec,
|
||||||
GoMinorVersion: minor,
|
GoMinorVersion: minor,
|
||||||
ClangHeaders: clangHeaderPath,
|
|
||||||
TestConfig: options.TestConfig,
|
TestConfig: options.TestConfig,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
-105
@@ -1,105 +0,0 @@
|
|||||||
package builder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io/fs"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"tinygo.org/x/go-llvm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// getClangHeaderPath returns the path to the built-in Clang headers. It tries
|
|
||||||
// multiple locations, which should make it find the directory when installed in
|
|
||||||
// various ways.
|
|
||||||
func getClangHeaderPath(TINYGOROOT string) string {
|
|
||||||
// Check whether we're running from the source directory.
|
|
||||||
path := filepath.Join(TINYGOROOT, "llvm-project", "clang", "lib", "Headers")
|
|
||||||
if _, err := os.Stat(path); !errors.Is(err, fs.ErrNotExist) {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether we're running from the installation directory.
|
|
||||||
path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
|
|
||||||
if _, err := os.Stat(path); !errors.Is(err, fs.ErrNotExist) {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// It looks like we are built with a system-installed LLVM. Do a last
|
|
||||||
// attempt: try to use Clang headers relative to the clang binary.
|
|
||||||
llvmMajor := strings.Split(llvm.Version, ".")[0]
|
|
||||||
for _, cmdName := range commands["clang"] {
|
|
||||||
binpath, err := exec.LookPath(cmdName)
|
|
||||||
if err == nil {
|
|
||||||
// This should be the command that will also be used by
|
|
||||||
// execCommand. To avoid inconsistencies, make sure we use the
|
|
||||||
// headers relative to this command.
|
|
||||||
binpath, err = filepath.EvalSymlinks(binpath)
|
|
||||||
if err != nil {
|
|
||||||
// Unexpected.
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
// Example executable:
|
|
||||||
// /usr/lib/llvm-9/bin/clang
|
|
||||||
// Example include path:
|
|
||||||
// /usr/lib/llvm-9/lib64/clang/9.0.1/include/
|
|
||||||
llvmRoot := filepath.Dir(filepath.Dir(binpath))
|
|
||||||
clangVersionRoot := filepath.Join(llvmRoot, "lib64", "clang")
|
|
||||||
dirs64, err64 := ioutil.ReadDir(clangVersionRoot)
|
|
||||||
// Example include path:
|
|
||||||
// /usr/lib/llvm-9/lib/clang/9.0.1/include/
|
|
||||||
clangVersionRoot = filepath.Join(llvmRoot, "lib", "clang")
|
|
||||||
dirs32, err32 := ioutil.ReadDir(clangVersionRoot)
|
|
||||||
if err64 != nil && err32 != nil {
|
|
||||||
// Unexpected.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dirnames := make([]string, len(dirs64)+len(dirs32))
|
|
||||||
dirCount := 0
|
|
||||||
for _, d := range dirs32 {
|
|
||||||
name := d.Name()
|
|
||||||
if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") {
|
|
||||||
dirnames[dirCount] = filepath.Join(llvmRoot, "lib", "clang", name)
|
|
||||||
dirCount++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, d := range dirs64 {
|
|
||||||
name := d.Name()
|
|
||||||
if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") {
|
|
||||||
dirnames[dirCount] = filepath.Join(llvmRoot, "lib64", "clang", name)
|
|
||||||
dirCount++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(dirnames)
|
|
||||||
// Check for the highest version first.
|
|
||||||
for i := dirCount - 1; i >= 0; i-- {
|
|
||||||
path := filepath.Join(dirnames[i], "include")
|
|
||||||
_, err := os.Stat(filepath.Join(path, "stdint.h"))
|
|
||||||
if err == nil {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// On Arch Linux, the clang executable is stored in /usr/bin rather than being symlinked from there.
|
|
||||||
// Search directly in /usr/lib for clang.
|
|
||||||
if matches, err := filepath.Glob("/usr/lib/clang/" + llvmMajor + ".*.*"); err == nil {
|
|
||||||
// Check for the highest version first.
|
|
||||||
sort.Strings(matches)
|
|
||||||
for i := len(matches) - 1; i >= 0; i-- {
|
|
||||||
path := filepath.Join(matches[i], "include")
|
|
||||||
_, err := os.Stat(filepath.Join(path, "stdint.h"))
|
|
||||||
if err == nil {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Could not find it.
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
@@ -143,6 +143,10 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
// reproducible. Otherwise the temporary directory is stored in the archive
|
// reproducible. Otherwise the temporary directory is stored in the archive
|
||||||
// itself, which varies each run.
|
// itself, which varies each run.
|
||||||
args := append(l.cflags(target, headerPath), "-c", "-Oz", "-gdwarf-4", "-ffunction-sections", "-fdata-sections", "-Wno-macro-redefined", "--target="+target, "-fdebug-prefix-map="+dir+"="+remapDir)
|
args := append(l.cflags(target, headerPath), "-c", "-Oz", "-gdwarf-4", "-ffunction-sections", "-fdata-sections", "-Wno-macro-redefined", "--target="+target, "-fdebug-prefix-map="+dir+"="+remapDir)
|
||||||
|
resourceDir := goenv.ClangResourceDir(false)
|
||||||
|
if resourceDir != "" {
|
||||||
|
args = append(args, "-resource-dir="+resourceDir)
|
||||||
|
}
|
||||||
cpu := config.CPU()
|
cpu := config.CPU()
|
||||||
if cpu != "" {
|
if cpu != "" {
|
||||||
// X86 has deprecated the -mcpu flag, so we need to use -march instead.
|
// X86 has deprecated the -mcpu flag, so we need to use -march instead.
|
||||||
|
|||||||
+9
-20
@@ -5,7 +5,11 @@
|
|||||||
#include <lld/Common/Driver.h>
|
#include <lld/Common/Driver.h>
|
||||||
#include <llvm/Support/Parallel.h>
|
#include <llvm/Support/Parallel.h>
|
||||||
|
|
||||||
extern "C" {
|
LLD_HAS_DRIVER(coff)
|
||||||
|
LLD_HAS_DRIVER(elf)
|
||||||
|
LLD_HAS_DRIVER(mingw)
|
||||||
|
LLD_HAS_DRIVER(macho)
|
||||||
|
LLD_HAS_DRIVER(wasm)
|
||||||
|
|
||||||
static void configure() {
|
static void configure() {
|
||||||
#if _WIN64
|
#if _WIN64
|
||||||
@@ -16,28 +20,13 @@ static void configure() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tinygo_link_elf(int argc, char **argv) {
|
extern "C" {
|
||||||
configure();
|
|
||||||
std::vector<const char*> args(argv, argv + argc);
|
|
||||||
return lld::elf::link(args, llvm::outs(), llvm::errs(), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tinygo_link_macho(int argc, char **argv) {
|
bool tinygo_link(int argc, char **argv) {
|
||||||
configure();
|
configure();
|
||||||
std::vector<const char*> args(argv, argv + argc);
|
std::vector<const char*> args(argv, argv + argc);
|
||||||
return lld::macho::link(args, llvm::outs(), llvm::errs(), false, false);
|
lld::Result r = lld::lldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS);
|
||||||
}
|
return !r.retCode;
|
||||||
|
|
||||||
bool tinygo_link_mingw(int argc, char **argv) {
|
|
||||||
configure();
|
|
||||||
std::vector<const char*> args(argv, argv + argc);
|
|
||||||
return lld::mingw::link(args, llvm::outs(), llvm::errs(), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tinygo_link_wasm(int argc, char **argv) {
|
|
||||||
configure();
|
|
||||||
std::vector<const char*> args(argv, argv + argc);
|
|
||||||
return lld::wasm::link(args, llvm::outs(), llvm::errs(), false, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // external "C"
|
} // external "C"
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ var Musl = Library{
|
|||||||
"internal/syscall_ret.c",
|
"internal/syscall_ret.c",
|
||||||
"internal/vdso.c",
|
"internal/vdso.c",
|
||||||
"legacy/*.c",
|
"legacy/*.c",
|
||||||
|
"linux/*.c",
|
||||||
"malloc/*.c",
|
"malloc/*.c",
|
||||||
"malloc/mallocng/*.c",
|
"malloc/mallocng/*.c",
|
||||||
"mman/*.c",
|
"mman/*.c",
|
||||||
|
|||||||
+99
-79
@@ -3,6 +3,7 @@ package builder
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
@@ -41,91 +42,23 @@ var Picolibc = Library{
|
|||||||
},
|
},
|
||||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib") },
|
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib") },
|
||||||
librarySources: func(target string) ([]string, error) {
|
librarySources: func(target string) ([]string, error) {
|
||||||
return picolibcSources, nil
|
sources := append([]string(nil), picolibcSources...)
|
||||||
|
if !strings.HasPrefix(target, "avr") {
|
||||||
|
// Small chips without long jumps can't compile many files (printf,
|
||||||
|
// pow, etc). Therefore exclude those source files for those chips.
|
||||||
|
// Unfortunately it's difficult to exclude only some chips, so this
|
||||||
|
// excludes those files on all AVR chips for now.
|
||||||
|
// More information:
|
||||||
|
// https://github.com/llvm/llvm-project/issues/67042
|
||||||
|
sources = append(sources, picolibcSourcesLarge...)
|
||||||
|
}
|
||||||
|
return sources, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var picolibcSources = []string{
|
var picolibcSources = []string{
|
||||||
"../../picolibc-stdio.c",
|
"../../picolibc-stdio.c",
|
||||||
|
|
||||||
// srcs_tinystdio
|
|
||||||
"libc/tinystdio/asprintf.c",
|
|
||||||
"libc/tinystdio/bufio.c",
|
|
||||||
"libc/tinystdio/clearerr.c",
|
|
||||||
"libc/tinystdio/ecvt_r.c",
|
|
||||||
"libc/tinystdio/ecvt.c",
|
|
||||||
"libc/tinystdio/ecvtf_r.c",
|
|
||||||
"libc/tinystdio/ecvtf.c",
|
|
||||||
"libc/tinystdio/fcvt.c",
|
|
||||||
"libc/tinystdio/fcvt_r.c",
|
|
||||||
"libc/tinystdio/fcvtf.c",
|
|
||||||
"libc/tinystdio/fcvtf_r.c",
|
|
||||||
"libc/tinystdio/gcvt.c",
|
|
||||||
"libc/tinystdio/gcvtf.c",
|
|
||||||
"libc/tinystdio/fclose.c",
|
|
||||||
"libc/tinystdio/fdevopen.c",
|
|
||||||
"libc/tinystdio/feof.c",
|
|
||||||
"libc/tinystdio/ferror.c",
|
|
||||||
"libc/tinystdio/fflush.c",
|
|
||||||
"libc/tinystdio/fgetc.c",
|
|
||||||
"libc/tinystdio/fgets.c",
|
|
||||||
"libc/tinystdio/fileno.c",
|
|
||||||
"libc/tinystdio/filestrget.c",
|
|
||||||
"libc/tinystdio/filestrput.c",
|
|
||||||
"libc/tinystdio/filestrputalloc.c",
|
|
||||||
"libc/tinystdio/fmemopen.c",
|
|
||||||
"libc/tinystdio/fprintf.c",
|
|
||||||
"libc/tinystdio/fputc.c",
|
|
||||||
"libc/tinystdio/fputs.c",
|
|
||||||
"libc/tinystdio/fread.c",
|
|
||||||
//"libc/tinystdio/freopen.c", // crashes with AVR, see: https://github.com/picolibc/picolibc/pull/369
|
|
||||||
"libc/tinystdio/fscanf.c",
|
|
||||||
"libc/tinystdio/fseek.c",
|
|
||||||
"libc/tinystdio/fseeko.c",
|
|
||||||
"libc/tinystdio/ftell.c",
|
|
||||||
"libc/tinystdio/ftello.c",
|
|
||||||
"libc/tinystdio/fwrite.c",
|
|
||||||
"libc/tinystdio/getchar.c",
|
|
||||||
"libc/tinystdio/gets.c",
|
|
||||||
"libc/tinystdio/matchcaseprefix.c",
|
|
||||||
"libc/tinystdio/mktemp.c",
|
|
||||||
"libc/tinystdio/perror.c",
|
|
||||||
"libc/tinystdio/printf.c",
|
|
||||||
"libc/tinystdio/putchar.c",
|
|
||||||
"libc/tinystdio/puts.c",
|
|
||||||
"libc/tinystdio/rewind.c",
|
|
||||||
"libc/tinystdio/scanf.c",
|
|
||||||
"libc/tinystdio/setbuf.c",
|
|
||||||
"libc/tinystdio/setbuffer.c",
|
|
||||||
"libc/tinystdio/setlinebuf.c",
|
|
||||||
"libc/tinystdio/setvbuf.c",
|
|
||||||
"libc/tinystdio/snprintf.c",
|
|
||||||
"libc/tinystdio/sprintf.c",
|
|
||||||
"libc/tinystdio/snprintfd.c",
|
|
||||||
"libc/tinystdio/snprintff.c",
|
|
||||||
"libc/tinystdio/sprintff.c",
|
|
||||||
"libc/tinystdio/sprintfd.c",
|
|
||||||
"libc/tinystdio/sscanf.c",
|
|
||||||
"libc/tinystdio/strfromf.c",
|
|
||||||
"libc/tinystdio/strfromd.c",
|
|
||||||
"libc/tinystdio/strtof.c",
|
|
||||||
"libc/tinystdio/strtof_l.c",
|
|
||||||
"libc/tinystdio/strtod.c",
|
|
||||||
"libc/tinystdio/strtod_l.c",
|
|
||||||
"libc/tinystdio/ungetc.c",
|
|
||||||
"libc/tinystdio/vasprintf.c",
|
|
||||||
"libc/tinystdio/vfiprintf.c",
|
|
||||||
"libc/tinystdio/vfprintf.c",
|
|
||||||
"libc/tinystdio/vfprintff.c",
|
|
||||||
"libc/tinystdio/vfscanf.c",
|
|
||||||
"libc/tinystdio/vfiscanf.c",
|
|
||||||
"libc/tinystdio/vfscanff.c",
|
|
||||||
"libc/tinystdio/vprintf.c",
|
|
||||||
"libc/tinystdio/vscanf.c",
|
|
||||||
"libc/tinystdio/vsscanf.c",
|
|
||||||
"libc/tinystdio/vsnprintf.c",
|
|
||||||
"libc/tinystdio/vsprintf.c",
|
|
||||||
|
|
||||||
"libc/string/bcmp.c",
|
"libc/string/bcmp.c",
|
||||||
"libc/string/bcopy.c",
|
"libc/string/bcopy.c",
|
||||||
"libc/string/bzero.c",
|
"libc/string/bzero.c",
|
||||||
@@ -229,6 +162,87 @@ var picolibcSources = []string{
|
|||||||
"libc/string/wmempcpy.c",
|
"libc/string/wmempcpy.c",
|
||||||
"libc/string/wmemset.c",
|
"libc/string/wmemset.c",
|
||||||
"libc/string/xpg_strerror_r.c",
|
"libc/string/xpg_strerror_r.c",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parts of picolibc that are too large for small AVRs.
|
||||||
|
var picolibcSourcesLarge = []string{
|
||||||
|
// srcs_tinystdio
|
||||||
|
"libc/tinystdio/asprintf.c",
|
||||||
|
"libc/tinystdio/bufio.c",
|
||||||
|
"libc/tinystdio/clearerr.c",
|
||||||
|
"libc/tinystdio/ecvt_r.c",
|
||||||
|
"libc/tinystdio/ecvt.c",
|
||||||
|
"libc/tinystdio/ecvtf_r.c",
|
||||||
|
"libc/tinystdio/ecvtf.c",
|
||||||
|
"libc/tinystdio/fcvt.c",
|
||||||
|
"libc/tinystdio/fcvt_r.c",
|
||||||
|
"libc/tinystdio/fcvtf.c",
|
||||||
|
"libc/tinystdio/fcvtf_r.c",
|
||||||
|
"libc/tinystdio/gcvt.c",
|
||||||
|
"libc/tinystdio/gcvtf.c",
|
||||||
|
"libc/tinystdio/fclose.c",
|
||||||
|
"libc/tinystdio/fdevopen.c",
|
||||||
|
"libc/tinystdio/feof.c",
|
||||||
|
"libc/tinystdio/ferror.c",
|
||||||
|
"libc/tinystdio/fflush.c",
|
||||||
|
"libc/tinystdio/fgetc.c",
|
||||||
|
"libc/tinystdio/fgets.c",
|
||||||
|
"libc/tinystdio/fileno.c",
|
||||||
|
"libc/tinystdio/filestrget.c",
|
||||||
|
"libc/tinystdio/filestrput.c",
|
||||||
|
"libc/tinystdio/filestrputalloc.c",
|
||||||
|
"libc/tinystdio/fmemopen.c",
|
||||||
|
"libc/tinystdio/fprintf.c",
|
||||||
|
"libc/tinystdio/fputc.c",
|
||||||
|
"libc/tinystdio/fputs.c",
|
||||||
|
"libc/tinystdio/fread.c",
|
||||||
|
//"libc/tinystdio/freopen.c", // crashes with AVR, see: https://github.com/picolibc/picolibc/pull/369
|
||||||
|
"libc/tinystdio/fscanf.c",
|
||||||
|
"libc/tinystdio/fseek.c",
|
||||||
|
"libc/tinystdio/fseeko.c",
|
||||||
|
"libc/tinystdio/ftell.c",
|
||||||
|
"libc/tinystdio/ftello.c",
|
||||||
|
"libc/tinystdio/fwrite.c",
|
||||||
|
"libc/tinystdio/getchar.c",
|
||||||
|
"libc/tinystdio/gets.c",
|
||||||
|
"libc/tinystdio/matchcaseprefix.c",
|
||||||
|
"libc/tinystdio/mktemp.c",
|
||||||
|
"libc/tinystdio/perror.c",
|
||||||
|
"libc/tinystdio/printf.c",
|
||||||
|
"libc/tinystdio/putchar.c",
|
||||||
|
"libc/tinystdio/puts.c",
|
||||||
|
"libc/tinystdio/rewind.c",
|
||||||
|
"libc/tinystdio/scanf.c",
|
||||||
|
"libc/tinystdio/setbuf.c",
|
||||||
|
"libc/tinystdio/setbuffer.c",
|
||||||
|
"libc/tinystdio/setlinebuf.c",
|
||||||
|
"libc/tinystdio/setvbuf.c",
|
||||||
|
"libc/tinystdio/snprintf.c",
|
||||||
|
"libc/tinystdio/sprintf.c",
|
||||||
|
"libc/tinystdio/snprintfd.c",
|
||||||
|
"libc/tinystdio/snprintff.c",
|
||||||
|
"libc/tinystdio/sprintff.c",
|
||||||
|
"libc/tinystdio/sprintfd.c",
|
||||||
|
"libc/tinystdio/sscanf.c",
|
||||||
|
"libc/tinystdio/strfromf.c",
|
||||||
|
"libc/tinystdio/strfromd.c",
|
||||||
|
"libc/tinystdio/strtof.c",
|
||||||
|
"libc/tinystdio/strtof_l.c",
|
||||||
|
"libc/tinystdio/strtod.c",
|
||||||
|
"libc/tinystdio/strtod_l.c",
|
||||||
|
"libc/tinystdio/ungetc.c",
|
||||||
|
"libc/tinystdio/vasprintf.c",
|
||||||
|
"libc/tinystdio/vfiprintf.c",
|
||||||
|
"libc/tinystdio/vfprintf.c",
|
||||||
|
"libc/tinystdio/vfprintff.c",
|
||||||
|
"libc/tinystdio/vfscanf.c",
|
||||||
|
"libc/tinystdio/vfiscanf.c",
|
||||||
|
"libc/tinystdio/vfscanff.c",
|
||||||
|
"libc/tinystdio/vprintf.c",
|
||||||
|
"libc/tinystdio/vscanf.c",
|
||||||
|
"libc/tinystdio/vsscanf.c",
|
||||||
|
"libc/tinystdio/vsnprintf.c",
|
||||||
|
"libc/tinystdio/vsprintf.c",
|
||||||
|
|
||||||
"libm/common/sf_finite.c",
|
"libm/common/sf_finite.c",
|
||||||
"libm/common/sf_copysign.c",
|
"libm/common/sf_copysign.c",
|
||||||
@@ -323,6 +337,12 @@ var picolibcSources = []string{
|
|||||||
"libm/common/math_err_may_uflow.c",
|
"libm/common/math_err_may_uflow.c",
|
||||||
"libm/common/math_err_check_uflow.c",
|
"libm/common/math_err_check_uflow.c",
|
||||||
"libm/common/math_err_check_oflow.c",
|
"libm/common/math_err_check_oflow.c",
|
||||||
|
"libm/common/math_errf_divzerof.c",
|
||||||
|
"libm/common/math_errf_invalidf.c",
|
||||||
|
"libm/common/math_errf_may_uflowf.c",
|
||||||
|
"libm/common/math_errf_oflowf.c",
|
||||||
|
"libm/common/math_errf_uflowf.c",
|
||||||
|
"libm/common/math_errf_with_errnof.c",
|
||||||
"libm/common/math_inexact.c",
|
"libm/common/math_inexact.c",
|
||||||
"libm/common/math_inexactf.c",
|
"libm/common/math_inexactf.c",
|
||||||
"libm/common/log.c",
|
"libm/common/log.c",
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ func TestBinarySize(t *testing.T) {
|
|||||||
// This is a small number of very diverse targets that we want to test.
|
// This is a small number of very diverse targets that we want to test.
|
||||||
tests := []sizeTest{
|
tests := []sizeTest{
|
||||||
// microcontrollers
|
// microcontrollers
|
||||||
{"hifive1b", "examples/echo", 4484, 280, 0, 2252},
|
{"hifive1b", "examples/echo", 4476, 280, 0, 2252},
|
||||||
{"microbit", "examples/serial", 2724, 388, 8, 2256},
|
{"microbit", "examples/serial", 2724, 388, 8, 2256},
|
||||||
{"wioterminal", "examples/pininterrupt", 6000, 1484, 116, 6816},
|
{"wioterminal", "examples/pininterrupt", 5996, 1484, 116, 6816},
|
||||||
|
|
||||||
// TODO: also check wasm. Right now this is difficult, because
|
// TODO: also check wasm. Right now this is difficult, because
|
||||||
// wasm binaries are run through wasm-opt and therefore the
|
// wasm binaries are run through wasm-opt and therefore the
|
||||||
|
|||||||
@@ -12,10 +12,7 @@ import (
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#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(int argc, char **argv);
|
||||||
bool tinygo_link_macho(int argc, char **argv);
|
|
||||||
bool tinygo_link_mingw(int argc, char **argv);
|
|
||||||
bool tinygo_link_wasm(int argc, char **argv);
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
@@ -26,16 +23,7 @@ const hasBuiltinTools = true
|
|||||||
// This version actually runs the tools because TinyGo was compiled while
|
// This version actually runs the tools because TinyGo was compiled while
|
||||||
// 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"
|
args = append([]string{tool}, args...)
|
||||||
if tool == "ld.lld" && len(args) >= 2 {
|
|
||||||
if args[0] == "-m" && (args[1] == "i386pep" || args[1] == "arm64pe") {
|
|
||||||
linker = "mingw"
|
|
||||||
} else if args[0] == "-flavor" {
|
|
||||||
linker = args[1]
|
|
||||||
args = args[2:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args = append([]string{"tinygo:" + tool}, args...)
|
|
||||||
|
|
||||||
var cflag *C.char
|
var cflag *C.char
|
||||||
buf := C.calloc(C.size_t(len(args)), C.size_t(unsafe.Sizeof(cflag)))
|
buf := C.calloc(C.size_t(len(args)), C.size_t(unsafe.Sizeof(cflag)))
|
||||||
@@ -51,19 +39,8 @@ func RunTool(tool string, args ...string) error {
|
|||||||
switch tool {
|
switch tool {
|
||||||
case "clang":
|
case "clang":
|
||||||
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", "wasm-ld":
|
||||||
switch linker {
|
ok = C.tinygo_link(C.int(len(args)), (**C.char)(buf))
|
||||||
case "darwin":
|
|
||||||
ok = C.tinygo_link_macho(C.int(len(args)), (**C.char)(buf))
|
|
||||||
case "elf":
|
|
||||||
ok = C.tinygo_link_elf(C.int(len(args)), (**C.char)(buf))
|
|
||||||
case "mingw":
|
|
||||||
ok = C.tinygo_link_mingw(C.int(len(args)), (**C.char)(buf))
|
|
||||||
default:
|
|
||||||
return errors.New("unknown linker: " + linker)
|
|
||||||
}
|
|
||||||
case "wasm-ld":
|
|
||||||
ok = C.tinygo_link_wasm(C.int(len(args)), (**C.char)(buf))
|
|
||||||
default:
|
default:
|
||||||
return errors.New("unknown tool: " + tool)
|
return errors.New("unknown tool: " + tool)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package builder
|
package builder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
@@ -12,11 +11,6 @@ import (
|
|||||||
func runCCompiler(flags ...string) error {
|
func runCCompiler(flags ...string) error {
|
||||||
if hasBuiltinTools {
|
if hasBuiltinTools {
|
||||||
// Compile this with the internal Clang compiler.
|
// Compile this with the internal Clang compiler.
|
||||||
headerPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
|
||||||
if headerPath == "" {
|
|
||||||
return errors.New("could not locate Clang headers")
|
|
||||||
}
|
|
||||||
flags = append(flags, "-I"+headerPath)
|
|
||||||
cmd := exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
|
cmd := exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
|||||||
+10
-5
@@ -25,9 +25,15 @@ import (
|
|||||||
"golang.org/x/tools/go/ast/astutil"
|
"golang.org/x/tools/go/ast/astutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Function that's only defined in Go 1.22.
|
||||||
|
var setASTFileFields = func(f *ast.File, start, end token.Pos) {
|
||||||
|
}
|
||||||
|
|
||||||
// cgoPackage holds all CGo-related information of a package.
|
// cgoPackage holds all CGo-related information of a package.
|
||||||
type cgoPackage struct {
|
type cgoPackage struct {
|
||||||
generated *ast.File
|
generated *ast.File
|
||||||
|
packageName string
|
||||||
|
cgoFiles []*ast.File
|
||||||
generatedPos token.Pos
|
generatedPos token.Pos
|
||||||
errors []error
|
errors []error
|
||||||
currentDir string // current working directory
|
currentDir string // current working directory
|
||||||
@@ -165,8 +171,9 @@ 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, importPath string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string) ([]*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
||||||
p := &cgoPackage{
|
p := &cgoPackage{
|
||||||
|
packageName: files[0].Name.Name,
|
||||||
currentDir: dir,
|
currentDir: dir,
|
||||||
importPath: importPath,
|
importPath: importPath,
|
||||||
fset: fset,
|
fset: fset,
|
||||||
@@ -202,6 +209,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
|||||||
// This is always a bug in the cgo package.
|
// This is always a bug in the cgo package.
|
||||||
panic("unexpected error: " + err.Error())
|
panic("unexpected error: " + err.Error())
|
||||||
}
|
}
|
||||||
|
p.cgoFiles = append(p.cgoFiles, p.generated)
|
||||||
// If the Comments field is not set to nil, the go/format package will get
|
// If the Comments field is not set to nil, the go/format package will get
|
||||||
// confused about where comments should go.
|
// confused about where comments should go.
|
||||||
p.generated.Comments = nil
|
p.generated.Comments = nil
|
||||||
@@ -292,9 +300,6 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
|||||||
// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve types such as C.int, C.longlong, etc from C.
|
// Retrieve types such as C.int, C.longlong, etc from C.
|
||||||
p.newCGoFile(nil, -1).readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
|
p.newCGoFile(nil, -1).readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
|
||||||
@@ -335,7 +340,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
|||||||
// Print the newly generated in-memory AST, for debugging.
|
// Print the newly generated in-memory AST, for debugging.
|
||||||
//ast.Print(fset, p.generated)
|
//ast.Print(fset, p.generated)
|
||||||
|
|
||||||
return p.generated, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
return p.cgoFiles, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
|
func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//go:build go1.22
|
||||||
|
|
||||||
|
package cgo
|
||||||
|
|
||||||
|
// Code specifically for Go 1.22.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
setASTFileFields = func(f *ast.File, start, end token.Pos) {
|
||||||
|
f.FileStart = start
|
||||||
|
f.FileEnd = end
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -55,7 +55,7 @@ func TestCGo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process the AST with CGo.
|
// Process the AST with CGo.
|
||||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags, "")
|
cgoFiles, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags)
|
||||||
|
|
||||||
// Check the AST for type errors.
|
// Check the AST for type errors.
|
||||||
var typecheckErrors []error
|
var typecheckErrors []error
|
||||||
@@ -66,7 +66,7 @@ func TestCGo(t *testing.T) {
|
|||||||
Importer: simpleImporter{},
|
Importer: simpleImporter{},
|
||||||
Sizes: types.SizesFor("gccgo", "arm"),
|
Sizes: types.SizesFor("gccgo", "arm"),
|
||||||
}
|
}
|
||||||
_, err = config.Check("", fset, []*ast.File{f, cgoAST}, nil)
|
_, err = config.Check("", fset, append([]*ast.File{f}, cgoFiles...), nil)
|
||||||
if err != nil && len(typecheckErrors) == 0 {
|
if err != nil && len(typecheckErrors) == 0 {
|
||||||
// Only report errors when no type errors are found (an
|
// Only report errors when no type errors are found (an
|
||||||
// unexpected condition).
|
// unexpected condition).
|
||||||
@@ -91,7 +91,7 @@ func TestCGo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
buf.WriteString("\n")
|
buf.WriteString("\n")
|
||||||
}
|
}
|
||||||
err = format.Node(buf, fset, cgoAST)
|
err = format.Node(buf, fset, cgoFiles[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("could not write out CGo AST: %v", err)
|
t.Errorf("could not write out CGo AST: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -589,6 +589,13 @@ func (p *cgoPackage) getClangLocationPosition(location C.CXSourceLocation, tu C.
|
|||||||
f := p.fset.AddFile(filename, -1, int(size))
|
f := p.fset.AddFile(filename, -1, int(size))
|
||||||
f.SetLines(lines)
|
f.SetLines(lines)
|
||||||
p.tokenFiles[filename] = f
|
p.tokenFiles[filename] = f
|
||||||
|
// Add dummy file AST, to satisfy the type checker.
|
||||||
|
astFile := &ast.File{
|
||||||
|
Package: f.Pos(0),
|
||||||
|
Name: ast.NewIdent(p.packageName),
|
||||||
|
}
|
||||||
|
setASTFileFields(astFile, f.Pos(0), f.Pos(int(size)))
|
||||||
|
p.cgoFiles = append(p.cgoFiles, astFile)
|
||||||
}
|
}
|
||||||
positionFile := p.tokenFiles[filename]
|
positionFile := p.tokenFiles[filename]
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ package cgo
|
|||||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@15/include
|
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@15/include
|
||||||
#cgo freebsd CFLAGS: -I/usr/local/llvm15/include
|
#cgo freebsd CFLAGS: -I/usr/local/llvm15/include
|
||||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-15/lib -lclang
|
#cgo linux LDFLAGS: -L/usr/lib/llvm-15/lib -lclang
|
||||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@15/lib -lclang -lffi
|
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@15/lib -lclang
|
||||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@15/lib -lclang -lffi
|
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@15/lib -lclang
|
||||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm15/lib -lclang
|
#cgo freebsd LDFLAGS: -L/usr/local/llvm15/lib -lclang
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//go:build !byollvm && !llvm15
|
//go:build !byollvm && llvm16
|
||||||
|
|
||||||
package cgo
|
package cgo
|
||||||
|
|
||||||
// As of 2023-05-05, there is a packaging issue on Debian:
|
// As of 2023-05-05, there is a packaging issue with LLVM 16 on Debian:
|
||||||
// https://github.com/llvm/llvm-project/issues/62199
|
// https://github.com/llvm/llvm-project/issues/62199
|
||||||
// A workaround is to fix this locally, using something like this:
|
// A workaround is to fix this locally, using something like this:
|
||||||
//
|
//
|
||||||
@@ -14,8 +14,8 @@ package cgo
|
|||||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@16/include
|
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@16/include
|
||||||
#cgo freebsd CFLAGS: -I/usr/local/llvm16/include
|
#cgo freebsd CFLAGS: -I/usr/local/llvm16/include
|
||||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-16/lib -lclang
|
#cgo linux LDFLAGS: -L/usr/lib/llvm-16/lib -lclang
|
||||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@16/lib -lclang -lffi
|
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@16/lib -lclang
|
||||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@16/lib -lclang -lffi
|
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@16/lib -lclang
|
||||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm16/lib -lclang
|
#cgo freebsd LDFLAGS: -L/usr/local/llvm16/lib -lclang
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
//go:build !byollvm && !llvm15 && !llvm16
|
||||||
|
|
||||||
|
package cgo
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo linux CFLAGS: -I/usr/include/llvm-17 -I/usr/include/llvm-c-17 -I/usr/lib/llvm-17/include
|
||||||
|
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@17/include
|
||||||
|
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@17/include
|
||||||
|
#cgo freebsd CFLAGS: -I/usr/local/llvm17/include
|
||||||
|
#cgo linux LDFLAGS: -L/usr/lib/llvm-17/lib -lclang
|
||||||
|
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@17/lib -lclang
|
||||||
|
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@17/lib -lclang
|
||||||
|
#cgo freebsd LDFLAGS: -L/usr/local/llvm17/lib -lclang
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
+32
-13
@@ -19,7 +19,6 @@ type Config struct {
|
|||||||
Options *Options
|
Options *Options
|
||||||
Target *TargetSpec
|
Target *TargetSpec
|
||||||
GoMinorVersion int
|
GoMinorVersion int
|
||||||
ClangHeaders string // Clang built-in header include path
|
|
||||||
TestConfig TestConfig
|
TestConfig TestConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +74,12 @@ func (c *Config) GOARM() string {
|
|||||||
|
|
||||||
// BuildTags returns the complete list of build tags used during this build.
|
// BuildTags returns the complete list of build tags used during this build.
|
||||||
func (c *Config) BuildTags() []string {
|
func (c *Config) BuildTags() []string {
|
||||||
tags := append(c.Target.BuildTags, []string{"tinygo", "math_big_pure_go", "gc." + c.GC(), "scheduler." + c.Scheduler(), "serial." + c.Serial()}...)
|
tags := append(c.Target.BuildTags, []string{
|
||||||
|
"tinygo", // that's the compiler
|
||||||
|
"purego", // to get various crypto packages to work
|
||||||
|
"math_big_pure_go", // to get math/big to work
|
||||||
|
"gc." + c.GC(), "scheduler." + c.Scheduler(), // used inside the runtime package
|
||||||
|
"serial." + c.Serial()}...) // used inside the machine package
|
||||||
for i := 1; i <= c.GoMinorVersion; i++ {
|
for i := 1; i <= c.GoMinorVersion; i++ {
|
||||||
tags = append(tags, fmt.Sprintf("go1.%d", i))
|
tags = append(tags, fmt.Sprintf("go1.%d", i))
|
||||||
}
|
}
|
||||||
@@ -83,12 +87,6 @@ func (c *Config) BuildTags() []string {
|
|||||||
return tags
|
return tags
|
||||||
}
|
}
|
||||||
|
|
||||||
// CgoEnabled returns true if (and only if) CGo is enabled. It is true by
|
|
||||||
// default and false if CGO_ENABLED is set to "0".
|
|
||||||
func (c *Config) CgoEnabled() bool {
|
|
||||||
return goenv.Get("CGO_ENABLED") == "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
// GC returns the garbage collection strategy in use on this platform. Valid
|
// GC returns the garbage collection strategy in use on this platform. Valid
|
||||||
// values are "none", "leaking", "conservative" and "precise".
|
// values are "none", "leaking", "conservative" and "precise".
|
||||||
func (c *Config) GC() string {
|
func (c *Config) GC() string {
|
||||||
@@ -190,6 +188,15 @@ func (c *Config) StackSize() uint64 {
|
|||||||
return c.Target.DefaultStackSize
|
return c.Target.DefaultStackSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MaxStackAlloc returns the size of the maximum allocation to put on the stack vs heap.
|
||||||
|
func (c *Config) MaxStackAlloc() uint64 {
|
||||||
|
if c.StackSize() > 32*1024 {
|
||||||
|
return 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
return 256
|
||||||
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
@@ -259,24 +266,35 @@ func (c *Config) DefaultBinaryExtension() string {
|
|||||||
|
|
||||||
// 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(libclang bool) []string {
|
||||||
var cflags []string
|
var cflags []string
|
||||||
for _, flag := range c.Target.CFlags {
|
for _, flag := range c.Target.CFlags {
|
||||||
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
|
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
|
||||||
}
|
}
|
||||||
|
resourceDir := goenv.ClangResourceDir(libclang)
|
||||||
|
if resourceDir != "" {
|
||||||
|
// The resource directory contains the built-in clang headers like
|
||||||
|
// stdbool.h, stdint.h, float.h, etc.
|
||||||
|
// It is left empty if we're using an external compiler (that already
|
||||||
|
// knows these headers).
|
||||||
|
cflags = append(cflags,
|
||||||
|
"-resource-dir="+resourceDir,
|
||||||
|
)
|
||||||
|
}
|
||||||
switch c.Target.Libc {
|
switch c.Target.Libc {
|
||||||
case "darwin-libSystem":
|
case "darwin-libSystem":
|
||||||
root := goenv.Get("TINYGOROOT")
|
root := goenv.Get("TINYGOROOT")
|
||||||
cflags = append(cflags,
|
cflags = append(cflags,
|
||||||
"--sysroot="+filepath.Join(root, "lib/macos-minimal-sdk/src"),
|
"-nostdlibinc",
|
||||||
|
"-isystem", filepath.Join(root, "lib/macos-minimal-sdk/src/usr/include"),
|
||||||
)
|
)
|
||||||
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,
|
"-nostdlibinc",
|
||||||
"-isystem", filepath.Join(path, "include"), // necessary for Xtensa
|
"-isystem", filepath.Join(path, "include"),
|
||||||
"-isystem", filepath.Join(picolibcDir, "include"),
|
"-isystem", filepath.Join(picolibcDir, "include"),
|
||||||
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
|
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
|
||||||
)
|
)
|
||||||
@@ -297,7 +315,8 @@ func (c *Config) CFlags() []string {
|
|||||||
root := goenv.Get("TINYGOROOT")
|
root := goenv.Get("TINYGOROOT")
|
||||||
path, _ := c.LibcPath("mingw-w64")
|
path, _ := c.LibcPath("mingw-w64")
|
||||||
cflags = append(cflags,
|
cflags = append(cflags,
|
||||||
"--sysroot="+path,
|
"-nostdlibinc",
|
||||||
|
"-isystem", filepath.Join(path, "include"),
|
||||||
"-isystem", filepath.Join(root, "lib", "mingw-w64", "mingw-w64-headers", "crt"),
|
"-isystem", filepath.Join(root, "lib", "mingw-w64", "mingw-w64-headers", "crt"),
|
||||||
"-isystem", filepath.Join(root, "lib", "mingw-w64", "mingw-w64-headers", "defaults", "include"),
|
"-isystem", filepath.Join(root, "lib", "mingw-w64", "mingw-w64-headers", "defaults", "include"),
|
||||||
"-D_UCRT",
|
"-D_UCRT",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
|
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
|
||||||
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
|
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
|
||||||
validSerialOptions = []string{"none", "uart", "usb"}
|
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
|
||||||
validPrintSizeOptions = []string{"none", "short", "full"}
|
validPrintSizeOptions = []string{"none", "short", "full"}
|
||||||
validPanicStrategyOptions = []string{"print", "trap"}
|
validPanicStrategyOptions = []string{"print", "trap"}
|
||||||
validOptOptions = []string{"none", "0", "1", "2", "s", "z"}
|
validOptOptions = []string{"none", "0", "1", "2", "s", "z"}
|
||||||
@@ -23,6 +23,7 @@ type Options struct {
|
|||||||
GOOS string // environment variable
|
GOOS string // environment variable
|
||||||
GOARCH string // environment variable
|
GOARCH string // environment variable
|
||||||
GOARM string // environment variable (only used with GOARCH=arm)
|
GOARM string // environment variable (only used with GOARCH=arm)
|
||||||
|
Directory string // working dir, leave it unset to use the current working dir
|
||||||
Target string
|
Target string
|
||||||
Opt string
|
Opt string
|
||||||
GC string
|
GC string
|
||||||
@@ -48,7 +49,6 @@ type Options struct {
|
|||||||
Programmer string
|
Programmer string
|
||||||
OpenOCDCommands []string
|
OpenOCDCommands []string
|
||||||
LLVMFeatures string
|
LLVMFeatures string
|
||||||
Directory string
|
|
||||||
PrintJSON bool
|
PrintJSON bool
|
||||||
Monitor bool
|
Monitor bool
|
||||||
BaudRate int
|
BaudRate int
|
||||||
|
|||||||
+58
-5
@@ -246,6 +246,43 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
|
|||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTargetSpecs retrieves target specifications from the TINYGOROOT targets
|
||||||
|
// directory. Only valid target JSON files are considered, and the function
|
||||||
|
// returns a map of target names to their respective TargetSpec.
|
||||||
|
func GetTargetSpecs() (map[string]*TargetSpec, error) {
|
||||||
|
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
||||||
|
entries, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not list targets: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
maps := map[string]*TargetSpec{}
|
||||||
|
for _, entry := range entries {
|
||||||
|
entryInfo, err := entry.Info()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not get entry info: %w", err)
|
||||||
|
}
|
||||||
|
if !entryInfo.Mode().IsRegular() || !strings.HasSuffix(entry.Name(), ".json") {
|
||||||
|
// Only inspect JSON files.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
path := filepath.Join(dir, entry.Name())
|
||||||
|
spec, err := LoadTarget(&Options{Target: path})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not list target: %w", err)
|
||||||
|
}
|
||||||
|
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
|
||||||
|
// This doesn't look like a regular target file, but rather like
|
||||||
|
// a parent target (such as targets/cortex-m.json).
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := entry.Name()
|
||||||
|
name = name[:len(name)-5]
|
||||||
|
maps[name] = spec
|
||||||
|
}
|
||||||
|
return maps, nil
|
||||||
|
}
|
||||||
|
|
||||||
func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
||||||
// No target spec available. Use the default one, useful on most systems
|
// No target spec available. Use the default one, useful on most systems
|
||||||
// with a regular OS.
|
// with a regular OS.
|
||||||
@@ -264,10 +301,10 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
|||||||
switch goarch {
|
switch goarch {
|
||||||
case "386":
|
case "386":
|
||||||
spec.CPU = "pentium4"
|
spec.CPU = "pentium4"
|
||||||
spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
spec.Features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
||||||
case "amd64":
|
case "amd64":
|
||||||
spec.CPU = "x86-64"
|
spec.CPU = "x86-64"
|
||||||
spec.Features = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
spec.Features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
|
||||||
case "arm":
|
case "arm":
|
||||||
spec.CPU = "generic"
|
spec.CPU = "generic"
|
||||||
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||||
@@ -283,8 +320,10 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
|||||||
spec.CPU = "generic"
|
spec.CPU = "generic"
|
||||||
if goos == "darwin" {
|
if goos == "darwin" {
|
||||||
spec.Features = "+neon"
|
spec.Features = "+neon"
|
||||||
} else { // windows, linux
|
} else if goos == "windows" {
|
||||||
spec.Features = "+neon,-fmv"
|
spec.Features = "+neon,-fmv"
|
||||||
|
} else { // linux
|
||||||
|
spec.Features = "+neon,-fmv,-outline-atomics"
|
||||||
}
|
}
|
||||||
case "wasm":
|
case "wasm":
|
||||||
spec.CPU = "generic"
|
spec.CPU = "generic"
|
||||||
@@ -312,6 +351,20 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
|||||||
spec.RTLib = "compiler-rt"
|
spec.RTLib = "compiler-rt"
|
||||||
spec.Libc = "musl"
|
spec.Libc = "musl"
|
||||||
spec.LDFlags = append(spec.LDFlags, "--gc-sections")
|
spec.LDFlags = append(spec.LDFlags, "--gc-sections")
|
||||||
|
if goarch == "arm64" {
|
||||||
|
// Disable outline atomics. For details, see:
|
||||||
|
// https://cpufun.substack.com/p/atomics-in-aarch64
|
||||||
|
// A better way would be to fully support outline atomics, which
|
||||||
|
// makes atomics slightly more efficient on systems with many cores.
|
||||||
|
// But the instructions are only supported on newer aarch64 CPUs, so
|
||||||
|
// this feature is normally put in a system library which does
|
||||||
|
// feature detection for you.
|
||||||
|
// We take the lazy way out and simply disable this feature, instead
|
||||||
|
// of enabling it in compiler-rt (which is a bit more complicated).
|
||||||
|
// We don't really need this feature anyway as we don't even support
|
||||||
|
// proper threading.
|
||||||
|
spec.CFlags = append(spec.CFlags, "-mno-outline-atomics")
|
||||||
|
}
|
||||||
} else if goos == "windows" {
|
} else if goos == "windows" {
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.Libc = "mingw-w64"
|
spec.Libc = "mingw-w64"
|
||||||
@@ -344,12 +397,12 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
|
|||||||
spec.Linker = "wasm-ld"
|
spec.Linker = "wasm-ld"
|
||||||
spec.RTLib = "compiler-rt"
|
spec.RTLib = "compiler-rt"
|
||||||
spec.Libc = "wasi-libc"
|
spec.Libc = "wasi-libc"
|
||||||
spec.DefaultStackSize = 1024 * 32 // 32kB
|
spec.DefaultStackSize = 1024 * 64 // 64kB
|
||||||
spec.LDFlags = append(spec.LDFlags,
|
spec.LDFlags = append(spec.LDFlags,
|
||||||
"--stack-first",
|
"--stack-first",
|
||||||
"--no-demangle",
|
"--no-demangle",
|
||||||
)
|
)
|
||||||
spec.Emulator = "wasmtime --mapdir=/tmp::{tmpDir} {}"
|
spec.Emulator = "wasmtime --dir={tmpDir}::/tmp {}"
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles,
|
spec.ExtraFiles = append(spec.ExtraFiles,
|
||||||
"src/runtime/asm_tinygowasm.S",
|
"src/runtime/asm_tinygowasm.S",
|
||||||
"src/internal/task/task_asyncify_wasm.S",
|
"src/internal/task/task_asyncify_wasm.S",
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ type Config struct {
|
|||||||
Scheduler string
|
Scheduler string
|
||||||
AutomaticStackSize bool
|
AutomaticStackSize bool
|
||||||
DefaultStackSize uint64
|
DefaultStackSize uint64
|
||||||
|
MaxStackAlloc uint64
|
||||||
NeedsStackObjects bool
|
NeedsStackObjects bool
|
||||||
Debug bool // Whether to emit debug information in the LLVM module.
|
Debug bool // Whether to emit debug information in the LLVM module.
|
||||||
}
|
}
|
||||||
@@ -1997,8 +1998,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) {
|
|||||||
case *ssa.Alloc:
|
case *ssa.Alloc:
|
||||||
typ := b.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
|
typ := b.getLLVMType(expr.Type().Underlying().(*types.Pointer).Elem())
|
||||||
size := b.targetData.TypeAllocSize(typ)
|
size := b.targetData.TypeAllocSize(typ)
|
||||||
// Move all "large" allocations to the heap. This value is also transform.maxStackAlloc.
|
// Move all "large" allocations to the heap.
|
||||||
if expr.Heap || size > 256 {
|
if expr.Heap || size > b.MaxStackAlloc {
|
||||||
// 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 {
|
||||||
@@ -3261,7 +3262,11 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
|
|||||||
// Instead of a load from the global, create a bitcast of the
|
// Instead of a load from the global, create a bitcast of the
|
||||||
// function pointer itself.
|
// function pointer itself.
|
||||||
name := strings.TrimSuffix(unop.X.(*ssa.Global).Name(), "$funcaddr")
|
name := strings.TrimSuffix(unop.X.(*ssa.Global).Name(), "$funcaddr")
|
||||||
_, fn := b.getFunction(b.fn.Pkg.Members[name].(*ssa.Function))
|
pkg := b.fn.Pkg
|
||||||
|
if pkg == nil {
|
||||||
|
pkg = b.fn.Origin().Pkg
|
||||||
|
}
|
||||||
|
_, fn := b.getFunction(pkg.Members[name].(*ssa.Function))
|
||||||
if fn.IsNil() {
|
if fn.IsNil() {
|
||||||
return llvm.Value{}, b.makeError(unop.Pos(), "cgo function not found: "+name)
|
return llvm.Value{}, b.makeError(unop.Pos(), "cgo function not found: "+name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ func testCompilePackage(t *testing.T, options *compileopts.Options, file string)
|
|||||||
defer machine.Dispose()
|
defer machine.Dispose()
|
||||||
|
|
||||||
// Load entire program AST into memory.
|
// Load entire program AST into memory.
|
||||||
lprogram, err := loader.Load(config, "./testdata/"+file, config.ClangHeaders, types.Config{
|
lprogram, err := loader.Load(config, "./testdata/"+file, types.Config{
|
||||||
Sizes: Sizes(machine),
|
Sizes: Sizes(machine),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+18
-12
@@ -684,19 +684,25 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
|
|||||||
|
|
||||||
actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type")
|
actualTypeNum := b.CreateExtractValue(itf, 0, "interface.type")
|
||||||
commaOk := llvm.Value{}
|
commaOk := llvm.Value{}
|
||||||
if _, ok := expr.AssertedType.Underlying().(*types.Interface); ok {
|
|
||||||
// Type assert on interface type.
|
|
||||||
// This is a call to an interface type assert function.
|
|
||||||
// The interface lowering pass will define this function by filling it
|
|
||||||
// with a type switch over all concrete types that implement this
|
|
||||||
// interface, and returning whether it's one of the matched types.
|
|
||||||
// This is very different from how interface asserts are implemented in
|
|
||||||
// the main Go compiler, where the runtime checks whether the type
|
|
||||||
// implements each method of the interface. See:
|
|
||||||
// https://research.swtch.com/interfaces
|
|
||||||
fn := b.getInterfaceImplementsFunc(expr.AssertedType)
|
|
||||||
commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, "")
|
|
||||||
|
|
||||||
|
if intf, ok := expr.AssertedType.Underlying().(*types.Interface); ok {
|
||||||
|
if intf.Empty() {
|
||||||
|
// intf is the empty interface => no methods
|
||||||
|
// This type assertion always succeeds, so we can just set commaOk to true.
|
||||||
|
commaOk = llvm.ConstInt(b.ctx.Int1Type(), 1, true)
|
||||||
|
} else {
|
||||||
|
// Type assert on interface type with methods.
|
||||||
|
// This is a call to an interface type assert function.
|
||||||
|
// The interface lowering pass will define this function by filling it
|
||||||
|
// with a type switch over all concrete types that implement this
|
||||||
|
// interface, and returning whether it's one of the matched types.
|
||||||
|
// This is very different from how interface asserts are implemented in
|
||||||
|
// the main Go compiler, where the runtime checks whether the type
|
||||||
|
// implements each method of the interface. See:
|
||||||
|
// https://research.swtch.com/interfaces
|
||||||
|
fn := b.getInterfaceImplementsFunc(expr.AssertedType)
|
||||||
|
commaOk = b.CreateCall(fn.GlobalValueType(), fn, []llvm.Value{actualTypeNum}, "")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
name, _ := getTypeCodeName(expr.AssertedType)
|
name, _ := getTypeCodeName(expr.AssertedType)
|
||||||
globalName := "reflect/types.typeid:" + name
|
globalName := "reflect/types.typeid:" + name
|
||||||
|
|||||||
+5
-5
@@ -21,7 +21,7 @@ entry:
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
define hidden void @main.regularFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 32768, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.regularFunction$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ declare void @"internal/task.start"(i32, ptr, i32, ptr) #1
|
|||||||
; Function Attrs: nounwind
|
; Function Attrs: nounwind
|
||||||
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
define hidden void @main.inlineFunctionGoroutine(ptr %context) unnamed_addr #2 {
|
||||||
entry:
|
entry:
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 32768, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.inlineFunctionGoroutine$1$gowrapper" to i32), ptr nonnull inttoptr (i32 5 to ptr), i32 65536, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ entry:
|
|||||||
store i32 5, ptr %0, align 4
|
store i32 5, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
|
%1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1
|
||||||
store ptr %n, ptr %1, align 4
|
store ptr %n, ptr %1, align 4
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 32768, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"main.closureFunctionGoroutine$1$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9
|
||||||
%2 = load i32, ptr %n, align 4
|
%2 = load i32, ptr %n, align 4
|
||||||
call void @runtime.printint32(i32 %2, ptr undef) #9
|
call void @runtime.printint32(i32 %2, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
@@ -113,7 +113,7 @@ entry:
|
|||||||
store ptr %fn.context, ptr %1, align 4
|
store ptr %fn.context, ptr %1, align 4
|
||||||
%2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
|
%2 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 2
|
||||||
store ptr %fn.funcptr, ptr %2, align 4
|
store ptr %fn.funcptr, ptr %2, align 4
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 32768, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @main.funcGoroutine.gowrapper to i32), ptr nonnull %0, i32 65536, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ entry:
|
|||||||
store i32 4, ptr %.repack1, align 4
|
store i32 4, ptr %.repack1, align 4
|
||||||
%2 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 2
|
%2 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 2
|
||||||
store ptr %itf.typecode, ptr %2, align 4
|
store ptr %itf.typecode, ptr %2, align 4
|
||||||
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 32768, ptr undef) #9
|
call void @"internal/task.start"(i32 ptrtoint (ptr @"interface:{Print:func:{basic:string}{}}.Print$invoke$gowrapper" to i32), ptr nonnull %0, i32 65536, ptr undef) #9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+60
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694529238,
|
||||||
|
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1703068421,
|
||||||
|
"narHash": "sha256-WSw5Faqlw75McIflnl5v7qVD/B3S2sLh+968bpOGrWA=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "d65bceaee0fb1e64363f7871bc43dc1c6ecad99f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-23.11",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# A Nix flake file, mainly intended for developing TinyGo.
|
||||||
|
# You can download Nix here, for use on your Linux or macOS system:
|
||||||
|
# https://nixos.org/download.html
|
||||||
|
# After you have installed Nix, you can enter the development environment as
|
||||||
|
# follows:
|
||||||
|
#
|
||||||
|
# nix develop
|
||||||
|
#
|
||||||
|
# This drops you into a bash shell, where you can install TinyGo simply using
|
||||||
|
# the following command:
|
||||||
|
#
|
||||||
|
# go install
|
||||||
|
#
|
||||||
|
# That's all! Assuming you've set up your $PATH correctly, you can now use the
|
||||||
|
# tinygo command as usual:
|
||||||
|
#
|
||||||
|
# tinygo version
|
||||||
|
#
|
||||||
|
# But you'll need a bit more to make TinyGo actually able to compile code:
|
||||||
|
#
|
||||||
|
# make llvm-source # fetch compiler-rt
|
||||||
|
# git submodule update --init --recursive # fetch lots of other libraries and SVD files
|
||||||
|
# make gen-device -j4 # build src/device/*/*.go files
|
||||||
|
# make wasi-libc # build support for wasi/wasm
|
||||||
|
#
|
||||||
|
# With this, you should have an environment that can compile anything - except
|
||||||
|
# for the Xtensa architecture (ESP8266/ESP32) because support for that lives in
|
||||||
|
# a separate LLVM fork.
|
||||||
|
#
|
||||||
|
# You can also do many other things from this environment. Building and flashing
|
||||||
|
# should work as you're used to: it's not a VM or container so there are no
|
||||||
|
# access restrictions and you're running in the same host environment - just
|
||||||
|
# with a slightly different set of tools available.
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
# Use a recent stable release, but fix the version to make it reproducible.
|
||||||
|
# This version should be updated from time to time.
|
||||||
|
nixpkgs.url = "nixpkgs/nixos-23.11";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
in
|
||||||
|
with pkgs;
|
||||||
|
{
|
||||||
|
devShells.default = mkShell {
|
||||||
|
buildInputs = [
|
||||||
|
# These dependencies are required for building tinygo (go install).
|
||||||
|
go
|
||||||
|
llvmPackages_17.llvm
|
||||||
|
llvmPackages_17.libclang
|
||||||
|
llvmPackages_17.libcxx
|
||||||
|
# Additional dependencies needed at runtime, for building and/or
|
||||||
|
# flashing.
|
||||||
|
llvmPackages_17.lld
|
||||||
|
avrdude
|
||||||
|
binaryen
|
||||||
|
# Additional dependencies needed for on-chip debugging.
|
||||||
|
# These tools are rather big (especially GDB) and not frequently
|
||||||
|
# used, so are commented out. On-chip debugging is still possible if
|
||||||
|
# these tools are available in the host environment.
|
||||||
|
#gdb
|
||||||
|
#openocd
|
||||||
|
];
|
||||||
|
shellHook= ''
|
||||||
|
# Configure CLANG, LLVM_AR, and LLVM_NM for `make wasi-libc`.
|
||||||
|
# Without setting these explicitly, Homebrew versions might be used
|
||||||
|
# or the default `ar` and `nm` tools might be used (which don't
|
||||||
|
# support wasi).
|
||||||
|
export CLANG="clang-17 -resource-dir ${llvmPackages_17.clang.cc.lib}/lib/clang/17"
|
||||||
|
export LLVM_AR=llvm-ar
|
||||||
|
export LLVM_NM=llvm-nm
|
||||||
|
|
||||||
|
# Make `make smoketest` work (the default is `md5`, while Nix only
|
||||||
|
# has `md5sum`).
|
||||||
|
export MD5SUM=md5sum
|
||||||
|
|
||||||
|
# Ugly hack to make the Clang resources directory available.
|
||||||
|
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_17.clang.cc.lib}/lib/clang/17"\"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -15,10 +15,11 @@ require (
|
|||||||
github.com/mattn/go-tty v0.0.4
|
github.com/mattn/go-tty v0.0.4
|
||||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
|
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
|
||||||
go.bug.st/serial v1.6.0
|
go.bug.st/serial v1.6.0
|
||||||
golang.org/x/sys v0.11.0
|
golang.org/x/net v0.20.0
|
||||||
golang.org/x/tools v0.12.0
|
golang.org/x/sys v0.16.0
|
||||||
|
golang.org/x/tools v0.17.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
tinygo.org/x/go-llvm v0.0.0-20230920233244-32ed56c6be9c
|
tinygo.org/x/go-llvm v0.0.0-20240106122909-c2c543540318
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -30,4 +31,5 @@ require (
|
|||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||||
|
golang.org/x/text v0.14.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9
|
|||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
|
go.bug.st/serial v1.6.0 h1:mAbRGN4cKE2J5gMwsMHC2KQisdLRQssO9WSM+rbZJ8A=
|
||||||
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
go.bug.st/serial v1.6.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
||||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
|
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||||
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -56,14 +58,16 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||||
|
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20230920233244-32ed56c6be9c h1:rS8mAFqf0CfxPCbtfsI3bWL4jkb0TBYA1wx7tY1nu28=
|
tinygo.org/x/go-llvm v0.0.0-20240106122909-c2c543540318 h1:4KjZvPtcN1UwobevcGbdzeinx0L1i8HDdJu84bu7NI8=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20230920233244-32ed56c6be9c/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
tinygo.org/x/go-llvm v0.0.0-20240106122909-c2c543540318/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||||
|
|||||||
+105
-5
@@ -14,6 +14,8 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Keys is a slice of all available environment variable keys.
|
// Keys is a slice of all available environment variable keys.
|
||||||
@@ -33,11 +35,20 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set to true if we're linking statically against LLVM.
|
||||||
|
var hasBuiltinTools = false
|
||||||
|
|
||||||
// TINYGOROOT is the path to the final location for checking tinygo files. If
|
// TINYGOROOT is the path to the final location for checking tinygo files. If
|
||||||
// unset (by a -X ldflag), then sourceDir() will fallback to the original build
|
// unset (by a -X ldflag), then sourceDir() will fallback to the original build
|
||||||
// directory.
|
// directory.
|
||||||
var TINYGOROOT string
|
var TINYGOROOT string
|
||||||
|
|
||||||
|
// If a particular Clang resource dir must always be used and TinyGo can't
|
||||||
|
// figure out the directory using heuristics, this global can be set using a
|
||||||
|
// linker flag.
|
||||||
|
// This is needed for Nix.
|
||||||
|
var clangResourceDir string
|
||||||
|
|
||||||
// Variables read from a `go env` command invocation.
|
// Variables read from a `go env` command invocation.
|
||||||
var goEnvVars struct {
|
var goEnvVars struct {
|
||||||
GOPATH string
|
GOPATH string
|
||||||
@@ -131,11 +142,8 @@ func Get(name string) string {
|
|||||||
}
|
}
|
||||||
return filepath.Join(dir, "tinygo")
|
return filepath.Join(dir, "tinygo")
|
||||||
case "CGO_ENABLED":
|
case "CGO_ENABLED":
|
||||||
val := os.Getenv("CGO_ENABLED")
|
// Always enable CGo. It is required by a number of targets, including
|
||||||
if val == "1" || val == "0" {
|
// macOS and the rp2040.
|
||||||
return val
|
|
||||||
}
|
|
||||||
// Default to enabling CGo.
|
|
||||||
return "1"
|
return "1"
|
||||||
case "TINYGOROOT":
|
case "TINYGOROOT":
|
||||||
return sourceDir()
|
return sourceDir()
|
||||||
@@ -284,3 +292,95 @@ func isSourceDir(root string) bool {
|
|||||||
_, err = os.Stat(filepath.Join(root, "src/device/arm/arm.go"))
|
_, err = os.Stat(filepath.Join(root, "src/device/arm/arm.go"))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClangResourceDir returns the clang resource dir if available. This is the
|
||||||
|
// -resource-dir flag. If it isn't available, an empty string is returned and
|
||||||
|
// -resource-dir should be left unset.
|
||||||
|
// The libclang flag must be set if the resource dir is read for use by
|
||||||
|
// libclang.
|
||||||
|
// In that case, the resource dir is always returned (even when linking
|
||||||
|
// dynamically against LLVM) because libclang always needs this directory.
|
||||||
|
func ClangResourceDir(libclang bool) string {
|
||||||
|
if clangResourceDir != "" {
|
||||||
|
// The resource dir is forced to a particular value at build time.
|
||||||
|
// This is needed on Nix for example, where Clang and libclang don't
|
||||||
|
// know their own resource dir.
|
||||||
|
// Also see:
|
||||||
|
// https://discourse.nixos.org/t/why-is-the-clang-resource-dir-split-in-a-separate-package/34114
|
||||||
|
return clangResourceDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasBuiltinTools && !libclang {
|
||||||
|
// Using external tools, so the resource dir doesn't need to be
|
||||||
|
// specified. Clang knows where to find it.
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether we're running from a TinyGo release directory.
|
||||||
|
// This is the case for release binaries on GitHub.
|
||||||
|
root := Get("TINYGOROOT")
|
||||||
|
releaseHeaderDir := filepath.Join(root, "lib", "clang")
|
||||||
|
if _, err := os.Stat(releaseHeaderDir); !errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return releaseHeaderDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasBuiltinTools {
|
||||||
|
// We are statically linked to LLVM.
|
||||||
|
// Check whether we're running from the source directory.
|
||||||
|
// This typically happens when TinyGo was built using `make` as part of
|
||||||
|
// development.
|
||||||
|
llvmMajor := strings.Split(llvm.Version, ".")[0]
|
||||||
|
buildResourceDir := filepath.Join(root, "llvm-build", "lib", "clang", llvmMajor)
|
||||||
|
if _, err := os.Stat(buildResourceDir); !errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return buildResourceDir
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We use external tools, either when installed using `go install` or
|
||||||
|
// when packaged in a Linux distribution (Linux distros typically prefer
|
||||||
|
// dynamic linking).
|
||||||
|
// Try to detect the system clang resources directory.
|
||||||
|
resourceDir := findSystemClangResources(root)
|
||||||
|
if resourceDir != "" {
|
||||||
|
return resourceDir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resource directory not found.
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the Clang resource dir on this particular system.
|
||||||
|
// Return the empty string when they aren't found.
|
||||||
|
func findSystemClangResources(TINYGOROOT string) string {
|
||||||
|
llvmMajor := strings.Split(llvm.Version, ".")[0]
|
||||||
|
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux", "android":
|
||||||
|
// Header files are typically stored in /usr/lib/clang/<version>/include.
|
||||||
|
// Tested on Fedora 39, Debian 12, and Arch Linux.
|
||||||
|
path := filepath.Join("/usr/lib/clang", llvmMajor)
|
||||||
|
_, err := os.Stat(filepath.Join(path, "include", "stdint.h"))
|
||||||
|
if err == nil {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
case "darwin":
|
||||||
|
// This assumes a Homebrew installation, like in builder/commands.go.
|
||||||
|
var prefix string
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "amd64":
|
||||||
|
prefix = "/usr/local/opt/llvm@" + llvmMajor
|
||||||
|
case "arm64":
|
||||||
|
prefix = "/opt/homebrew/opt/llvm@" + llvmMajor
|
||||||
|
default:
|
||||||
|
return "" // very unlikely for now
|
||||||
|
}
|
||||||
|
path := fmt.Sprintf("%s/lib/clang/%s", prefix, llvmMajor)
|
||||||
|
_, err := os.Stat(path + "/include/stdint.h")
|
||||||
|
if err == nil {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could not find it.
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build byollvm
|
||||||
|
|
||||||
|
package goenv
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
hasBuiltinTools = true
|
||||||
|
}
|
||||||
+11
-1
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
// Version of TinyGo.
|
// Version of TinyGo.
|
||||||
// Update this value before release of new version of software.
|
// Update this value before release of new version of software.
|
||||||
const Version = "0.30.0"
|
const version = "0.31.0"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// This variable is set at build time using -ldflags parameters.
|
// This variable is set at build time using -ldflags parameters.
|
||||||
@@ -17,6 +17,16 @@ var (
|
|||||||
GitSha1 string
|
GitSha1 string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Return TinyGo version, either in the form 0.30.0 or as a development version
|
||||||
|
// (like 0.30.0-dev-abcd012).
|
||||||
|
func Version() string {
|
||||||
|
v := version
|
||||||
|
if strings.HasSuffix(version, "-dev") && GitSha1 != "" {
|
||||||
|
v += "-" + GitSha1
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
// GetGorootVersion returns the major and minor version for a given GOROOT path.
|
||||||
// If the goroot cannot be determined, (0, 0) is returned.
|
// If the goroot cannot be determined, (0, 0) is returned.
|
||||||
func GetGorootVersion() (major, minor int, err error) {
|
func GetGorootVersion() (major, minor int, err error) {
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Docker hub does a recursive clone, then checks the branch out,
|
# Docker hub does a recursive clone, then checks the branch out,
|
||||||
# so when a PR adds a submodule (or updates it), it fails.
|
# so when a PR adds a submodule (or updates it), it fails.
|
||||||
git submodule update --init
|
git submodule update --init --recursive
|
||||||
|
|||||||
@@ -239,7 +239,8 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
// already be emitted in initAll.
|
// already be emitted in initAll.
|
||||||
continue
|
continue
|
||||||
case strings.HasPrefix(callFn.name, "runtime.print") || callFn.name == "runtime._panic" || callFn.name == "runtime.hashmapGet" || callFn.name == "runtime.hashmapInterfaceHash" ||
|
case strings.HasPrefix(callFn.name, "runtime.print") || callFn.name == "runtime._panic" || callFn.name == "runtime.hashmapGet" || callFn.name == "runtime.hashmapInterfaceHash" ||
|
||||||
callFn.name == "os.runtime_args" || callFn.name == "internal/task.start" || callFn.name == "internal/task.Current":
|
callFn.name == "os.runtime_args" || callFn.name == "internal/task.start" || callFn.name == "internal/task.Current" ||
|
||||||
|
callFn.name == "time.startTimer" || callFn.name == "time.stopTimer" || callFn.name == "time.resetTimer":
|
||||||
// These functions should be run at runtime. Specifically:
|
// These functions should be run at runtime. Specifically:
|
||||||
// * Print and panic functions are best emitted directly without
|
// * Print and panic functions are best emitted directly without
|
||||||
// interpreting them, otherwise we get a ton of putchar (etc.)
|
// interpreting them, otherwise we get a ton of putchar (etc.)
|
||||||
@@ -252,6 +253,8 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
// at runtime.
|
// at runtime.
|
||||||
// * internal/task.start, internal/task.Current: start and read shcheduler state,
|
// * internal/task.start, internal/task.Current: start and read shcheduler state,
|
||||||
// which is modified elsewhere.
|
// which is modified elsewhere.
|
||||||
|
// * Timer functions access runtime internal state which may
|
||||||
|
// not be initialized.
|
||||||
err := r.runAtRuntime(fn, inst, locals, &mem, indent)
|
err := r.runAtRuntime(fn, inst, locals, &mem, indent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, mem, err
|
return nil, mem, err
|
||||||
|
|||||||
+1
-1
Submodule lib/binaryen updated: 96f7acf09a...11dba9b1c2
+1
-1
Submodule lib/cmsis-svd updated: df75ff974c...40327a4d2d
+1
-1
Submodule lib/wasi-libc updated: 30094b6ed0...1dfe5c302d
+5
-3
@@ -18,7 +18,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
@@ -157,7 +156,7 @@ func listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool)
|
|||||||
|
|
||||||
// Add files from TinyGo.
|
// Add files from TinyGo.
|
||||||
tinygoDir := filepath.Join(tinygoSrc, dir)
|
tinygoDir := filepath.Join(tinygoSrc, dir)
|
||||||
tinygoEntries, err := ioutil.ReadDir(tinygoDir)
|
tinygoEntries, err := os.ReadDir(tinygoDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -177,7 +176,7 @@ func listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool)
|
|||||||
// Add all directories from $GOROOT that are not part of the TinyGo
|
// Add all directories from $GOROOT that are not part of the TinyGo
|
||||||
// overrides.
|
// overrides.
|
||||||
goDir := filepath.Join(goSrc, dir)
|
goDir := filepath.Join(goSrc, dir)
|
||||||
goEntries, err := ioutil.ReadDir(goDir)
|
goEntries, err := os.ReadDir(goDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -233,6 +232,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
|||||||
"": true,
|
"": true,
|
||||||
"crypto/": true,
|
"crypto/": true,
|
||||||
"crypto/rand/": false,
|
"crypto/rand/": false,
|
||||||
|
"crypto/tls/": false,
|
||||||
"device/": false,
|
"device/": false,
|
||||||
"examples/": false,
|
"examples/": false,
|
||||||
"internal/": true,
|
"internal/": true,
|
||||||
@@ -242,7 +242,9 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
|||||||
"internal/task/": false,
|
"internal/task/": false,
|
||||||
"machine/": false,
|
"machine/": false,
|
||||||
"net/": true,
|
"net/": true,
|
||||||
|
"net/http/": false,
|
||||||
"os/": true,
|
"os/": true,
|
||||||
|
"os/user/": false,
|
||||||
"reflect/": false,
|
"reflect/": false,
|
||||||
"runtime/": false,
|
"runtime/": false,
|
||||||
"sync/": true,
|
"sync/": true,
|
||||||
|
|||||||
+1
-5
@@ -22,12 +22,8 @@ func List(config *compileopts.Config, extraArgs, pkgs []string) (*exec.Cmd, erro
|
|||||||
args = append(args, "-tags", strings.Join(config.BuildTags(), " "))
|
args = append(args, "-tags", strings.Join(config.BuildTags(), " "))
|
||||||
}
|
}
|
||||||
args = append(args, pkgs...)
|
args = append(args, pkgs...)
|
||||||
cgoEnabled := "0"
|
|
||||||
if config.CgoEnabled() {
|
|
||||||
cgoEnabled = "1"
|
|
||||||
}
|
|
||||||
cmd := exec.Command(filepath.Join(goenv.Get("GOROOT"), "bin", "go"), args...)
|
cmd := exec.Command(filepath.Join(goenv.Get("GOROOT"), "bin", "go"), args...)
|
||||||
cmd.Env = append(os.Environ(), "GOROOT="+goroot, "GOOS="+config.GOOS(), "GOARCH="+config.GOARCH(), "CGO_ENABLED="+cgoEnabled)
|
cmd.Env = append(os.Environ(), "GOROOT="+goroot, "GOOS="+config.GOOS(), "GOARCH="+config.GOARCH(), "CGO_ENABLED=1")
|
||||||
if config.Options.Directory != "" {
|
if config.Options.Directory != "" {
|
||||||
cmd.Dir = config.Options.Directory
|
cmd.Dir = config.Options.Directory
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-16
@@ -27,13 +27,14 @@ import (
|
|||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var initFileVersions = func(info *types.Info) {}
|
||||||
|
|
||||||
// Program holds all packages and some metadata about the program as a whole.
|
// Program holds all packages and some metadata about the program as a whole.
|
||||||
type Program struct {
|
type Program struct {
|
||||||
config *compileopts.Config
|
config *compileopts.Config
|
||||||
clangHeaders string
|
typeChecker types.Config
|
||||||
typeChecker types.Config
|
goroot string // synthetic GOROOT
|
||||||
goroot string // synthetic GOROOT
|
workingDir string
|
||||||
workingDir string
|
|
||||||
|
|
||||||
Packages map[string]*Package
|
Packages map[string]*Package
|
||||||
sorted []*Package
|
sorted []*Package
|
||||||
@@ -103,7 +104,7 @@ type EmbedFile struct {
|
|||||||
// Load loads the given package with all dependencies (including the runtime
|
// Load loads the given package with all dependencies (including the runtime
|
||||||
// package). Call .Parse() afterwards to parse all Go files (including CGo
|
// package). Call .Parse() afterwards to parse all Go files (including CGo
|
||||||
// processing, if necessary).
|
// processing, if necessary).
|
||||||
func Load(config *compileopts.Config, inputPkg string, clangHeaders string, typeChecker types.Config) (*Program, error) {
|
func Load(config *compileopts.Config, inputPkg string, typeChecker types.Config) (*Program, error) {
|
||||||
goroot, err := GetCachedGoroot(config)
|
goroot, err := GetCachedGoroot(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -118,13 +119,12 @@ func Load(config *compileopts.Config, inputPkg string, clangHeaders string, type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p := &Program{
|
p := &Program{
|
||||||
config: config,
|
config: config,
|
||||||
clangHeaders: clangHeaders,
|
typeChecker: typeChecker,
|
||||||
typeChecker: typeChecker,
|
goroot: goroot,
|
||||||
goroot: goroot,
|
workingDir: wd,
|
||||||
workingDir: wd,
|
Packages: make(map[string]*Package),
|
||||||
Packages: make(map[string]*Package),
|
fset: token.NewFileSet(),
|
||||||
fset: token.NewFileSet(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List the dependencies of this package, in raw JSON format.
|
// List the dependencies of this package, in raw JSON format.
|
||||||
@@ -380,6 +380,24 @@ func (p *Package) Check() error {
|
|||||||
typeErrors = append(typeErrors, err)
|
typeErrors = append(typeErrors, err)
|
||||||
}
|
}
|
||||||
checker.Importer = p
|
checker.Importer = p
|
||||||
|
if p.Module.GoVersion != "" {
|
||||||
|
// Setting the Go version for a module makes sure the type checker
|
||||||
|
// errors out on language features not supported in that particular
|
||||||
|
// version.
|
||||||
|
checker.GoVersion = "go" + p.Module.GoVersion
|
||||||
|
} else {
|
||||||
|
// Version is not known, so use the currently installed Go version.
|
||||||
|
// This is needed for `tinygo run` for example.
|
||||||
|
// Normally we'd use goenv.GorootVersionString(), but for compatibility
|
||||||
|
// with Go 1.20 and below we need a version in the form of "go1.12" (no
|
||||||
|
// patch version).
|
||||||
|
major, minor, err := goenv.GetGorootVersion()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
checker.GoVersion = fmt.Sprintf("go%d.%d", major, minor)
|
||||||
|
}
|
||||||
|
initFileVersions(&p.info)
|
||||||
|
|
||||||
// Do typechecking of the package.
|
// Do typechecking of the package.
|
||||||
packageName := p.ImportPath
|
packageName := p.ImportPath
|
||||||
@@ -438,9 +456,9 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
|||||||
// to call cgo.Process in that case as it will only cause issues.
|
// to call cgo.Process in that case as it will only cause issues.
|
||||||
if len(p.CgoFiles) != 0 && len(files) != 0 {
|
if len(p.CgoFiles) != 0 && len(files) != 0 {
|
||||||
var initialCFlags []string
|
var initialCFlags []string
|
||||||
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
initialCFlags = append(initialCFlags, p.program.config.CFlags(true)...)
|
||||||
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
||||||
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.ImportPath, p.program.fset, initialCFlags, p.program.clangHeaders)
|
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.ImportPath, p.program.fset, initialCFlags)
|
||||||
p.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 {
|
||||||
@@ -449,7 +467,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
|||||||
if errs != nil {
|
if errs != nil {
|
||||||
fileErrs = append(fileErrs, errs...)
|
fileErrs = append(fileErrs, errs...)
|
||||||
}
|
}
|
||||||
files = append(files, generated)
|
files = append(files, generated...)
|
||||||
p.program.LDFlags = append(p.program.LDFlags, ldflags...)
|
p.program.LDFlags = append(p.program.LDFlags, ldflags...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//go:build go1.22
|
||||||
|
|
||||||
|
// types.Info.FileVersions was added in Go 1.22, so we can only initialize it
|
||||||
|
// when built with Go 1.22.
|
||||||
|
|
||||||
|
package loader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
initFileVersions = func(info *types.Info) {
|
||||||
|
info.FileVersions = make(map[*ast.File]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"go/scanner"
|
"go/scanner"
|
||||||
"go/types"
|
"go/types"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@@ -533,7 +532,7 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
|||||||
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
||||||
}
|
}
|
||||||
if options.Monitor {
|
if options.Monitor {
|
||||||
return Monitor(result.Executable, "", options)
|
return Monitor(result.Executable, "", config)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -798,7 +797,7 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
needsEnvInVars = true
|
needsEnvInVars = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var args, env []string
|
var args, emuArgs, env []string
|
||||||
var extraCmdEnv []string
|
var extraCmdEnv []string
|
||||||
if needsEnvInVars {
|
if needsEnvInVars {
|
||||||
runtimeGlobals := make(map[string]string)
|
runtimeGlobals := make(map[string]string)
|
||||||
@@ -821,13 +820,14 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
} else if config.EmulatorName() == "wasmtime" {
|
} else if config.EmulatorName() == "wasmtime" {
|
||||||
// Wasmtime needs some special flags to pass environment variables
|
// Wasmtime needs some special flags to pass environment variables
|
||||||
// and allow reading from the current directory.
|
// and allow reading from the current directory.
|
||||||
args = append(args, "--dir=.")
|
emuArgs = append(emuArgs, "--dir=.")
|
||||||
for _, v := range environmentVars {
|
for _, v := range environmentVars {
|
||||||
args = append(args, "--env", v)
|
emuArgs = append(emuArgs, "--env", v)
|
||||||
}
|
}
|
||||||
if len(cmdArgs) != 0 {
|
if len(cmdArgs) != 0 {
|
||||||
// mark end of wasmtime arguments and start of program ones: --
|
// Use of '--' argument no longer necessary as of Wasmtime v14:
|
||||||
args = append(args, "--")
|
// https://github.com/bytecodealliance/wasmtime/pull/6946
|
||||||
|
// args = append(args, "--")
|
||||||
args = append(args, cmdArgs...)
|
args = append(args, cmdArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,7 +877,7 @@ func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, c
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
name = emulator[0]
|
name = emulator[0]
|
||||||
emuArgs := append([]string(nil), emulator[1:]...)
|
emuArgs = append(emuArgs, emulator[1:]...)
|
||||||
args = append(emuArgs, args...)
|
args = append(emuArgs, args...)
|
||||||
}
|
}
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
@@ -1212,15 +1212,10 @@ func getBMPPorts() (gdbPort, uartPort string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func usage(command string) {
|
func usage(command string) {
|
||||||
version := goenv.Version
|
|
||||||
if strings.HasSuffix(version, "-dev") && goenv.GitSha1 != "" {
|
|
||||||
version += "-" + goenv.GitSha1
|
|
||||||
}
|
|
||||||
|
|
||||||
switch command {
|
switch command {
|
||||||
default:
|
default:
|
||||||
fmt.Fprintln(os.Stderr, "TinyGo is a Go compiler for small places.")
|
fmt.Fprintln(os.Stderr, "TinyGo is a Go compiler for small places.")
|
||||||
fmt.Fprintln(os.Stderr, "version:", version)
|
fmt.Fprintln(os.Stderr, "version:", goenv.Version())
|
||||||
fmt.Fprintf(os.Stderr, "usage: %s <command> [arguments]\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "usage: %s <command> [arguments]\n", os.Args[0])
|
||||||
fmt.Fprintln(os.Stderr, "\ncommands:")
|
fmt.Fprintln(os.Stderr, "\ncommands:")
|
||||||
fmt.Fprintln(os.Stderr, " build: compile packages and dependencies")
|
fmt.Fprintln(os.Stderr, " build: compile packages and dependencies")
|
||||||
@@ -1230,6 +1225,7 @@ func usage(command string) {
|
|||||||
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
|
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
|
||||||
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
|
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
|
||||||
fmt.Fprintln(os.Stderr, " monitor: open communication port")
|
fmt.Fprintln(os.Stderr, " monitor: open communication port")
|
||||||
|
fmt.Fprintln(os.Stderr, " ports: list available serial ports")
|
||||||
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
|
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
|
||||||
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
|
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
|
||||||
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
||||||
@@ -1737,35 +1733,33 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
case "monitor":
|
case "monitor":
|
||||||
err := Monitor("", *port, options)
|
config, err := builder.NewConfig(options)
|
||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
|
err = Monitor("", *port, config)
|
||||||
|
handleCompilerError(err)
|
||||||
|
case "ports":
|
||||||
|
serialPortInfo, err := ListSerialPorts()
|
||||||
|
handleCompilerError(err)
|
||||||
|
if len(serialPortInfo) == 0 {
|
||||||
|
fmt.Println("No serial ports found.")
|
||||||
|
}
|
||||||
|
fmt.Printf("%-20s %-9s %s\n", "Port", "ID", "Boards")
|
||||||
|
for _, s := range serialPortInfo {
|
||||||
|
fmt.Printf("%-20s %4s:%4s %s\n", s.Name, s.VID, s.PID, s.Target)
|
||||||
|
}
|
||||||
case "targets":
|
case "targets":
|
||||||
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
specs, err := compileopts.GetTargetSpecs()
|
||||||
entries, err := ioutil.ReadDir(dir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "could not list targets:", err)
|
fmt.Fprintln(os.Stderr, "could not list targets:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, entry := range entries {
|
names := []string{}
|
||||||
if !entry.Mode().IsRegular() || !strings.HasSuffix(entry.Name(), ".json") {
|
for key := range specs {
|
||||||
// Only inspect JSON files.
|
names = append(names, key)
|
||||||
continue
|
}
|
||||||
}
|
sort.Strings(names)
|
||||||
path := filepath.Join(dir, entry.Name())
|
for _, name := range names {
|
||||||
spec, err := compileopts.LoadTarget(&compileopts.Options{Target: path})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, "could not list target:", err)
|
|
||||||
os.Exit(1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
|
|
||||||
// This doesn't look like a regular target file, but rather like
|
|
||||||
// a parent target (such as targets/cortex-m.json).
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := entry.Name()
|
|
||||||
name = name[:len(name)-5]
|
|
||||||
fmt.Println(name)
|
fmt.Println(name)
|
||||||
}
|
}
|
||||||
case "info":
|
case "info":
|
||||||
@@ -1874,11 +1868,7 @@ func main() {
|
|||||||
if s, err := goenv.GorootVersionString(); err == nil {
|
if s, err := goenv.GorootVersionString(); err == nil {
|
||||||
goversion = s
|
goversion = s
|
||||||
}
|
}
|
||||||
version := goenv.Version
|
fmt.Printf("tinygo version %s %s/%s (using go version %s and LLVM version %s)\n", goenv.Version(), runtime.GOOS, runtime.GOARCH, goversion, llvm.Version)
|
||||||
if strings.HasSuffix(goenv.Version, "-dev") && goenv.GitSha1 != "" {
|
|
||||||
version += "-" + goenv.GitSha1
|
|
||||||
}
|
|
||||||
fmt.Printf("tinygo version %s %s/%s (using go version %s and LLVM version %s)\n", version, runtime.GOOS, runtime.GOARCH, goversion, llvm.Version)
|
|
||||||
case "env":
|
case "env":
|
||||||
if flag.NArg() == 0 {
|
if flag.NArg() == 0 {
|
||||||
// Show all environment variables.
|
// Show all environment variables.
|
||||||
|
|||||||
+8
-1
@@ -69,6 +69,7 @@ func TestBuild(t *testing.T) {
|
|||||||
"json.go",
|
"json.go",
|
||||||
"map.go",
|
"map.go",
|
||||||
"math.go",
|
"math.go",
|
||||||
|
"oldgo/",
|
||||||
"print.go",
|
"print.go",
|
||||||
"reflect.go",
|
"reflect.go",
|
||||||
"slice.go",
|
"slice.go",
|
||||||
@@ -90,6 +91,9 @@ func TestBuild(t *testing.T) {
|
|||||||
if minor >= 21 {
|
if minor >= 21 {
|
||||||
tests = append(tests, "go1.21.go")
|
tests = append(tests, "go1.21.go")
|
||||||
}
|
}
|
||||||
|
if minor >= 22 {
|
||||||
|
tests = append(tests, "go1.22/")
|
||||||
|
}
|
||||||
|
|
||||||
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),
|
||||||
@@ -333,8 +337,11 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
|||||||
path := TESTDATA + "/" + name
|
path := TESTDATA + "/" + name
|
||||||
// Get the expected output for this test.
|
// Get the expected output for this test.
|
||||||
txtpath := path[:len(path)-3] + ".txt"
|
txtpath := path[:len(path)-3] + ".txt"
|
||||||
|
pkgName := "./" + path
|
||||||
if path[len(path)-1] == '/' {
|
if path[len(path)-1] == '/' {
|
||||||
txtpath = path + "out.txt"
|
txtpath = path + "out.txt"
|
||||||
|
options.Directory = path
|
||||||
|
pkgName = "."
|
||||||
}
|
}
|
||||||
expected, err := os.ReadFile(txtpath)
|
expected, err := os.ReadFile(txtpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -348,7 +355,7 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
|||||||
|
|
||||||
// Build the test binary.
|
// Build the test binary.
|
||||||
stdout := &bytes.Buffer{}
|
stdout := &bytes.Buffer{}
|
||||||
_, err = buildAndRun("./"+path, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
_, err = buildAndRun(pkgName, config, stdout, cmdArgs, environmentVars, time.Minute, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+199
-32
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"debug/dwarf"
|
"debug/dwarf"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"debug/macho"
|
"debug/macho"
|
||||||
@@ -9,57 +10,167 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mattn/go-tty"
|
"github.com/mattn/go-tty"
|
||||||
"github.com/tinygo-org/tinygo/builder"
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
|
|
||||||
"go.bug.st/serial"
|
"go.bug.st/serial"
|
||||||
|
"go.bug.st/serial/enumerator"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Monitor connects to the given port and reads/writes the serial port.
|
// Monitor connects to the given port and reads/writes the serial port.
|
||||||
func Monitor(executable, port string, options *compileopts.Options) error {
|
func Monitor(executable, port string, config *compileopts.Config) error {
|
||||||
config, err := builder.NewConfig(options)
|
const timeout = time.Second * 3
|
||||||
if err != nil {
|
var exit func() // function to be called before exiting
|
||||||
return err
|
var serialConn io.ReadWriter
|
||||||
}
|
|
||||||
|
|
||||||
wait := 300
|
if config.Options.Serial == "rtt" {
|
||||||
for i := 0; i <= wait; i++ {
|
// Use the RTT interface, which is documented (in part) here:
|
||||||
port, err = getDefaultPort(port, config.Target.SerialPort)
|
// https://wiki.segger.com/RTT
|
||||||
|
|
||||||
|
// Try to find the "machine.rttSerialInstance" symbol, which is the RTT
|
||||||
|
// control block.
|
||||||
|
file, err := elf.Open(executable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if i < wait {
|
return fmt.Errorf("could not open ELF file to determine RTT control block: %w", err)
|
||||||
time.Sleep(10 * time.Millisecond)
|
}
|
||||||
continue
|
defer file.Close()
|
||||||
|
symbols, err := file.Symbols()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not read ELF symbol table to determine RTT control block: %w", err)
|
||||||
|
}
|
||||||
|
var address uint64
|
||||||
|
for _, symbol := range symbols {
|
||||||
|
if symbol.Name == "machine.rttSerialInstance" {
|
||||||
|
address = symbol.Value
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if address == 0 {
|
||||||
|
return fmt.Errorf("could not find RTT control block in ELF file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start an openocd process in the background.
|
||||||
|
args, err := config.OpenOCDConfiguration()
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
break
|
args = append(args,
|
||||||
}
|
"-c", fmt.Sprintf("rtt setup 0x%x 16 \"SEGGER RTT\"", address),
|
||||||
|
"-c", "init",
|
||||||
br := options.BaudRate
|
"-c", "rtt server start 0 0")
|
||||||
if br <= 0 {
|
cmd := executeCommand(config.Options, "openocd", args...)
|
||||||
br = 115200
|
stderr, err := cmd.StderrPipe()
|
||||||
}
|
|
||||||
|
|
||||||
wait = 300
|
|
||||||
var p serial.Port
|
|
||||||
for i := 0; i <= wait; i++ {
|
|
||||||
p, err = serial.Open(port, &serial.Mode{BaudRate: br})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if i < wait {
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
break
|
cmd.Stdout = os.Stdout
|
||||||
|
err = cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer cmd.Process.Kill()
|
||||||
|
exit = func() {
|
||||||
|
// Make sure the openocd process is terminated at exit.
|
||||||
|
// This does not happen through the defer above when exiting through
|
||||||
|
// os.Exit.
|
||||||
|
cmd.Process.Kill()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the stderr, which logs various important messages we need.
|
||||||
|
r := bufio.NewReader(stderr)
|
||||||
|
var telnet net.Conn
|
||||||
|
var timeoutAt time.Time
|
||||||
|
for {
|
||||||
|
// Read the next line from the openocd process.
|
||||||
|
lineBytes, err := r.ReadBytes('\n')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
line := string(lineBytes)
|
||||||
|
|
||||||
|
if line == "Info : rtt: No control block found\n" {
|
||||||
|
// Message that is sent back when OpenOCD can't find the control
|
||||||
|
// block after a 'rtt start' message.
|
||||||
|
if time.Now().After(timeoutAt) {
|
||||||
|
return fmt.Errorf("RTT timeout (could not locate RTT control block at 0x%08x)", address)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Millisecond * 100)
|
||||||
|
telnet.Write([]byte("rtt start\r\n"))
|
||||||
|
} else if strings.HasPrefix(line, "Info : Listening on port") {
|
||||||
|
// We need two different ports for controlling OpenOCD
|
||||||
|
// (typically port 4444) and the RTT channel 0 socket (arbitrary
|
||||||
|
// port).
|
||||||
|
var port int
|
||||||
|
var protocol string
|
||||||
|
fmt.Sscanf(line, "Info : Listening on port %d for %s connections\n", &port, &protocol)
|
||||||
|
if protocol == "telnet" && telnet == nil {
|
||||||
|
// Connect to the "telnet" command line interface.
|
||||||
|
telnet, err = net.Dial("tcp4", fmt.Sprintf("localhost:%d", port))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Tell OpenOCD to start scanning for the RTT control block.
|
||||||
|
telnet.Write([]byte("rtt start\r\n"))
|
||||||
|
// Also make sure we will time out if the control block just
|
||||||
|
// can't be found.
|
||||||
|
timeoutAt = time.Now().Add(timeout)
|
||||||
|
} else if protocol == "rtt" {
|
||||||
|
// Connect to the RTT channel, for both stdin and stdout.
|
||||||
|
conn, err := net.Dial("tcp4", fmt.Sprintf("localhost:%d", port))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
serialConn = conn
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(line, "Info : rtt: Control block found at") {
|
||||||
|
// Connection established!
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // -serial=uart or -serial=usb
|
||||||
|
var err error
|
||||||
|
wait := 300
|
||||||
|
for i := 0; i <= wait; i++ {
|
||||||
|
port, err = getDefaultPort(port, config.Target.SerialPort)
|
||||||
|
if err != nil {
|
||||||
|
if i < wait {
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
br := config.Options.BaudRate
|
||||||
|
if br <= 0 {
|
||||||
|
br = 115200
|
||||||
|
}
|
||||||
|
|
||||||
|
wait = 300
|
||||||
|
var p serial.Port
|
||||||
|
for i := 0; i <= wait; i++ {
|
||||||
|
p, err = serial.Open(port, &serial.Mode{BaudRate: br})
|
||||||
|
if err != nil {
|
||||||
|
if i < wait {
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
serialConn = p
|
||||||
|
break
|
||||||
|
}
|
||||||
|
defer p.Close()
|
||||||
}
|
}
|
||||||
defer p.Close()
|
|
||||||
|
|
||||||
tty, err := tty.Open()
|
tty, err := tty.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -74,6 +185,9 @@ func Monitor(executable, port string, options *compileopts.Options) error {
|
|||||||
go func() {
|
go func() {
|
||||||
<-sig
|
<-sig
|
||||||
tty.Close()
|
tty.Close()
|
||||||
|
if exit != nil {
|
||||||
|
exit()
|
||||||
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -85,7 +199,7 @@ func Monitor(executable, port string, options *compileopts.Options) error {
|
|||||||
buf := make([]byte, 100*1024)
|
buf := make([]byte, 100*1024)
|
||||||
var line []byte
|
var line []byte
|
||||||
for {
|
for {
|
||||||
n, err := p.Read(buf)
|
n, err := serialConn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errCh <- fmt.Errorf("read error: %w", err)
|
errCh <- fmt.Errorf("read error: %w", err)
|
||||||
return
|
return
|
||||||
@@ -121,13 +235,66 @@ func Monitor(executable, port string, options *compileopts.Options) error {
|
|||||||
if r == 0 {
|
if r == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p.Write([]byte(string(r)))
|
serialConn.Write([]byte(string(r)))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return <-errCh
|
return <-errCh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SerialPortInfo is a structure that holds information about the port and its
|
||||||
|
// associated TargetSpec.
|
||||||
|
type SerialPortInfo struct {
|
||||||
|
Name string
|
||||||
|
IsUSB bool
|
||||||
|
VID string
|
||||||
|
PID string
|
||||||
|
Target string
|
||||||
|
Spec *compileopts.TargetSpec
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListSerialPort returns serial port information and any detected TinyGo
|
||||||
|
// target.
|
||||||
|
func ListSerialPorts() ([]SerialPortInfo, error) {
|
||||||
|
maps, err := compileopts.GetTargetSpecs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
portsList, err := enumerator.GetDetailedPortsList()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
serialPortInfo := []SerialPortInfo{}
|
||||||
|
for _, p := range portsList {
|
||||||
|
info := SerialPortInfo{
|
||||||
|
Name: p.Name,
|
||||||
|
IsUSB: p.IsUSB,
|
||||||
|
VID: p.VID,
|
||||||
|
PID: p.PID,
|
||||||
|
}
|
||||||
|
vid := strings.ToLower(p.VID)
|
||||||
|
pid := strings.ToLower(p.PID)
|
||||||
|
for k, v := range maps {
|
||||||
|
usbInterfaces := v.SerialPort
|
||||||
|
for _, s := range usbInterfaces {
|
||||||
|
parts := strings.Split(s, ":")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if vid == strings.ToLower(parts[0]) && pid == strings.ToLower(parts[1]) {
|
||||||
|
info.Target = k
|
||||||
|
info.Spec = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serialPortInfo = append(serialPortInfo, info)
|
||||||
|
}
|
||||||
|
|
||||||
|
return serialPortInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
var addressMatch = regexp.MustCompile(`^panic: runtime error at 0x([0-9a-f]+): `)
|
var addressMatch = regexp.MustCompile(`^panic: runtime error at 0x([0-9a-f]+): `)
|
||||||
|
|
||||||
// Extract the address from the "panic: runtime error at" message.
|
// Extract the address from the "panic: runtime error at" message.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
//go:build nrf || stm32 || (sam && atsamd51) || (sam && atsame5x)
|
//go:build nrf || (stm32 && !(stm32f103 || stm32l0x1)) || (sam && atsamd51) || (sam && atsame5x) || esp32c3
|
||||||
|
|
||||||
|
// If you update the above build constraint, you'll probably also need to update
|
||||||
|
// src/runtime/rand_hwrng.go.
|
||||||
|
|
||||||
package rand
|
package rand
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,447 @@
|
|||||||
|
// TINYGO: The following is copied and modified from Go 1.19.3 official implementation.
|
||||||
|
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package tls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto"
|
||||||
|
"crypto/x509"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CurveID is the type of a TLS identifier for an elliptic curve. See
|
||||||
|
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8.
|
||||||
|
//
|
||||||
|
// In TLS 1.3, this type is called NamedGroup, but at this time this library
|
||||||
|
// only supports Elliptic Curve based groups. See RFC 8446, Section 4.2.7.
|
||||||
|
type CurveID uint16
|
||||||
|
|
||||||
|
// ConnectionState records basic TLS details about the connection.
|
||||||
|
type ConnectionState struct {
|
||||||
|
// TINYGO: empty; TLS connection offloaded to device
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientAuthType declares the policy the server will follow for
|
||||||
|
// TLS Client Authentication.
|
||||||
|
type ClientAuthType int
|
||||||
|
|
||||||
|
// ClientSessionCache is a cache of ClientSessionState objects that can be used
|
||||||
|
// by a client to resume a TLS session with a given server. ClientSessionCache
|
||||||
|
// implementations should expect to be called concurrently from different
|
||||||
|
// goroutines. Up to TLS 1.2, only ticket-based resumption is supported, not
|
||||||
|
// SessionID-based resumption. In TLS 1.3 they were merged into PSK modes, which
|
||||||
|
// are supported via this interface.
|
||||||
|
type ClientSessionCache interface {
|
||||||
|
// Get searches for a ClientSessionState associated with the given key.
|
||||||
|
// On return, ok is true if one was found.
|
||||||
|
Get(sessionKey string) (session *ClientSessionState, ok bool)
|
||||||
|
|
||||||
|
// Put adds the ClientSessionState to the cache with the given key. It might
|
||||||
|
// get called multiple times in a connection if a TLS 1.3 server provides
|
||||||
|
// more than one session ticket. If called with a nil *ClientSessionState,
|
||||||
|
// it should remove the cache entry.
|
||||||
|
Put(sessionKey string, cs *ClientSessionState)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate stringer -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go
|
||||||
|
|
||||||
|
// SignatureScheme identifies a signature algorithm supported by TLS. See
|
||||||
|
// RFC 8446, Section 4.2.3.
|
||||||
|
type SignatureScheme uint16
|
||||||
|
|
||||||
|
// ClientHelloInfo contains information from a ClientHello message in order to
|
||||||
|
// guide application logic in the GetCertificate and GetConfigForClient callbacks.
|
||||||
|
type ClientHelloInfo struct {
|
||||||
|
// CipherSuites lists the CipherSuites supported by the client (e.g.
|
||||||
|
// TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256).
|
||||||
|
CipherSuites []uint16
|
||||||
|
|
||||||
|
// ServerName indicates the name of the server requested by the client
|
||||||
|
// in order to support virtual hosting. ServerName is only set if the
|
||||||
|
// client is using SNI (see RFC 4366, Section 3.1).
|
||||||
|
ServerName string
|
||||||
|
|
||||||
|
// SupportedCurves lists the elliptic curves supported by the client.
|
||||||
|
// SupportedCurves is set only if the Supported Elliptic Curves
|
||||||
|
// Extension is being used (see RFC 4492, Section 5.1.1).
|
||||||
|
SupportedCurves []CurveID
|
||||||
|
|
||||||
|
// SupportedPoints lists the point formats supported by the client.
|
||||||
|
// SupportedPoints is set only if the Supported Point Formats Extension
|
||||||
|
// is being used (see RFC 4492, Section 5.1.2).
|
||||||
|
SupportedPoints []uint8
|
||||||
|
|
||||||
|
// SignatureSchemes lists the signature and hash schemes that the client
|
||||||
|
// is willing to verify. SignatureSchemes is set only if the Signature
|
||||||
|
// Algorithms Extension is being used (see RFC 5246, Section 7.4.1.4.1).
|
||||||
|
SignatureSchemes []SignatureScheme
|
||||||
|
|
||||||
|
// SupportedProtos lists the application protocols supported by the client.
|
||||||
|
// SupportedProtos is set only if the Application-Layer Protocol
|
||||||
|
// Negotiation Extension is being used (see RFC 7301, Section 3.1).
|
||||||
|
//
|
||||||
|
// Servers can select a protocol by setting Config.NextProtos in a
|
||||||
|
// GetConfigForClient return value.
|
||||||
|
SupportedProtos []string
|
||||||
|
|
||||||
|
// SupportedVersions lists the TLS versions supported by the client.
|
||||||
|
// For TLS versions less than 1.3, this is extrapolated from the max
|
||||||
|
// version advertised by the client, so values other than the greatest
|
||||||
|
// might be rejected if used.
|
||||||
|
SupportedVersions []uint16
|
||||||
|
|
||||||
|
// Conn is the underlying net.Conn for the connection. Do not read
|
||||||
|
// from, or write to, this connection; that will cause the TLS
|
||||||
|
// connection to fail.
|
||||||
|
Conn net.Conn
|
||||||
|
|
||||||
|
// config is embedded by the GetCertificate or GetConfigForClient caller,
|
||||||
|
// for use with SupportsCertificate.
|
||||||
|
config *Config
|
||||||
|
|
||||||
|
// ctx is the context of the handshake that is in progress.
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// CertificateRequestInfo contains information from a server's
|
||||||
|
// CertificateRequest message, which is used to demand a certificate and proof
|
||||||
|
// of control from a client.
|
||||||
|
type CertificateRequestInfo struct {
|
||||||
|
// AcceptableCAs contains zero or more, DER-encoded, X.501
|
||||||
|
// Distinguished Names. These are the names of root or intermediate CAs
|
||||||
|
// that the server wishes the returned certificate to be signed by. An
|
||||||
|
// empty slice indicates that the server has no preference.
|
||||||
|
AcceptableCAs [][]byte
|
||||||
|
|
||||||
|
// SignatureSchemes lists the signature schemes that the server is
|
||||||
|
// willing to verify.
|
||||||
|
SignatureSchemes []SignatureScheme
|
||||||
|
|
||||||
|
// Version is the TLS version that was negotiated for this connection.
|
||||||
|
Version uint16
|
||||||
|
|
||||||
|
// ctx is the context of the handshake that is in progress.
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenegotiationSupport enumerates the different levels of support for TLS
|
||||||
|
// renegotiation. TLS renegotiation is the act of performing subsequent
|
||||||
|
// handshakes on a connection after the first. This significantly complicates
|
||||||
|
// the state machine and has been the source of numerous, subtle security
|
||||||
|
// issues. Initiating a renegotiation is not supported, but support for
|
||||||
|
// accepting renegotiation requests may be enabled.
|
||||||
|
//
|
||||||
|
// Even when enabled, the server may not change its identity between handshakes
|
||||||
|
// (i.e. the leaf certificate must be the same). Additionally, concurrent
|
||||||
|
// handshake and application data flow is not permitted so renegotiation can
|
||||||
|
// only be used with protocols that synchronise with the renegotiation, such as
|
||||||
|
// HTTPS.
|
||||||
|
//
|
||||||
|
// Renegotiation is not defined in TLS 1.3.
|
||||||
|
type RenegotiationSupport int
|
||||||
|
|
||||||
|
// A Config structure is used to configure a TLS client or server.
|
||||||
|
// After one has been passed to a TLS function it must not be
|
||||||
|
// modified. A Config may be reused; the tls package will also not
|
||||||
|
// modify it.
|
||||||
|
type Config struct {
|
||||||
|
// Rand provides the source of entropy for nonces and RSA blinding.
|
||||||
|
// If Rand is nil, TLS uses the cryptographic random reader in package
|
||||||
|
// crypto/rand.
|
||||||
|
// The Reader must be safe for use by multiple goroutines.
|
||||||
|
Rand io.Reader
|
||||||
|
|
||||||
|
// Time returns the current time as the number of seconds since the epoch.
|
||||||
|
// If Time is nil, TLS uses time.Now.
|
||||||
|
Time func() time.Time
|
||||||
|
|
||||||
|
// Certificates contains one or more certificate chains to present to the
|
||||||
|
// other side of the connection. The first certificate compatible with the
|
||||||
|
// peer's requirements is selected automatically.
|
||||||
|
//
|
||||||
|
// Server configurations must set one of Certificates, GetCertificate or
|
||||||
|
// GetConfigForClient. Clients doing client-authentication may set either
|
||||||
|
// Certificates or GetClientCertificate.
|
||||||
|
//
|
||||||
|
// Note: if there are multiple Certificates, and they don't have the
|
||||||
|
// optional field Leaf set, certificate selection will incur a significant
|
||||||
|
// per-handshake performance cost.
|
||||||
|
Certificates []Certificate
|
||||||
|
|
||||||
|
// NameToCertificate maps from a certificate name to an element of
|
||||||
|
// Certificates. Note that a certificate name can be of the form
|
||||||
|
// '*.example.com' and so doesn't have to be a domain name as such.
|
||||||
|
//
|
||||||
|
// Deprecated: NameToCertificate only allows associating a single
|
||||||
|
// certificate with a given name. Leave this field nil to let the library
|
||||||
|
// select the first compatible chain from Certificates.
|
||||||
|
NameToCertificate map[string]*Certificate
|
||||||
|
|
||||||
|
// GetCertificate returns a Certificate based on the given
|
||||||
|
// ClientHelloInfo. It will only be called if the client supplies SNI
|
||||||
|
// information or if Certificates is empty.
|
||||||
|
//
|
||||||
|
// If GetCertificate is nil or returns nil, then the certificate is
|
||||||
|
// retrieved from NameToCertificate. If NameToCertificate is nil, the
|
||||||
|
// best element of Certificates will be used.
|
||||||
|
//
|
||||||
|
// Once a Certificate is returned it should not be modified.
|
||||||
|
GetCertificate func(*ClientHelloInfo) (*Certificate, error)
|
||||||
|
|
||||||
|
// GetClientCertificate, if not nil, is called when a server requests a
|
||||||
|
// certificate from a client. If set, the contents of Certificates will
|
||||||
|
// be ignored.
|
||||||
|
//
|
||||||
|
// If GetClientCertificate returns an error, the handshake will be
|
||||||
|
// aborted and that error will be returned. Otherwise
|
||||||
|
// GetClientCertificate must return a non-nil Certificate. If
|
||||||
|
// Certificate.Certificate is empty then no certificate will be sent to
|
||||||
|
// the server. If this is unacceptable to the server then it may abort
|
||||||
|
// the handshake.
|
||||||
|
//
|
||||||
|
// GetClientCertificate may be called multiple times for the same
|
||||||
|
// connection if renegotiation occurs or if TLS 1.3 is in use.
|
||||||
|
//
|
||||||
|
// Once a Certificate is returned it should not be modified.
|
||||||
|
GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error)
|
||||||
|
|
||||||
|
// GetConfigForClient, if not nil, is called after a ClientHello is
|
||||||
|
// received from a client. It may return a non-nil Config in order to
|
||||||
|
// change the Config that will be used to handle this connection. If
|
||||||
|
// the returned Config is nil, the original Config will be used. The
|
||||||
|
// Config returned by this callback may not be subsequently modified.
|
||||||
|
//
|
||||||
|
// If GetConfigForClient is nil, the Config passed to Server() will be
|
||||||
|
// used for all connections.
|
||||||
|
//
|
||||||
|
// If SessionTicketKey was explicitly set on the returned Config, or if
|
||||||
|
// SetSessionTicketKeys was called on the returned Config, those keys will
|
||||||
|
// be used. Otherwise, the original Config keys will be used (and possibly
|
||||||
|
// rotated if they are automatically managed).
|
||||||
|
GetConfigForClient func(*ClientHelloInfo) (*Config, error)
|
||||||
|
|
||||||
|
// VerifyPeerCertificate, if not nil, is called after normal
|
||||||
|
// certificate verification by either a TLS client or server. It
|
||||||
|
// receives the raw ASN.1 certificates provided by the peer and also
|
||||||
|
// any verified chains that normal processing found. If it returns a
|
||||||
|
// non-nil error, the handshake is aborted and that error results.
|
||||||
|
//
|
||||||
|
// If normal verification fails then the handshake will abort before
|
||||||
|
// considering this callback. If normal verification is disabled (on the
|
||||||
|
// client when InsecureSkipVerify is set, or on a server when ClientAuth is
|
||||||
|
// RequestClientCert or RequireAnyClientCert), then this callback will be
|
||||||
|
// considered but the verifiedChains argument will always be nil. When
|
||||||
|
// ClientAuth is NoClientCert, this callback is not called on the server.
|
||||||
|
// rawCerts may be empty on the server if ClientAuth is RequestClientCert or
|
||||||
|
// VerifyClientCertIfGiven.
|
||||||
|
//
|
||||||
|
// This callback is not invoked on resumed connections, as certificates are
|
||||||
|
// not re-verified on resumption.
|
||||||
|
//
|
||||||
|
// verifiedChains and its contents should not be modified.
|
||||||
|
VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
|
||||||
|
|
||||||
|
// VerifyConnection, if not nil, is called after normal certificate
|
||||||
|
// verification and after VerifyPeerCertificate by either a TLS client
|
||||||
|
// or server. If it returns a non-nil error, the handshake is aborted
|
||||||
|
// and that error results.
|
||||||
|
//
|
||||||
|
// If normal verification fails then the handshake will abort before
|
||||||
|
// considering this callback. This callback will run for all connections,
|
||||||
|
// including resumptions, regardless of InsecureSkipVerify or ClientAuth
|
||||||
|
// settings.
|
||||||
|
VerifyConnection func(ConnectionState) error
|
||||||
|
|
||||||
|
// RootCAs defines the set of root certificate authorities
|
||||||
|
// that clients use when verifying server certificates.
|
||||||
|
// If RootCAs is nil, TLS uses the host's root CA set.
|
||||||
|
RootCAs *x509.CertPool
|
||||||
|
|
||||||
|
// NextProtos is a list of supported application level protocols, in
|
||||||
|
// order of preference. If both peers support ALPN, the selected
|
||||||
|
// protocol will be one from this list, and the connection will fail
|
||||||
|
// if there is no mutually supported protocol. If NextProtos is empty
|
||||||
|
// or the peer doesn't support ALPN, the connection will succeed and
|
||||||
|
// ConnectionState.NegotiatedProtocol will be empty.
|
||||||
|
NextProtos []string
|
||||||
|
|
||||||
|
// ServerName is used to verify the hostname on the returned
|
||||||
|
// certificates unless InsecureSkipVerify is given. It is also included
|
||||||
|
// in the client's handshake to support virtual hosting unless it is
|
||||||
|
// an IP address.
|
||||||
|
ServerName string
|
||||||
|
|
||||||
|
// ClientAuth determines the server's policy for
|
||||||
|
// TLS Client Authentication. The default is NoClientCert.
|
||||||
|
ClientAuth ClientAuthType
|
||||||
|
|
||||||
|
// ClientCAs defines the set of root certificate authorities
|
||||||
|
// that servers use if required to verify a client certificate
|
||||||
|
// by the policy in ClientAuth.
|
||||||
|
ClientCAs *x509.CertPool
|
||||||
|
|
||||||
|
// InsecureSkipVerify controls whether a client verifies the server's
|
||||||
|
// certificate chain and host name. If InsecureSkipVerify is true, crypto/tls
|
||||||
|
// accepts any certificate presented by the server and any host name in that
|
||||||
|
// certificate. In this mode, TLS is susceptible to machine-in-the-middle
|
||||||
|
// attacks unless custom verification is used. This should be used only for
|
||||||
|
// testing or in combination with VerifyConnection or VerifyPeerCertificate.
|
||||||
|
InsecureSkipVerify bool
|
||||||
|
|
||||||
|
// CipherSuites is a list of enabled TLS 1.0–1.2 cipher suites. The order of
|
||||||
|
// the list is ignored. Note that TLS 1.3 ciphersuites are not configurable.
|
||||||
|
//
|
||||||
|
// If CipherSuites is nil, a safe default list is used. The default cipher
|
||||||
|
// suites might change over time.
|
||||||
|
CipherSuites []uint16
|
||||||
|
|
||||||
|
// PreferServerCipherSuites is a legacy field and has no effect.
|
||||||
|
//
|
||||||
|
// It used to control whether the server would follow the client's or the
|
||||||
|
// server's preference. Servers now select the best mutually supported
|
||||||
|
// cipher suite based on logic that takes into account inferred client
|
||||||
|
// hardware, server hardware, and security.
|
||||||
|
//
|
||||||
|
// Deprecated: PreferServerCipherSuites is ignored.
|
||||||
|
PreferServerCipherSuites bool
|
||||||
|
|
||||||
|
// SessionTicketsDisabled may be set to true to disable session ticket and
|
||||||
|
// PSK (resumption) support. Note that on clients, session ticket support is
|
||||||
|
// also disabled if ClientSessionCache is nil.
|
||||||
|
SessionTicketsDisabled bool
|
||||||
|
|
||||||
|
// SessionTicketKey is used by TLS servers to provide session resumption.
|
||||||
|
// See RFC 5077 and the PSK mode of RFC 8446. If zero, it will be filled
|
||||||
|
// with random data before the first server handshake.
|
||||||
|
//
|
||||||
|
// Deprecated: if this field is left at zero, session ticket keys will be
|
||||||
|
// automatically rotated every day and dropped after seven days. For
|
||||||
|
// customizing the rotation schedule or synchronizing servers that are
|
||||||
|
// terminating connections for the same host, use SetSessionTicketKeys.
|
||||||
|
SessionTicketKey [32]byte
|
||||||
|
|
||||||
|
// ClientSessionCache is a cache of ClientSessionState entries for TLS
|
||||||
|
// session resumption. It is only used by clients.
|
||||||
|
ClientSessionCache ClientSessionCache
|
||||||
|
|
||||||
|
// UnwrapSession is called on the server to turn a ticket/identity
|
||||||
|
// previously produced by [WrapSession] into a usable session.
|
||||||
|
//
|
||||||
|
// UnwrapSession will usually either decrypt a session state in the ticket
|
||||||
|
// (for example with [Config.EncryptTicket]), or use the ticket as a handle
|
||||||
|
// to recover a previously stored state. It must use [ParseSessionState] to
|
||||||
|
// deserialize the session state.
|
||||||
|
//
|
||||||
|
// If UnwrapSession returns an error, the connection is terminated. If it
|
||||||
|
// returns (nil, nil), the session is ignored. crypto/tls may still choose
|
||||||
|
// not to resume the returned session.
|
||||||
|
UnwrapSession func(identity []byte, cs ConnectionState) (*SessionState, error)
|
||||||
|
|
||||||
|
// WrapSession is called on the server to produce a session ticket/identity.
|
||||||
|
//
|
||||||
|
// WrapSession must serialize the session state with [SessionState.Bytes].
|
||||||
|
// It may then encrypt the serialized state (for example with
|
||||||
|
// [Config.DecryptTicket]) and use it as the ticket, or store the state and
|
||||||
|
// return a handle for it.
|
||||||
|
//
|
||||||
|
// If WrapSession returns an error, the connection is terminated.
|
||||||
|
//
|
||||||
|
// Warning: the return value will be exposed on the wire and to clients in
|
||||||
|
// plaintext. The application is in charge of encrypting and authenticating
|
||||||
|
// it (and rotating keys) or returning high-entropy identifiers. Failing to
|
||||||
|
// do so correctly can compromise current, previous, and future connections
|
||||||
|
// depending on the protocol version.
|
||||||
|
WrapSession func(ConnectionState, *SessionState) ([]byte, error)
|
||||||
|
|
||||||
|
// MinVersion contains the minimum TLS version that is acceptable.
|
||||||
|
//
|
||||||
|
// By default, TLS 1.2 is currently used as the minimum when acting as a
|
||||||
|
// client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum
|
||||||
|
// supported by this package, both as a client and as a server.
|
||||||
|
//
|
||||||
|
// The client-side default can temporarily be reverted to TLS 1.0 by
|
||||||
|
// including the value "x509sha1=1" in the GODEBUG environment variable.
|
||||||
|
// Note that this option will be removed in Go 1.19 (but it will still be
|
||||||
|
// possible to set this field to VersionTLS10 explicitly).
|
||||||
|
MinVersion uint16
|
||||||
|
|
||||||
|
// MaxVersion contains the maximum TLS version that is acceptable.
|
||||||
|
//
|
||||||
|
// By default, the maximum version supported by this package is used,
|
||||||
|
// which is currently TLS 1.3.
|
||||||
|
MaxVersion uint16
|
||||||
|
|
||||||
|
// CurvePreferences contains the elliptic curves that will be used in
|
||||||
|
// an ECDHE handshake, in preference order. If empty, the default will
|
||||||
|
// be used. The client will use the first preference as the type for
|
||||||
|
// its key share in TLS 1.3. This may change in the future.
|
||||||
|
CurvePreferences []CurveID
|
||||||
|
|
||||||
|
// DynamicRecordSizingDisabled disables adaptive sizing of TLS records.
|
||||||
|
// When true, the largest possible TLS record size is always used. When
|
||||||
|
// false, the size of TLS records may be adjusted in an attempt to
|
||||||
|
// improve latency.
|
||||||
|
DynamicRecordSizingDisabled bool
|
||||||
|
|
||||||
|
// Renegotiation controls what types of renegotiation are supported.
|
||||||
|
// The default, none, is correct for the vast majority of applications.
|
||||||
|
Renegotiation RenegotiationSupport
|
||||||
|
|
||||||
|
// KeyLogWriter optionally specifies a destination for TLS master secrets
|
||||||
|
// in NSS key log format that can be used to allow external programs
|
||||||
|
// such as Wireshark to decrypt TLS connections.
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
|
||||||
|
// Use of KeyLogWriter compromises security and should only be
|
||||||
|
// used for debugging.
|
||||||
|
KeyLogWriter io.Writer
|
||||||
|
|
||||||
|
// mutex protects sessionTicketKeys and autoSessionTicketKeys.
|
||||||
|
mutex sync.RWMutex
|
||||||
|
// sessionTicketKeys contains zero or more ticket keys. If set, it means
|
||||||
|
// the keys were set with SessionTicketKey or SetSessionTicketKeys. The
|
||||||
|
// first key is used for new tickets and any subsequent keys can be used to
|
||||||
|
// decrypt old tickets. The slice contents are not protected by the mutex
|
||||||
|
// and are immutable.
|
||||||
|
sessionTicketKeys []ticketKey
|
||||||
|
// autoSessionTicketKeys is like sessionTicketKeys but is owned by the
|
||||||
|
// auto-rotation logic. See Config.ticketKeys.
|
||||||
|
autoSessionTicketKeys []ticketKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// ticketKey is the internal representation of a session ticket key.
|
||||||
|
type ticketKey struct {
|
||||||
|
aesKey [16]byte
|
||||||
|
hmacKey [16]byte
|
||||||
|
// created is the time at which this ticket key was created. See Config.ticketKeys.
|
||||||
|
created time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Certificate is a chain of one or more certificates, leaf first.
|
||||||
|
type Certificate struct {
|
||||||
|
Certificate [][]byte
|
||||||
|
// PrivateKey contains the private key corresponding to the public key in
|
||||||
|
// Leaf. This must implement crypto.Signer with an RSA, ECDSA or Ed25519 PublicKey.
|
||||||
|
// For a server up to TLS 1.2, it can also implement crypto.Decrypter with
|
||||||
|
// an RSA PublicKey.
|
||||||
|
PrivateKey crypto.PrivateKey
|
||||||
|
// SupportedSignatureAlgorithms is an optional list restricting what
|
||||||
|
// signature algorithms the PrivateKey can be used for.
|
||||||
|
SupportedSignatureAlgorithms []SignatureScheme
|
||||||
|
// OCSPStaple contains an optional OCSP response which will be served
|
||||||
|
// to clients that request it.
|
||||||
|
OCSPStaple []byte
|
||||||
|
// SignedCertificateTimestamps contains an optional list of Signed
|
||||||
|
// Certificate Timestamps which will be served to clients that request it.
|
||||||
|
SignedCertificateTimestamps [][]byte
|
||||||
|
// Leaf is the parsed form of the leaf certificate, which may be initialized
|
||||||
|
// using x509.ParseCertificate to reduce per-handshake processing. If nil,
|
||||||
|
// the leaf certificate will be parsed as needed.
|
||||||
|
Leaf *x509.Certificate
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package tls
|
||||||
|
|
||||||
|
// A SessionState is a resumable session.
|
||||||
|
type SessionState struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientSessionState contains the state needed by a client to
|
||||||
|
// resume a previous TLS session.
|
||||||
|
type ClientSessionState struct {
|
||||||
|
ticket []byte
|
||||||
|
session *SessionState
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
// TINYGO: The following is copied and modified from Go 1.21.4 official implementation.
|
||||||
|
|
||||||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package tls partially implements TLS 1.2, as specified in RFC 5246,
|
||||||
|
// and TLS 1.3, as specified in RFC 8446.
|
||||||
|
package tls
|
||||||
|
|
||||||
|
// BUG(agl): The crypto/tls package only implements some countermeasures
|
||||||
|
// against Lucky13 attacks on CBC-mode encryption, and only on SHA1
|
||||||
|
// variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and
|
||||||
|
// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client returns a new TLS client side connection
|
||||||
|
// using conn as the underlying transport.
|
||||||
|
// The config cannot be nil: users must set either ServerName or
|
||||||
|
// InsecureSkipVerify in the config.
|
||||||
|
func Client(conn net.Conn, config *Config) *net.TLSConn {
|
||||||
|
panic("tls.Client() not implemented")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A listener implements a network listener (net.Listener) for TLS connections.
|
||||||
|
type listener struct {
|
||||||
|
net.Listener
|
||||||
|
config *Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewListener creates a Listener which accepts connections from an inner
|
||||||
|
// Listener and wraps each connection with Server.
|
||||||
|
// The configuration config must be non-nil and must include
|
||||||
|
// at least one certificate or else set GetCertificate.
|
||||||
|
func NewListener(inner net.Listener, config *Config) net.Listener {
|
||||||
|
l := new(listener)
|
||||||
|
l.Listener = inner
|
||||||
|
l.config = config
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialWithDialer connects to the given network address using dialer.Dial and
|
||||||
|
// then initiates a TLS handshake, returning the resulting TLS connection. Any
|
||||||
|
// timeout or deadline given in the dialer apply to connection and TLS
|
||||||
|
// handshake as a whole.
|
||||||
|
//
|
||||||
|
// DialWithDialer interprets a nil configuration as equivalent to the zero
|
||||||
|
// configuration; see the documentation of Config for the defaults.
|
||||||
|
//
|
||||||
|
// DialWithDialer uses context.Background internally; to specify the context,
|
||||||
|
// use Dialer.DialContext with NetDialer set to the desired dialer.
|
||||||
|
func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*net.TLSConn, error) {
|
||||||
|
switch network {
|
||||||
|
case "tcp", "tcp4":
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Network %s not supported", network)
|
||||||
|
}
|
||||||
|
|
||||||
|
return net.DialTLS(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial connects to the given network address using net.Dial
|
||||||
|
// and then initiates a TLS handshake, returning the resulting
|
||||||
|
// TLS connection.
|
||||||
|
// Dial interprets a nil configuration as equivalent to
|
||||||
|
// the zero configuration; see the documentation of Config
|
||||||
|
// for the defaults.
|
||||||
|
func Dial(network, addr string, config *Config) (*net.TLSConn, error) {
|
||||||
|
return DialWithDialer(new(net.Dialer), network, addr, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dialer dials TLS connections given a configuration and a Dialer for the
|
||||||
|
// underlying connection.
|
||||||
|
type Dialer struct {
|
||||||
|
// NetDialer is the optional dialer to use for the TLS connections'
|
||||||
|
// underlying TCP connections.
|
||||||
|
// A nil NetDialer is equivalent to the net.Dialer zero value.
|
||||||
|
NetDialer *net.Dialer
|
||||||
|
|
||||||
|
// Config is the TLS configuration to use for new connections.
|
||||||
|
// A nil configuration is equivalent to the zero
|
||||||
|
// configuration; see the documentation of Config for the
|
||||||
|
// defaults.
|
||||||
|
Config *Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContext connects to the given network address and initiates a TLS
|
||||||
|
// handshake, returning the resulting TLS connection.
|
||||||
|
//
|
||||||
|
// The provided Context must be non-nil. If the context expires before
|
||||||
|
// the connection is complete, an error is returned. Once successfully
|
||||||
|
// connected, any expiration of the context will not affect the
|
||||||
|
// connection.
|
||||||
|
//
|
||||||
|
// The returned Conn, if any, will always be of type *Conn.
|
||||||
|
func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
return nil, errors.New("tls:DialContext not implmented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadX509KeyPair reads and parses a public/private key pair from a pair
|
||||||
|
// of files. The files must contain PEM encoded data. The certificate file
|
||||||
|
// may contain intermediate certificates following the leaf certificate to
|
||||||
|
// form a certificate chain. On successful return, Certificate.Leaf will
|
||||||
|
// be nil because the parsed form of the certificate is not retained.
|
||||||
|
func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) {
|
||||||
|
return Certificate{}, errors.New("tls:LoadX509KeyPair not implemented")
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
|
// For efficiency, it's best to get the device ID once and cache it
|
||||||
|
// (e.g. on RP2040 XIP flash and interrupts disabled for period of
|
||||||
|
// retrieving the hardware ID from ROM chip)
|
||||||
|
id := machine.DeviceID()
|
||||||
|
|
||||||
|
for {
|
||||||
|
println("Device ID:", hex.EncodeToString(id))
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// this is intended to be used as wasm32-unknown-unknown module.
|
||||||
|
// to compile it, run:
|
||||||
|
// tinygo build -size short -o hello-unknown.wasm -target wasm-unknown -gc=leaking -no-debug ./src/examples/hello-wasm-unknown/
|
||||||
|
package main
|
||||||
|
|
||||||
|
var x int32
|
||||||
|
|
||||||
|
//go:wasmimport hosted echo_i32
|
||||||
|
func echo(x int32)
|
||||||
|
|
||||||
|
//go:export update
|
||||||
|
func update() {
|
||||||
|
x++
|
||||||
|
echo(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// to override the USB Manufacturer or Product names:
|
// to override the USB Manufacturer or Product names:
|
||||||
//
|
//
|
||||||
// tinygo flash -target circuitplay-express -ldflags="-X main.usbManufacturer='TinyGopher Labs' -X main.usbProduct='GopherKeyboard'" examples/hid-keyboard
|
// tinygo flash -target circuitplay-express -ldflags="-X main.usbManufacturer='TinyGopher Labs' -X main.usbProduct='GopherKeyboard' -X main.usbSerial='XXXXX'" examples/hid-keyboard
|
||||||
//
|
//
|
||||||
// you can also override the VID/PID. however, only set this if you know what you are doing,
|
// you can also override the VID/PID. however, only set this if you know what you are doing,
|
||||||
// since changing it can make it difficult to reflash some devices.
|
// since changing it can make it difficult to reflash some devices.
|
||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var usbVID, usbPID string
|
var usbVID, usbPID string
|
||||||
var usbManufacturer, usbProduct string
|
var usbManufacturer, usbProduct, usbSerial string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
button := machine.BUTTON
|
button := machine.BUTTON
|
||||||
@@ -49,4 +49,8 @@ func init() {
|
|||||||
if usbProduct != "" {
|
if usbProduct != "" {
|
||||||
usb.Product = usbProduct
|
usb.Product = usbProduct
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if usbSerial != "" {
|
||||||
|
usb.Serial = usbSerial
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ func main() {
|
|||||||
|
|
||||||
// Schedule and enable recurring interrupt.
|
// Schedule and enable recurring interrupt.
|
||||||
// The callback function is executed in the context of an interrupt handler,
|
// The callback function is executed in the context of an interrupt handler,
|
||||||
// so regular restructions for this sort of code apply: no blocking, no memory allocation, etc.
|
// so regular restrictions for this sort of code apply: no blocking, no memory allocation, etc.
|
||||||
|
// Please check the online documentation for the details about interrupts:
|
||||||
|
// https://tinygo.org/docs/concepts/compiler-internals/interrupts/
|
||||||
delay := time.Minute + 12*time.Second
|
delay := time.Minute + 12*time.Second
|
||||||
machine.RTC.SetInterrupt(uint32(delay.Seconds()), true, func() { println("Peekaboo!") })
|
machine.RTC.SetInterrupt(uint32(delay.Seconds()), true, func() { println("Peekaboo!") })
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
package bytealg
|
package bytealg
|
||||||
|
|
||||||
|
// Some code in this file has been copied from the Go source code, and has
|
||||||
|
// copyright of their original authors:
|
||||||
|
//
|
||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
//
|
||||||
|
// This is indicated specifically in the file.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Index can search any valid length of string.
|
// Index can search any valid length of string.
|
||||||
|
|
||||||
@@ -125,10 +134,6 @@ func IndexString(str, sub string) int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// The following code has been copied from the Go 1.15 release tree.
|
// The following code has been copied from the Go 1.15 release tree.
|
||||||
|
|
||||||
// PrimeRK is the prime base used in Rabin-Karp algorithm.
|
// PrimeRK is the prime base used in Rabin-Karp algorithm.
|
||||||
@@ -136,6 +141,8 @@ const PrimeRK = 16777619
|
|||||||
|
|
||||||
// HashStrBytes returns the hash and the appropriate multiplicative
|
// HashStrBytes returns the hash and the appropriate multiplicative
|
||||||
// factor for use in Rabin-Karp algorithm.
|
// factor for use in Rabin-Karp algorithm.
|
||||||
|
//
|
||||||
|
// This function was removed in Go 1.22.
|
||||||
func HashStrBytes(sep []byte) (uint32, uint32) {
|
func HashStrBytes(sep []byte) (uint32, uint32) {
|
||||||
hash := uint32(0)
|
hash := uint32(0)
|
||||||
for i := 0; i < len(sep); i++ {
|
for i := 0; i < len(sep); i++ {
|
||||||
@@ -153,7 +160,9 @@ func HashStrBytes(sep []byte) (uint32, uint32) {
|
|||||||
|
|
||||||
// HashStr returns the hash and the appropriate multiplicative
|
// HashStr returns the hash and the appropriate multiplicative
|
||||||
// factor for use in Rabin-Karp algorithm.
|
// factor for use in Rabin-Karp algorithm.
|
||||||
func HashStr(sep string) (uint32, uint32) {
|
//
|
||||||
|
// This function was removed in Go 1.22.
|
||||||
|
func HashStr[T string | []byte](sep T) (uint32, uint32) {
|
||||||
hash := uint32(0)
|
hash := uint32(0)
|
||||||
for i := 0; i < len(sep); i++ {
|
for i := 0; i < len(sep); i++ {
|
||||||
hash = hash*PrimeRK + uint32(sep[i])
|
hash = hash*PrimeRK + uint32(sep[i])
|
||||||
@@ -170,6 +179,8 @@ func HashStr(sep string) (uint32, uint32) {
|
|||||||
|
|
||||||
// HashStrRevBytes returns the hash of the reverse of sep and the
|
// HashStrRevBytes returns the hash of the reverse of sep and the
|
||||||
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
|
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
|
||||||
|
//
|
||||||
|
// This function was removed in Go 1.22.
|
||||||
func HashStrRevBytes(sep []byte) (uint32, uint32) {
|
func HashStrRevBytes(sep []byte) (uint32, uint32) {
|
||||||
hash := uint32(0)
|
hash := uint32(0)
|
||||||
for i := len(sep) - 1; i >= 0; i-- {
|
for i := len(sep) - 1; i >= 0; i-- {
|
||||||
@@ -187,7 +198,9 @@ func HashStrRevBytes(sep []byte) (uint32, uint32) {
|
|||||||
|
|
||||||
// HashStrRev returns the hash of the reverse of sep and the
|
// HashStrRev returns the hash of the reverse of sep and the
|
||||||
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
|
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
|
||||||
func HashStrRev(sep string) (uint32, uint32) {
|
//
|
||||||
|
// Copied from the Go 1.22rc1 source tree.
|
||||||
|
func HashStrRev[T string | []byte](sep T) (uint32, uint32) {
|
||||||
hash := uint32(0)
|
hash := uint32(0)
|
||||||
for i := len(sep) - 1; i >= 0; i-- {
|
for i := len(sep) - 1; i >= 0; i-- {
|
||||||
hash = hash*PrimeRK + uint32(sep[i])
|
hash = hash*PrimeRK + uint32(sep[i])
|
||||||
@@ -204,6 +217,8 @@ func HashStrRev(sep string) (uint32, uint32) {
|
|||||||
|
|
||||||
// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the
|
// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the
|
||||||
// first occurence of substr in s, or -1 if not present.
|
// first occurence of substr in s, or -1 if not present.
|
||||||
|
//
|
||||||
|
// This function was removed in Go 1.22.
|
||||||
func IndexRabinKarpBytes(s, sep []byte) int {
|
func IndexRabinKarpBytes(s, sep []byte) int {
|
||||||
// Rabin-Karp search
|
// Rabin-Karp search
|
||||||
hashsep, pow := HashStrBytes(sep)
|
hashsep, pow := HashStrBytes(sep)
|
||||||
@@ -228,16 +243,18 @@ func IndexRabinKarpBytes(s, sep []byte) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the
|
// IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the
|
||||||
// first occurence of substr in s, or -1 if not present.
|
// first occurrence of sep in s, or -1 if not present.
|
||||||
func IndexRabinKarp(s, substr string) int {
|
//
|
||||||
|
// Copied from the Go 1.22rc1 source tree.
|
||||||
|
func IndexRabinKarp[T string | []byte](s, sep T) int {
|
||||||
// Rabin-Karp search
|
// Rabin-Karp search
|
||||||
hashss, pow := HashStr(substr)
|
hashss, pow := HashStr(sep)
|
||||||
n := len(substr)
|
n := len(sep)
|
||||||
var h uint32
|
var h uint32
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
h = h*PrimeRK + uint32(s[i])
|
h = h*PrimeRK + uint32(s[i])
|
||||||
}
|
}
|
||||||
if h == hashss && s[:n] == substr {
|
if h == hashss && string(s[:n]) == string(sep) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
for i := n; i < len(s); {
|
for i := n; i < len(s); {
|
||||||
@@ -245,7 +262,7 @@ func IndexRabinKarp(s, substr string) int {
|
|||||||
h += uint32(s[i])
|
h += uint32(s[i])
|
||||||
h -= pow * uint32(s[i-n])
|
h -= pow * uint32(s[i-n])
|
||||||
i++
|
i++
|
||||||
if h == hashss && s[i-n:i] == substr {
|
if h == hashss && string(s[i-n:i]) == string(sep) {
|
||||||
return i - n
|
return i - n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,3 +278,50 @@ func MakeNoZero(n int) []byte {
|
|||||||
// malloc function implemented in the runtime).
|
// malloc function implemented in the runtime).
|
||||||
return make([]byte, n)
|
return make([]byte, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copied from the Go 1.22rc1 source tree.
|
||||||
|
func LastIndexByte(s []byte, c byte) int {
|
||||||
|
for i := len(s) - 1; i >= 0; i-- {
|
||||||
|
if s[i] == c {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from the Go 1.22rc1 source tree.
|
||||||
|
func LastIndexByteString(s string, c byte) int {
|
||||||
|
for i := len(s) - 1; i >= 0; i-- {
|
||||||
|
if s[i] == c {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastIndexRabinKarp uses the Rabin-Karp search algorithm to return the last index of the
|
||||||
|
// occurrence of sep in s, or -1 if not present.
|
||||||
|
//
|
||||||
|
// Copied from the Go 1.22rc1 source tree.
|
||||||
|
func LastIndexRabinKarp[T string | []byte](s, sep T) int {
|
||||||
|
// Rabin-Karp search from the end of the string
|
||||||
|
hashss, pow := HashStrRev(sep)
|
||||||
|
n := len(sep)
|
||||||
|
last := len(s) - n
|
||||||
|
var h uint32
|
||||||
|
for i := len(s) - 1; i >= last; i-- {
|
||||||
|
h = h*PrimeRK + uint32(s[i])
|
||||||
|
}
|
||||||
|
if h == hashss && string(s[last:]) == string(sep) {
|
||||||
|
return last
|
||||||
|
}
|
||||||
|
for i := last - 1; i >= 0; i-- {
|
||||||
|
h *= PrimeRK
|
||||||
|
h += uint32(s[i])
|
||||||
|
h -= pow * uint32(s[i+n])
|
||||||
|
if h == hashss && string(s[i:i+n]) == string(sep) {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
|
||||||
// Only generate .debug_frame, don't generate .eh_frame.
|
// Only generate .debug_frame, don't generate .eh_frame.
|
||||||
.cfi_sections .debug_frame
|
.cfi_sections .debug_frame
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
|
||||||
.section .bss.tinygo_systemStack
|
.section .bss.tinygo_systemStack
|
||||||
.global tinygo_systemStack
|
.global tinygo_systemStack
|
||||||
.type tinygo_systemStack, %object
|
.type tinygo_systemStack, %object
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
|
||||||
// Only generate .debug_frame, don't generate .eh_frame.
|
// Only generate .debug_frame, don't generate .eh_frame.
|
||||||
.cfi_sections .debug_frame
|
.cfi_sections .debug_frame
|
||||||
|
|
||||||
|
|||||||
@@ -52,17 +52,17 @@ func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *state) resume() {
|
func (s *state) resume() {
|
||||||
switchToTask(s.sp)
|
tinygo_switchToTask(s.sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export tinygo_switchToTask
|
//export tinygo_switchToTask
|
||||||
func switchToTask(uintptr)
|
func tinygo_switchToTask(uintptr)
|
||||||
|
|
||||||
//export tinygo_switchToScheduler
|
//export tinygo_switchToScheduler
|
||||||
func switchToScheduler(*uintptr)
|
func tinygo_switchToScheduler(*uintptr)
|
||||||
|
|
||||||
func (s *state) pause() {
|
func (s *state) pause() {
|
||||||
switchToScheduler(&s.sp)
|
tinygo_switchToScheduler(&s.sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SystemStack returns the system stack pointer. On Cortex-M, it is always
|
// SystemStack returns the system stack pointer. On Cortex-M, it is always
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
|
||||||
.section .text.tinygo_startTask,"ax",@progbits
|
.section .text.tinygo_startTask,"ax",@progbits
|
||||||
.global tinygo_startTask
|
.global tinygo_startTask
|
||||||
.type tinygo_startTask, %function
|
.type tinygo_startTask, %function
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
|
||||||
.section .text.tinygo_startTask,"ax",@progbits
|
.section .text.tinygo_startTask,"ax",@progbits
|
||||||
.global tinygo_startTask
|
.global tinygo_startTask
|
||||||
.type tinygo_startTask, %function
|
.type tinygo_startTask, %function
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//go:build tinygo
|
||||||
|
|
||||||
.section .text.tinygo_startTask
|
.section .text.tinygo_startTask
|
||||||
.global tinygo_startTask
|
.global tinygo_startTask
|
||||||
.type tinygo_startTask, %function
|
.type tinygo_startTask, %function
|
||||||
|
|||||||
@@ -2,11 +2,6 @@
|
|||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
// Return the current CPU frequency in hertz.
|
|
||||||
func CPUFrequency() uint32 {
|
|
||||||
return 16000000
|
|
||||||
}
|
|
||||||
|
|
||||||
// Digital pins, marked as plain numbers on the board.
|
// Digital pins, marked as plain numbers on the board.
|
||||||
const (
|
const (
|
||||||
D0 = PD0 // RX
|
D0 = PD0 // RX
|
||||||
|
|||||||
@@ -2,11 +2,6 @@
|
|||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
// Return the current CPU frequency in hertz.
|
|
||||||
func CPUFrequency() uint32 {
|
|
||||||
return 16000000
|
|
||||||
}
|
|
||||||
|
|
||||||
// Digital pins.
|
// Digital pins.
|
||||||
const (
|
const (
|
||||||
D0 = PD0 // RX0
|
D0 = PD0 // RX0
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ var UART1 = &sercomUSART3
|
|||||||
// UART2 on the Arduino Nano 33 connects to the normal TX/RX pins.
|
// UART2 on the Arduino Nano 33 connects to the normal TX/RX pins.
|
||||||
var UART2 = &sercomUSART5
|
var UART2 = &sercomUSART5
|
||||||
|
|
||||||
|
// UART_NINA on the Arduino Nano 33 connects to the NINA HCI.
|
||||||
|
var UART_NINA = &sercomUSART2
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
const (
|
const (
|
||||||
SDA_PIN Pin = A4 // SDA: SERCOM4/PAD[1]
|
SDA_PIN Pin = A4 // SDA: SERCOM4/PAD[1]
|
||||||
@@ -99,8 +102,17 @@ const (
|
|||||||
NINA_GPIO0 Pin = PA27
|
NINA_GPIO0 Pin = PA27
|
||||||
NINA_RESETN Pin = PA08
|
NINA_RESETN Pin = PA08
|
||||||
NINA_ACK Pin = PA28
|
NINA_ACK Pin = PA28
|
||||||
NINA_TX Pin = PA22
|
NINA_TX Pin = PA12
|
||||||
NINA_RX Pin = PA23
|
NINA_RX Pin = PA13
|
||||||
|
NINA_RTS Pin = PA14
|
||||||
|
NINA_CTS Pin = PA15
|
||||||
|
)
|
||||||
|
|
||||||
|
// NINA-W102 settings
|
||||||
|
const (
|
||||||
|
NINA_BAUDRATE = 912600
|
||||||
|
NINA_RESET_INVERTED = true
|
||||||
|
NINA_SOFT_FLOWCONTROL = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// I2S pins
|
// I2S pins
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
|
// Return the current CPU frequency in hertz.
|
||||||
|
func CPUFrequency() uint32 {
|
||||||
|
return 16000000
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Note: start at port B because there is no port A.
|
// Note: start at port B because there is no port A.
|
||||||
portB Pin = iota * 8
|
portB Pin = iota * 8
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
//go:build avr && atmega328pb
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Return the current CPU frequency in hertz.
|
||||||
|
func CPUFrequency() uint32 {
|
||||||
|
return 16000000
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Note: start at port B because there is no port A.
|
||||||
|
portB Pin = iota * 8
|
||||||
|
portC
|
||||||
|
portD
|
||||||
|
portE
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PB0 = portB + 0
|
||||||
|
PB1 = portB + 1 // peripherals: Timer1 channel A
|
||||||
|
PB2 = portB + 2 // peripherals: Timer1 channel B
|
||||||
|
PB3 = portB + 3 // peripherals: Timer2 channel A
|
||||||
|
PB4 = portB + 4
|
||||||
|
PB5 = portB + 5
|
||||||
|
PB6 = portB + 6
|
||||||
|
PB7 = portB + 7
|
||||||
|
PC0 = portC + 0
|
||||||
|
PC1 = portC + 1
|
||||||
|
PC2 = portC + 2
|
||||||
|
PC3 = portC + 3
|
||||||
|
PC4 = portC + 4
|
||||||
|
PC5 = portC + 5
|
||||||
|
PC6 = portC + 6
|
||||||
|
PC7 = portC + 7
|
||||||
|
PD0 = portD + 0
|
||||||
|
PD1 = portD + 1
|
||||||
|
PD2 = portD + 2
|
||||||
|
PD3 = portD + 3 // peripherals: Timer2 channel B
|
||||||
|
PD4 = portD + 4
|
||||||
|
PD5 = portD + 5 // peripherals: Timer0 channel B
|
||||||
|
PD6 = portD + 6 // peripherals: Timer0 channel A
|
||||||
|
PD7 = portD + 7
|
||||||
|
PE0 = portE + 0
|
||||||
|
PE1 = portE + 1
|
||||||
|
PE2 = portE + 2
|
||||||
|
PE3 = portE + 3
|
||||||
|
PE4 = portE + 4
|
||||||
|
PE5 = portE + 5
|
||||||
|
PE6 = portE + 6
|
||||||
|
PE7 = portE + 7
|
||||||
|
)
|
||||||
@@ -73,7 +73,7 @@ const (
|
|||||||
|
|
||||||
// USB CDC identifiers
|
// USB CDC identifiers
|
||||||
const (
|
const (
|
||||||
usb_STRING_PRODUCT = "Gopher Badger"
|
usb_STRING_PRODUCT = "Gopher Badge"
|
||||||
usb_STRING_MANUFACTURER = "TinyGo"
|
usb_STRING_MANUFACTURER = "TinyGo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,15 @@ var (
|
|||||||
UART2 = &sercomUSART0
|
UART2 = &sercomUSART0
|
||||||
|
|
||||||
DefaultUART = UART1
|
DefaultUART = UART1
|
||||||
|
|
||||||
|
UART_NINA = UART2
|
||||||
|
)
|
||||||
|
|
||||||
|
// NINA-W102 settings
|
||||||
|
const (
|
||||||
|
NINA_BAUDRATE = 115200
|
||||||
|
NINA_RESET_INVERTED = true
|
||||||
|
NINA_SOFT_FLOWCONTROL = true
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -70,9 +79,12 @@ const (
|
|||||||
NINA_GPIO0 = PB01
|
NINA_GPIO0 = PB01
|
||||||
NINA_RESETN = PB05
|
NINA_RESETN = PB05
|
||||||
|
|
||||||
|
// pins used for the ESP32 connection do not allow hardware
|
||||||
|
// flow control, which is required. have to emulate with software.
|
||||||
NINA_TX = PA04
|
NINA_TX = PA04
|
||||||
NINA_RX = PA07
|
NINA_RX = PA07
|
||||||
NINA_RTS = PB23
|
NINA_CTS = NINA_ACK
|
||||||
|
NINA_RTS = NINA_GPIO0
|
||||||
)
|
)
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
//go:build mksnanov3
|
||||||
|
|
||||||
|
// The MKS Robin Nano V3.X board.
|
||||||
|
// Documented at https://github.com/makerbase-mks/MKS-Robin-Nano-V3.X.
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/stm32"
|
||||||
|
"runtime/interrupt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LED is also wired to the SD card card detect (CD) pin.
|
||||||
|
const LED = PD12
|
||||||
|
|
||||||
|
// UART pins
|
||||||
|
const (
|
||||||
|
UART_TX_PIN = PB10
|
||||||
|
UART_RX_PIN = PB11
|
||||||
|
)
|
||||||
|
|
||||||
|
// EXP1 and EXP2 expansion ports for connecting
|
||||||
|
// the MKS TS35 V2.0 expansion board.
|
||||||
|
const (
|
||||||
|
BEEPER = EXP1_1
|
||||||
|
|
||||||
|
// LCD pins.
|
||||||
|
LCD_DC = EXP1_8
|
||||||
|
LCD_CS = EXP1_7
|
||||||
|
LCD_RS = EXP1_4
|
||||||
|
LCD_BACKLIGHT = EXP1_3
|
||||||
|
|
||||||
|
// Touch pins. Note that some pins are shared with the
|
||||||
|
// LCD SPI1 interface.
|
||||||
|
TOUCH_CLK = EXP2_2
|
||||||
|
TOUCH_CS = EXP1_5
|
||||||
|
TOUCH_DIN = EXP2_6
|
||||||
|
TOUCH_DOUT = EXP2_1
|
||||||
|
TOUCH_IRQ = EXP1_6
|
||||||
|
|
||||||
|
BUTTON = BUTTON_JOG
|
||||||
|
BUTTON_JOG = EXP1_2
|
||||||
|
BUTTON_JOG_CCW = EXP2_3
|
||||||
|
BUTTON_JOG_CW = EXP2_5
|
||||||
|
|
||||||
|
EXP1_1 = PC5
|
||||||
|
EXP1_2 = PE13
|
||||||
|
EXP1_3 = PD13
|
||||||
|
EXP1_4 = PC6
|
||||||
|
EXP1_5 = PE14
|
||||||
|
EXP1_6 = PE15
|
||||||
|
EXP1_7 = PD11
|
||||||
|
EXP1_8 = PD10
|
||||||
|
|
||||||
|
EXP2_1 = PA6
|
||||||
|
EXP2_2 = PA5
|
||||||
|
EXP2_3 = PE8
|
||||||
|
EXP2_4 = PE10
|
||||||
|
EXP2_5 = PE11
|
||||||
|
EXP2_6 = PA7
|
||||||
|
EXP2_7 = PE12
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
UART3 = &_UART3
|
||||||
|
_UART3 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: stm32.USART3,
|
||||||
|
TxAltFuncSelector: AF7_USART1_2_3,
|
||||||
|
RxAltFuncSelector: AF7_USART1_2_3,
|
||||||
|
}
|
||||||
|
DefaultUART = UART3
|
||||||
|
)
|
||||||
|
|
||||||
|
// set up RX IRQ handler. Follow similar pattern for other UARTx instances
|
||||||
|
func init() {
|
||||||
|
UART3.Interrupt = interrupt.New(stm32.IRQ_USART3, _UART3.handleInterrupt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
const (
|
||||||
|
SPI1_SCK_PIN = EXP2_2
|
||||||
|
SPI1_SDI_PIN = EXP2_1
|
||||||
|
SPI1_SDO_PIN = EXP2_6
|
||||||
|
SPI0_SCK_PIN = SPI1_SCK_PIN
|
||||||
|
SPI0_SDI_PIN = SPI1_SDI_PIN
|
||||||
|
SPI0_SDO_PIN = SPI1_SDO_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
// Since the first interface is named SPI1, both SPI0 and SPI1 refer to SPI1.
|
||||||
|
var (
|
||||||
|
SPI0 = SPI{
|
||||||
|
Bus: stm32.SPI1,
|
||||||
|
AltFuncSelector: AF5_SPI1_SPI2,
|
||||||
|
}
|
||||||
|
SPI1 = &SPI0
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
I2C0_SCL_PIN = PB6
|
||||||
|
I2C0_SDA_PIN = PB7
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
I2C0 = &I2C{
|
||||||
|
Bus: stm32.I2C1,
|
||||||
|
AltFuncSelector: AF4_I2C1_2_3,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Motor control pins.
|
||||||
|
const (
|
||||||
|
X_ENABLE = PE4
|
||||||
|
X_STEP = PE3
|
||||||
|
X_DIR = PE2
|
||||||
|
X_DIAG = PA15
|
||||||
|
X_UART = PD5
|
||||||
|
|
||||||
|
Y_ENABLE = PE1
|
||||||
|
Y_STEP = PE0
|
||||||
|
Y_DIR = PB9
|
||||||
|
Y_DIAG = PD2
|
||||||
|
Y_UART = PD7
|
||||||
|
|
||||||
|
Z_ENABLE = PB8
|
||||||
|
Z_STEP = PB5
|
||||||
|
Z_DIR = PB4
|
||||||
|
Z_DIAG = PC8
|
||||||
|
Z_UART = PD4
|
||||||
|
|
||||||
|
E0_ENABLE = PB3
|
||||||
|
E0_STEP = PD6
|
||||||
|
E0_DIR = PD3
|
||||||
|
E0_DIAG = PC4
|
||||||
|
E0_UART = PD9
|
||||||
|
|
||||||
|
E1_ENABLE = PA3
|
||||||
|
E1_STEP = PD15
|
||||||
|
E1_DIR = PA1
|
||||||
|
E1_DIAG = PE7
|
||||||
|
E1_UART = PD8
|
||||||
|
)
|
||||||
@@ -87,8 +87,17 @@ const (
|
|||||||
NINA_GPIO0 Pin = GPIO2
|
NINA_GPIO0 Pin = GPIO2
|
||||||
NINA_RESETN Pin = GPIO3
|
NINA_RESETN Pin = GPIO3
|
||||||
|
|
||||||
NINA_TX Pin = GPIO9
|
NINA_TX Pin = GPIO8
|
||||||
NINA_RX Pin = GPIO8
|
NINA_RX Pin = GPIO9
|
||||||
|
NINA_CTS Pin = GPIO10
|
||||||
|
NINA_RTS Pin = GPIO11
|
||||||
|
)
|
||||||
|
|
||||||
|
// NINA-W102 settings
|
||||||
|
const (
|
||||||
|
NINA_BAUDRATE = 115200
|
||||||
|
NINA_RESET_INVERTED = true
|
||||||
|
NINA_SOFT_FLOWCONTROL = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// Onboard crystal oscillator frequency, in MHz.
|
// Onboard crystal oscillator frequency, in MHz.
|
||||||
@@ -123,10 +132,20 @@ var (
|
|||||||
Buffer: NewRingBuffer(),
|
Buffer: NewRingBuffer(),
|
||||||
Bus: rp.UART0,
|
Bus: rp.UART0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UART1 = &_UART1
|
||||||
|
_UART1 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: rp.UART1,
|
||||||
|
}
|
||||||
|
|
||||||
|
// UART_NINA on the Arduino Nano RP2040 connects to the NINA HCI.
|
||||||
|
UART_NINA = UART1
|
||||||
)
|
)
|
||||||
|
|
||||||
var DefaultUART = UART0
|
var DefaultUART = UART0
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
|
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
|
||||||
|
UART1.Interrupt = interrupt.New(rp.IRQ_UART1_IRQ, _UART1.handleInterrupt)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//go:build nrf52840 && nrf52840_generic
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
var (
|
||||||
|
LED = NoPin
|
||||||
|
SDA_PIN = NoPin
|
||||||
|
SCL_PIN = NoPin
|
||||||
|
UART_TX_PIN = NoPin
|
||||||
|
UART_RX_PIN = NoPin
|
||||||
|
SPI0_SCK_PIN = NoPin
|
||||||
|
SPI0_SDO_PIN = NoPin
|
||||||
|
SPI0_SDI_PIN = NoPin
|
||||||
|
|
||||||
|
// https://pid.codes/org/TinyGo/
|
||||||
|
usb_VID uint16 = 0x1209
|
||||||
|
usb_PID uint16 = 0x9090
|
||||||
|
|
||||||
|
usb_STRING_MANUFACTURER = "TinyGo"
|
||||||
|
usb_STRING_PRODUCT = "nRF52840 Generic board"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultUART = UART0
|
||||||
|
)
|
||||||
@@ -130,3 +130,33 @@ var (
|
|||||||
usb_VID uint16 = 0x239A
|
usb_VID uint16 = 0x239A
|
||||||
usb_PID uint16 = 0x8033
|
usb_PID uint16 = 0x8033
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NINA-W102 settings when using AirLift WiFi FeatherWing
|
||||||
|
const (
|
||||||
|
NINA_BAUDRATE = 115200
|
||||||
|
NINA_RESET_INVERTED = true
|
||||||
|
NINA_SOFT_FLOWCONTROL = true
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NINA_CS = D13
|
||||||
|
NINA_ACK = D11
|
||||||
|
NINA_GPIO0 = D10
|
||||||
|
NINA_RESETN = D12
|
||||||
|
|
||||||
|
// pins used for the ESP32 connection do not allow hardware
|
||||||
|
// flow control, which is required. have to emulate with software.
|
||||||
|
NINA_TX = UART_TX_PIN
|
||||||
|
NINA_RX = UART_RX_PIN
|
||||||
|
NINA_CTS = NINA_ACK
|
||||||
|
NINA_RTS = NINA_GPIO0
|
||||||
|
|
||||||
|
NINA_SDO = SPI0_SDO_PIN
|
||||||
|
NINA_SDI = SPI0_SDI_PIN
|
||||||
|
NINA_SCK = SPI0_SCK_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
NINA_SPI = SPI0
|
||||||
|
UART_NINA = UART1
|
||||||
|
)
|
||||||
|
|||||||
@@ -53,9 +53,12 @@ const (
|
|||||||
NINA_GPIO0 = D6
|
NINA_GPIO0 = D6
|
||||||
NINA_RESETN = D7
|
NINA_RESETN = D7
|
||||||
|
|
||||||
|
// pins used for the ESP32 connection do not allow hardware
|
||||||
|
// flow control, which is required. have to emulate with software.
|
||||||
NINA_TX = D1
|
NINA_TX = D1
|
||||||
NINA_RX = D0
|
NINA_RX = D0
|
||||||
NINA_RTS = D51
|
NINA_CTS = NINA_ACK
|
||||||
|
NINA_RTS = NINA_GPIO0
|
||||||
|
|
||||||
LCD_DATA0 = D34
|
LCD_DATA0 = D34
|
||||||
|
|
||||||
@@ -111,6 +114,15 @@ var (
|
|||||||
UART1 = &sercomUSART4
|
UART1 = &sercomUSART4
|
||||||
|
|
||||||
DefaultUART = UART1
|
DefaultUART = UART1
|
||||||
|
|
||||||
|
UART_NINA = UART1
|
||||||
|
)
|
||||||
|
|
||||||
|
// NINA-W102 settings
|
||||||
|
const (
|
||||||
|
NINA_BAUDRATE = 115200
|
||||||
|
NINA_RESET_INVERTED = true
|
||||||
|
NINA_SOFT_FLOWCONTROL = true
|
||||||
)
|
)
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
//go:build qtpy_esp32c3
|
||||||
|
|
||||||
|
// This file contains the pin mappings for the Adafruit QtPy ESP32C3 boards.
|
||||||
|
//
|
||||||
|
// https://learn.adafruit.com/adafruit-qt-py-esp32-c3-wifi-dev-board/pinouts
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Digital Pins
|
||||||
|
const (
|
||||||
|
D0 = GPIO4
|
||||||
|
D1 = GPIO3
|
||||||
|
D2 = GPIO1
|
||||||
|
D3 = GPIO0
|
||||||
|
)
|
||||||
|
|
||||||
|
// Analog pins (ADC1)
|
||||||
|
const (
|
||||||
|
A0 = GPIO4
|
||||||
|
A1 = GPIO3
|
||||||
|
A2 = GPIO1
|
||||||
|
A3 = GPIO0
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART pins
|
||||||
|
const (
|
||||||
|
RX_PIN = GPIO20
|
||||||
|
TX_PIN = GPIO21
|
||||||
|
|
||||||
|
UART_RX_PIN = RX_PIN
|
||||||
|
UART_TX_PIN = TX_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C pins
|
||||||
|
const (
|
||||||
|
SDA_PIN = GPIO5
|
||||||
|
SCL_PIN = GPIO6
|
||||||
|
|
||||||
|
I2C0_SDA_PIN = SDA_PIN
|
||||||
|
I2C0_SCL_PIN = SCL_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
const (
|
||||||
|
SCK_PIN = GPIO10
|
||||||
|
MI_PIN = GPIO8
|
||||||
|
MO_PIN = GPIO7
|
||||||
|
|
||||||
|
SPI_SCK_PIN = SCK_PIN
|
||||||
|
SPI_SDI_PIN = MI_PIN
|
||||||
|
SPI_SDO_PIN = MO_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NEOPIXEL = GPIO2
|
||||||
|
WS2812 = GPIO2
|
||||||
|
|
||||||
|
// also used for boot button.
|
||||||
|
// set it to be an input-with-pullup
|
||||||
|
BUTTON = GPIO9
|
||||||
|
)
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
//go:build thumby
|
||||||
|
|
||||||
|
// This contains the pin mappings for the Thumby.
|
||||||
|
//
|
||||||
|
// https://thumby.us/
|
||||||
|
package machine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"device/rp"
|
||||||
|
"runtime/interrupt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
THUMBY_SCK_PIN = I2C1_SDA_PIN
|
||||||
|
THUMBY_SDA_PIN = I2C1_SCL_PIN
|
||||||
|
|
||||||
|
THUMBY_CS_PIN = GPIO16
|
||||||
|
THUMBY_DC_PIN = GPIO17
|
||||||
|
THUMBY_RESET_PIN = GPIO20
|
||||||
|
|
||||||
|
THUMBY_LINK_TX_PIN = UART0_TX_PIN
|
||||||
|
THUMBY_LINK_RX_PIN = UART0_RX_PIN
|
||||||
|
THUMBY_LINK_PU_PIN = GPIO2
|
||||||
|
|
||||||
|
THUMBY_BTN_LDPAD_PIN = GPIO3
|
||||||
|
THUMBY_BTN_RDPAD_PIN = GPIO5
|
||||||
|
THUMBY_BTN_UDPAD_PIN = GPIO4
|
||||||
|
THUMBY_BTN_DDPAD_PIN = GPIO6
|
||||||
|
THUMBY_BTN_B_PIN = GPIO24
|
||||||
|
THUMBY_BTN_A_PIN = GPIO27
|
||||||
|
|
||||||
|
THUMBY_AUDIO_PIN = GPIO28
|
||||||
|
|
||||||
|
THUMBY_SCREEN_RESET_PIN = GPIO20
|
||||||
|
)
|
||||||
|
|
||||||
|
// I2C pins
|
||||||
|
const (
|
||||||
|
I2C0_SDA_PIN Pin = NoPin
|
||||||
|
I2C0_SCL_PIN Pin = NoPin
|
||||||
|
|
||||||
|
I2C1_SDA_PIN Pin = GPIO18
|
||||||
|
I2C1_SCL_PIN Pin = GPIO19
|
||||||
|
)
|
||||||
|
|
||||||
|
// SPI pins
|
||||||
|
const (
|
||||||
|
SPI0_SCK_PIN = GPIO18
|
||||||
|
SPI0_SDO_PIN = GPIO19
|
||||||
|
SPI0_SDI_PIN = GPIO16
|
||||||
|
|
||||||
|
SPI1_SCK_PIN = NoPin
|
||||||
|
SPI1_SDO_PIN = NoPin
|
||||||
|
SPI1_SDI_PIN = NoPin
|
||||||
|
)
|
||||||
|
|
||||||
|
// Onboard crystal oscillator frequency, in MHz.
|
||||||
|
const (
|
||||||
|
xoscFreq = 12 // MHz
|
||||||
|
)
|
||||||
|
|
||||||
|
// USB CDC identifiers
|
||||||
|
const (
|
||||||
|
usb_STRING_PRODUCT = "Thumby"
|
||||||
|
usb_STRING_MANUFACTURER = "TinyCircuits"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
usb_VID uint16 = 0x2E8A
|
||||||
|
usb_PID uint16 = 0x0005
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART pins
|
||||||
|
const (
|
||||||
|
UART0_TX_PIN = GPIO0
|
||||||
|
UART0_RX_PIN = GPIO1
|
||||||
|
UART_TX_PIN = UART0_TX_PIN
|
||||||
|
UART_RX_PIN = UART0_RX_PIN
|
||||||
|
)
|
||||||
|
|
||||||
|
// UART on the Thumby
|
||||||
|
var (
|
||||||
|
UART0 = &_UART0
|
||||||
|
_UART0 = UART{
|
||||||
|
Buffer: NewRingBuffer(),
|
||||||
|
Bus: rp.UART0,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var DefaultUART = UART0
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
|
||||||
|
}
|
||||||
@@ -353,6 +353,9 @@ var (
|
|||||||
|
|
||||||
// RTL8720D (tx: PB24, rx: PC24)
|
// RTL8720D (tx: PB24, rx: PC24)
|
||||||
UART3 = &sercomUSART0
|
UART3 = &sercomUSART0
|
||||||
|
|
||||||
|
// Right-hand grove port (tx: D0, rx: D1)
|
||||||
|
UART4 = &sercomUSART4
|
||||||
)
|
)
|
||||||
|
|
||||||
// I2C pins
|
// I2C pins
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import (
|
|||||||
"runtime/volatile"
|
"runtime/volatile"
|
||||||
)
|
)
|
||||||
|
|
||||||
const bufferSize = 128
|
|
||||||
|
|
||||||
// RingBuffer is ring buffer implementation inspired by post at
|
// RingBuffer is ring buffer implementation inspired by post at
|
||||||
// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php
|
// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php
|
||||||
type RingBuffer struct {
|
type RingBuffer struct {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
//go:build atmega
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
const bufferSize = 32
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
//go:build !atmega
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
const bufferSize = 128
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//go:build rp2040 || nrf || sam
|
||||||
|
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// DeviceID returns an identifier that is unique within
|
||||||
|
// a particular chipset.
|
||||||
|
//
|
||||||
|
// The identity is one burnt into the MCU itself, or the
|
||||||
|
// flash chip at time of manufacture.
|
||||||
|
//
|
||||||
|
// It's possible that two different vendors may allocate
|
||||||
|
// the same DeviceID, so callers should take this into
|
||||||
|
// account if needing to generate a globally unique id.
|
||||||
|
//
|
||||||
|
// The length of the hardware ID is vendor-specific, but
|
||||||
|
// 8 bytes (64 bits) and 16 bytes (128 bits) are common.
|
||||||
|
var _ = (func() []byte)(DeviceID)
|
||||||
+13
-1
@@ -1,4 +1,4 @@
|
|||||||
//go:build atmega || nrf || sam || stm32 || fe310 || k210 || rp2040
|
//go:build atmega || nrf || sam || stm32 || fe310 || k210 || rp2040 || mimxrt1062 || (esp32c3 && !m5stamp_c3)
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
@@ -6,6 +6,17 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// If you are getting a compile error on this line please check to see you've
|
||||||
|
// correctly implemented the methods on the I2C type. They must match
|
||||||
|
// the i2cController interface method signatures type to type perfectly.
|
||||||
|
// If not implementing the I2C type please remove your target from the build tags
|
||||||
|
// at the top of this file.
|
||||||
|
var _ interface { // 2
|
||||||
|
Configure(config I2CConfig) error
|
||||||
|
Tx(addr uint16, w, r []byte) error
|
||||||
|
SetBaudRate(br uint32) error
|
||||||
|
} = (*I2C)(nil)
|
||||||
|
|
||||||
// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.
|
// TWI_FREQ is the I2C bus speed. Normally either 100 kHz, or 400 kHz for high-speed bus.
|
||||||
//
|
//
|
||||||
// Deprecated: use 100 * machine.KHz or 400 * machine.KHz instead.
|
// Deprecated: use 100 * machine.KHz or 400 * machine.KHz instead.
|
||||||
@@ -25,6 +36,7 @@ var (
|
|||||||
errI2CBusError = errors.New("I2C bus error")
|
errI2CBusError = errors.New("I2C bus error")
|
||||||
errI2COverflow = errors.New("I2C receive buffer overflow")
|
errI2COverflow = errors.New("I2C receive buffer overflow")
|
||||||
errI2COverread = errors.New("I2C transmit buffer overflow")
|
errI2COverread = errors.New("I2C transmit buffer overflow")
|
||||||
|
errI2CNotImplemented = errors.New("I2C operation not yet implemented")
|
||||||
)
|
)
|
||||||
|
|
||||||
// I2CTargetEvent reflects events on the I2C bus
|
// I2CTargetEvent reflects events on the I2C bus
|
||||||
|
|||||||
@@ -11,10 +11,19 @@ import (
|
|||||||
|
|
||||||
// I2C on AVR.
|
// I2C on AVR.
|
||||||
type I2C struct {
|
type I2C struct {
|
||||||
}
|
srReg *volatile.Register8
|
||||||
|
brReg *volatile.Register8
|
||||||
|
crReg *volatile.Register8
|
||||||
|
drReg *volatile.Register8
|
||||||
|
|
||||||
// I2C0 is the only I2C interface on most AVRs.
|
srPS0 byte
|
||||||
var I2C0 *I2C = nil
|
srPS1 byte
|
||||||
|
crEN byte
|
||||||
|
crINT byte
|
||||||
|
crSTO byte
|
||||||
|
crEA byte
|
||||||
|
crSTA byte
|
||||||
|
}
|
||||||
|
|
||||||
// I2CConfig is used to store config info for I2C.
|
// I2CConfig is used to store config info for I2C.
|
||||||
type I2CConfig struct {
|
type I2CConfig struct {
|
||||||
@@ -31,17 +40,22 @@ func (i2c *I2C) Configure(config I2CConfig) error {
|
|||||||
// Activate internal pullups for twi.
|
// Activate internal pullups for twi.
|
||||||
avr.PORTC.SetBits((avr.DIDR0_ADC4D | avr.DIDR0_ADC5D))
|
avr.PORTC.SetBits((avr.DIDR0_ADC4D | avr.DIDR0_ADC5D))
|
||||||
|
|
||||||
|
return i2c.SetBaudRate(config.Frequency)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBaudRate sets the communication speed for I2C.
|
||||||
|
func (i2c *I2C) SetBaudRate(br uint32) error {
|
||||||
// Initialize twi prescaler and bit rate.
|
// Initialize twi prescaler and bit rate.
|
||||||
avr.TWSR.SetBits((avr.TWSR_TWPS0 | avr.TWSR_TWPS1))
|
i2c.srReg.SetBits((i2c.srPS0 | i2c.srPS1))
|
||||||
|
|
||||||
// twi bit rate formula from atmega128 manual pg. 204:
|
// twi bit rate formula from atmega128 manual pg. 204:
|
||||||
// SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
|
// SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
|
||||||
// NOTE: TWBR should be 10 or higher for controller mode.
|
// NOTE: TWBR should be 10 or higher for controller mode.
|
||||||
// It is 72 for a 16mhz board with 100kHz TWI
|
// It is 72 for a 16mhz board with 100kHz TWI
|
||||||
avr.TWBR.Set(uint8(((CPUFrequency() / config.Frequency) - 16) / 2))
|
i2c.brReg.Set(uint8(((CPUFrequency() / br) - 16) / 2))
|
||||||
|
|
||||||
// Enable twi module.
|
// Enable twi module.
|
||||||
avr.TWCR.Set(avr.TWCR_TWEN)
|
i2c.crReg.Set(i2c.crEN)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -72,10 +86,10 @@ func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
|
|||||||
// start starts an I2C communication session.
|
// start starts an I2C communication session.
|
||||||
func (i2c *I2C) start(address uint8, write bool) {
|
func (i2c *I2C) start(address uint8, write bool) {
|
||||||
// Clear TWI interrupt flag, put start condition on SDA, and enable TWI.
|
// Clear TWI interrupt flag, put start condition on SDA, and enable TWI.
|
||||||
avr.TWCR.Set((avr.TWCR_TWINT | avr.TWCR_TWSTA | avr.TWCR_TWEN))
|
i2c.crReg.Set((i2c.crINT | i2c.crSTA | i2c.crEN))
|
||||||
|
|
||||||
// Wait till start condition is transmitted.
|
// Wait till start condition is transmitted.
|
||||||
for !avr.TWCR.HasBits(avr.TWCR_TWINT) {
|
for !i2c.crReg.HasBits(i2c.crINT) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write 7-bit shifted peripheral address.
|
// Write 7-bit shifted peripheral address.
|
||||||
@@ -89,23 +103,23 @@ func (i2c *I2C) start(address uint8, write bool) {
|
|||||||
// stop ends an I2C communication session.
|
// stop ends an I2C communication session.
|
||||||
func (i2c *I2C) stop() {
|
func (i2c *I2C) stop() {
|
||||||
// Send stop condition.
|
// Send stop condition.
|
||||||
avr.TWCR.Set(avr.TWCR_TWEN | avr.TWCR_TWINT | avr.TWCR_TWSTO)
|
i2c.crReg.Set(i2c.crEN | i2c.crINT | i2c.crSTO)
|
||||||
|
|
||||||
// Wait for stop condition to be executed on bus.
|
// Wait for stop condition to be executed on bus.
|
||||||
for !avr.TWCR.HasBits(avr.TWCR_TWSTO) {
|
for !i2c.crReg.HasBits(i2c.crSTO) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeByte writes a single byte to the I2C bus.
|
// writeByte writes a single byte to the I2C bus.
|
||||||
func (i2c *I2C) writeByte(data byte) error {
|
func (i2c *I2C) writeByte(data byte) error {
|
||||||
// Write data to register.
|
// Write data to register.
|
||||||
avr.TWDR.Set(data)
|
i2c.drReg.Set(data)
|
||||||
|
|
||||||
// Clear TWI interrupt flag and enable TWI.
|
// Clear TWI interrupt flag and enable TWI.
|
||||||
avr.TWCR.Set(avr.TWCR_TWEN | avr.TWCR_TWINT)
|
i2c.crReg.Set(i2c.crEN | i2c.crINT)
|
||||||
|
|
||||||
// Wait till data is transmitted.
|
// Wait till data is transmitted.
|
||||||
for !avr.TWCR.HasBits(avr.TWCR_TWINT) {
|
for !i2c.crReg.HasBits(i2c.crINT) {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -113,13 +127,13 @@ func (i2c *I2C) writeByte(data byte) error {
|
|||||||
// readByte reads a single byte from the I2C bus.
|
// readByte reads a single byte from the I2C bus.
|
||||||
func (i2c *I2C) readByte() byte {
|
func (i2c *I2C) readByte() byte {
|
||||||
// Clear TWI interrupt flag and enable TWI.
|
// Clear TWI interrupt flag and enable TWI.
|
||||||
avr.TWCR.Set(avr.TWCR_TWEN | avr.TWCR_TWINT | avr.TWCR_TWEA)
|
i2c.crReg.Set(i2c.crEN | i2c.crINT | i2c.crEA)
|
||||||
|
|
||||||
// Wait till read request is transmitted.
|
// Wait till read request is transmitted.
|
||||||
for !avr.TWCR.HasBits(avr.TWCR_TWINT) {
|
for !i2c.crReg.HasBits(i2c.crINT) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return byte(avr.TWDR.Get())
|
return byte(i2c.drReg.Get())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always use UART0 as the serial output.
|
// Always use UART0 as the serial output.
|
||||||
@@ -165,10 +179,18 @@ func (uart *UART) Configure(config UARTConfig) {
|
|||||||
config.BaudRate = 9600
|
config.BaudRate = 9600
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set baud rate based on prescale formula from
|
// Prescale formula for u2x mode from AVR MiniCore source code.
|
||||||
// https://www.microchip.com/webdoc/AVRLibcReferenceManual/FAQ_1faq_wrong_baud_rate.html
|
// Same as formula from specification but taking into account rounding error.
|
||||||
// ((F_CPU + UART_BAUD_RATE * 8L) / (UART_BAUD_RATE * 16L) - 1)
|
ps := (CPUFrequency()/4/config.BaudRate - 1) / 2
|
||||||
ps := ((CPUFrequency()+config.BaudRate*8)/(config.BaudRate*16) - 1)
|
uart.statusRegA.SetBits(avr.UCSR0A_U2X0)
|
||||||
|
|
||||||
|
// Hardcoded exception for 57600 for compatibility with older bootloaders.
|
||||||
|
// Also, prescale cannot be > 4095, so switch back to non-u2x mode if the baud rate is too low.
|
||||||
|
if (CPUFrequency() == 16000000 && config.BaudRate == 57600) || ps > 0xfff {
|
||||||
|
ps = (CPUFrequency()/8/config.BaudRate - 1) / 2
|
||||||
|
uart.statusRegA.ClearBits(avr.UCSR0A_U2X0)
|
||||||
|
}
|
||||||
|
|
||||||
uart.baudRegH.Set(uint8(ps >> 8))
|
uart.baudRegH.Set(uint8(ps >> 8))
|
||||||
uart.baudRegL.Set(uint8(ps & 0xff))
|
uart.baudRegL.Set(uint8(ps & 0xff))
|
||||||
|
|
||||||
@@ -216,6 +238,17 @@ type SPI struct {
|
|||||||
spdr *volatile.Register8
|
spdr *volatile.Register8
|
||||||
spsr *volatile.Register8
|
spsr *volatile.Register8
|
||||||
|
|
||||||
|
spcrR0 byte
|
||||||
|
spcrR1 byte
|
||||||
|
spcrCPHA byte
|
||||||
|
spcrCPOL byte
|
||||||
|
spcrDORD byte
|
||||||
|
spcrSPE byte
|
||||||
|
spcrMSTR byte
|
||||||
|
|
||||||
|
spsrI2X byte
|
||||||
|
spsrSPIF byte
|
||||||
|
|
||||||
// The io pins for the SPIx port set by the chip
|
// The io pins for the SPIx port set by the chip
|
||||||
sck Pin
|
sck Pin
|
||||||
sdi Pin
|
sdi Pin
|
||||||
@@ -259,39 +292,39 @@ func (s SPI) Configure(config SPIConfig) error {
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case frequencyDivider >= 128:
|
case frequencyDivider >= 128:
|
||||||
s.spcr.SetBits(avr.SPCR_SPR0 | avr.SPCR_SPR1)
|
s.spcr.SetBits(s.spcrR0 | s.spcrR1)
|
||||||
case frequencyDivider >= 64:
|
case frequencyDivider >= 64:
|
||||||
s.spcr.SetBits(avr.SPCR_SPR1)
|
s.spcr.SetBits(s.spcrR1)
|
||||||
case frequencyDivider >= 32:
|
case frequencyDivider >= 32:
|
||||||
s.spcr.SetBits(avr.SPCR_SPR1)
|
s.spcr.SetBits(s.spcrR1)
|
||||||
s.spsr.SetBits(avr.SPSR_SPI2X)
|
s.spsr.SetBits(s.spsrI2X)
|
||||||
case frequencyDivider >= 16:
|
case frequencyDivider >= 16:
|
||||||
s.spcr.SetBits(avr.SPCR_SPR0)
|
s.spcr.SetBits(s.spcrR0)
|
||||||
case frequencyDivider >= 8:
|
case frequencyDivider >= 8:
|
||||||
s.spcr.SetBits(avr.SPCR_SPR0)
|
s.spcr.SetBits(s.spcrR0)
|
||||||
s.spsr.SetBits(avr.SPSR_SPI2X)
|
s.spsr.SetBits(s.spsrI2X)
|
||||||
case frequencyDivider >= 4:
|
case frequencyDivider >= 4:
|
||||||
// The clock is already set to all 0's.
|
// The clock is already set to all 0's.
|
||||||
default: // defaults to fastest which is /2
|
default: // defaults to fastest which is /2
|
||||||
s.spsr.SetBits(avr.SPSR_SPI2X)
|
s.spsr.SetBits(s.spsrI2X)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch config.Mode {
|
switch config.Mode {
|
||||||
case Mode1:
|
case Mode1:
|
||||||
s.spcr.SetBits(avr.SPCR_CPHA)
|
s.spcr.SetBits(s.spcrCPHA)
|
||||||
case Mode2:
|
case Mode2:
|
||||||
s.spcr.SetBits(avr.SPCR_CPOL)
|
s.spcr.SetBits(s.spcrCPHA)
|
||||||
case Mode3:
|
case Mode3:
|
||||||
s.spcr.SetBits(avr.SPCR_CPHA | avr.SPCR_CPOL)
|
s.spcr.SetBits(s.spcrCPHA | s.spcrCPOL)
|
||||||
default: // default is mode 0
|
default: // default is mode 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.LSBFirst {
|
if config.LSBFirst {
|
||||||
s.spcr.SetBits(avr.SPCR_DORD)
|
s.spcr.SetBits(s.spcrDORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable SPI, set controller, set clock rate
|
// enable SPI, set controller, set clock rate
|
||||||
s.spcr.SetBits(avr.SPCR_SPE | avr.SPCR_MSTR)
|
s.spcr.SetBits(s.spcrSPE | s.spcrMSTR)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -300,7 +333,7 @@ func (s SPI) Configure(config SPIConfig) error {
|
|||||||
func (s SPI) Transfer(b byte) (byte, error) {
|
func (s SPI) Transfer(b byte) (byte, error) {
|
||||||
s.spdr.Set(uint8(b))
|
s.spdr.Set(uint8(b))
|
||||||
|
|
||||||
for !s.spsr.HasBits(avr.SPSR_SPIF) {
|
for !s.spsr.HasBits(s.spsrSPIF) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return byte(s.spdr.Get()), nil
|
return byte(s.spdr.Get()), nil
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user