mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-07 04:23:41 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9ce6c3374 |
+20
-12
@@ -73,6 +73,14 @@ commands:
|
|||||||
- go-cache-v4-{{ 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:
|
||||||
|
keys:
|
||||||
|
- wasi-libc-sysroot-systemclang-v7
|
||||||
|
- run: make wasi-libc
|
||||||
|
- save_cache:
|
||||||
|
key: wasi-libc-sysroot-systemclang-v7
|
||||||
|
paths:
|
||||||
|
- lib/wasi-libc/sysroot
|
||||||
- when:
|
- when:
|
||||||
condition: <<parameters.fmt-check>>
|
condition: <<parameters.fmt-check>>
|
||||||
steps:
|
steps:
|
||||||
@@ -92,28 +100,28 @@ commands:
|
|||||||
- /go/pkg/mod
|
- /go/pkg/mod
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-oldest:
|
test-llvm15-go119:
|
||||||
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
|
||||||
# least the smoke tests still pass.
|
|
||||||
docker:
|
docker:
|
||||||
- image: golang:1.22-bullseye
|
- image: golang:1.19-bullseye
|
||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "15"
|
llvm: "15"
|
||||||
|
# "make lint" fails before go 1.21 because internal/tools/go.mod specifies packages that require go 1.21
|
||||||
|
fmt-check: false
|
||||||
resource_class: large
|
resource_class: large
|
||||||
test-newest:
|
test-llvm19-go124:
|
||||||
# This tests the latest supported LLVM version when linking against system
|
|
||||||
# libraries.
|
|
||||||
docker:
|
docker:
|
||||||
- image: golang:1.25-bullseye
|
- image: golang:1.24-bullseye
|
||||||
steps:
|
steps:
|
||||||
- test-linux:
|
- test-linux:
|
||||||
llvm: "20"
|
llvm: "19"
|
||||||
resource_class: large
|
resource_class: large
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
test-all:
|
test-all:
|
||||||
jobs:
|
jobs:
|
||||||
- test-oldest
|
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
||||||
# disable this test, since CircleCI seems unable to download due to rate-limits on Dockerhub.
|
# least the smoke tests still pass.
|
||||||
# - test-newest
|
- test-llvm15-go119
|
||||||
|
# This tests LLVM 19 support when linking against system libraries.
|
||||||
|
- test-llvm19-go124
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
@@ -89,10 +89,19 @@ jobs:
|
|||||||
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
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: cache-wasi-libc
|
||||||
|
with:
|
||||||
|
key: wasi-libc-sysroot-${{ matrix.os }}-v1
|
||||||
|
path: lib/wasi-libc/sysroot
|
||||||
|
- name: Build wasi-libc
|
||||||
|
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||||
|
run: make wasi-libc
|
||||||
- name: make gen-device
|
- name: make gen-device
|
||||||
run: make -j3 gen-device
|
run: make -j3 gen-device
|
||||||
- name: Test TinyGo
|
- name: Test TinyGo
|
||||||
run: make test GOTESTFLAGS="-only-current-os"
|
run: make test GOTESTFLAGS="-short"
|
||||||
- name: Build TinyGo release tarball
|
- name: Build TinyGo release tarball
|
||||||
run: make release -j3
|
run: make release -j3
|
||||||
- name: Test stdlib packages
|
- name: Test stdlib packages
|
||||||
@@ -117,7 +126,7 @@ jobs:
|
|||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
version: [16, 17, 18, 19, 20]
|
version: [16, 17, 18, 19]
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Homebrew
|
- name: Set up Homebrew
|
||||||
uses: Homebrew/actions/setup-homebrew@master
|
uses: Homebrew/actions/setup-homebrew@master
|
||||||
@@ -134,15 +143,15 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Build TinyGo (LLVM ${{ matrix.version }})
|
- name: Build TinyGo (LLVM ${{ matrix.version }})
|
||||||
run: go install -tags=llvm${{ matrix.version }}
|
run: go install -tags=llvm${{ matrix.version }}
|
||||||
- name: Check binary
|
- name: Check binary
|
||||||
run: tinygo version
|
run: tinygo version
|
||||||
- name: Build TinyGo (default LLVM)
|
- name: Build TinyGo (default LLVM)
|
||||||
if: matrix.version == 20
|
if: matrix.version == 19
|
||||||
run: go install
|
run: go install
|
||||||
- name: Check binary
|
- name: Check binary
|
||||||
if: matrix.version == 20
|
if: matrix.version == 19
|
||||||
run: tinygo version
|
run: tinygo version
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
# statically linked binary.
|
# statically linked binary.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: golang:1.25-alpine
|
image: golang:1.24-alpine
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.version.outputs.version }}
|
version: ${{ steps.version.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
@@ -104,6 +104,15 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
apk add cmake samurai python3
|
apk add cmake samurai python3
|
||||||
make binaryen STATIC=1
|
make binaryen STATIC=1
|
||||||
|
- name: Cache wasi-libc
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: cache-wasi-libc
|
||||||
|
with:
|
||||||
|
key: wasi-libc-sysroot-linux-alpine-v2
|
||||||
|
path: lib/wasi-libc/sysroot
|
||||||
|
- name: Build wasi-libc
|
||||||
|
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||||
|
run: make wasi-libc
|
||||||
- name: Install fpm
|
- name: Install fpm
|
||||||
run: |
|
run: |
|
||||||
gem install --version 4.0.7 public_suffix
|
gem install --version 4.0.7 public_suffix
|
||||||
@@ -137,7 +146,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install wasmtime
|
- name: Install wasmtime
|
||||||
uses: bytecodealliance/actions/wasmtime/setup@v1
|
uses: bytecodealliance/actions/wasmtime/setup@v1
|
||||||
@@ -181,7 +190,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
@@ -249,6 +258,15 @@ jobs:
|
|||||||
- name: Build Binaryen
|
- name: Build Binaryen
|
||||||
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
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: cache-wasi-libc
|
||||||
|
with:
|
||||||
|
key: wasi-libc-sysroot-linux-asserts-v6
|
||||||
|
path: lib/wasi-libc/sysroot
|
||||||
|
- name: Build wasi-libc
|
||||||
|
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||||
|
run: make wasi-libc
|
||||||
- run: make gen-device -j4
|
- run: make gen-device -j4
|
||||||
- name: Test TinyGo
|
- name: Test TinyGo
|
||||||
run: make ASSERT=1 test
|
run: make ASSERT=1 test
|
||||||
@@ -298,7 +316,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ name: LLVM
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ build-llvm-image ]
|
branches: [ build-llvm-image ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ jobs:
|
|||||||
run: sudo apt-get remove llvm-18
|
run: sudo apt-get remove llvm-18
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Pull musl, bdwgc
|
- name: Pull musl
|
||||||
run: |
|
run: |
|
||||||
git submodule update --init lib/musl lib/bdwgc
|
git submodule update --init lib/musl
|
||||||
- name: Restore LLVM source cache
|
- name: Restore LLVM source cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-source
|
id: cache-llvm-source
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
# still works after checking out the dev branch (that is, when going from LLVM
|
# 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).
|
# 16 to LLVM 17 for example, both Clang 16 and Clang 17 are installed).
|
||||||
|
|
||||||
echo 'deb https://apt.llvm.org/noble/ llvm-toolchain-noble-20 main' | sudo tee /etc/apt/sources.list.d/llvm.list
|
echo 'deb https://apt.llvm.org/noble/ llvm-toolchain-noble-19 main' | sudo tee /etc/apt/sources.list.d/llvm.list
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install --no-install-recommends -y \
|
sudo apt-get install --no-install-recommends -y \
|
||||||
llvm-20-dev \
|
llvm-19-dev \
|
||||||
clang-20 \
|
clang-19 \
|
||||||
libclang-20-dev \
|
libclang-19-dev \
|
||||||
lld-20
|
lld-19
|
||||||
|
|||||||
@@ -13,17 +13,9 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-windows:
|
build-windows:
|
||||||
runs-on: ${{ matrix.image }}
|
runs-on: windows-2022
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ steps.version.outputs.version }}
|
version: ${{ steps.version.outputs.version }}
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
goarch: [ amd64, arm64 ]
|
|
||||||
include:
|
|
||||||
- goarch: amd64
|
|
||||||
image: windows-2022
|
|
||||||
- goarch: arm64
|
|
||||||
image: windows-11-arm
|
|
||||||
steps:
|
steps:
|
||||||
- name: Configure pagefile
|
- name: Configure pagefile
|
||||||
uses: al-cheb/configure-pagefile-action@v1.4
|
uses: al-cheb/configure-pagefile-action@v1.4
|
||||||
@@ -31,7 +23,7 @@ jobs:
|
|||||||
minimum-size: 8GB
|
minimum-size: 8GB
|
||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
- uses: MinoruSekine/setup-scoop@v4
|
- uses: brechtm/setup-scoop@v2
|
||||||
with:
|
with:
|
||||||
scoop_update: 'false'
|
scoop_update: 'false'
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
@@ -49,7 +41,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Restore cached LLVM source
|
- name: Restore cached LLVM source
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
@@ -80,7 +72,7 @@ jobs:
|
|||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
id: cache-llvm-build
|
id: cache-llvm-build
|
||||||
with:
|
with:
|
||||||
key: llvm-build-19-windows-${{ matrix.goarch }}-v1
|
key: llvm-build-19-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'
|
||||||
@@ -99,10 +91,19 @@ jobs:
|
|||||||
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
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: cache-wasi-libc
|
||||||
|
with:
|
||||||
|
key: wasi-libc-sysroot-v5
|
||||||
|
path: lib/wasi-libc/sysroot
|
||||||
|
- name: Build wasi-libc
|
||||||
|
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
|
||||||
|
run: make wasi-libc
|
||||||
- name: Cache Go cache
|
- name: Cache Go cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
key: go-cache-windows-${{ matrix.goarch }}-v1-${{ hashFiles('go.mod') }}
|
key: go-cache-windows-v1-${{ hashFiles('go.mod') }}
|
||||||
path: |
|
path: |
|
||||||
C:/Users/runneradmin/AppData/Local/go-build
|
C:/Users/runneradmin/AppData/Local/go-build
|
||||||
C:/Users/runneradmin/go/pkg/mod
|
C:/Users/runneradmin/go/pkg/mod
|
||||||
@@ -113,15 +114,14 @@ jobs:
|
|||||||
run: make -j3 gen-device
|
run: make -j3 gen-device
|
||||||
- name: Test TinyGo
|
- name: Test TinyGo
|
||||||
shell: bash
|
shell: bash
|
||||||
if: matrix.goarch == 'amd64' # skip on ARM64 to speed up build
|
run: make test GOTESTFLAGS="-short"
|
||||||
run: make test GOTESTFLAGS="-only-current-os"
|
|
||||||
- name: Build TinyGo release tarball
|
- name: Build TinyGo release tarball
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make build/release -j4
|
run: make build/release -j4
|
||||||
- name: Make release artifact
|
- name: Make release artifact
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: build/release
|
working-directory: build/release
|
||||||
run: 7z -tzip a tinygo${{ steps.version.outputs.version }}.windows-${{ matrix.goarch }}.zip tinygo
|
run: 7z -tzip a tinygo${{ steps.version.outputs.version }}.windows-amd64.zip tinygo
|
||||||
- name: Publish release artifact
|
- name: Publish release artifact
|
||||||
# Note: this release artifact is double-zipped, see:
|
# Note: this release artifact is double-zipped, see:
|
||||||
# https://github.com/actions/upload-artifact/issues/39
|
# https://github.com/actions/upload-artifact/issues/39
|
||||||
@@ -131,8 +131,8 @@ jobs:
|
|||||||
# 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@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: windows-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}
|
name: windows-amd64-double-zipped-${{ steps.version.outputs.version }}
|
||||||
path: build/release/tinygo${{ steps.version.outputs.version }}.windows-${{ matrix.goarch }}.zip
|
path: build/release/tinygo${{ steps.version.outputs.version }}.windows-amd64.zip
|
||||||
|
|
||||||
smoke-test-windows:
|
smoke-test-windows:
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
@@ -144,7 +144,7 @@ jobs:
|
|||||||
minimum-size: 8GB
|
minimum-size: 8GB
|
||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
- uses: MinoruSekine/setup-scoop@v4
|
- uses: brechtm/setup-scoop@v2
|
||||||
with:
|
with:
|
||||||
scoop_update: 'false'
|
scoop_update: 'false'
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
@@ -156,7 +156,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
@@ -186,7 +186,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
@@ -210,7 +210,7 @@ jobs:
|
|||||||
minimum-size: 8GB
|
minimum-size: 8GB
|
||||||
maximum-size: 24GB
|
maximum-size: 24GB
|
||||||
disk-root: "C:"
|
disk-root: "C:"
|
||||||
- uses: MinoruSekine/setup-scoop@v4
|
- uses: brechtm/setup-scoop@v2
|
||||||
with:
|
with:
|
||||||
scoop_update: 'false'
|
scoop_update: 'false'
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
@@ -222,7 +222,7 @@ jobs:
|
|||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.25.0'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
- name: Download TinyGo build
|
- name: Download TinyGo build
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
|
|||||||
+1
-3
@@ -35,9 +35,7 @@
|
|||||||
[submodule "src/net"]
|
[submodule "src/net"]
|
||||||
path = src/net
|
path = src/net
|
||||||
url = https://github.com/tinygo-org/net.git
|
url = https://github.com/tinygo-org/net.git
|
||||||
|
branch = dev
|
||||||
[submodule "lib/wasi-cli"]
|
[submodule "lib/wasi-cli"]
|
||||||
path = lib/wasi-cli
|
path = lib/wasi-cli
|
||||||
url = https://github.com/WebAssembly/wasi-cli
|
url = https://github.com/WebAssembly/wasi-cli
|
||||||
[submodule "lib/bdwgc"]
|
|
||||||
path = lib/bdwgc
|
|
||||||
url = https://github.com/ivmai/bdwgc.git
|
|
||||||
|
|||||||
+2
-8
@@ -85,17 +85,11 @@ Try running TinyGo:
|
|||||||
|
|
||||||
./build/tinygo help
|
./build/tinygo help
|
||||||
|
|
||||||
Also, make sure the `tinygo` binary really is statically linked. The command to check for
|
Also, make sure the `tinygo` binary really is statically linked. Check this
|
||||||
dynamic dependencies differs depending on your operating system.
|
using `ldd` (not to be confused with `lld`):
|
||||||
|
|
||||||
On Linux, use `ldd` (not to be confused with `lld`):
|
|
||||||
|
|
||||||
ldd ./build/tinygo
|
ldd ./build/tinygo
|
||||||
|
|
||||||
On macOS, use otool -L:
|
|
||||||
|
|
||||||
otool -L ./build/tinygo
|
|
||||||
|
|
||||||
The result should not contain libclang or libLLVM.
|
The result should not contain libclang or libLLVM.
|
||||||
|
|
||||||
## Make a release tarball
|
## Make a release tarball
|
||||||
|
|||||||
-200
@@ -1,203 +1,3 @@
|
|||||||
0.39.0
|
|
||||||
---
|
|
||||||
* **general**
|
|
||||||
- all: add Go 1.25 support
|
|
||||||
- net: update to latest tinygo net package
|
|
||||||
- docs: clarify build verification step for macOS users
|
|
||||||
- Add flag to skip Renesas SVD builds
|
|
||||||
* **build**
|
|
||||||
- Makefile: install missing dlmalloc files
|
|
||||||
- flash: add -o flag support to save built binary (Fixes #4937) (#4942)
|
|
||||||
- fix: update version of clang to 17 to accommodate latest Go 1.25 docker base image
|
|
||||||
* **ci**
|
|
||||||
- chore: update all CI builds to test Go 1.25 release
|
|
||||||
- fix: disable test-newest since CircleCI seems unable to download due to rate-limits on Dockerhub
|
|
||||||
- ci: rename some jobs to avoid churn on every Go/LLVM version bump
|
|
||||||
- ci: make the goroutines test less racy
|
|
||||||
- tests: de-flake goroutines test
|
|
||||||
* **compiler**
|
|
||||||
- compiler: implement internal/abi.Escape
|
|
||||||
* **main**
|
|
||||||
- main: show the compiler error (if any) for `tinygo test -c`
|
|
||||||
- chore: correct GOOS=js name in error messages for WASM
|
|
||||||
* **machine**
|
|
||||||
- machine: add international keys
|
|
||||||
- machine: remove some unnecessary "// peripherals:" comments
|
|
||||||
- machine: add I2C pin comments
|
|
||||||
- machine: standardize I2C errors with "i2c:" prefix
|
|
||||||
- machine: make I2C usable in the simulator
|
|
||||||
- fix: add SPI and I2C to teensy 4.1 (#4943)
|
|
||||||
- `rp2`: use the correct channel mask for rp2350 ADC; hold lock during read (#4938)
|
|
||||||
- `rp2`: disable digital input for analog inputs
|
|
||||||
* **runtime**
|
|
||||||
- runtime: ensure time.Sleep(d) sleeps at least d
|
|
||||||
- runtime: stub out weak pointer support
|
|
||||||
- runtime: implement dummy AddCleanup
|
|
||||||
- runtime: enable multi-core scheduler for rp2350
|
|
||||||
- `internal/task`: use -stack-size flag when starting a new thread
|
|
||||||
- `internal/task`: add SA_RESTART flag to GC interrupts
|
|
||||||
- `internal/task`: a few small correctness fixes
|
|
||||||
- `internal/gclayout`: make gclayout values constants
|
|
||||||
- darwin: add threading support and use it by default
|
|
||||||
* **standard library**
|
|
||||||
- `sync`: implement sync.Swap
|
|
||||||
- `reflect`: implement Method.IsExported
|
|
||||||
* **testing**
|
|
||||||
- testing: stub out testing.B.Loop
|
|
||||||
* **targets**
|
|
||||||
- `stm32`: add support for the STM32L031G6U6
|
|
||||||
- add metro-rp2350 board definition (#4989)
|
|
||||||
- `rp2040/rp2350`: set the default stack size to 8k for rp2040/rp2350 based boards where this was not already the case
|
|
||||||
|
|
||||||
|
|
||||||
0.38.0
|
|
||||||
---
|
|
||||||
* **general**
|
|
||||||
- `go.*`: upgrade `golang.org/x/tools` to v0.30.0
|
|
||||||
- `all`: add support for LLVM 20
|
|
||||||
* **build**
|
|
||||||
- go back to using MinoruSekine/setup-scoop for Windows CI builds
|
|
||||||
- `flake.*`: upgrade to nixpkgs 25.05, LLVM 20
|
|
||||||
- `Makefile`: only detect ccache command when needed
|
|
||||||
- `Makefile`: create random filename inside rule
|
|
||||||
- `Makefile`: don't set GOROOT
|
|
||||||
- `Makefile`: call uname at most once
|
|
||||||
- `Makefile`: only read NodeJS version when it is needed
|
|
||||||
* **compiler**
|
|
||||||
- add support for `GODEBUG=gotypesalias=1`
|
|
||||||
- `interp`: fix `copy()` from/to external buffers
|
|
||||||
- add `-nobounds` (similar to `-gcflags=-B`)
|
|
||||||
- `compileopts`: add library version to cached library path
|
|
||||||
- `builder`: build wasi-libc inside TinyGo
|
|
||||||
- `builder`: simplify bdwgc libc dependency
|
|
||||||
- `builder`: don't use precompiled libraries
|
|
||||||
- `compileopts`: enable support for `GOARCH=wasm` in `tinygo test`
|
|
||||||
* **fixes**
|
|
||||||
- `rp2350`: Fix DMA to SPI transmits on RP2350 (#4903)
|
|
||||||
- `microbit v2`: use OpenOCD flash method on microbit v2 when using Nordic Semi SoftDevice
|
|
||||||
- `main`: display all of the current GC options for the `-gc` flag
|
|
||||||
- Remove duplicated error handling
|
|
||||||
- `sync`: fix `TestMutexConcurrent` test
|
|
||||||
- fix race condition in `testdata/goroutines.go`
|
|
||||||
- fix build warnings on Windows ARM
|
|
||||||
* **machine**
|
|
||||||
- `usb`: add USB mass storage class support
|
|
||||||
- implement usb receive message throttling
|
|
||||||
- declare usb endpoints per-platform
|
|
||||||
- `samd21`: implement watchdog
|
|
||||||
- `samd51`: write to flash memory in 512 byte long chunks
|
|
||||||
- `samd21`: write to flash memory in 64 byte long chunks
|
|
||||||
- don't inline RTT `WriteByte` everywhere
|
|
||||||
- `rp2`: unexport machine-specific errors
|
|
||||||
- `rp2`: discount scheduling delays in I2C timeouts (#4876)
|
|
||||||
- use pointer receiver in simulated PWM peripherals
|
|
||||||
- add simulated PWM/timer peripherals
|
|
||||||
- `rp2`: expose usb endpoint stall handling
|
|
||||||
- `arm`: clear pending interrupts before enabling them
|
|
||||||
- `rp2`: merge common usb code (#4856)
|
|
||||||
* **main**
|
|
||||||
- add "cores" and "threads" schedulers to help text
|
|
||||||
- add `StartPos` and `EndPos` to `-json` build output
|
|
||||||
- change `-json` flag to match upstream Go
|
|
||||||
* **runtime**
|
|
||||||
- don't lock the print output inside interrupts
|
|
||||||
- don't try to interrupt other cores before they are started
|
|
||||||
- implement `NumCPU` for the multicore scheduler
|
|
||||||
- add support for multicore scheduler
|
|
||||||
- refactor obtaining the system stack
|
|
||||||
- `interrupt`: add `Checkpoint` type
|
|
||||||
- add `exportedFuncPtr`
|
|
||||||
- avoid an allocation in `(*time.Timer).Reset`
|
|
||||||
- stub runtime signal functions for `os/signal` on wasip1
|
|
||||||
- move `timeUnit` to a single place
|
|
||||||
- implement `NumCPU` for `-scheduler=threads`
|
|
||||||
- move `mainExited` boolean
|
|
||||||
- `internal/task`: rename `tinygo_pause` to `tinygo_task_exit`
|
|
||||||
- map every goroutine to a new OS thread
|
|
||||||
- refactor `timerQueue`
|
|
||||||
- make conservative and precise GC MT-safe
|
|
||||||
- `internal/task`: implement atomic primitives for preemptive scheduling
|
|
||||||
- Use diskutil on macOS to extract volume name and path for FAT mounts #4928
|
|
||||||
* **standard library**
|
|
||||||
- `net`: update submodule to latest commits
|
|
||||||
- `runtime/debug`: add GC related stubs
|
|
||||||
- `metrics`: flesh out some of the metric types
|
|
||||||
- `reflect`: Chan related stubs
|
|
||||||
- `os`: handle relative and abs paths in `Executable()`
|
|
||||||
- `os`: add `os.Executable()` for Darwin
|
|
||||||
- `sync`: implement `RWMutex` using futexes
|
|
||||||
- `reflect`: Add `SliceOf`, `ArrayOf`, `StructOf`, `MapOf`, `FuncOf`
|
|
||||||
* **targets**
|
|
||||||
- `rp2040`: add multicore support
|
|
||||||
- `riscv32`: use `gdb` binary as a fallback
|
|
||||||
- add target for Microbit v2 with SoftDevice S140 support for both peripheral and central
|
|
||||||
- `windows`: use MSVCRT.DLL instead of UCRT on i386
|
|
||||||
- `windows`: add windows/386 support
|
|
||||||
- `arm64`: remove unnecessary `.section` directive
|
|
||||||
- `riscv-qemu`: actually sleep in `time.Sleep()`
|
|
||||||
- `riscv`: define CSR constants and use them where possible
|
|
||||||
- `darwin`: support Boehm GC (and use by default)
|
|
||||||
- `windows`: add support for the Boehm-Demers-Weiser GC
|
|
||||||
- `windows`: fix wrong register for first parameter
|
|
||||||
* **wasm**
|
|
||||||
- add Boehm GC support
|
|
||||||
- refactor/modify stub signal handling
|
|
||||||
- don't block `//go:wasmexport` because of running goroutines
|
|
||||||
- use `int64` instead of `float64` for the `timeUnit`
|
|
||||||
* **boards**
|
|
||||||
- Add board support for BigTreeTech SKR Pico (#4842)
|
|
||||||
|
|
||||||
|
|
||||||
0.37.0
|
|
||||||
---
|
|
||||||
* **general**
|
|
||||||
- add the Boehm-Demers-Weiser GC on Linux
|
|
||||||
* **ci**
|
|
||||||
- add more tests for wasm and baremetal
|
|
||||||
* **compiler**
|
|
||||||
- crypto/internal/sysrand is allowed to use unsafe signatures
|
|
||||||
* **examples**
|
|
||||||
- add goroutine benchmark to examples
|
|
||||||
* **fixes**
|
|
||||||
- ensure use of pointers for SPI interface on atsam21/atsam51 and other machines/boards that were missing implementation (#4798)
|
|
||||||
- replace loop counter with hw timer for USB SetAddressReq on rp2040 (#4796)
|
|
||||||
* **internal**
|
|
||||||
- update to go.bytecodealliance.org@v0.6.2 in GNUmakefile and internal/wasm-tools
|
|
||||||
- exclude certain files when copying package in internal/cm
|
|
||||||
- update to go.bytecodealliance.org/cm@v0.2.2 in internal/cm
|
|
||||||
- remove old reflect.go in internal/reflectlite
|
|
||||||
* **loader**
|
|
||||||
- use build tags for package iter and iter methods on reflect.Value in loader, iter, reflect
|
|
||||||
- add shim for go1.22 and earlier in loader, iter
|
|
||||||
* **machine**
|
|
||||||
- bump rp2040 to 200MHz (#4768)
|
|
||||||
- correct register address for Pin.SetInterrupt for rp2350 (#4782)
|
|
||||||
- don't block the rp2xxx UART interrupt handler
|
|
||||||
- fix RP2040 Pico board on the playground
|
|
||||||
- add flash support for rp2350 (#4803)
|
|
||||||
* **os**
|
|
||||||
- add stub Symlink for wasm
|
|
||||||
* **refactor**
|
|
||||||
- use *SPI everywhere to make consistent for implementations. Fixes #4663 "in reverse" by making SPI a pointer everywhere, as discussed in the comments.
|
|
||||||
* **reflect**
|
|
||||||
- add Value.SetIter{Key,Value} and MapIter.Reset in reflect, internal/reflectlite
|
|
||||||
- embed reflectlite types into reflect types in reflect, internal/reflectlite
|
|
||||||
- add Go 1.24 iter.Seq[2] methods
|
|
||||||
- copy reflect iter tests from upstream Go
|
|
||||||
- panic on Type.CanSeq[2] instead of returning false
|
|
||||||
- remove strconv.go
|
|
||||||
- remove unused go:linkname functions
|
|
||||||
* **riscv-qemu**
|
|
||||||
- add VirtIO RNG device
|
|
||||||
- increase stack size
|
|
||||||
* **runtime**
|
|
||||||
- only allocate heap memory when needed
|
|
||||||
- remove unused file func.go
|
|
||||||
- use package reflectlite
|
|
||||||
* **transform**
|
|
||||||
- cherry-pick from #4774
|
|
||||||
|
|
||||||
|
|
||||||
0.36.0
|
0.36.0
|
||||||
---
|
---
|
||||||
* **general**
|
* **general**
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||||
FROM golang:1.25 AS tinygo-llvm
|
FROM golang:1.24 AS tinygo-llvm
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y apt-utils make cmake clang-17 ninja-build && \
|
apt-get install -y apt-utils make cmake clang-15 ninja-build && \
|
||||||
rm -rf \
|
rm -rf \
|
||||||
/var/lib/apt/lists/* \
|
/var/lib/apt/lists/* \
|
||||||
/var/log/* \
|
/var/log/* \
|
||||||
@@ -33,7 +33,7 @@ RUN cd /tinygo/ && \
|
|||||||
|
|
||||||
# tinygo-compiler copies the compiler build over to a base Go container (without
|
# tinygo-compiler copies the compiler build over to a base Go container (without
|
||||||
# all the build tools etc).
|
# all the build tools etc).
|
||||||
FROM golang:1.25 AS tinygo-compiler
|
FROM golang:1.24 AS tinygo-compiler
|
||||||
|
|
||||||
# Copy tinygo build.
|
# Copy tinygo build.
|
||||||
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
|
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
|
||||||
|
|||||||
+57
-103
@@ -8,20 +8,13 @@ LLVM_PROJECTDIR ?= llvm-project
|
|||||||
CLANG_SRC ?= $(LLVM_PROJECTDIR)/clang
|
CLANG_SRC ?= $(LLVM_PROJECTDIR)/clang
|
||||||
LLD_SRC ?= $(LLVM_PROJECTDIR)/lld
|
LLD_SRC ?= $(LLVM_PROJECTDIR)/lld
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
|
||||||
# avoid calling uname on Windows
|
|
||||||
uname := Windows_NT
|
|
||||||
else
|
|
||||||
uname := $(shell uname -s)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# 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 = 19 18 17 16 15
|
LLVM_VERSIONS = 19 18 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)
|
||||||
ifeq ($(uname),Darwin)
|
ifeq ($(shell uname -s),Darwin)
|
||||||
# Also explicitly search Brew's copy, which is not in PATH by default.
|
# Also explicitly search Brew's copy, which is not in PATH by default.
|
||||||
BREW_PREFIX := $(shell brew --prefix)
|
BREW_PREFIX := $(shell brew --prefix)
|
||||||
toolSearchPathsVersion += $(BREW_PREFIX)/opt/llvm@$(2)/bin/$(1)-$(2) $(BREW_PREFIX)/opt/llvm@$(2)/bin/$(1)
|
toolSearchPathsVersion += $(BREW_PREFIX)/opt/llvm@$(2)/bin/$(1)-$(2) $(BREW_PREFIX)/opt/llvm@$(2)/bin/$(1)
|
||||||
@@ -34,6 +27,7 @@ LLVM_NM ?= $(call findLLVMTool,llvm-nm)
|
|||||||
|
|
||||||
# Go binary and GOROOT to select
|
# Go binary and GOROOT to select
|
||||||
GO ?= go
|
GO ?= go
|
||||||
|
export GOROOT = $(shell $(GO) env GOROOT)
|
||||||
|
|
||||||
# Flags to pass to go test.
|
# Flags to pass to go test.
|
||||||
GOTESTFLAGS ?=
|
GOTESTFLAGS ?=
|
||||||
@@ -44,10 +38,14 @@ TINYGO ?= $(call detect,tinygo,tinygo $(CURDIR)/build/tinygo)
|
|||||||
|
|
||||||
# Check for ccache if the user hasn't set it to on or off.
|
# Check for ccache if the user hasn't set it to on or off.
|
||||||
ifeq (, $(CCACHE))
|
ifeq (, $(CCACHE))
|
||||||
LLVM_OPTION += '-DLLVM_CCACHE_BUILD=$(if $(shell command -v ccache 2> /dev/null),ON,OFF)'
|
# Use CCACHE for LLVM if possible
|
||||||
else
|
ifneq (, $(shell command -v ccache 2> /dev/null))
|
||||||
LLVM_OPTION += '-DLLVM_CCACHE_BUILD=$(CCACHE)'
|
CCACHE := ON
|
||||||
|
else
|
||||||
|
CCACHE := OFF
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
LLVM_OPTION += '-DLLVM_CCACHE_BUILD=$(CCACHE)'
|
||||||
|
|
||||||
# Allow enabling LLVM assertions
|
# Allow enabling LLVM assertions
|
||||||
ifeq (1, $(ASSERT))
|
ifeq (1, $(ASSERT))
|
||||||
@@ -129,14 +127,14 @@ ifeq ($(OS),Windows_NT)
|
|||||||
|
|
||||||
USE_SYSTEM_BINARYEN ?= 1
|
USE_SYSTEM_BINARYEN ?= 1
|
||||||
|
|
||||||
else ifeq ($(uname),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 ($(uname),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
|
||||||
@@ -187,10 +185,7 @@ fmt-check: ## Warn if any source needs reformatting
|
|||||||
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
|
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
|
||||||
|
|
||||||
|
|
||||||
gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp ## Generate microcontroller-specific sources
|
gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-kendryte gen-device-nxp gen-device-rp gen-device-renesas ## Generate microcontroller-specific sources
|
||||||
ifneq ($(RENESAS), 0)
|
|
||||||
gen-device: gen-device-renesas
|
|
||||||
endif
|
|
||||||
ifneq ($(STM32), 0)
|
ifneq ($(STM32), 0)
|
||||||
gen-device: gen-device-stm32
|
gen-device: gen-device-stm32
|
||||||
endif
|
endif
|
||||||
@@ -264,34 +259,40 @@ build/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
|
||||||
|
|
||||||
|
# Build wasi-libc sysroot
|
||||||
|
.PHONY: wasi-libc
|
||||||
|
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
|
||||||
|
lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
|
||||||
|
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
|
||||||
|
cd lib/wasi-libc && $(MAKE) -j4 EXTRA_CFLAGS="-O2 -g -DNDEBUG -mnontrapping-fptoint -msign-ext" MALLOC_IMPL=none CC="$(CLANG)" AR=$(LLVM_AR) NM=$(LLVM_NM)
|
||||||
|
|
||||||
# Generate WASI syscall bindings
|
# Generate WASI syscall bindings
|
||||||
WASM_TOOLS_MODULE=go.bytecodealliance.org
|
WASM_TOOLS_MODULE=github.com/bytecodealliance/wasm-tools-go
|
||||||
.PHONY: wasi-syscall
|
.PHONY: wasi-syscall
|
||||||
wasi-syscall: wasi-cm
|
wasi-syscall: wasi-cm
|
||||||
rm -rf ./src/internal/wasi/*
|
|
||||||
go run -modfile ./internal/wasm-tools/go.mod $(WASM_TOOLS_MODULE)/cmd/wit-bindgen-go generate --versioned -o ./src/internal -p internal --cm internal/cm ./lib/wasi-cli/wit
|
go run -modfile ./internal/wasm-tools/go.mod $(WASM_TOOLS_MODULE)/cmd/wit-bindgen-go generate --versioned -o ./src/internal -p internal --cm internal/cm ./lib/wasi-cli/wit
|
||||||
|
|
||||||
# Copy package cm into src/internal/cm
|
# Copy package cm into src/internal/cm
|
||||||
.PHONY: wasi-cm
|
.PHONY: wasi-cm
|
||||||
wasi-cm:
|
wasi-cm:
|
||||||
rm -rf ./src/internal/cm/*
|
# rm -rf ./src/internal/cm
|
||||||
rsync -rv --delete --exclude go.mod --exclude '*_test.go' --exclude '*_json.go' --exclude '*.md' --exclude LICENSE $(shell go list -modfile ./internal/wasm-tools/go.mod -m -f {{.Dir}} $(WASM_TOOLS_MODULE)/cm)/ ./src/internal/cm
|
rsync -rv --delete --exclude '*_test.go' $(shell go list -modfile ./internal/wasm-tools/go.mod -m -f {{.Dir}} $(WASM_TOOLS_MODULE))/cm ./src/internal/
|
||||||
|
|
||||||
# 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-)))
|
||||||
MIN_NODEJS_VERSION=18
|
MIN_NODEJS_VERSION=18
|
||||||
|
|
||||||
.PHONY: check-nodejs-version
|
.PHONY: check-nodejs-version
|
||||||
check-nodejs-version:
|
check-nodejs-version:
|
||||||
@# Check whether NodeJS is available.
|
ifeq (, $(shell which node))
|
||||||
@if ! command -v node 2>&1 >/dev/null; then echo "Install NodeJS version ${MIN_NODEJS_VERSION}+ to run tests."; exit 1; fi
|
@echo "Install NodeJS version 18+ to run tests."; exit 1;
|
||||||
|
endif
|
||||||
@# Check whether the version is high enough.
|
@if [ $(NODEJS_VERSION) -lt $(MIN_NODEJS_VERSION) ]; then echo "Install NodeJS version 18+ to run tests."; exit 1; fi
|
||||||
@if [ "`node -v | sed 's/v\([0-9]\+\).*/\\1/g'`" -lt $(MIN_NODEJS_VERSION) ]; then echo "Install NodeJS version $(MIN_NODEJS_VERSION)+ to run tests."; exit 1; fi
|
|
||||||
|
|
||||||
tinygo: ## Build the TinyGo compiler
|
tinygo: ## Build the TinyGo compiler
|
||||||
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " $(MAKE) llvm-source"; echo " $(MAKE) $(LLVM_BUILDDIR)"; exit 1; fi
|
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " $(MAKE) llvm-source"; echo " $(MAKE) $(LLVM_BUILDDIR)"; exit 1; fi
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags "byollvm osusergo" .
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GOENVFLAGS) $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags "byollvm osusergo" .
|
||||||
test: check-nodejs-version
|
test: wasi-libc check-nodejs-version
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags "byollvm osusergo" $(GOTESTPKGS)
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags "byollvm osusergo" $(GOTESTPKGS)
|
||||||
|
|
||||||
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
|
# Standard library packages that pass tests on darwin, linux, wasi, and windows, but take over a minute in wasi
|
||||||
@@ -430,15 +431,22 @@ TEST_PACKAGES_NONWASM = \
|
|||||||
# (just like wasm).
|
# (just like wasm).
|
||||||
# * picolibc math functions apparently are less precise, the math package
|
# * picolibc math functions apparently are less precise, the math package
|
||||||
# fails on baremetal.
|
# fails on baremetal.
|
||||||
|
# * Some packages fail or hang for an unknown reason, this should be
|
||||||
|
# investigated and fixed.
|
||||||
TEST_PACKAGES_BAREMETAL = $(filter-out $(TEST_PACKAGES_NONBAREMETAL), $(TEST_PACKAGES_FAST))
|
TEST_PACKAGES_BAREMETAL = $(filter-out $(TEST_PACKAGES_NONBAREMETAL), $(TEST_PACKAGES_FAST))
|
||||||
TEST_PACKAGES_NONBAREMETAL = \
|
TEST_PACKAGES_NONBAREMETAL = \
|
||||||
$(TEST_PACKAGES_NONWASM) \
|
$(TEST_PACKAGES_NONWASM) \
|
||||||
|
crypto/elliptic \
|
||||||
math \
|
math \
|
||||||
|
reflect \
|
||||||
|
encoding/asn1 \
|
||||||
|
encoding/base32 \
|
||||||
|
go/ast \
|
||||||
$(nil)
|
$(nil)
|
||||||
|
|
||||||
# Report platforms on which each standard library package is known to pass tests
|
# Report platforms on which each standard library package is known to pass tests
|
||||||
|
jointmp := $(shell echo /tmp/join.$$$$)
|
||||||
report-stdlib-tests-pass:
|
report-stdlib-tests-pass:
|
||||||
$(eval jointmp := $(shell echo /tmp/join.$$$$))
|
|
||||||
@for t in $(TEST_PACKAGES_DARWIN); do echo "$$t darwin"; done | sort > $(jointmp).darwin
|
@for t in $(TEST_PACKAGES_DARWIN); do echo "$$t darwin"; done | sort > $(jointmp).darwin
|
||||||
@for t in $(TEST_PACKAGES_LINUX); do echo "$$t linux"; done | sort > $(jointmp).linux
|
@for t in $(TEST_PACKAGES_LINUX); do echo "$$t linux"; done | sort > $(jointmp).linux
|
||||||
@for t in $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW); do echo "$$t darwin linux wasi windows"; done | sort > $(jointmp).portable
|
@for t in $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW); do echo "$$t darwin linux wasi windows"; done | sort > $(jointmp).portable
|
||||||
@@ -447,11 +455,11 @@ report-stdlib-tests-pass:
|
|||||||
@rm $(jointmp).*
|
@rm $(jointmp).*
|
||||||
|
|
||||||
# Standard library packages that pass tests quickly on the current platform
|
# Standard library packages that pass tests quickly on the current platform
|
||||||
ifeq ($(uname),Darwin)
|
ifeq ($(shell uname),Darwin)
|
||||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
||||||
TEST_IOFS := true
|
TEST_IOFS := true
|
||||||
endif
|
endif
|
||||||
ifeq ($(uname),Linux)
|
ifeq ($(shell uname),Linux)
|
||||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
||||||
TEST_IOFS := true
|
TEST_IOFS := true
|
||||||
endif
|
endif
|
||||||
@@ -460,15 +468,11 @@ TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
|||||||
TEST_IOFS := false
|
TEST_IOFS := false
|
||||||
endif
|
endif
|
||||||
|
|
||||||
TEST_SKIP_FLAG := -skip='TestExtraMethods|TestParseAndBytesRoundTrip/P256/Generic'
|
|
||||||
|
|
||||||
# Test known-working standard library packages.
|
# Test known-working standard library packages.
|
||||||
# TODO: parallelize, and only show failing tests (no implied -v flag).
|
# TODO: parallelize, and only show failing tests (no implied -v flag).
|
||||||
.PHONY: tinygo-test
|
.PHONY: tinygo-test
|
||||||
tinygo-test:
|
tinygo-test:
|
||||||
@# TestExtraMethods: used by many crypto packages and uses reflect.Type.Method which is not implemented.
|
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||||
@# TestParseAndBytesRoundTrip/P256/Generic: relies on t.Skip() which is not implemented
|
|
||||||
$(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
|
||||||
@# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also
|
@# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also
|
||||||
@# requires a large stack-size. Hence, io/fs is only run conditionally.
|
@# requires a large stack-size. Hence, io/fs is only run conditionally.
|
||||||
@# For more details, see the comments on issue #3143.
|
@# For more details, see the comments on issue #3143.
|
||||||
@@ -476,7 +480,7 @@ ifeq ($(TEST_IOFS),true)
|
|||||||
$(TINYGO) test -stack-size=6MB io/fs
|
$(TINYGO) test -stack-size=6MB io/fs
|
||||||
endif
|
endif
|
||||||
tinygo-test-fast:
|
tinygo-test-fast:
|
||||||
$(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_HOST)
|
$(TINYGO) test $(TEST_PACKAGES_HOST)
|
||||||
tinygo-bench:
|
tinygo-bench:
|
||||||
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||||
tinygo-bench-fast:
|
tinygo-bench-fast:
|
||||||
@@ -484,18 +488,18 @@ tinygo-bench-fast:
|
|||||||
|
|
||||||
# Same thing, except for wasi rather than the current platform.
|
# Same thing, except for wasi rather than the current platform.
|
||||||
tinygo-test-wasm:
|
tinygo-test-wasm:
|
||||||
$(TINYGO) test -target wasm $(TEST_SKIP_FLAG) $(TEST_PACKAGES_WASM)
|
$(TINYGO) test -target wasm $(TEST_PACKAGES_WASM)
|
||||||
tinygo-test-wasi:
|
tinygo-test-wasi:
|
||||||
$(TINYGO) test -target wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
$(TINYGO) test -target wasip1 $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
||||||
tinygo-test-wasip1:
|
tinygo-test-wasip1:
|
||||||
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
||||||
tinygo-test-wasip1-fast:
|
tinygo-test-wasip1-fast:
|
||||||
$(TINYGO) test -target=wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
|
$(TINYGO) test -target=wasip1 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
|
||||||
|
|
||||||
tinygo-test-wasip2-slow:
|
tinygo-test-wasip2-slow:
|
||||||
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_SLOW)
|
$(TINYGO) test -target=wasip2 $(TEST_PACKAGES_SLOW)
|
||||||
tinygo-test-wasip2-fast:
|
tinygo-test-wasip2-fast:
|
||||||
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
|
$(TINYGO) test -target=wasip2 $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
|
||||||
|
|
||||||
tinygo-test-wasip2-sum-slow:
|
tinygo-test-wasip2-sum-slow:
|
||||||
TINYGO=$(TINYGO) \
|
TINYGO=$(TINYGO) \
|
||||||
@@ -521,16 +525,16 @@ tinygo-bench-wasip2-fast:
|
|||||||
|
|
||||||
# Run tests on riscv-qemu since that one provides a large amount of memory.
|
# Run tests on riscv-qemu since that one provides a large amount of memory.
|
||||||
tinygo-test-baremetal:
|
tinygo-test-baremetal:
|
||||||
$(TINYGO) test -target riscv-qemu $(TEST_SKIP_FLAG) $(TEST_PACKAGES_BAREMETAL)
|
$(TINYGO) test -target riscv-qemu $(TEST_PACKAGES_BAREMETAL)
|
||||||
|
|
||||||
# Test external packages in a large corpus.
|
# Test external packages in a large corpus.
|
||||||
test-corpus:
|
test-corpus:
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml
|
||||||
test-corpus-fast:
|
test-corpus-fast:
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus -short . -corpus=testdata/corpus.yaml
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus -short . -corpus=testdata/corpus.yaml
|
||||||
test-corpus-wasi:
|
test-corpus-wasi: wasi-libc
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip1
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip1
|
||||||
test-corpus-wasip2:
|
test-corpus-wasip2: wasi-libc
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip2
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test $(GOTESTFLAGS) -timeout=1h -buildmode exe -tags byollvm -run TestCorpus . -corpus=testdata/corpus.yaml -target=wasip2
|
||||||
|
|
||||||
.PHONY: testchdir
|
.PHONY: testchdir
|
||||||
@@ -633,12 +637,8 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=microbit-v2-s113v7 examples/microbit-blink
|
$(TINYGO) build -size short -o test.hex -target=microbit-v2-s113v7 examples/microbit-blink
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=microbit-v2-s140v7 examples/microbit-blink
|
|
||||||
@$(MD5SUM) test.hex
|
|
||||||
$(TINYGO) build -size short -o test.hex -target=nrf52840-mdk examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=nrf52840-mdk examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=btt-skr-pico examples/uart
|
|
||||||
@$(MD5SUM) test.hex
|
|
||||||
$(TINYGO) build -size short -o test.hex -target=pca10031 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pca10031 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=reelboard examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=reelboard examples/blinky1
|
||||||
@@ -785,8 +785,6 @@ endif
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=pico-plus2 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=pico-plus2 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=metro-rp2350 examples/blinky1
|
|
||||||
@$(MD5SUM) test.hex
|
|
||||||
$(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-tiny examples/echo
|
$(TINYGO) build -size short -o test.hex -target=waveshare-rp2040-tiny examples/echo
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
# test pwm
|
# test pwm
|
||||||
@@ -803,10 +801,6 @@ 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=pico examples/usb-storage
|
|
||||||
@$(MD5SUM) test.hex
|
|
||||||
$(TINYGO) build -size short -o test.hex -target=pico2 examples/usb-storage
|
|
||||||
@$(MD5SUM) test.hex
|
|
||||||
$(TINYGO) build -size short -o test.hex -target=nrf52840-s140v6-uf2-generic examples/machinetest
|
$(TINYGO) build -size short -o test.hex -target=nrf52840-s140v6-uf2-generic examples/machinetest
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
ifneq ($(STM32), 0)
|
ifneq ($(STM32), 0)
|
||||||
@@ -846,8 +840,6 @@ ifneq ($(STM32), 0)
|
|||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=mksnanov3 examples/blinky1
|
$(TINYGO) build -size short -o test.hex -target=mksnanov3 examples/blinky1
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=stm32l0x1 examples/serial
|
|
||||||
@$(MD5SUM) test.hex
|
|
||||||
endif
|
endif
|
||||||
$(TINYGO) build -size short -o test.hex -target=atmega328pb examples/blinkm
|
$(TINYGO) build -size short -o test.hex -target=atmega328pb examples/blinkm
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
@@ -918,7 +910,7 @@ endif
|
|||||||
$(TINYGO) build -size short -o test.hex -target=hw-651 examples/machinetest
|
$(TINYGO) build -size short -o test.hex -target=hw-651 examples/machinetest
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
$(TINYGO) build -size short -o test.hex -target=hw-651-s110v8 examples/machinetest
|
$(TINYGO) build -size short -o test.hex -target=hw-651-s110v8 examples/machinetest
|
||||||
@$(MD5SUM) test.hex
|
@$(MD5SUM) test.hex
|
||||||
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
|
||||||
@@ -953,15 +945,13 @@ endif
|
|||||||
wasmtest:
|
wasmtest:
|
||||||
$(GO) test ./tests/wasm
|
$(GO) test ./tests/wasm
|
||||||
|
|
||||||
build/release: tinygo gen-device $(if $(filter 1,$(USE_SYSTEM_BINARYEN)),,binaryen)
|
build/release: tinygo gen-device wasi-libc $(if $(filter 1,$(USE_SYSTEM_BINARYEN)),,binaryen)
|
||||||
@mkdir -p build/release/tinygo/bin
|
@mkdir -p build/release/tinygo/bin
|
||||||
@mkdir -p build/release/tinygo/lib/bdwgc
|
|
||||||
@mkdir -p build/release/tinygo/lib/clang/include
|
@mkdir -p build/release/tinygo/lib/clang/include
|
||||||
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
|
||||||
@mkdir -p build/release/tinygo/lib/macos-minimal-sdk
|
@mkdir -p build/release/tinygo/lib/macos-minimal-sdk
|
||||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/crt
|
|
||||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/math
|
|
||||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||||
|
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-crt/stdio
|
||||||
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
@mkdir -p build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
||||||
@mkdir -p build/release/tinygo/lib/musl/arch
|
@mkdir -p build/release/tinygo/lib/musl/arch
|
||||||
@mkdir -p build/release/tinygo/lib/musl/crt
|
@mkdir -p build/release/tinygo/lib/musl/crt
|
||||||
@@ -969,8 +959,7 @@ build/release: tinygo gen-device $(if $(filter 1,$(USE_SYSTEM_BINARYEN)),,binary
|
|||||||
@mkdir -p build/release/tinygo/lib/nrfx
|
@mkdir -p build/release/tinygo/lib/nrfx
|
||||||
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libc
|
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libc
|
||||||
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libm
|
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libm
|
||||||
@mkdir -p build/release/tinygo/lib/wasi-libc/dlmalloc
|
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-bottom-half/headers
|
||||||
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-bottom-half
|
|
||||||
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
||||||
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
@mkdir -p build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||||
@mkdir -p build/release/tinygo/lib/wasi-cli/
|
@mkdir -p build/release/tinygo/lib/wasi-cli/
|
||||||
@@ -979,7 +968,6 @@ build/release: tinygo gen-device $(if $(filter 1,$(USE_SYSTEM_BINARYEN)),,binary
|
|||||||
ifneq ($(USE_SYSTEM_BINARYEN),1)
|
ifneq ($(USE_SYSTEM_BINARYEN),1)
|
||||||
@cp -p build/wasm-opt$(EXE) build/release/tinygo/bin
|
@cp -p build/wasm-opt$(EXE) build/release/tinygo/bin
|
||||||
endif
|
endif
|
||||||
@cp -rp lib/bdwgc/* build/release/tinygo/lib/bdwgc
|
|
||||||
@cp -p $(abspath $(CLANG_SRC))/lib/Headers/*.h build/release/tinygo/lib/clang/include
|
@cp -p $(abspath $(CLANG_SRC))/lib/Headers/*.h build/release/tinygo/lib/clang/include
|
||||||
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
|
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
|
||||||
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
|
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
|
||||||
@@ -993,8 +981,6 @@ endif
|
|||||||
@cp -rp lib/musl/crt/crt1.c build/release/tinygo/lib/musl/crt
|
@cp -rp lib/musl/crt/crt1.c build/release/tinygo/lib/musl/crt
|
||||||
@cp -rp lib/musl/COPYRIGHT build/release/tinygo/lib/musl
|
@cp -rp lib/musl/COPYRIGHT build/release/tinygo/lib/musl
|
||||||
@cp -rp lib/musl/include build/release/tinygo/lib/musl
|
@cp -rp lib/musl/include build/release/tinygo/lib/musl
|
||||||
@cp -rp lib/musl/src/conf build/release/tinygo/lib/musl/src
|
|
||||||
@cp -rp lib/musl/src/ctype build/release/tinygo/lib/musl/src
|
|
||||||
@cp -rp lib/musl/src/env build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/env build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/errno build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/errno build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/exit build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/exit build/release/tinygo/lib/musl/src
|
||||||
@@ -1009,29 +995,19 @@ endif
|
|||||||
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/misc build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/misc build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/multibyte build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/multibyte build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/sched build/release/tinygo/lib/musl/src
|
|
||||||
@cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/stdlib build/release/tinygo/lib/musl/src
|
|
||||||
@cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/thread build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/thread build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/time build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/time build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/unistd build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/unistd build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/musl/src/process build/release/tinygo/lib/musl/src
|
@cp -rp lib/musl/src/process build/release/tinygo/lib/musl/src
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/crt/pseudo-reloc.c build/release/tinygo/lib/mingw-w64/mingw-w64-crt/crt
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/def-include build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
@cp -rp lib/mingw-w64/mingw-w64-crt/def-include build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/gdtoa build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/include build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/api-ms-win-crt-* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/api-ms-win-crt-* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/advapi32.def.in build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/kernel32.def.in build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/kernel32.def.in build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/lib-common/msvcrt.def.in build/release/tinygo/lib/mingw-w64/mingw-w64-crt/lib-common
|
@cp -rp lib/mingw-w64/mingw-w64-crt/stdio/ucrt_* build/release/tinygo/lib/mingw-w64/mingw-w64-crt/stdio
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/math/x86 build/release/tinygo/lib/mingw-w64/mingw-w64-crt/math
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/misc build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-crt/stdio build/release/tinygo/lib/mingw-w64/mingw-w64-crt
|
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-headers/crt/ build/release/tinygo/lib/mingw-w64/mingw-w64-headers
|
@cp -rp lib/mingw-w64/mingw-w64-headers/crt/ build/release/tinygo/lib/mingw-w64/mingw-w64-headers
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-headers/defaults/include build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
@cp -rp lib/mingw-w64/mingw-w64-headers/defaults/include build/release/tinygo/lib/mingw-w64/mingw-w64-headers/defaults
|
||||||
@cp -rp lib/mingw-w64/mingw-w64-headers/include build/release/tinygo/lib/mingw-w64/mingw-w64-headers
|
|
||||||
@cp -rp lib/nrfx/* build/release/tinygo/lib/nrfx
|
@cp -rp lib/nrfx/* build/release/tinygo/lib/nrfx
|
||||||
@cp -rp lib/picolibc/newlib/libc/ctype build/release/tinygo/lib/picolibc/newlib/libc
|
@cp -rp lib/picolibc/newlib/libc/ctype build/release/tinygo/lib/picolibc/newlib/libc
|
||||||
@cp -rp lib/picolibc/newlib/libc/include build/release/tinygo/lib/picolibc/newlib/libc
|
@cp -rp lib/picolibc/newlib/libc/include build/release/tinygo/lib/picolibc/newlib/libc
|
||||||
@@ -1041,37 +1017,15 @@ endif
|
|||||||
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
|
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
|
||||||
@cp -rp lib/picolibc/newlib/libm/math build/release/tinygo/lib/picolibc/newlib/libm
|
@cp -rp lib/picolibc/newlib/libm/math build/release/tinygo/lib/picolibc/newlib/libm
|
||||||
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
||||||
@cp -rp lib/wasi-libc/dlmalloc/src build/release/tinygo/lib/wasi-libc/dlmalloc
|
@cp -rp lib/wasi-libc/libc-bottom-half/headers/public build/release/tinygo/lib/wasi-libc/libc-bottom-half/headers
|
||||||
@cp -rp lib/wasi-libc/libc-bottom-half/cloudlibc build/release/tinygo/lib/wasi-libc/libc-bottom-half
|
|
||||||
@cp -rp lib/wasi-libc/libc-bottom-half/headers build/release/tinygo/lib/wasi-libc/libc-bottom-half
|
|
||||||
@cp -rp lib/wasi-libc/libc-bottom-half/sources build/release/tinygo/lib/wasi-libc/libc-bottom-half
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/headers build/release/tinygo/lib/wasi-libc/libc-top-half
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/arch/generic build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
@cp -rp lib/wasi-libc/libc-top-half/musl/arch/generic build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/arch/wasm32 build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
@cp -rp lib/wasi-libc/libc-top-half/musl/arch/wasm32 build/release/tinygo/lib/wasi-libc/libc-top-half/musl/arch
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/include build/release/tinygo/lib/wasi-libc/libc-top-half/musl
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/conf build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/dirent build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/env build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/errno build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/exit build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/fcntl build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/fenv build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/include build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
@cp -rp lib/wasi-libc/libc-top-half/musl/src/include build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/internal build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
@cp -rp lib/wasi-libc/libc-top-half/musl/src/internal build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/legacy build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/locale build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/math build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
@cp -rp lib/wasi-libc/libc-top-half/musl/src/math build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/misc build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/multibyte build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/network build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/stat build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/stdio build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/stdlib build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/string build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
@cp -rp lib/wasi-libc/libc-top-half/musl/src/string build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/thread build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
@cp -rp lib/wasi-libc/libc-top-half/musl/include build/release/tinygo/lib/wasi-libc/libc-top-half/musl
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/time build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/musl/src/unistd build/release/tinygo/lib/wasi-libc/libc-top-half/musl/src
|
|
||||||
@cp -rp lib/wasi-libc/libc-top-half/sources build/release/tinygo/lib/wasi-libc/libc-top-half
|
|
||||||
@cp -rp lib/wasi-cli/wit build/release/tinygo/lib/wasi-cli/wit
|
@cp -rp lib/wasi-cli/wit build/release/tinygo/lib/wasi-cli/wit
|
||||||
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
|
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
|
||||||
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
|
@cp -rp llvm-project/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt-builtins
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package builder
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"debug/macho"
|
|
||||||
"debug/pe"
|
"debug/pe"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -63,20 +62,6 @@ func makeArchive(arfile *os.File, objs []string) error {
|
|||||||
fileIndex int
|
fileIndex int
|
||||||
}{symbol.Name, i})
|
}{symbol.Name, i})
|
||||||
}
|
}
|
||||||
} else if dbg, err := macho.NewFile(objfile); err == nil {
|
|
||||||
for _, symbol := range dbg.Symtab.Syms {
|
|
||||||
// See mach-o/nlist.h
|
|
||||||
if symbol.Type&0x0e != 0xe { // (symbol.Type & N_TYPE) != N_SECT
|
|
||||||
continue // undefined symbol
|
|
||||||
}
|
|
||||||
if symbol.Type&0x01 == 0 { // (symbol.Type & N_EXT) == 0
|
|
||||||
continue // internal symbol (static, etc)
|
|
||||||
}
|
|
||||||
symbolTable = append(symbolTable, struct {
|
|
||||||
name string
|
|
||||||
fileIndex int
|
|
||||||
}{symbol.Name, i})
|
|
||||||
}
|
|
||||||
} else if dbg, err := pe.NewFile(objfile); err == nil {
|
} else if dbg, err := pe.NewFile(objfile); err == nil {
|
||||||
for _, symbol := range dbg.Symbols {
|
for _, symbol := range dbg.Symbols {
|
||||||
if symbol.StorageClass != 2 {
|
if symbol.StorageClass != 2 {
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
package builder
|
|
||||||
|
|
||||||
// The well-known conservative Boehm-Demers-Weiser GC.
|
|
||||||
// This file provides a way to compile this GC for use with TinyGo.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
|
||||||
)
|
|
||||||
|
|
||||||
var BoehmGC = Library{
|
|
||||||
name: "bdwgc",
|
|
||||||
cflags: func(target, headerPath string) []string {
|
|
||||||
libdir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/bdwgc")
|
|
||||||
flags := []string{
|
|
||||||
// use a modern environment
|
|
||||||
"-DUSE_MMAP", // mmap is available
|
|
||||||
"-DUSE_MUNMAP", // return memory to the OS using munmap
|
|
||||||
"-DGC_BUILTIN_ATOMIC", // use compiler intrinsics for atomic operations
|
|
||||||
"-DNO_EXECUTE_PERMISSION", // don't make the heap executable
|
|
||||||
|
|
||||||
// specific flags for TinyGo
|
|
||||||
"-DALL_INTERIOR_POINTERS", // scan interior pointers (needed for Go)
|
|
||||||
"-DIGNORE_DYNAMIC_LOADING", // we don't support dynamic loading at the moment
|
|
||||||
"-DNO_GETCONTEXT", // musl doesn't support getcontext()
|
|
||||||
"-DGC_DISABLE_INCREMENTAL", // don't mess with SIGSEGV and such
|
|
||||||
|
|
||||||
// Use a minimal environment.
|
|
||||||
"-DNO_MSGBOX_ON_ERROR", // don't call MessageBoxA on Windows
|
|
||||||
"-DDONT_USE_ATEXIT",
|
|
||||||
"-DNO_GETENV",
|
|
||||||
|
|
||||||
// Special flag to work around the lack of __data_start in ld.lld.
|
|
||||||
// TODO: try to fix this in LLVM/lld directly so we don't have to
|
|
||||||
// work around it anymore.
|
|
||||||
"-DGC_DONT_REGISTER_MAIN_STATIC_DATA",
|
|
||||||
|
|
||||||
// Do not scan the stack. We have our own mechanism to do this.
|
|
||||||
"-DSTACK_NOT_SCANNED",
|
|
||||||
|
|
||||||
// Assertions can be enabled while debugging GC issues.
|
|
||||||
//"-DGC_ASSERTIONS",
|
|
||||||
|
|
||||||
// We use our own way of dealing with threads (that is a bit hacky).
|
|
||||||
// See src/runtime/gc_boehm.go.
|
|
||||||
//"-DGC_THREADS",
|
|
||||||
//"-DTHREAD_LOCAL_ALLOC",
|
|
||||||
|
|
||||||
"-I" + libdir + "/include",
|
|
||||||
}
|
|
||||||
return flags
|
|
||||||
},
|
|
||||||
needsLibc: true,
|
|
||||||
sourceDir: func() string {
|
|
||||||
return filepath.Join(goenv.Get("TINYGOROOT"), "lib/bdwgc")
|
|
||||||
},
|
|
||||||
librarySources: func(target string, _ bool) ([]string, error) {
|
|
||||||
sources := []string{
|
|
||||||
"allchblk.c",
|
|
||||||
"alloc.c",
|
|
||||||
"blacklst.c",
|
|
||||||
"dbg_mlc.c",
|
|
||||||
"dyn_load.c",
|
|
||||||
"finalize.c",
|
|
||||||
"headers.c",
|
|
||||||
"mach_dep.c",
|
|
||||||
"malloc.c",
|
|
||||||
"mark.c",
|
|
||||||
"mark_rts.c",
|
|
||||||
"misc.c",
|
|
||||||
"new_hblk.c",
|
|
||||||
"obj_map.c",
|
|
||||||
"os_dep.c",
|
|
||||||
"reclaim.c",
|
|
||||||
}
|
|
||||||
if strings.Split(target, "-")[2] == "windows" {
|
|
||||||
// Due to how the linker on Windows works (that doesn't allow
|
|
||||||
// undefined functions), we need to include these extra files.
|
|
||||||
sources = append(sources,
|
|
||||||
"mallocx.c",
|
|
||||||
"ptr_chck.c",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return sources, nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
+53
-64
@@ -14,6 +14,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
|
"io/fs"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -148,17 +149,16 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
var libcDependencies []*compileJob
|
var libcDependencies []*compileJob
|
||||||
switch config.Target.Libc {
|
switch config.Target.Libc {
|
||||||
case "darwin-libSystem":
|
case "darwin-libSystem":
|
||||||
libcJob := makeDarwinLibSystemJob(config, tmpdir)
|
job := makeDarwinLibSystemJob(config, tmpdir)
|
||||||
libcDependencies = append(libcDependencies, libcJob)
|
libcDependencies = append(libcDependencies, job)
|
||||||
case "musl":
|
case "musl":
|
||||||
var unlock func()
|
job, unlock, err := libMusl.load(config, tmpdir)
|
||||||
libcJob, unlock, err := libMusl.load(config, tmpdir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BuildResult{}, err
|
return BuildResult{}, err
|
||||||
}
|
}
|
||||||
defer unlock()
|
defer unlock()
|
||||||
libcDependencies = append(libcDependencies, dummyCompileJob(filepath.Join(filepath.Dir(libcJob.result), "crt1.o")))
|
libcDependencies = append(libcDependencies, dummyCompileJob(filepath.Join(filepath.Dir(job.result), "crt1.o")))
|
||||||
libcDependencies = append(libcDependencies, libcJob)
|
libcDependencies = append(libcDependencies, job)
|
||||||
case "picolibc":
|
case "picolibc":
|
||||||
libcJob, unlock, err := libPicolibc.load(config, tmpdir)
|
libcJob, unlock, err := libPicolibc.load(config, tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -167,12 +167,11 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
defer unlock()
|
defer unlock()
|
||||||
libcDependencies = append(libcDependencies, libcJob)
|
libcDependencies = append(libcDependencies, libcJob)
|
||||||
case "wasi-libc":
|
case "wasi-libc":
|
||||||
libcJob, unlock, err := libWasiLibc.load(config, tmpdir)
|
path := filepath.Join(root, "lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a")
|
||||||
if err != nil {
|
if _, err := os.Stat(path); errors.Is(err, fs.ErrNotExist) {
|
||||||
return BuildResult{}, err
|
return BuildResult{}, errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?")
|
||||||
}
|
}
|
||||||
defer unlock()
|
libcDependencies = append(libcDependencies, dummyCompileJob(path))
|
||||||
libcDependencies = append(libcDependencies, libcJob)
|
|
||||||
case "wasmbuiltins":
|
case "wasmbuiltins":
|
||||||
libcJob, unlock, err := libWasmBuiltins.load(config, tmpdir)
|
libcJob, unlock, err := libWasmBuiltins.load(config, tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -181,12 +180,12 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
defer unlock()
|
defer unlock()
|
||||||
libcDependencies = append(libcDependencies, libcJob)
|
libcDependencies = append(libcDependencies, libcJob)
|
||||||
case "mingw-w64":
|
case "mingw-w64":
|
||||||
libcJob, unlock, err := libMinGW.load(config, tmpdir)
|
job, unlock, err := libMinGW.load(config, tmpdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BuildResult{}, err
|
return BuildResult{}, err
|
||||||
}
|
}
|
||||||
defer unlock()
|
defer unlock()
|
||||||
libcDependencies = append(libcDependencies, libcJob)
|
libcDependencies = append(libcDependencies, job)
|
||||||
libcDependencies = append(libcDependencies, makeMinGWExtraLibs(tmpdir, config.GOARCH())...)
|
libcDependencies = append(libcDependencies, makeMinGWExtraLibs(tmpdir, config.GOARCH())...)
|
||||||
case "":
|
case "":
|
||||||
// no library specified, so nothing to do
|
// no library specified, so nothing to do
|
||||||
@@ -214,7 +213,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
MaxStackAlloc: config.MaxStackAlloc(),
|
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
|
||||||
Nobounds: config.Options.Nobounds,
|
|
||||||
PanicStrategy: config.PanicStrategy(),
|
PanicStrategy: config.PanicStrategy(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,15 +449,8 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
if global.IsNil() {
|
if global.IsNil() {
|
||||||
return errors.New("global not found: " + globalName)
|
return errors.New("global not found: " + globalName)
|
||||||
}
|
}
|
||||||
globalType := global.GlobalValueType()
|
|
||||||
if globalType.TypeKind() != llvm.StructTypeKind || globalType.StructName() != "runtime._string" {
|
|
||||||
// Verify this is indeed a string. This is needed so
|
|
||||||
// that makeGlobalsModule can just create the right
|
|
||||||
// globals of string type without checking.
|
|
||||||
return fmt.Errorf("%s: not a string", globalName)
|
|
||||||
}
|
|
||||||
name := global.Name()
|
name := global.Name()
|
||||||
newGlobal := llvm.AddGlobal(mod, globalType, name+".tmp")
|
newGlobal := llvm.AddGlobal(mod, global.GlobalValueType(), name+".tmp")
|
||||||
global.ReplaceAllUsesWith(newGlobal)
|
global.ReplaceAllUsesWith(newGlobal)
|
||||||
global.EraseFromParentAsGlobal()
|
global.EraseFromParentAsGlobal()
|
||||||
newGlobal.SetName(name)
|
newGlobal.SetName(name)
|
||||||
@@ -547,15 +538,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert values from -ldflags="-X ..." into the IR.
|
|
||||||
// This is a separate module, so that the "runtime._string" type
|
|
||||||
// doesn't need to match precisely. LLVM tends to rename that type
|
|
||||||
// sometimes, leading to errors. But linking in a separate module
|
|
||||||
// works fine. See:
|
|
||||||
// https://github.com/tinygo-org/tinygo/issues/4810
|
|
||||||
globalsMod := makeGlobalsModule(ctx, globalValues, machine)
|
|
||||||
llvm.LinkModules(mod, globalsMod)
|
|
||||||
|
|
||||||
// Create runtime.initAll function that calls the runtime
|
// Create runtime.initAll function that calls the runtime
|
||||||
// initializer of each package.
|
// initializer of each package.
|
||||||
llvmInitFn := mod.NamedFunction("runtime.initAll")
|
llvmInitFn := mod.NamedFunction("runtime.initAll")
|
||||||
@@ -608,7 +590,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
|
||||||
}
|
}
|
||||||
@@ -711,16 +693,6 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
|
|||||||
linkerDependencies = append(linkerDependencies, job)
|
linkerDependencies = append(linkerDependencies, job)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Boehm collector is stored in a separate C library.
|
|
||||||
if config.GC() == "boehm" {
|
|
||||||
job, unlock, err := BoehmGC.load(config, tmpdir)
|
|
||||||
if err != nil {
|
|
||||||
return BuildResult{}, err
|
|
||||||
}
|
|
||||||
defer unlock()
|
|
||||||
linkerDependencies = append(linkerDependencies, job)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add jobs to compile extra files. These files are in C or assembly and
|
// Add jobs to compile extra files. These files are in C or assembly and
|
||||||
// contain things like the interrupt vector table and low level operations
|
// contain things like the interrupt vector table and low level operations
|
||||||
// such as stack switching.
|
// such as stack switching.
|
||||||
@@ -1173,7 +1145,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
|
||||||
@@ -1191,6 +1163,12 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert values from -ldflags="-X ..." into the IR.
|
||||||
|
err = setGlobalValues(mod, globalValues)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Run most of the whole-program optimizations (including the whole
|
// Run most of the whole-program optimizations (including the whole
|
||||||
// O0/O1/O2/Os/Oz optimization pipeline).
|
// O0/O1/O2/Os/Oz optimization pipeline).
|
||||||
errs := transform.Optimize(mod, config)
|
errs := transform.Optimize(mod, config)
|
||||||
@@ -1204,19 +1182,10 @@ func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeGlobalsModule(ctx llvm.Context, globals map[string]map[string]string, machine llvm.TargetMachine) llvm.Module {
|
// setGlobalValues sets the global values from the -ldflags="-X ..." compiler
|
||||||
mod := ctx.NewModule("cmdline-globals")
|
// option in the given module. An error may be returned if the global is not of
|
||||||
targetData := machine.CreateTargetData()
|
// the expected type.
|
||||||
defer targetData.Dispose()
|
func setGlobalValues(mod llvm.Module, globals map[string]map[string]string) error {
|
||||||
mod.SetDataLayout(targetData.String())
|
|
||||||
|
|
||||||
stringType := ctx.StructCreateNamed("runtime._string")
|
|
||||||
uintptrType := ctx.IntType(targetData.PointerSize() * 8)
|
|
||||||
stringType.StructSetBody([]llvm.Type{
|
|
||||||
llvm.PointerType(ctx.Int8Type(), 0),
|
|
||||||
uintptrType,
|
|
||||||
}, false)
|
|
||||||
|
|
||||||
var pkgPaths []string
|
var pkgPaths []string
|
||||||
for pkgPath := range globals {
|
for pkgPath := range globals {
|
||||||
pkgPaths = append(pkgPaths, pkgPath)
|
pkgPaths = append(pkgPaths, pkgPath)
|
||||||
@@ -1232,6 +1201,24 @@ func makeGlobalsModule(ctx llvm.Context, globals map[string]map[string]string, m
|
|||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
value := pkg[name]
|
value := pkg[name]
|
||||||
globalName := pkgPath + "." + name
|
globalName := pkgPath + "." + name
|
||||||
|
global := mod.NamedGlobal(globalName)
|
||||||
|
if global.IsNil() || !global.Initializer().IsNil() {
|
||||||
|
// The global either does not exist (optimized away?) or has
|
||||||
|
// some value, in which case it has already been initialized at
|
||||||
|
// package init time.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// A strin is a {ptr, len} pair. We need these types to build the
|
||||||
|
// initializer.
|
||||||
|
initializerType := global.GlobalValueType()
|
||||||
|
if initializerType.TypeKind() != llvm.StructTypeKind || initializerType.StructName() == "" {
|
||||||
|
return fmt.Errorf("%s: not a string", globalName)
|
||||||
|
}
|
||||||
|
elementTypes := initializerType.StructElementTypes()
|
||||||
|
if len(elementTypes) != 2 {
|
||||||
|
return fmt.Errorf("%s: not a string", globalName)
|
||||||
|
}
|
||||||
|
|
||||||
// Create a buffer for the string contents.
|
// Create a buffer for the string contents.
|
||||||
bufInitializer := mod.Context().ConstString(value, false)
|
bufInitializer := mod.Context().ConstString(value, false)
|
||||||
@@ -1242,20 +1229,22 @@ func makeGlobalsModule(ctx llvm.Context, globals map[string]map[string]string, m
|
|||||||
buf.SetLinkage(llvm.PrivateLinkage)
|
buf.SetLinkage(llvm.PrivateLinkage)
|
||||||
|
|
||||||
// Create the string value, which is a {ptr, len} pair.
|
// Create the string value, which is a {ptr, len} pair.
|
||||||
length := llvm.ConstInt(uintptrType, uint64(len(value)), false)
|
zero := llvm.ConstInt(mod.Context().Int32Type(), 0, false)
|
||||||
initializer := llvm.ConstNamedStruct(stringType, []llvm.Value{
|
ptr := llvm.ConstGEP(bufInitializer.Type(), buf, []llvm.Value{zero, zero})
|
||||||
buf,
|
if ptr.Type() != elementTypes[0] {
|
||||||
|
return fmt.Errorf("%s: not a string", globalName)
|
||||||
|
}
|
||||||
|
length := llvm.ConstInt(elementTypes[1], uint64(len(value)), false)
|
||||||
|
initializer := llvm.ConstNamedStruct(initializerType, []llvm.Value{
|
||||||
|
ptr,
|
||||||
length,
|
length,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create the string global.
|
// Set the initializer. No initializer should be set at this point.
|
||||||
global := llvm.AddGlobal(mod, stringType, globalName)
|
|
||||||
global.SetInitializer(initializer)
|
global.SetInitializer(initializer)
|
||||||
global.SetAlignment(targetData.PrefTypeAlignment(stringType))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
return mod
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// functionStackSizes keeps stack size information about a single function
|
// functionStackSizes keeps stack size information about a single function
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ func TestClangAttributes(t *testing.T) {
|
|||||||
{GOOS: "linux", GOARCH: "mipsle", GOMIPS: "softfloat"},
|
{GOOS: "linux", GOARCH: "mipsle", GOMIPS: "softfloat"},
|
||||||
{GOOS: "darwin", GOARCH: "amd64"},
|
{GOOS: "darwin", GOARCH: "amd64"},
|
||||||
{GOOS: "darwin", GOARCH: "arm64"},
|
{GOOS: "darwin", GOARCH: "arm64"},
|
||||||
{GOOS: "windows", GOARCH: "386"},
|
|
||||||
{GOOS: "windows", GOARCH: "amd64"},
|
{GOOS: "windows", GOARCH: "amd64"},
|
||||||
{GOOS: "windows", GOARCH: "arm64"},
|
{GOOS: "windows", GOARCH: "arm64"},
|
||||||
} {
|
} {
|
||||||
|
|||||||
+1
-11
@@ -3,7 +3,6 @@ package builder
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
@@ -202,11 +201,6 @@ var avrBuiltins = []string{
|
|||||||
"avr/udivmodqi4.S",
|
"avr/udivmodqi4.S",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builtins needed specifically for windows/386.
|
|
||||||
var windowsI386Builtins = []string{
|
|
||||||
"i386/chkstk.S", // also _alloca
|
|
||||||
}
|
|
||||||
|
|
||||||
// libCompilerRT is a library with symbols required by programs compiled with
|
// libCompilerRT is a library with symbols required by programs compiled with
|
||||||
// LLVM. These symbols are for operations that cannot be emitted with a single
|
// LLVM. These symbols are for operations that cannot be emitted with a single
|
||||||
// instruction or a short sequence of instructions for that target.
|
// instruction or a short sequence of instructions for that target.
|
||||||
@@ -226,7 +220,7 @@ var libCompilerRT = Library{
|
|||||||
// Development build.
|
// Development build.
|
||||||
return filepath.Join(goenv.Get("TINYGOROOT"), "lib/compiler-rt-builtins")
|
return filepath.Join(goenv.Get("TINYGOROOT"), "lib/compiler-rt-builtins")
|
||||||
},
|
},
|
||||||
librarySources: func(target string, _ bool) ([]string, error) {
|
librarySources: func(target string) ([]string, error) {
|
||||||
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
|
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
|
||||||
switch compileopts.CanonicalArchName(target) {
|
switch compileopts.CanonicalArchName(target) {
|
||||||
case "arm":
|
case "arm":
|
||||||
@@ -235,10 +229,6 @@ var libCompilerRT = Library{
|
|||||||
builtins = append(builtins, avrBuiltins...)
|
builtins = append(builtins, avrBuiltins...)
|
||||||
case "x86_64", "aarch64", "riscv64": // any 64-bit arch
|
case "x86_64", "aarch64", "riscv64": // any 64-bit arch
|
||||||
builtins = append(builtins, genericBuiltins128...)
|
builtins = append(builtins, genericBuiltins128...)
|
||||||
case "i386":
|
|
||||||
if strings.Split(target, "-")[2] == "windows" {
|
|
||||||
builtins = append(builtins, windowsI386Builtins...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return builtins, nil
|
return builtins, nil
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
|||||||
|
|
||||||
// Version range supported by TinyGo.
|
// Version range supported by TinyGo.
|
||||||
const minorMin = 19
|
const minorMin = 19
|
||||||
const minorMax = 25
|
const minorMax = 24
|
||||||
|
|
||||||
// Check that we support this Go toolchain version.
|
// Check that we support this Go toolchain version.
|
||||||
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
|
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
|
||||||
|
|||||||
+12
-25
@@ -15,9 +15,6 @@ import (
|
|||||||
|
|
||||||
// Library is a container for information about a single C library, such as a
|
// Library is a container for information about a single C library, such as a
|
||||||
// compiler runtime or libc.
|
// compiler runtime or libc.
|
||||||
//
|
|
||||||
// Note: whenever a library gets changed, the version in compileopts/config.go
|
|
||||||
// probably also needs to be incremented.
|
|
||||||
type Library struct {
|
type Library struct {
|
||||||
// The library name, such as compiler-rt or picolibc.
|
// The library name, such as compiler-rt or picolibc.
|
||||||
name string
|
name string
|
||||||
@@ -28,17 +25,11 @@ type Library struct {
|
|||||||
// cflags returns the C flags specific to this library
|
// cflags returns the C flags specific to this library
|
||||||
cflags func(target, headerPath string) []string
|
cflags func(target, headerPath string) []string
|
||||||
|
|
||||||
// cflagsForFile returns additional C flags for a particular source file.
|
|
||||||
cflagsForFile func(path string) []string
|
|
||||||
|
|
||||||
// needsLibc is set to true if this library needs libc headers.
|
|
||||||
needsLibc bool
|
|
||||||
|
|
||||||
// The source directory.
|
// The source directory.
|
||||||
sourceDir func() string
|
sourceDir func() string
|
||||||
|
|
||||||
// The source files, relative to sourceDir.
|
// The source files, relative to sourceDir.
|
||||||
librarySources func(target string, libcNeedsMalloc bool) ([]string, error)
|
librarySources func(target string) ([]string, error)
|
||||||
|
|
||||||
// The source code for the crt1.o file, relative to sourceDir.
|
// The source code for the crt1.o file, relative to sourceDir.
|
||||||
crt1Source string
|
crt1Source string
|
||||||
@@ -53,8 +44,13 @@ type Library struct {
|
|||||||
// As a side effect, this call creates the library header files if they didn't
|
// As a side effect, this call creates the library header files if they didn't
|
||||||
// exist yet.
|
// exist yet.
|
||||||
func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJob, abortLock func(), err error) {
|
func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJob, abortLock func(), err error) {
|
||||||
outdir := config.LibraryPath(l.name)
|
outdir, precompiled := config.LibcPath(l.name)
|
||||||
archiveFilePath := filepath.Join(outdir, "lib.a")
|
archiveFilePath := filepath.Join(outdir, "lib.a")
|
||||||
|
if precompiled {
|
||||||
|
// Found a precompiled library for this OS/architecture. Return the path
|
||||||
|
// directly.
|
||||||
|
return dummyCompileJob(archiveFilePath), func() {}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Create a lock on the output (if supported).
|
// Create a lock on the output (if supported).
|
||||||
// This is a bit messy, but avoids a deadlock because it is ordered consistently with other library loads within a build.
|
// This is a bit messy, but avoids a deadlock because it is ordered consistently with other library loads within a build.
|
||||||
@@ -185,9 +181,6 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
args = append(args, "-mfpu=vfpv2")
|
args = append(args, "-mfpu=vfpv2")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if l.needsLibc {
|
|
||||||
args = append(args, config.LibcCFlags()...)
|
|
||||||
}
|
|
||||||
|
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
|
|
||||||
@@ -226,13 +219,12 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
|
|
||||||
// Create jobs to compile all sources. These jobs are depended upon by the
|
// Create jobs to compile all sources. These jobs are depended upon by the
|
||||||
// archive job above, so must be run first.
|
// archive job above, so must be run first.
|
||||||
paths, err := l.librarySources(target, config.LibcNeedsMalloc())
|
paths, err := l.librarySources(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
// Strip leading "../" parts off the path.
|
// Strip leading "../" parts off the path.
|
||||||
path := path
|
|
||||||
cleanpath := path
|
cleanpath := path
|
||||||
for strings.HasPrefix(cleanpath, "../") {
|
for strings.HasPrefix(cleanpath, "../") {
|
||||||
cleanpath = cleanpath[3:]
|
cleanpath = cleanpath[3:]
|
||||||
@@ -241,14 +233,11 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
objpath := filepath.Join(dir, cleanpath+".o")
|
objpath := filepath.Join(dir, cleanpath+".o")
|
||||||
os.MkdirAll(filepath.Dir(objpath), 0o777)
|
os.MkdirAll(filepath.Dir(objpath), 0o777)
|
||||||
objs = append(objs, objpath)
|
objs = append(objs, objpath)
|
||||||
objfile := &compileJob{
|
job.dependencies = append(job.dependencies, &compileJob{
|
||||||
description: "compile " + srcpath,
|
description: "compile " + srcpath,
|
||||||
run: func(*compileJob) error {
|
run: func(*compileJob) error {
|
||||||
var compileArgs []string
|
var compileArgs []string
|
||||||
compileArgs = append(compileArgs, args...)
|
compileArgs = append(compileArgs, args...)
|
||||||
if l.cflagsForFile != nil {
|
|
||||||
compileArgs = append(compileArgs, l.cflagsForFile(path)...)
|
|
||||||
}
|
|
||||||
compileArgs = append(compileArgs, "-o", objpath, srcpath)
|
compileArgs = append(compileArgs, "-o", objpath, srcpath)
|
||||||
if config.Options.PrintCommands != nil {
|
if config.Options.PrintCommands != nil {
|
||||||
config.Options.PrintCommands("clang", compileArgs...)
|
config.Options.PrintCommands("clang", compileArgs...)
|
||||||
@@ -259,8 +248,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
job.dependencies = append(job.dependencies, objfile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create crt1.o job, if needed.
|
// Create crt1.o job, if needed.
|
||||||
@@ -269,7 +257,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
// won't make much of a difference in speed).
|
// won't make much of a difference in speed).
|
||||||
if l.crt1Source != "" {
|
if l.crt1Source != "" {
|
||||||
srcpath := filepath.Join(sourceDir, l.crt1Source)
|
srcpath := filepath.Join(sourceDir, l.crt1Source)
|
||||||
crt1Job := &compileJob{
|
job.dependencies = append(job.dependencies, &compileJob{
|
||||||
description: "compile " + srcpath,
|
description: "compile " + srcpath,
|
||||||
run: func(*compileJob) error {
|
run: func(*compileJob) error {
|
||||||
var compileArgs []string
|
var compileArgs []string
|
||||||
@@ -289,8 +277,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
|||||||
}
|
}
|
||||||
return os.Rename(tmpfile.Name(), filepath.Join(outdir, "crt1.o"))
|
return os.Rename(tmpfile.Name(), filepath.Join(outdir, "crt1.o"))
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
job.dependencies = append(job.dependencies, crt1Job)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = true
|
ok = true
|
||||||
|
|||||||
+33
-87
@@ -30,62 +30,25 @@ var libMinGW = Library{
|
|||||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/mingw-w64") },
|
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/mingw-w64") },
|
||||||
cflags: func(target, headerPath string) []string {
|
cflags: func(target, headerPath string) []string {
|
||||||
mingwDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/mingw-w64")
|
mingwDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/mingw-w64")
|
||||||
flags := []string{
|
return []string{
|
||||||
"-nostdlibinc",
|
"-nostdlibinc",
|
||||||
"-isystem", mingwDir + "/mingw-w64-crt/include",
|
|
||||||
"-isystem", mingwDir + "/mingw-w64-headers/crt",
|
"-isystem", mingwDir + "/mingw-w64-headers/crt",
|
||||||
"-isystem", mingwDir + "/mingw-w64-headers/include",
|
|
||||||
"-I", mingwDir + "/mingw-w64-headers/defaults/include",
|
"-I", mingwDir + "/mingw-w64-headers/defaults/include",
|
||||||
"-I" + headerPath,
|
"-I" + headerPath,
|
||||||
}
|
}
|
||||||
if strings.Split(target, "-")[0] == "i386" {
|
|
||||||
flags = append(flags,
|
|
||||||
"-D__MSVCRT_VERSION__=0x700", // Microsoft Visual C++ .NET 2002
|
|
||||||
"-D_WIN32_WINNT=0x0501", // target Windows XP
|
|
||||||
"-D_CRTBLD",
|
|
||||||
"-Wno-pragma-pack",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return flags
|
|
||||||
},
|
},
|
||||||
librarySources: func(target string, _ bool) ([]string, error) {
|
librarySources: func(target string) ([]string, error) {
|
||||||
// These files are needed so that printf and the like are supported.
|
// These files are needed so that printf and the like are supported.
|
||||||
var sources []string
|
sources := []string{
|
||||||
if strings.Split(target, "-")[0] == "i386" {
|
"mingw-w64-crt/stdio/ucrt_fprintf.c",
|
||||||
// Old 32-bit x86 systems use msvcrt.dll.
|
"mingw-w64-crt/stdio/ucrt_fwprintf.c",
|
||||||
sources = []string{
|
"mingw-w64-crt/stdio/ucrt_printf.c",
|
||||||
"mingw-w64-crt/crt/pseudo-reloc.c",
|
"mingw-w64-crt/stdio/ucrt_snprintf.c",
|
||||||
"mingw-w64-crt/gdtoa/dmisc.c",
|
"mingw-w64-crt/stdio/ucrt_sprintf.c",
|
||||||
"mingw-w64-crt/gdtoa/gdtoa.c",
|
"mingw-w64-crt/stdio/ucrt_vfprintf.c",
|
||||||
"mingw-w64-crt/gdtoa/gmisc.c",
|
"mingw-w64-crt/stdio/ucrt_vprintf.c",
|
||||||
"mingw-w64-crt/gdtoa/misc.c",
|
"mingw-w64-crt/stdio/ucrt_vsnprintf.c",
|
||||||
"mingw-w64-crt/math/x86/exp2.S",
|
"mingw-w64-crt/stdio/ucrt_vsprintf.c",
|
||||||
"mingw-w64-crt/math/x86/trunc.S",
|
|
||||||
"mingw-w64-crt/misc/___mb_cur_max_func.c",
|
|
||||||
"mingw-w64-crt/misc/lc_locale_func.c",
|
|
||||||
"mingw-w64-crt/misc/mbrtowc.c",
|
|
||||||
"mingw-w64-crt/misc/strnlen.c",
|
|
||||||
"mingw-w64-crt/misc/wcrtomb.c",
|
|
||||||
"mingw-w64-crt/misc/wcsnlen.c",
|
|
||||||
"mingw-w64-crt/stdio/acrt_iob_func.c",
|
|
||||||
"mingw-w64-crt/stdio/mingw_lock.c",
|
|
||||||
"mingw-w64-crt/stdio/mingw_pformat.c",
|
|
||||||
"mingw-w64-crt/stdio/mingw_vfprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/mingw_vsnprintf.c",
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Anything somewhat modern (amd64, arm64) uses UCRT.
|
|
||||||
sources = []string{
|
|
||||||
"mingw-w64-crt/stdio/ucrt_fprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_fwprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_printf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_snprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_sprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_vfprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_vprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_vsnprintf.c",
|
|
||||||
"mingw-w64-crt/stdio/ucrt_vsprintf.c",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return sources, nil
|
return sources, nil
|
||||||
},
|
},
|
||||||
@@ -100,41 +63,27 @@ var libMinGW = Library{
|
|||||||
func makeMinGWExtraLibs(tmpdir, goarch string) []*compileJob {
|
func makeMinGWExtraLibs(tmpdir, goarch string) []*compileJob {
|
||||||
var jobs []*compileJob
|
var jobs []*compileJob
|
||||||
root := goenv.Get("TINYGOROOT")
|
root := goenv.Get("TINYGOROOT")
|
||||||
var libs []string
|
// Normally all the api-ms-win-crt-*.def files are all compiled to a single
|
||||||
if goarch == "386" {
|
// .lib file. But to simplify things, we're going to leave them as separate
|
||||||
libs = []string{
|
// files.
|
||||||
// x86 uses msvcrt.dll instead of UCRT for compatibility with old
|
for _, name := range []string{
|
||||||
// Windows versions.
|
"kernel32.def.in",
|
||||||
"advapi32.def.in",
|
"api-ms-win-crt-conio-l1-1-0.def",
|
||||||
"kernel32.def.in",
|
"api-ms-win-crt-convert-l1-1-0.def.in",
|
||||||
"msvcrt.def.in",
|
"api-ms-win-crt-environment-l1-1-0.def",
|
||||||
}
|
"api-ms-win-crt-filesystem-l1-1-0.def",
|
||||||
} else {
|
"api-ms-win-crt-heap-l1-1-0.def",
|
||||||
// Use the modernized UCRT on new systems.
|
"api-ms-win-crt-locale-l1-1-0.def",
|
||||||
// Normally all the api-ms-win-crt-*.def files are all compiled to a
|
"api-ms-win-crt-math-l1-1-0.def.in",
|
||||||
// single .lib file. But to simplify things, we're going to leave them
|
"api-ms-win-crt-multibyte-l1-1-0.def",
|
||||||
// as separate files.
|
"api-ms-win-crt-private-l1-1-0.def.in",
|
||||||
libs = []string{
|
"api-ms-win-crt-process-l1-1-0.def",
|
||||||
"advapi32.def.in",
|
"api-ms-win-crt-runtime-l1-1-0.def.in",
|
||||||
"kernel32.def.in",
|
"api-ms-win-crt-stdio-l1-1-0.def",
|
||||||
"api-ms-win-crt-conio-l1-1-0.def",
|
"api-ms-win-crt-string-l1-1-0.def",
|
||||||
"api-ms-win-crt-convert-l1-1-0.def.in",
|
"api-ms-win-crt-time-l1-1-0.def",
|
||||||
"api-ms-win-crt-environment-l1-1-0.def",
|
"api-ms-win-crt-utility-l1-1-0.def",
|
||||||
"api-ms-win-crt-filesystem-l1-1-0.def",
|
} {
|
||||||
"api-ms-win-crt-heap-l1-1-0.def",
|
|
||||||
"api-ms-win-crt-locale-l1-1-0.def",
|
|
||||||
"api-ms-win-crt-math-l1-1-0.def.in",
|
|
||||||
"api-ms-win-crt-multibyte-l1-1-0.def",
|
|
||||||
"api-ms-win-crt-private-l1-1-0.def.in",
|
|
||||||
"api-ms-win-crt-process-l1-1-0.def",
|
|
||||||
"api-ms-win-crt-runtime-l1-1-0.def.in",
|
|
||||||
"api-ms-win-crt-stdio-l1-1-0.def",
|
|
||||||
"api-ms-win-crt-string-l1-1-0.def",
|
|
||||||
"api-ms-win-crt-time-l1-1-0.def",
|
|
||||||
"api-ms-win-crt-utility-l1-1-0.def",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, name := range libs {
|
|
||||||
outpath := filepath.Join(tmpdir, filepath.Base(name)+".lib")
|
outpath := filepath.Join(tmpdir, filepath.Base(name)+".lib")
|
||||||
inpath := filepath.Join(root, "lib/mingw-w64/mingw-w64-crt/lib-common/"+name)
|
inpath := filepath.Join(root, "lib/mingw-w64/mingw-w64-crt/lib-common/"+name)
|
||||||
job := &compileJob{
|
job := &compileJob{
|
||||||
@@ -144,9 +93,6 @@ func makeMinGWExtraLibs(tmpdir, goarch string) []*compileJob {
|
|||||||
defpath := inpath
|
defpath := inpath
|
||||||
var archDef, emulation string
|
var archDef, emulation string
|
||||||
switch goarch {
|
switch goarch {
|
||||||
case "386":
|
|
||||||
archDef = "-DDEF_I386"
|
|
||||||
emulation = "i386pe"
|
|
||||||
case "amd64":
|
case "amd64":
|
||||||
archDef = "-DDEF_X64"
|
archDef = "-DDEF_X64"
|
||||||
emulation = "i386pep"
|
emulation = "i386pep"
|
||||||
|
|||||||
+31
-49
@@ -12,45 +12,6 @@ import (
|
|||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create the alltypes.h file from the appropriate alltypes.h.in files.
|
|
||||||
func buildMuslAllTypes(arch, muslDir, outputBitsDir string) error {
|
|
||||||
// Create the file alltypes.h.
|
|
||||||
f, err := os.Create(filepath.Join(outputBitsDir, "alltypes.h"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
infiles := []string{
|
|
||||||
filepath.Join(muslDir, "arch", arch, "bits", "alltypes.h.in"),
|
|
||||||
filepath.Join(muslDir, "include", "alltypes.h.in"),
|
|
||||||
}
|
|
||||||
for _, infile := range infiles {
|
|
||||||
data, err := os.ReadFile(infile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
lines := strings.Split(string(data), "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
if strings.HasPrefix(line, "TYPEDEF ") {
|
|
||||||
matches := regexp.MustCompile(`TYPEDEF (.*) ([^ ]*);`).FindStringSubmatch(line)
|
|
||||||
value := matches[1]
|
|
||||||
name := matches[2]
|
|
||||||
line = fmt.Sprintf("#if defined(__NEED_%s) && !defined(__DEFINED_%s)\ntypedef %s %s;\n#define __DEFINED_%s\n#endif\n", name, name, value, name, name)
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(line, "STRUCT ") {
|
|
||||||
matches := regexp.MustCompile(`STRUCT * ([^ ]*) (.*);`).FindStringSubmatch(line)
|
|
||||||
name := matches[1]
|
|
||||||
value := matches[2]
|
|
||||||
line = fmt.Sprintf("#if defined(__NEED_struct_%s) && !defined(__DEFINED_struct_%s)\nstruct %s %s;\n#define __DEFINED_struct_%s\n#endif\n", name, name, name, value, name)
|
|
||||||
}
|
|
||||||
_, err := f.WriteString(line + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
var libMusl = Library{
|
var libMusl = Library{
|
||||||
name: "musl",
|
name: "musl",
|
||||||
makeHeaders: func(target, includeDir string) error {
|
makeHeaders: func(target, includeDir string) error {
|
||||||
@@ -63,13 +24,41 @@ var libMusl = Library{
|
|||||||
arch := compileopts.MuslArchitecture(target)
|
arch := compileopts.MuslArchitecture(target)
|
||||||
muslDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib", "musl")
|
muslDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib", "musl")
|
||||||
|
|
||||||
err = buildMuslAllTypes(arch, muslDir, bits)
|
// Create the file alltypes.h.
|
||||||
|
f, err := os.Create(filepath.Join(bits, "alltypes.h"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
infiles := []string{
|
||||||
|
filepath.Join(muslDir, "arch", arch, "bits", "alltypes.h.in"),
|
||||||
|
filepath.Join(muslDir, "include", "alltypes.h.in"),
|
||||||
|
}
|
||||||
|
for _, infile := range infiles {
|
||||||
|
data, err := os.ReadFile(infile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.HasPrefix(line, "TYPEDEF ") {
|
||||||
|
matches := regexp.MustCompile(`TYPEDEF (.*) ([^ ]*);`).FindStringSubmatch(line)
|
||||||
|
value := matches[1]
|
||||||
|
name := matches[2]
|
||||||
|
line = fmt.Sprintf("#if defined(__NEED_%s) && !defined(__DEFINED_%s)\ntypedef %s %s;\n#define __DEFINED_%s\n#endif\n", name, name, value, name, name)
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(line, "STRUCT ") {
|
||||||
|
matches := regexp.MustCompile(`STRUCT * ([^ ]*) (.*);`).FindStringSubmatch(line)
|
||||||
|
name := matches[1]
|
||||||
|
value := matches[2]
|
||||||
|
line = fmt.Sprintf("#if defined(__NEED_struct_%s) && !defined(__DEFINED_struct_%s)\nstruct %s %s;\n#define __DEFINED_struct_%s\n#endif\n", name, name, name, value, name)
|
||||||
|
}
|
||||||
|
f.WriteString(line + "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
// Create the file syscall.h.
|
// Create the file syscall.h.
|
||||||
f, err := os.Create(filepath.Join(bits, "syscall.h"))
|
f, err = os.Create(filepath.Join(bits, "syscall.h"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -121,36 +110,29 @@ var libMusl = Library{
|
|||||||
return cflags
|
return cflags
|
||||||
},
|
},
|
||||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl/src") },
|
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl/src") },
|
||||||
librarySources: func(target string, _ bool) ([]string, error) {
|
librarySources: func(target string) ([]string, error) {
|
||||||
arch := compileopts.MuslArchitecture(target)
|
arch := compileopts.MuslArchitecture(target)
|
||||||
globs := []string{
|
globs := []string{
|
||||||
"conf/*.c",
|
|
||||||
"ctype/*.c",
|
|
||||||
"env/*.c",
|
"env/*.c",
|
||||||
"errno/*.c",
|
"errno/*.c",
|
||||||
"exit/*.c",
|
"exit/*.c",
|
||||||
"fcntl/*.c",
|
"fcntl/*.c",
|
||||||
"internal/defsysinfo.c",
|
"internal/defsysinfo.c",
|
||||||
"internal/intscan.c",
|
|
||||||
"internal/libc.c",
|
"internal/libc.c",
|
||||||
"internal/shgetc.c",
|
|
||||||
"internal/syscall_ret.c",
|
"internal/syscall_ret.c",
|
||||||
"internal/vdso.c",
|
"internal/vdso.c",
|
||||||
"legacy/*.c",
|
"legacy/*.c",
|
||||||
"locale/*.c",
|
"locale/*.c",
|
||||||
"linux/*.c",
|
"linux/*.c",
|
||||||
"locale/*.c",
|
|
||||||
"malloc/*.c",
|
"malloc/*.c",
|
||||||
"malloc/mallocng/*.c",
|
"malloc/mallocng/*.c",
|
||||||
"mman/*.c",
|
"mman/*.c",
|
||||||
"math/*.c",
|
"math/*.c",
|
||||||
"misc/*.c",
|
"misc/*.c",
|
||||||
"multibyte/*.c",
|
"multibyte/*.c",
|
||||||
"sched/*.c",
|
|
||||||
"signal/" + arch + "/*.s",
|
"signal/" + arch + "/*.s",
|
||||||
"signal/*.c",
|
"signal/*.c",
|
||||||
"stdio/*.c",
|
"stdio/*.c",
|
||||||
"stdlib/*.c",
|
|
||||||
"string/*.c",
|
"string/*.c",
|
||||||
"thread/" + arch + "/*.s",
|
"thread/" + arch + "/*.s",
|
||||||
"thread/*.c",
|
"thread/*.c",
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ var libPicolibc = 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, _ bool) ([]string, error) {
|
librarySources: func(target string) ([]string, error) {
|
||||||
sources := append([]string(nil), picolibcSources...)
|
sources := append([]string(nil), picolibcSources...)
|
||||||
if !strings.HasPrefix(target, "avr") {
|
if !strings.HasPrefix(target, "avr") {
|
||||||
// Small chips without long jumps can't compile many files (printf,
|
// Small chips without long jumps can't compile many files (printf,
|
||||||
|
|||||||
+1
-1
@@ -490,7 +490,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if section.Type == elf.SHT_NOBITS {
|
if section.Type == elf.SHT_NOBITS {
|
||||||
if strings.HasPrefix(section.Name, ".stack") {
|
if section.Name == ".stack" {
|
||||||
// TinyGo emits stack sections on microcontroller using the
|
// TinyGo emits stack sections on microcontroller using the
|
||||||
// ".stack" name.
|
// ".stack" name.
|
||||||
// This is a bit ugly, but I don't think there is a way to
|
// This is a bit ugly, but I don't think there is a way to
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) {
|
|||||||
// This is a small number of very diverse targets that we want to test.
|
// This is a small number of very diverse targets that we want to test.
|
||||||
tests := []sizeTest{
|
tests := []sizeTest{
|
||||||
// microcontrollers
|
// microcontrollers
|
||||||
{"hifive1b", "examples/echo", 4580, 280, 0, 2264},
|
{"hifive1b", "examples/echo", 4560, 280, 0, 2268},
|
||||||
{"microbit", "examples/serial", 2928, 388, 8, 2272},
|
{"microbit", "examples/serial", 2916, 388, 8, 2272},
|
||||||
{"wioterminal", "examples/pininterrupt", 7387, 1489, 116, 6912},
|
{"wioterminal", "examples/pininterrupt", 7359, 1489, 116, 6912},
|
||||||
|
|
||||||
// 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
|
||||||
|
|||||||
@@ -1,284 +0,0 @@
|
|||||||
package builder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
|
||||||
)
|
|
||||||
|
|
||||||
var libWasiLibc = Library{
|
|
||||||
name: "wasi-libc",
|
|
||||||
makeHeaders: func(target, includeDir string) error {
|
|
||||||
bits := filepath.Join(includeDir, "bits")
|
|
||||||
err := os.Mkdir(bits, 0777)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
muslDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib", "wasi-libc/libc-top-half/musl")
|
|
||||||
err = buildMuslAllTypes("wasm32", muslDir, bits)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// See MUSL_OMIT_HEADERS in the Makefile.
|
|
||||||
omitHeaders := map[string]struct{}{
|
|
||||||
"syslog.h": {},
|
|
||||||
"wait.h": {},
|
|
||||||
"ucontext.h": {},
|
|
||||||
"paths.h": {},
|
|
||||||
"utmp.h": {},
|
|
||||||
"utmpx.h": {},
|
|
||||||
"lastlog.h": {},
|
|
||||||
"elf.h": {},
|
|
||||||
"link.h": {},
|
|
||||||
"pwd.h": {},
|
|
||||||
"shadow.h": {},
|
|
||||||
"grp.h": {},
|
|
||||||
"mntent.h": {},
|
|
||||||
"netdb.h": {},
|
|
||||||
"resolv.h": {},
|
|
||||||
"pty.h": {},
|
|
||||||
"dlfcn.h": {},
|
|
||||||
"setjmp.h": {},
|
|
||||||
"ulimit.h": {},
|
|
||||||
"wordexp.h": {},
|
|
||||||
"spawn.h": {},
|
|
||||||
"termios.h": {},
|
|
||||||
"libintl.h": {},
|
|
||||||
"aio.h": {},
|
|
||||||
|
|
||||||
"stdarg.h": {},
|
|
||||||
"stddef.h": {},
|
|
||||||
|
|
||||||
"pthread.h": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, glob := range [][2]string{
|
|
||||||
{"libc-bottom-half/headers/public/*.h", ""},
|
|
||||||
{"libc-bottom-half/headers/public/wasi/*.h", "wasi"},
|
|
||||||
{"libc-top-half/musl/arch/wasm32/bits/*.h", "bits"},
|
|
||||||
{"libc-top-half/musl/include/*.h", ""},
|
|
||||||
{"libc-top-half/musl/include/netinet/*.h", "netinet"},
|
|
||||||
{"libc-top-half/musl/include/sys/*.h", "sys"},
|
|
||||||
} {
|
|
||||||
matches, _ := filepath.Glob(filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc", glob[0]))
|
|
||||||
outDir := filepath.Join(includeDir, glob[1])
|
|
||||||
os.MkdirAll(outDir, 0o777)
|
|
||||||
for _, match := range matches {
|
|
||||||
name := filepath.Base(match)
|
|
||||||
if _, ok := omitHeaders[name]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
data, err := os.ReadFile(match)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = os.WriteFile(filepath.Join(outDir, name), data, 0o666)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
cflags: func(target, headerPath string) []string {
|
|
||||||
libcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc")
|
|
||||||
return []string{
|
|
||||||
"-Werror",
|
|
||||||
"-Wall",
|
|
||||||
"-std=gnu11",
|
|
||||||
"-nostdlibinc",
|
|
||||||
"-mnontrapping-fptoint", "-msign-ext", "-mbulk-memory",
|
|
||||||
"-Wno-null-pointer-arithmetic", "-Wno-unused-parameter", "-Wno-sign-compare", "-Wno-unused-variable", "-Wno-unused-function", "-Wno-ignored-attributes", "-Wno-missing-braces", "-Wno-ignored-pragmas", "-Wno-unused-but-set-variable", "-Wno-unknown-warning-option",
|
|
||||||
"-Wno-parentheses", "-Wno-shift-op-parentheses", "-Wno-bitwise-op-parentheses", "-Wno-logical-op-parentheses", "-Wno-string-plus-int", "-Wno-dangling-else", "-Wno-unknown-pragmas",
|
|
||||||
"-DNDEBUG",
|
|
||||||
"-D__wasilibc_printscan_no_long_double",
|
|
||||||
"-D__wasilibc_printscan_full_support_option=\"long double support is disabled\"",
|
|
||||||
"-DBULK_MEMORY_THRESHOLD=32", // default threshold in wasi-libc
|
|
||||||
"-isystem", headerPath,
|
|
||||||
"-I" + libcDir + "/libc-top-half/musl/src/include",
|
|
||||||
"-I" + libcDir + "/libc-top-half/musl/src/internal",
|
|
||||||
"-I" + libcDir + "/libc-top-half/musl/arch/wasm32",
|
|
||||||
"-I" + libcDir + "/libc-top-half/musl/arch/generic",
|
|
||||||
"-I" + libcDir + "/libc-top-half/headers/private",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cflagsForFile: func(path string) []string {
|
|
||||||
if strings.HasPrefix(path, "libc-bottom-half"+string(os.PathSeparator)) {
|
|
||||||
libcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc")
|
|
||||||
return []string{
|
|
||||||
"-I" + libcDir + "/libc-bottom-half/headers/private",
|
|
||||||
"-I" + libcDir + "/libc-bottom-half/cloudlibc/src/include",
|
|
||||||
"-I" + libcDir + "/libc-bottom-half/cloudlibc/src",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc") },
|
|
||||||
librarySources: func(target string, libcNeedsMalloc bool) ([]string, error) {
|
|
||||||
type filePattern struct {
|
|
||||||
glob string
|
|
||||||
exclude []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// See: LIBC_TOP_HALF_MUSL_SOURCES in the Makefile
|
|
||||||
globs := []filePattern{
|
|
||||||
// Top half: mostly musl sources.
|
|
||||||
{glob: "libc-top-half/sources/*.c"},
|
|
||||||
{glob: "libc-top-half/musl/src/conf/*.c"},
|
|
||||||
{glob: "libc-top-half/musl/src/internal/*.c", exclude: []string{
|
|
||||||
"procfdname.c", "syscall.c", "syscall_ret.c", "vdso.c", "version.c",
|
|
||||||
}},
|
|
||||||
{glob: "libc-top-half/musl/src/locale/*.c", exclude: []string{
|
|
||||||
"dcngettext.c", "textdomain.c", "bind_textdomain_codeset.c"}},
|
|
||||||
{glob: "libc-top-half/musl/src/math/*.c", exclude: []string{
|
|
||||||
"__signbit.c", "__signbitf.c", "__signbitl.c",
|
|
||||||
"__fpclassify.c", "__fpclassifyf.c", "__fpclassifyl.c",
|
|
||||||
"ceilf.c", "ceil.c",
|
|
||||||
"floorf.c", "floor.c",
|
|
||||||
"truncf.c", "trunc.c",
|
|
||||||
"rintf.c", "rint.c",
|
|
||||||
"nearbyintf.c", "nearbyint.c",
|
|
||||||
"sqrtf.c", "sqrt.c",
|
|
||||||
"fabsf.c", "fabs.c",
|
|
||||||
"copysignf.c", "copysign.c",
|
|
||||||
"fminf.c", "fmaxf.c",
|
|
||||||
"fmin.c", "fmax.c,",
|
|
||||||
}},
|
|
||||||
{glob: "libc-top-half/musl/src/multibyte/*.c"},
|
|
||||||
{glob: "libc-top-half/musl/src/stdio/*.c", exclude: []string{
|
|
||||||
"vfwscanf.c", "vfwprintf.c", // long double is unsupported
|
|
||||||
"__lockfile.c", "flockfile.c", "funlockfile.c", "ftrylockfile.c",
|
|
||||||
"rename.c",
|
|
||||||
"tmpnam.c", "tmpfile.c", "tempnam.c",
|
|
||||||
"popen.c", "pclose.c",
|
|
||||||
"remove.c",
|
|
||||||
"gets.c"}},
|
|
||||||
{glob: "libc-top-half/musl/src/stdlib/*.c"},
|
|
||||||
{glob: "libc-top-half/musl/src/string/*.c", exclude: []string{
|
|
||||||
"strsignal.c"}},
|
|
||||||
|
|
||||||
// Bottom half: connect top half to WASI equivalents.
|
|
||||||
{glob: "libc-bottom-half/cloudlibc/src/libc/*/*.c"},
|
|
||||||
{glob: "libc-bottom-half/cloudlibc/src/libc/sys/*/*.c"},
|
|
||||||
{glob: "libc-bottom-half/sources/*.c"},
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're using the Boehm GC, so we need a heap implementation in the libc.
|
|
||||||
if libcNeedsMalloc {
|
|
||||||
globs = append(globs, filePattern{glob: "dlmalloc/src/dlmalloc.c"})
|
|
||||||
}
|
|
||||||
|
|
||||||
// See: LIBC_TOP_HALF_MUSL_SOURCES in the Makefile
|
|
||||||
sources := []string{
|
|
||||||
"libc-top-half/musl/src/misc/a64l.c",
|
|
||||||
"libc-top-half/musl/src/misc/basename.c",
|
|
||||||
"libc-top-half/musl/src/misc/dirname.c",
|
|
||||||
"libc-top-half/musl/src/misc/ffs.c",
|
|
||||||
"libc-top-half/musl/src/misc/ffsl.c",
|
|
||||||
"libc-top-half/musl/src/misc/ffsll.c",
|
|
||||||
"libc-top-half/musl/src/misc/fmtmsg.c",
|
|
||||||
"libc-top-half/musl/src/misc/getdomainname.c",
|
|
||||||
"libc-top-half/musl/src/misc/gethostid.c",
|
|
||||||
"libc-top-half/musl/src/misc/getopt.c",
|
|
||||||
"libc-top-half/musl/src/misc/getopt_long.c",
|
|
||||||
"libc-top-half/musl/src/misc/getsubopt.c",
|
|
||||||
"libc-top-half/musl/src/misc/uname.c",
|
|
||||||
"libc-top-half/musl/src/misc/nftw.c",
|
|
||||||
"libc-top-half/musl/src/errno/strerror.c",
|
|
||||||
"libc-top-half/musl/src/network/htonl.c",
|
|
||||||
"libc-top-half/musl/src/network/htons.c",
|
|
||||||
"libc-top-half/musl/src/network/ntohl.c",
|
|
||||||
"libc-top-half/musl/src/network/ntohs.c",
|
|
||||||
"libc-top-half/musl/src/network/inet_ntop.c",
|
|
||||||
"libc-top-half/musl/src/network/inet_pton.c",
|
|
||||||
"libc-top-half/musl/src/network/inet_aton.c",
|
|
||||||
"libc-top-half/musl/src/network/in6addr_any.c",
|
|
||||||
"libc-top-half/musl/src/network/in6addr_loopback.c",
|
|
||||||
"libc-top-half/musl/src/fenv/fenv.c",
|
|
||||||
"libc-top-half/musl/src/fenv/fesetround.c",
|
|
||||||
"libc-top-half/musl/src/fenv/feupdateenv.c",
|
|
||||||
"libc-top-half/musl/src/fenv/fesetexceptflag.c",
|
|
||||||
"libc-top-half/musl/src/fenv/fegetexceptflag.c",
|
|
||||||
"libc-top-half/musl/src/fenv/feholdexcept.c",
|
|
||||||
"libc-top-half/musl/src/exit/exit.c",
|
|
||||||
"libc-top-half/musl/src/exit/atexit.c",
|
|
||||||
"libc-top-half/musl/src/exit/assert.c",
|
|
||||||
"libc-top-half/musl/src/exit/quick_exit.c",
|
|
||||||
"libc-top-half/musl/src/exit/at_quick_exit.c",
|
|
||||||
"libc-top-half/musl/src/time/strftime.c",
|
|
||||||
"libc-top-half/musl/src/time/asctime.c",
|
|
||||||
"libc-top-half/musl/src/time/asctime_r.c",
|
|
||||||
"libc-top-half/musl/src/time/ctime.c",
|
|
||||||
"libc-top-half/musl/src/time/ctime_r.c",
|
|
||||||
"libc-top-half/musl/src/time/wcsftime.c",
|
|
||||||
"libc-top-half/musl/src/time/strptime.c",
|
|
||||||
"libc-top-half/musl/src/time/difftime.c",
|
|
||||||
"libc-top-half/musl/src/time/timegm.c",
|
|
||||||
"libc-top-half/musl/src/time/ftime.c",
|
|
||||||
"libc-top-half/musl/src/time/gmtime.c",
|
|
||||||
"libc-top-half/musl/src/time/gmtime_r.c",
|
|
||||||
"libc-top-half/musl/src/time/timespec_get.c",
|
|
||||||
"libc-top-half/musl/src/time/getdate.c",
|
|
||||||
"libc-top-half/musl/src/time/localtime.c",
|
|
||||||
"libc-top-half/musl/src/time/localtime_r.c",
|
|
||||||
"libc-top-half/musl/src/time/mktime.c",
|
|
||||||
"libc-top-half/musl/src/time/__tm_to_secs.c",
|
|
||||||
"libc-top-half/musl/src/time/__month_to_secs.c",
|
|
||||||
"libc-top-half/musl/src/time/__secs_to_tm.c",
|
|
||||||
"libc-top-half/musl/src/time/__year_to_secs.c",
|
|
||||||
"libc-top-half/musl/src/time/__tz.c",
|
|
||||||
"libc-top-half/musl/src/fcntl/creat.c",
|
|
||||||
"libc-top-half/musl/src/dirent/alphasort.c",
|
|
||||||
"libc-top-half/musl/src/dirent/versionsort.c",
|
|
||||||
"libc-top-half/musl/src/env/__stack_chk_fail.c",
|
|
||||||
"libc-top-half/musl/src/env/clearenv.c",
|
|
||||||
"libc-top-half/musl/src/env/getenv.c",
|
|
||||||
"libc-top-half/musl/src/env/putenv.c",
|
|
||||||
"libc-top-half/musl/src/env/setenv.c",
|
|
||||||
"libc-top-half/musl/src/env/unsetenv.c",
|
|
||||||
"libc-top-half/musl/src/unistd/posix_close.c",
|
|
||||||
"libc-top-half/musl/src/stat/futimesat.c",
|
|
||||||
"libc-top-half/musl/src/legacy/getpagesize.c",
|
|
||||||
"libc-top-half/musl/src/thread/thrd_sleep.c",
|
|
||||||
}
|
|
||||||
|
|
||||||
basepath := goenv.Get("TINYGOROOT") + "/lib/wasi-libc/"
|
|
||||||
for _, pattern := range globs {
|
|
||||||
matches, err := filepath.Glob(basepath + pattern.glob)
|
|
||||||
if err != nil {
|
|
||||||
// From the documentation:
|
|
||||||
// > Glob ignores file system errors such as I/O errors reading
|
|
||||||
// > directories. The only possible returned error is
|
|
||||||
// > ErrBadPattern, when pattern is malformed.
|
|
||||||
// So the only possible error is when the (statically defined)
|
|
||||||
// pattern is wrong. In other words, a programming bug.
|
|
||||||
return nil, fmt.Errorf("wasi-libc: could not glob source dirs: %w", err)
|
|
||||||
}
|
|
||||||
if len(matches) == 0 {
|
|
||||||
return nil, fmt.Errorf("wasi-libc: did not find any files for pattern %#v", pattern)
|
|
||||||
}
|
|
||||||
excludeSet := map[string]struct{}{}
|
|
||||||
for _, exclude := range pattern.exclude {
|
|
||||||
excludeSet[exclude] = struct{}{}
|
|
||||||
}
|
|
||||||
for _, match := range matches {
|
|
||||||
if _, ok := excludeSet[filepath.Base(match)]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
relpath, err := filepath.Rel(basepath, match)
|
|
||||||
if err != nil {
|
|
||||||
// Not sure if this is even possible.
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sources = append(sources, relpath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sources, nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -29,8 +29,6 @@ var libWasmBuiltins = Library{
|
|||||||
"-Wall",
|
"-Wall",
|
||||||
"-std=gnu11",
|
"-std=gnu11",
|
||||||
"-nostdlibinc",
|
"-nostdlibinc",
|
||||||
"-mnontrapping-fptoint", // match wasm-unknown (default on in LLVM 20)
|
|
||||||
"-mno-bulk-memory", // same here
|
|
||||||
"-isystem", libcDir + "/libc-top-half/musl/arch/wasm32",
|
"-isystem", libcDir + "/libc-top-half/musl/arch/wasm32",
|
||||||
"-isystem", libcDir + "/libc-top-half/musl/arch/generic",
|
"-isystem", libcDir + "/libc-top-half/musl/arch/generic",
|
||||||
"-isystem", libcDir + "/libc-top-half/musl/src/internal",
|
"-isystem", libcDir + "/libc-top-half/musl/src/internal",
|
||||||
@@ -41,7 +39,7 @@ var libWasmBuiltins = Library{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc") },
|
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc") },
|
||||||
librarySources: func(target string, _ bool) ([]string, error) {
|
librarySources: func(target string) ([]string, error) {
|
||||||
return []string{
|
return []string{
|
||||||
// memory builtins needed for llvm.memcpy.*, llvm.memmove.*, and
|
// memory builtins needed for llvm.memcpy.*, llvm.memmove.*, and
|
||||||
// llvm.memset.* LLVM intrinsics.
|
// llvm.memset.* LLVM intrinsics.
|
||||||
|
|||||||
+1
-1
@@ -71,7 +71,7 @@ unsigned tinygo_clang_Cursor_isMacroFunctionLike(GoCXCursor c);
|
|||||||
// libclang.go:68:5: note: previous declaration is here
|
// libclang.go:68:5: note: previous declaration is here
|
||||||
// See: https://github.com/golang/go/issues/49721
|
// See: https://github.com/golang/go/issues/49721
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define CGO_DECL __declspec(dllexport)
|
#define CGO_DECL // __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define CGO_DECL
|
#define CGO_DECL
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build !byollvm && llvm19
|
//go:build !byollvm && !llvm15 && !llvm16 && !llvm17 && !llvm18
|
||||||
|
|
||||||
package cgo
|
package cgo
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
//go:build !byollvm && !llvm15 && !llvm16 && !llvm17 && !llvm18 && !llvm19
|
|
||||||
|
|
||||||
package cgo
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo linux CFLAGS: -I/usr/include/llvm-20 -I/usr/include/llvm-c-20 -I/usr/lib/llvm-20/include
|
|
||||||
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@20/include
|
|
||||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@20/include
|
|
||||||
#cgo freebsd CFLAGS: -I/usr/local/llvm20/include
|
|
||||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-20/lib -lclang
|
|
||||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@20/lib -lclang
|
|
||||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@20/lib -lclang
|
|
||||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm20/lib -lclang
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
+65
-118
@@ -8,24 +8,12 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/shlex"
|
"github.com/google/shlex"
|
||||||
"github.com/tinygo-org/tinygo/goenv"
|
"github.com/tinygo-org/tinygo/goenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Library versions. Whenever an existing library is changed, this number should
|
|
||||||
// be added/increased so that existing caches are invalidated.
|
|
||||||
//
|
|
||||||
// (This is a bit of a layering violation, this should really be part of the
|
|
||||||
// builder.Library struct but that's hard to do since we want to know the
|
|
||||||
// library path in advance in several places).
|
|
||||||
var libVersions = map[string]int{
|
|
||||||
"musl": 3,
|
|
||||||
"bdwgc": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config keeps all configuration affecting the build in a single struct.
|
// Config keeps all configuration affecting the build in a single struct.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Options *Options
|
Options *Options
|
||||||
@@ -111,11 +99,6 @@ func (c *Config) BuildTags() []string {
|
|||||||
"math_big_pure_go", // to get math/big to work
|
"math_big_pure_go", // to get math/big to work
|
||||||
"gc." + c.GC(), "scheduler." + c.Scheduler(), // used inside the runtime package
|
"gc." + c.GC(), "scheduler." + c.Scheduler(), // used inside the runtime package
|
||||||
"serial." + c.Serial()}...) // used inside the machine package
|
"serial." + c.Serial()}...) // used inside the machine package
|
||||||
switch c.Scheduler() {
|
|
||||||
case "threads", "cores":
|
|
||||||
default:
|
|
||||||
tags = append(tags, "tinygo.unicore")
|
|
||||||
}
|
|
||||||
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))
|
||||||
}
|
}
|
||||||
@@ -139,7 +122,7 @@ func (c *Config) GC() string {
|
|||||||
// that can be traced by the garbage collector.
|
// that can be traced by the garbage collector.
|
||||||
func (c *Config) NeedsStackObjects() bool {
|
func (c *Config) NeedsStackObjects() bool {
|
||||||
switch c.GC() {
|
switch c.GC() {
|
||||||
case "conservative", "custom", "precise", "boehm":
|
case "conservative", "custom", "precise":
|
||||||
for _, tag := range c.BuildTags() {
|
for _, tag := range c.BuildTags() {
|
||||||
if tag == "tinygo.wasm" {
|
if tag == "tinygo.wasm" {
|
||||||
return true
|
return true
|
||||||
@@ -264,18 +247,10 @@ func MuslArchitecture(triple string) string {
|
|||||||
return CanonicalArchName(triple)
|
return CanonicalArchName(triple)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the libc needs to include malloc, for the libcs where this
|
// LibcPath returns the path to the libc directory. The libc path will be either
|
||||||
// matters.
|
// a precompiled libc shipped with a TinyGo build, or a libc path in the cache
|
||||||
func (c *Config) LibcNeedsMalloc() bool {
|
// directory (which might not yet be built).
|
||||||
if c.GC() == "boehm" && c.Target.Libc == "wasi-libc" {
|
func (c *Config) LibcPath(name string) (path string, precompiled bool) {
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// LibraryPath returns the path to the library build directory. The path will be
|
|
||||||
// a library path in the cache directory (which might not yet be built).
|
|
||||||
func (c *Config) LibraryPath(name string) string {
|
|
||||||
archname := c.Triple()
|
archname := c.Triple()
|
||||||
if c.CPU() != "" {
|
if c.CPU() != "" {
|
||||||
archname += "-" + c.CPU()
|
archname += "-" + c.CPU()
|
||||||
@@ -286,24 +261,18 @@ func (c *Config) LibraryPath(name string) string {
|
|||||||
if c.Target.SoftFloat {
|
if c.Target.SoftFloat {
|
||||||
archname += "-softfloat"
|
archname += "-softfloat"
|
||||||
}
|
}
|
||||||
if name == "bdwgc" {
|
|
||||||
// Boehm GC is compiled against a particular libc.
|
|
||||||
archname += "-" + c.Target.Libc
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append a version string, if this library has a version.
|
// Try to load a precompiled library.
|
||||||
if v, ok := libVersions[name]; ok {
|
precompiledDir := filepath.Join(goenv.Get("TINYGOROOT"), "pkg", archname, name)
|
||||||
archname += "-v" + strconv.Itoa(v)
|
if _, err := os.Stat(precompiledDir); err == nil {
|
||||||
}
|
// Found a precompiled library for this OS/architecture. Return the path
|
||||||
|
// directly.
|
||||||
options := ""
|
return precompiledDir, true
|
||||||
if c.LibcNeedsMalloc() {
|
|
||||||
options += "+malloc"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No precompiled library found. Determine the path name that will be used
|
// No precompiled library found. Determine the path name that will be used
|
||||||
// in the build cache.
|
// in the build cache.
|
||||||
return filepath.Join(goenv.Get("GOCACHE"), name+options+"-"+archname)
|
return filepath.Join(goenv.Get("GOCACHE"), name+"-"+archname), false
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultBinaryExtension returns the default extension for binaries, such as
|
// DefaultBinaryExtension returns the default extension for binaries, such as
|
||||||
@@ -346,7 +315,59 @@ func (c *Config) CFlags(libclang bool) []string {
|
|||||||
"-resource-dir="+resourceDir,
|
"-resource-dir="+resourceDir,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
cflags = append(cflags, c.LibcCFlags()...)
|
switch c.Target.Libc {
|
||||||
|
case "darwin-libSystem":
|
||||||
|
root := goenv.Get("TINYGOROOT")
|
||||||
|
cflags = append(cflags,
|
||||||
|
"-nostdlibinc",
|
||||||
|
"-isystem", filepath.Join(root, "lib/macos-minimal-sdk/src/usr/include"),
|
||||||
|
)
|
||||||
|
case "picolibc":
|
||||||
|
root := goenv.Get("TINYGOROOT")
|
||||||
|
picolibcDir := filepath.Join(root, "lib", "picolibc", "newlib", "libc")
|
||||||
|
path, _ := c.LibcPath("picolibc")
|
||||||
|
cflags = append(cflags,
|
||||||
|
"-nostdlibinc",
|
||||||
|
"-isystem", filepath.Join(path, "include"),
|
||||||
|
"-isystem", filepath.Join(picolibcDir, "include"),
|
||||||
|
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
|
||||||
|
"-D__PICOLIBC_ERRNO_FUNCTION=__errno_location",
|
||||||
|
)
|
||||||
|
case "musl":
|
||||||
|
root := goenv.Get("TINYGOROOT")
|
||||||
|
path, _ := c.LibcPath("musl")
|
||||||
|
arch := MuslArchitecture(c.Triple())
|
||||||
|
cflags = append(cflags,
|
||||||
|
"-nostdlibinc",
|
||||||
|
"-isystem", filepath.Join(path, "include"),
|
||||||
|
"-isystem", filepath.Join(root, "lib", "musl", "arch", arch),
|
||||||
|
"-isystem", filepath.Join(root, "lib", "musl", "arch", "generic"),
|
||||||
|
"-isystem", filepath.Join(root, "lib", "musl", "include"),
|
||||||
|
)
|
||||||
|
case "wasi-libc":
|
||||||
|
root := goenv.Get("TINYGOROOT")
|
||||||
|
cflags = append(cflags,
|
||||||
|
"-nostdlibinc",
|
||||||
|
"-isystem", root+"/lib/wasi-libc/sysroot/include")
|
||||||
|
case "wasmbuiltins":
|
||||||
|
// nothing to add (library is purely for builtins)
|
||||||
|
case "mingw-w64":
|
||||||
|
root := goenv.Get("TINYGOROOT")
|
||||||
|
path, _ := c.LibcPath("mingw-w64")
|
||||||
|
cflags = append(cflags,
|
||||||
|
"-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", "defaults", "include"),
|
||||||
|
"-D_UCRT",
|
||||||
|
)
|
||||||
|
case "":
|
||||||
|
// No libc specified, nothing to add.
|
||||||
|
default:
|
||||||
|
// Incorrect configuration. This could be handled in a better way, but
|
||||||
|
// usually this will be found by developers (not by TinyGo users).
|
||||||
|
panic("unknown libc: " + c.Target.Libc)
|
||||||
|
}
|
||||||
// Always emit debug information. It is optionally stripped at link time.
|
// Always emit debug information. It is optionally stripped at link time.
|
||||||
cflags = append(cflags, "-gdwarf-4")
|
cflags = append(cflags, "-gdwarf-4")
|
||||||
// Use the same optimization level as TinyGo.
|
// Use the same optimization level as TinyGo.
|
||||||
@@ -373,80 +394,6 @@ func (c *Config) CFlags(libclang bool) []string {
|
|||||||
return cflags
|
return cflags
|
||||||
}
|
}
|
||||||
|
|
||||||
// LibcCFlags returns the C compiler flags for the configured libc.
|
|
||||||
// It only uses flags that are part of the libc path (triple, cpu, abi, libc
|
|
||||||
// name) so it can safely be used to compile another C library.
|
|
||||||
func (c *Config) LibcCFlags() []string {
|
|
||||||
switch c.Target.Libc {
|
|
||||||
case "darwin-libSystem":
|
|
||||||
root := goenv.Get("TINYGOROOT")
|
|
||||||
return []string{
|
|
||||||
"-nostdlibinc",
|
|
||||||
"-isystem", filepath.Join(root, "lib/macos-minimal-sdk/src/usr/include"),
|
|
||||||
}
|
|
||||||
case "picolibc":
|
|
||||||
root := goenv.Get("TINYGOROOT")
|
|
||||||
picolibcDir := filepath.Join(root, "lib", "picolibc", "newlib", "libc")
|
|
||||||
path := c.LibraryPath("picolibc")
|
|
||||||
return []string{
|
|
||||||
"-nostdlibinc",
|
|
||||||
"-isystem", filepath.Join(path, "include"),
|
|
||||||
"-isystem", filepath.Join(picolibcDir, "include"),
|
|
||||||
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
|
|
||||||
"-D__PICOLIBC_ERRNO_FUNCTION=__errno_location",
|
|
||||||
}
|
|
||||||
case "musl":
|
|
||||||
root := goenv.Get("TINYGOROOT")
|
|
||||||
path := c.LibraryPath("musl")
|
|
||||||
arch := MuslArchitecture(c.Triple())
|
|
||||||
return []string{
|
|
||||||
"-nostdlibinc",
|
|
||||||
"-isystem", filepath.Join(path, "include"),
|
|
||||||
"-isystem", filepath.Join(root, "lib", "musl", "arch", arch),
|
|
||||||
"-isystem", filepath.Join(root, "lib", "musl", "arch", "generic"),
|
|
||||||
"-isystem", filepath.Join(root, "lib", "musl", "include"),
|
|
||||||
}
|
|
||||||
case "wasi-libc":
|
|
||||||
path := c.LibraryPath("wasi-libc")
|
|
||||||
return []string{
|
|
||||||
"-nostdlibinc",
|
|
||||||
"-isystem", filepath.Join(path, "include"),
|
|
||||||
}
|
|
||||||
case "wasmbuiltins":
|
|
||||||
// nothing to add (library is purely for builtins)
|
|
||||||
return nil
|
|
||||||
case "mingw-w64":
|
|
||||||
root := goenv.Get("TINYGOROOT")
|
|
||||||
path := c.LibraryPath("mingw-w64")
|
|
||||||
cflags := []string{
|
|
||||||
"-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", "include"),
|
|
||||||
"-isystem", filepath.Join(root, "lib", "mingw-w64", "mingw-w64-headers", "defaults", "include"),
|
|
||||||
}
|
|
||||||
if c.GOARCH() == "386" {
|
|
||||||
cflags = append(cflags,
|
|
||||||
"-D__MSVCRT_VERSION__=0x700", // Microsoft Visual C++ .NET 2002
|
|
||||||
"-D_WIN32_WINNT=0x0501", // target Windows XP
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
cflags = append(cflags,
|
|
||||||
"-D_UCRT",
|
|
||||||
"-D_WIN32_WINNT=0x0a00", // target Windows 10
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return cflags
|
|
||||||
case "":
|
|
||||||
// No libc specified, nothing to add.
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
// Incorrect configuration. This could be handled in a better way, but
|
|
||||||
// usually this will be found by developers (not by TinyGo users).
|
|
||||||
panic("unknown libc: " + c.Target.Libc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// LDFlags returns the flags to pass to the linker. A few more flags are needed
|
// LDFlags returns the flags to pass to the linker. A few more flags are needed
|
||||||
// (like the one for the compiler runtime), but this represents the majority of
|
// (like the one for the compiler runtime), but this represents the majority of
|
||||||
// the flags.
|
// the flags.
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
validBuildModeOptions = []string{"default", "c-shared", "wasi-legacy"}
|
validBuildModeOptions = []string{"default", "c-shared", "wasi-legacy"}
|
||||||
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise", "boehm"}
|
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
|
||||||
validSchedulerOptions = []string{"none", "tasks", "asyncify", "threads", "cores"}
|
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
|
||||||
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
|
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
|
||||||
validPrintSizeOptions = []string{"none", "short", "full", "html"}
|
validPrintSizeOptions = []string{"none", "short", "full", "html"}
|
||||||
validPanicStrategyOptions = []string{"print", "trap"}
|
validPanicStrategyOptions = []string{"print", "trap"}
|
||||||
@@ -43,7 +43,6 @@ type Options struct {
|
|||||||
PrintCommands func(cmd string, args ...string) `json:"-"`
|
PrintCommands func(cmd string, args ...string) `json:"-"`
|
||||||
Semaphore chan struct{} `json:"-"` // -p flag controls cap
|
Semaphore chan struct{} `json:"-"` // -p flag controls cap
|
||||||
Debug bool
|
Debug bool
|
||||||
Nobounds bool
|
|
||||||
PrintSizes string
|
PrintSizes string
|
||||||
PrintAllocs *regexp.Regexp // regexp string
|
PrintAllocs *regexp.Regexp // regexp string
|
||||||
PrintStacks bool
|
PrintStacks bool
|
||||||
@@ -53,6 +52,7 @@ type Options struct {
|
|||||||
Programmer string
|
Programmer string
|
||||||
OpenOCDCommands []string
|
OpenOCDCommands []string
|
||||||
LLVMFeatures string
|
LLVMFeatures string
|
||||||
|
PrintJSON bool
|
||||||
Monitor bool
|
Monitor bool
|
||||||
BaudRate int
|
BaudRate int
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
|
|
||||||
func TestVerifyOptions(t *testing.T) {
|
func TestVerifyOptions(t *testing.T) {
|
||||||
|
|
||||||
expectedGCError := errors.New(`invalid gc option 'incorrect': valid values are none, leaking, conservative, custom, precise, boehm`)
|
expectedGCError := errors.New(`invalid gc option 'incorrect': valid values are none, leaking, conservative, custom, precise`)
|
||||||
expectedSchedulerError := errors.New(`invalid scheduler option 'incorrect': valid values are none, tasks, asyncify, threads, cores`)
|
expectedSchedulerError := errors.New(`invalid scheduler option 'incorrect': valid values are none, tasks, asyncify`)
|
||||||
expectedPrintSizeError := errors.New(`invalid size option 'incorrect': valid values are none, short, full, html`)
|
expectedPrintSizeError := errors.New(`invalid size option 'incorrect': valid values are none, short, full, html`)
|
||||||
expectedPanicStrategyError := errors.New(`invalid panic option 'incorrect': valid values are print, trap`)
|
expectedPanicStrategyError := errors.New(`invalid panic option 'incorrect': valid values are print, trap`)
|
||||||
|
|
||||||
|
|||||||
+9
-44
@@ -178,21 +178,6 @@ func (spec *TargetSpec) resolveInherits() error {
|
|||||||
|
|
||||||
// Load a target specification.
|
// Load a target specification.
|
||||||
func LoadTarget(options *Options) (*TargetSpec, error) {
|
func LoadTarget(options *Options) (*TargetSpec, error) {
|
||||||
if options.Target == "" && options.GOARCH == "wasm" {
|
|
||||||
// Set a specific target if we're building from a known GOOS/GOARCH
|
|
||||||
// combination that is defined in a target JSON file.
|
|
||||||
switch options.GOOS {
|
|
||||||
case "js":
|
|
||||||
options.Target = "wasm"
|
|
||||||
case "wasip1":
|
|
||||||
options.Target = "wasip1"
|
|
||||||
case "wasip2":
|
|
||||||
options.Target = "wasip2"
|
|
||||||
default:
|
|
||||||
return nil, errors.New("GOARCH=wasm but GOOS is not set correctly. Please set GOOS to js, wasip1, or wasip2.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.Target == "" {
|
if options.Target == "" {
|
||||||
return defaultTarget(options)
|
return defaultTarget(options)
|
||||||
}
|
}
|
||||||
@@ -262,6 +247,8 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
GOOS: options.GOOS,
|
GOOS: options.GOOS,
|
||||||
GOARCH: options.GOARCH,
|
GOARCH: options.GOARCH,
|
||||||
BuildTags: []string{options.GOOS, options.GOARCH},
|
BuildTags: []string{options.GOOS, options.GOARCH},
|
||||||
|
GC: "precise",
|
||||||
|
Scheduler: "tasks",
|
||||||
Linker: "cc",
|
Linker: "cc",
|
||||||
DefaultStackSize: 1024 * 64, // 64kB
|
DefaultStackSize: 1024 * 64, // 64kB
|
||||||
GDB: []string{"gdb"},
|
GDB: []string{"gdb"},
|
||||||
@@ -369,7 +356,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
return nil, fmt.Errorf("invalid GOMIPS=%s: must be hardfloat or softfloat", options.GOMIPS)
|
return nil, fmt.Errorf("invalid GOMIPS=%s: must be hardfloat or softfloat", options.GOMIPS)
|
||||||
}
|
}
|
||||||
case "wasm":
|
case "wasm":
|
||||||
return nil, fmt.Errorf("GOARCH=wasm but GOOS is unset. Please set GOOS to js, wasip1, or wasip2.")
|
return nil, fmt.Errorf("GOARCH=wasm but GOOS is unset. Please set GOOS to wasm, wasip1, or wasip2.")
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown GOARCH=%s", options.GOARCH)
|
return nil, fmt.Errorf("unknown GOARCH=%s", options.GOARCH)
|
||||||
}
|
}
|
||||||
@@ -379,13 +366,11 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
llvmvendor := "unknown"
|
llvmvendor := "unknown"
|
||||||
switch options.GOOS {
|
switch options.GOOS {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
spec.GC = "boehm"
|
|
||||||
platformVersion := "10.12.0"
|
platformVersion := "10.12.0"
|
||||||
if options.GOARCH == "arm64" {
|
if options.GOARCH == "arm64" {
|
||||||
platformVersion = "11.0.0" // first macosx platform with arm64 support
|
platformVersion = "11.0.0" // first macosx platform with arm64 support
|
||||||
}
|
}
|
||||||
llvmvendor = "apple"
|
llvmvendor = "apple"
|
||||||
spec.Scheduler = "threads"
|
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.Libc = "darwin-libSystem"
|
spec.Libc = "darwin-libSystem"
|
||||||
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to
|
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to
|
||||||
@@ -399,13 +384,10 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
)
|
)
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles,
|
spec.ExtraFiles = append(spec.ExtraFiles,
|
||||||
"src/internal/futex/futex_darwin.c",
|
"src/internal/futex/futex_darwin.c",
|
||||||
"src/internal/task/task_threads.c",
|
|
||||||
"src/runtime/os_darwin.c",
|
"src/runtime/os_darwin.c",
|
||||||
"src/runtime/runtime_unix.c",
|
"src/runtime/runtime_unix.c",
|
||||||
"src/runtime/signal.c")
|
"src/runtime/signal.c")
|
||||||
case "linux":
|
case "linux":
|
||||||
spec.GC = "boehm"
|
|
||||||
spec.Scheduler = "threads"
|
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.RTLib = "compiler-rt"
|
spec.RTLib = "compiler-rt"
|
||||||
spec.Libc = "musl"
|
spec.Libc = "musl"
|
||||||
@@ -426,30 +408,19 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
}
|
}
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles,
|
spec.ExtraFiles = append(spec.ExtraFiles,
|
||||||
"src/internal/futex/futex_linux.c",
|
"src/internal/futex/futex_linux.c",
|
||||||
"src/internal/task/task_threads.c",
|
|
||||||
"src/runtime/runtime_unix.c",
|
"src/runtime/runtime_unix.c",
|
||||||
"src/runtime/signal.c")
|
"src/runtime/signal.c")
|
||||||
case "windows":
|
case "windows":
|
||||||
spec.GC = "boehm"
|
|
||||||
spec.Scheduler = "tasks"
|
|
||||||
spec.Linker = "ld.lld"
|
spec.Linker = "ld.lld"
|
||||||
spec.Libc = "mingw-w64"
|
spec.Libc = "mingw-w64"
|
||||||
|
// Note: using a medium code model, low image base and no ASLR
|
||||||
|
// because Go doesn't really need those features. ASLR patches
|
||||||
|
// around issues for unsafe languages like C/C++ that are not
|
||||||
|
// normally present in Go (without explicitly opting in).
|
||||||
|
// For more discussion:
|
||||||
|
// https://groups.google.com/g/Golang-nuts/c/Jd9tlNc6jUE/m/Zo-7zIP_m3MJ?pli=1
|
||||||
switch options.GOARCH {
|
switch options.GOARCH {
|
||||||
case "386":
|
|
||||||
spec.LDFlags = append(spec.LDFlags,
|
|
||||||
"-m", "i386pe",
|
|
||||||
"--major-os-version", "4",
|
|
||||||
"--major-subsystem-version", "4",
|
|
||||||
)
|
|
||||||
// __udivdi3 is not present in ucrt it seems.
|
|
||||||
spec.RTLib = "compiler-rt"
|
|
||||||
case "amd64":
|
case "amd64":
|
||||||
// Note: using a medium code model, low image base and no ASLR
|
|
||||||
// because Go doesn't really need those features. ASLR patches
|
|
||||||
// around issues for unsafe languages like C/C++ that are not
|
|
||||||
// normally present in Go (without explicitly opting in).
|
|
||||||
// For more discussion:
|
|
||||||
// https://groups.google.com/g/Golang-nuts/c/Jd9tlNc6jUE/m/Zo-7zIP_m3MJ?pli=1
|
|
||||||
spec.LDFlags = append(spec.LDFlags,
|
spec.LDFlags = append(spec.LDFlags,
|
||||||
"-m", "i386pep",
|
"-m", "i386pep",
|
||||||
"--image-base", "0x400000",
|
"--image-base", "0x400000",
|
||||||
@@ -471,12 +442,6 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
|
|||||||
return nil, fmt.Errorf("unknown GOOS=%s", options.GOOS)
|
return nil, fmt.Errorf("unknown GOOS=%s", options.GOOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
if spec.GC == "boehm" {
|
|
||||||
// Add this file only when needed. This fixes a build failure on
|
|
||||||
// Windows.
|
|
||||||
spec.ExtraFiles = append(spec.ExtraFiles, "src/runtime/gc_boehm.c")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Target triples (which actually have four components, but are called
|
// Target triples (which actually have four components, but are called
|
||||||
// triples for historical reasons) have the form:
|
// triples for historical reasons) have the form:
|
||||||
// arch-vendor-os-environment
|
// arch-vendor-os-environment
|
||||||
|
|||||||
+1
-9
@@ -76,15 +76,7 @@ func (b *builder) createCall(fnType llvm.Type, fn llvm.Value, args []llvm.Value,
|
|||||||
fragments := b.expandFormalParam(arg)
|
fragments := b.expandFormalParam(arg)
|
||||||
expanded = append(expanded, fragments...)
|
expanded = append(expanded, fragments...)
|
||||||
}
|
}
|
||||||
call := b.CreateCall(fnType, fn, expanded, name)
|
return b.CreateCall(fnType, fn, expanded, name)
|
||||||
if !fn.IsAFunction().IsNil() {
|
|
||||||
if cc := fn.FunctionCallConv(); cc != llvm.CCallConv {
|
|
||||||
// Set a different calling convention if needed.
|
|
||||||
// This is needed for GetModuleHandleExA on Windows, for example.
|
|
||||||
call.SetInstructionCallConv(cc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return call
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// createInvoke is like createCall but continues execution at the landing pad if
|
// createInvoke is like createCall but continues execution at the landing pad if
|
||||||
|
|||||||
+10
-39
@@ -58,7 +58,6 @@ type Config struct {
|
|||||||
MaxStackAlloc 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.
|
||||||
Nobounds bool // Whether to skip bounds checks
|
|
||||||
PanicStrategy string
|
PanicStrategy string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,7 +388,7 @@ func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
|
|||||||
// makeLLVMType creates a LLVM type for a Go type. Don't call this, use
|
// makeLLVMType creates a LLVM type for a Go type. Don't call this, use
|
||||||
// getLLVMType instead.
|
// getLLVMType instead.
|
||||||
func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
|
func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
|
||||||
switch typ := types.Unalias(goType).(type) {
|
switch typ := goType.(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elemType := c.getLLVMType(typ.Elem())
|
elemType := c.getLLVMType(typ.Elem())
|
||||||
return llvm.ArrayType(elemType, int(typ.Len()))
|
return llvm.ArrayType(elemType, int(typ.Len()))
|
||||||
@@ -497,21 +496,6 @@ func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
|||||||
llvmType := c.getLLVMType(typ)
|
llvmType := c.getLLVMType(typ)
|
||||||
sizeInBytes := c.targetData.TypeAllocSize(llvmType)
|
sizeInBytes := c.targetData.TypeAllocSize(llvmType)
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.(type) {
|
||||||
case *types.Alias:
|
|
||||||
// Implement types.Alias just like types.Named: by treating them like a
|
|
||||||
// C typedef.
|
|
||||||
temporaryMDNode := c.dibuilder.CreateReplaceableCompositeType(llvm.Metadata{}, llvm.DIReplaceableCompositeType{
|
|
||||||
Tag: dwarf.TagTypedef,
|
|
||||||
SizeInBits: sizeInBytes * 8,
|
|
||||||
AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
|
|
||||||
})
|
|
||||||
c.ditypes[typ] = temporaryMDNode
|
|
||||||
md := c.dibuilder.CreateTypedef(llvm.DITypedef{
|
|
||||||
Type: c.getDIType(types.Unalias(typ)), // TODO: use typ.Rhs in Go 1.23
|
|
||||||
Name: typ.String(),
|
|
||||||
})
|
|
||||||
temporaryMDNode.ReplaceAllUsesWith(md)
|
|
||||||
return md
|
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
return c.dibuilder.CreateArrayType(llvm.DIArrayType{
|
return c.dibuilder.CreateArrayType(llvm.DIArrayType{
|
||||||
SizeInBits: sizeInBytes * 8,
|
SizeInBits: sizeInBytes * 8,
|
||||||
@@ -874,11 +858,6 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
|
|||||||
// Interfaces don't have concrete methods.
|
// Interfaces don't have concrete methods.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, isalias := member.Type().(*types.Alias); isalias {
|
|
||||||
// Aliases don't need to be redefined, since they just refer to
|
|
||||||
// an already existing type whose methods will be defined.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Named type. We should make sure all methods are created.
|
// Named type. We should make sure all methods are created.
|
||||||
// This includes both functions with pointer receivers and those
|
// This includes both functions with pointer receivers and those
|
||||||
@@ -1856,7 +1835,15 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||||||
//
|
//
|
||||||
// This is also where compiler intrinsics are implemented.
|
// This is also where compiler intrinsics are implemented.
|
||||||
func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) {
|
func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) {
|
||||||
// See if this is an intrinsic function that is handled specially.
|
var params []llvm.Value
|
||||||
|
for _, param := range instr.Args {
|
||||||
|
params = append(params, b.getValue(param, getPos(instr)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to call the function directly for trivially static calls.
|
||||||
|
var callee, context llvm.Value
|
||||||
|
var calleeType llvm.Type
|
||||||
|
exported := false
|
||||||
if fn := instr.StaticCallee(); fn != nil {
|
if fn := instr.StaticCallee(); fn != nil {
|
||||||
// Direct function call, either to a named or anonymous (directly
|
// Direct function call, either to a named or anonymous (directly
|
||||||
// applied) function call. If it is anonymous, it may be a closure.
|
// applied) function call. If it is anonymous, it may be a closure.
|
||||||
@@ -1892,29 +1879,13 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
|||||||
return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil
|
return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil
|
||||||
case name == "runtime/interrupt.New":
|
case name == "runtime/interrupt.New":
|
||||||
return b.createInterruptGlobal(instr)
|
return b.createInterruptGlobal(instr)
|
||||||
case name == "runtime.exportedFuncPtr":
|
|
||||||
_, ptr := b.getFunction(instr.Args[0].(*ssa.Function))
|
|
||||||
return b.CreatePtrToInt(ptr, b.uintptrType, ""), nil
|
|
||||||
case name == "(*runtime/interrupt.Checkpoint).Save":
|
|
||||||
return b.createInterruptCheckpoint(instr.Args[0]), nil
|
|
||||||
case name == "internal/abi.FuncPCABI0":
|
case name == "internal/abi.FuncPCABI0":
|
||||||
retval := b.createDarwinFuncPCABI0Call(instr)
|
retval := b.createDarwinFuncPCABI0Call(instr)
|
||||||
if !retval.IsNil() {
|
if !retval.IsNil() {
|
||||||
return retval, nil
|
return retval, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var params []llvm.Value
|
|
||||||
for _, param := range instr.Args {
|
|
||||||
params = append(params, b.getValue(param, getPos(instr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to call the function directly for trivially static calls.
|
|
||||||
var callee, context llvm.Value
|
|
||||||
var calleeType llvm.Type
|
|
||||||
exported := false
|
|
||||||
if fn := instr.StaticCallee(); fn != nil {
|
|
||||||
calleeType, callee = b.getFunction(fn)
|
calleeType, callee = b.getFunction(fn)
|
||||||
info := b.getFunctionInfo(fn)
|
info := b.getFunctionInfo(fn)
|
||||||
if callee.IsNil() {
|
if callee.IsNil() {
|
||||||
|
|||||||
+6
-15
@@ -103,11 +103,10 @@ func (b *builder) createLandingPad() {
|
|||||||
b.CreateBr(b.blockEntries[b.fn.Recover])
|
b.CreateBr(b.blockEntries[b.fn.Recover])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a checkpoint (similar to setjmp). This emits inline assembly that
|
// createInvokeCheckpoint saves the function state at the given point, to
|
||||||
// stores the current program counter inside the ptr address (actually
|
// continue at the landing pad if a panic happened. This is implemented using a
|
||||||
// ptr+sizeof(ptr)) and then returns a boolean indicating whether this is the
|
// setjmp-like construct.
|
||||||
// normal flow (false) or we jumped here from somewhere else (true).
|
func (b *builder) createInvokeCheckpoint() {
|
||||||
func (b *builder) createCheckpoint(ptr llvm.Value) llvm.Value {
|
|
||||||
// Construct inline assembly equivalents of setjmp.
|
// Construct inline assembly equivalents of setjmp.
|
||||||
// The assembly works as follows:
|
// The assembly works as follows:
|
||||||
// * All registers (both callee-saved and caller saved) are clobbered
|
// * All registers (both callee-saved and caller saved) are clobbered
|
||||||
@@ -218,19 +217,11 @@ li a0, 0
|
|||||||
// This case should have been handled by b.supportsRecover().
|
// This case should have been handled by b.supportsRecover().
|
||||||
b.addError(b.fn.Pos(), "unknown architecture for defer: "+b.archFamily())
|
b.addError(b.fn.Pos(), "unknown architecture for defer: "+b.archFamily())
|
||||||
}
|
}
|
||||||
asmType := llvm.FunctionType(resultType, []llvm.Type{b.dataPtrType}, false)
|
asmType := llvm.FunctionType(resultType, []llvm.Type{b.deferFrame.Type()}, false)
|
||||||
asm := llvm.InlineAsm(asmType, asmString, constraints, false, false, 0, false)
|
asm := llvm.InlineAsm(asmType, asmString, constraints, false, false, 0, false)
|
||||||
result := b.CreateCall(asmType, asm, []llvm.Value{ptr}, "setjmp")
|
result := b.CreateCall(asmType, asm, []llvm.Value{b.deferFrame}, "setjmp")
|
||||||
result.AddCallSiteAttribute(-1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("returns_twice"), 0))
|
result.AddCallSiteAttribute(-1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("returns_twice"), 0))
|
||||||
isZero := b.CreateICmp(llvm.IntEQ, result, llvm.ConstInt(resultType, 0, false), "setjmp.result")
|
isZero := b.CreateICmp(llvm.IntEQ, result, llvm.ConstInt(resultType, 0, false), "setjmp.result")
|
||||||
return isZero
|
|
||||||
}
|
|
||||||
|
|
||||||
// createInvokeCheckpoint saves the function state at the given point, to
|
|
||||||
// continue at the landing pad if a panic happened. This is implemented using a
|
|
||||||
// setjmp-like construct.
|
|
||||||
func (b *builder) createInvokeCheckpoint() {
|
|
||||||
isZero := b.createCheckpoint(b.deferFrame)
|
|
||||||
continueBB := b.insertBasicBlock("")
|
continueBB := b.insertBasicBlock("")
|
||||||
b.CreateCondBr(isZero, continueBB, b.landingpad)
|
b.CreateCondBr(isZero, continueBB, b.landingpad)
|
||||||
b.SetInsertPointAtEnd(continueBB)
|
b.SetInsertPointAtEnd(continueBB)
|
||||||
|
|||||||
@@ -249,15 +249,3 @@ func (b *builder) emitCSROperation(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation: "+name)
|
return llvm.Value{}, b.makeError(call.Pos(), "unknown CSR operation: "+name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement runtime/interrupt.Checkpoint.Save. It needs to be implemented
|
|
||||||
// directly at the call site. If it isn't implemented directly at the call site
|
|
||||||
// (but instead through a function call), it might result in an overwritten
|
|
||||||
// stack in the non-jump return case.
|
|
||||||
func (b *builder) createInterruptCheckpoint(ptr ssa.Value) llvm.Value {
|
|
||||||
addr := b.getValue(ptr, ptr.Pos())
|
|
||||||
b.createNilCheck(ptr, addr, "deref")
|
|
||||||
stackPointer := b.readStackPointer()
|
|
||||||
b.CreateStore(stackPointer, addr)
|
|
||||||
return b.createCheckpoint(addr)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -122,9 +122,6 @@ func (c *compilerContext) pkgPathPtr(pkgpath string) llvm.Value {
|
|||||||
// This function returns a pointer to the 'kind' field (which might not be the
|
// This function returns a pointer to the 'kind' field (which might not be the
|
||||||
// first field in the struct).
|
// first field in the struct).
|
||||||
func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
||||||
// Resolve alias types: alias types are resolved at compile time.
|
|
||||||
typ = types.Unalias(typ)
|
|
||||||
|
|
||||||
ms := c.program.MethodSets.MethodSet(typ)
|
ms := c.program.MethodSets.MethodSet(typ)
|
||||||
hasMethodSet := ms.Len() != 0
|
hasMethodSet := ms.Len() != 0
|
||||||
_, isInterface := typ.Underlying().(*types.Interface)
|
_, isInterface := typ.Underlying().(*types.Interface)
|
||||||
@@ -515,7 +512,7 @@ var basicTypeNames = [...]string{
|
|||||||
// interface lowering pass to assign type codes as expected by the reflect
|
// interface lowering pass to assign type codes as expected by the reflect
|
||||||
// package. See getTypeCodeNum.
|
// package. See getTypeCodeNum.
|
||||||
func getTypeCodeName(t types.Type) (string, bool) {
|
func getTypeCodeName(t types.Type) (string, bool) {
|
||||||
switch t := types.Unalias(t).(type) {
|
switch t := t.(type) {
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
if t.Obj().Parent() != t.Obj().Pkg().Scope() {
|
if t.Obj().Parent() != t.Obj().Pkg().Scope() {
|
||||||
return "named:" + t.String() + "$local", true
|
return "named:" + t.String() + "$local", true
|
||||||
@@ -945,7 +942,7 @@ func signature(sig *types.Signature) string {
|
|||||||
// normalization around `byte` vs `uint8` for example.
|
// normalization around `byte` vs `uint8` for example.
|
||||||
func typestring(t types.Type) string {
|
func typestring(t types.Type) string {
|
||||||
// See: https://github.com/golang/go/blob/master/src/go/types/typestring.go
|
// See: https://github.com/golang/go/blob/master/src/go/types/typestring.go
|
||||||
switch t := types.Unalias(t).(type) {
|
switch t := t.(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
return "[" + strconv.FormatInt(t.Len(), 10) + "]" + typestring(t.Elem())
|
return "[" + strconv.FormatInt(t.Len(), 10) + "]" + typestring(t.Elem())
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
|
|||||||
@@ -121,29 +121,6 @@ func (b *builder) createKeepAliveImpl() {
|
|||||||
b.CreateRetVoid()
|
b.CreateRetVoid()
|
||||||
}
|
}
|
||||||
|
|
||||||
// createAbiEscapeImpl implements the generic internal/abi.Escape function. It
|
|
||||||
// currently only supports pointer types.
|
|
||||||
func (b *builder) createAbiEscapeImpl() {
|
|
||||||
b.createFunctionStart(true)
|
|
||||||
|
|
||||||
// The first parameter is assumed to be a pointer. This is checked at the
|
|
||||||
// call site of createAbiEscapeImpl.
|
|
||||||
pointerValue := b.getValue(b.fn.Params[0], getPos(b.fn))
|
|
||||||
|
|
||||||
// Create an equivalent of the following C code, which is basically just a
|
|
||||||
// nop but ensures the pointerValue is kept alive:
|
|
||||||
//
|
|
||||||
// __asm__ __volatile__("" : : "r"(pointerValue))
|
|
||||||
//
|
|
||||||
// It should be portable to basically everything as the "r" register type
|
|
||||||
// exists basically everywhere.
|
|
||||||
asmType := llvm.FunctionType(b.dataPtrType, []llvm.Type{b.dataPtrType}, false)
|
|
||||||
asmFn := llvm.InlineAsm(asmType, "", "=r,0", true, false, 0, false)
|
|
||||||
result := b.createCall(asmType, asmFn, []llvm.Value{pointerValue}, "")
|
|
||||||
|
|
||||||
b.CreateRet(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
var mathToLLVMMapping = map[string]string{
|
var mathToLLVMMapping = map[string]string{
|
||||||
"math.Ceil": "llvm.ceil.f64",
|
"math.Ceil": "llvm.ceil.f64",
|
||||||
"math.Exp": "llvm.exp.f64",
|
"math.Exp": "llvm.exp.f64",
|
||||||
|
|||||||
+7
-15
@@ -371,6 +371,13 @@ func (c *compilerContext) getPointerBitmap(typ llvm.Type, pos token.Pos) *big.In
|
|||||||
return big.NewInt(1)
|
return big.NewInt(1)
|
||||||
case llvm.StructTypeKind:
|
case llvm.StructTypeKind:
|
||||||
ptrs := big.NewInt(0)
|
ptrs := big.NewInt(0)
|
||||||
|
if typ.StructName() == "runtime.funcValue" {
|
||||||
|
// Hack: the type runtime.funcValue contains an 'id' field which is
|
||||||
|
// of type uintptr, but before the LowerFuncValues pass it actually
|
||||||
|
// contains a pointer (ptrtoint) to a global. This trips up the
|
||||||
|
// interp package. Therefore, make the id field a pointer for now.
|
||||||
|
typ = c.ctx.StructType([]llvm.Type{c.dataPtrType, c.dataPtrType}, false)
|
||||||
|
}
|
||||||
for i, subtyp := range typ.StructElementTypes() {
|
for i, subtyp := range typ.StructElementTypes() {
|
||||||
subptrs := c.getPointerBitmap(subtyp, pos)
|
subptrs := c.getPointerBitmap(subtyp, pos)
|
||||||
if subptrs.BitLen() == 0 {
|
if subptrs.BitLen() == 0 {
|
||||||
@@ -452,21 +459,6 @@ func (b *builder) readStackPointer() llvm.Value {
|
|||||||
return b.CreateCall(stacksave.GlobalValueType(), stacksave, nil, "")
|
return b.CreateCall(stacksave.GlobalValueType(), stacksave, nil, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeStackPointer emits a LLVM intrinsic call that updates the current stack
|
|
||||||
// pointer.
|
|
||||||
func (b *builder) writeStackPointer(sp llvm.Value) {
|
|
||||||
name := "llvm.stackrestore.p0"
|
|
||||||
if llvmutil.Version() < 18 {
|
|
||||||
name = "llvm.stackrestore" // backwards compatibility with LLVM 17 and below
|
|
||||||
}
|
|
||||||
stackrestore := b.mod.NamedFunction(name)
|
|
||||||
if stackrestore.IsNil() {
|
|
||||||
fnType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.dataPtrType}, false)
|
|
||||||
stackrestore = llvm.AddFunction(b.mod, name, fnType)
|
|
||||||
}
|
|
||||||
b.CreateCall(stackrestore.GlobalValueType(), stackrestore, []llvm.Value{sp}, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// createZExtOrTrunc lets the input value fit in the output type bits, by zero
|
// createZExtOrTrunc lets the input value fit in the output type bits, by zero
|
||||||
// extending or truncating the integer.
|
// extending or truncating the integer.
|
||||||
func (b *builder) createZExtOrTrunc(value llvm.Value, t llvm.Type) llvm.Value {
|
func (b *builder) createZExtOrTrunc(value llvm.Value, t llvm.Type) llvm.Value {
|
||||||
|
|||||||
+3
-1
@@ -248,7 +248,7 @@ func (b *builder) createMapIteratorNext(rangeVal ssa.Value, llvmRangeVal, it llv
|
|||||||
// can be compared with runtime.memequal. Note that padding bytes are undef
|
// can be compared with runtime.memequal. Note that padding bytes are undef
|
||||||
// and can alter two "equal" structs being equal when compared with memequal.
|
// and can alter two "equal" structs being equal when compared with memequal.
|
||||||
func hashmapIsBinaryKey(keyType types.Type) bool {
|
func hashmapIsBinaryKey(keyType types.Type) bool {
|
||||||
switch keyType := keyType.Underlying().(type) {
|
switch keyType := keyType.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
return keyType.Info()&(types.IsBoolean|types.IsInteger) != 0
|
return keyType.Info()&(types.IsBoolean|types.IsInteger) != 0
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
@@ -263,6 +263,8 @@ func hashmapIsBinaryKey(keyType types.Type) bool {
|
|||||||
return true
|
return true
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
return hashmapIsBinaryKey(keyType.Elem())
|
return hashmapIsBinaryKey(keyType.Elem())
|
||||||
|
case *types.Named:
|
||||||
|
return hashmapIsBinaryKey(keyType.Underlying())
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,12 +208,6 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
|
|||||||
// > circumstances, and should not be exposed to source languages.
|
// > circumstances, and should not be exposed to source languages.
|
||||||
llvmutil.AppendToGlobal(c.mod, "llvm.compiler.used", llvmFn)
|
llvmutil.AppendToGlobal(c.mod, "llvm.compiler.used", llvmFn)
|
||||||
}
|
}
|
||||||
case "GetModuleHandleExA", "GetProcAddress", "GetSystemInfo", "GetSystemTimeAsFileTime", "LoadLibraryExW", "QueryPerformanceCounter", "QueryPerformanceFrequency", "QueryUnbiasedInterruptTime", "SetEnvironmentVariableA", "Sleep", "SystemFunction036", "VirtualAlloc":
|
|
||||||
// On Windows we need to use a special calling convention for some
|
|
||||||
// external calls.
|
|
||||||
if c.GOOS == "windows" && c.GOARCH == "386" {
|
|
||||||
llvmFn.SetFunctionCallConv(llvm.X86StdcallCallConv)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// External/exported functions may not retain pointer values.
|
// External/exported functions may not retain pointer values.
|
||||||
@@ -253,23 +247,6 @@ func (c *compilerContext) maybeCreateSyntheticFunction(fn *ssa.Function, llvmFn
|
|||||||
// The exception is the package initializer, which does appear in the
|
// The exception is the package initializer, which does appear in the
|
||||||
// *ssa.Package members and so shouldn't be created here.
|
// *ssa.Package members and so shouldn't be created here.
|
||||||
if fn.Synthetic != "" && fn.Synthetic != "package initializer" && fn.Synthetic != "generic function" && fn.Synthetic != "range-over-func yield" {
|
if fn.Synthetic != "" && fn.Synthetic != "package initializer" && fn.Synthetic != "generic function" && fn.Synthetic != "range-over-func yield" {
|
||||||
if origin := fn.Origin(); origin != nil && origin.RelString(nil) == "internal/abi.Escape" {
|
|
||||||
// This is a special implementation or internal/abi.Escape, which
|
|
||||||
// can only really be implemented in the compiler.
|
|
||||||
// For simplicity we'll only implement pointer parameters for now.
|
|
||||||
if _, ok := fn.Params[0].Type().Underlying().(*types.Pointer); ok {
|
|
||||||
irbuilder := c.ctx.NewBuilder()
|
|
||||||
defer irbuilder.Dispose()
|
|
||||||
b := newBuilder(c, irbuilder, fn)
|
|
||||||
b.createAbiEscapeImpl()
|
|
||||||
llvmFn.SetLinkage(llvm.LinkOnceODRLinkage)
|
|
||||||
llvmFn.SetUnnamedAddr(true)
|
|
||||||
}
|
|
||||||
// If the parameter is not of a pointer type, it will be left
|
|
||||||
// unimplemented. This will result in a linker error if the function
|
|
||||||
// is really called, making it clear it needs to be implemented.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(fn.Blocks) == 0 {
|
if len(fn.Blocks) == 0 {
|
||||||
c.addError(fn.Pos(), "missing function body")
|
c.addError(fn.Pos(), "missing function body")
|
||||||
return
|
return
|
||||||
@@ -461,10 +438,6 @@ func (c *compilerContext) parsePragmas(info *functionInfo, f *ssa.Function) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Nobounds {
|
|
||||||
info.nobounds = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether this function can be used in //go:wasmimport or
|
// Check whether this function can be used in //go:wasmimport or
|
||||||
|
|||||||
+1
-24
@@ -268,8 +268,6 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
// The signature looks like this:
|
// The signature looks like this:
|
||||||
// func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
// func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
|
||||||
|
|
||||||
isI386 := strings.HasPrefix(b.Triple, "i386-")
|
|
||||||
|
|
||||||
// Prepare input values.
|
// Prepare input values.
|
||||||
var paramTypes []llvm.Type
|
var paramTypes []llvm.Type
|
||||||
var params []llvm.Value
|
var params []llvm.Value
|
||||||
@@ -287,17 +285,11 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
if setLastError.IsNil() {
|
if setLastError.IsNil() {
|
||||||
llvmType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.ctx.Int32Type()}, false)
|
llvmType := llvm.FunctionType(b.ctx.VoidType(), []llvm.Type{b.ctx.Int32Type()}, false)
|
||||||
setLastError = llvm.AddFunction(b.mod, "SetLastError", llvmType)
|
setLastError = llvm.AddFunction(b.mod, "SetLastError", llvmType)
|
||||||
if isI386 {
|
|
||||||
setLastError.SetFunctionCallConv(llvm.X86StdcallCallConv)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
getLastError := b.mod.NamedFunction("GetLastError")
|
getLastError := b.mod.NamedFunction("GetLastError")
|
||||||
if getLastError.IsNil() {
|
if getLastError.IsNil() {
|
||||||
llvmType := llvm.FunctionType(b.ctx.Int32Type(), nil, false)
|
llvmType := llvm.FunctionType(b.ctx.Int32Type(), nil, false)
|
||||||
getLastError = llvm.AddFunction(b.mod, "GetLastError", llvmType)
|
getLastError = llvm.AddFunction(b.mod, "GetLastError", llvmType)
|
||||||
if isI386 {
|
|
||||||
getLastError.SetFunctionCallConv(llvm.X86StdcallCallConv)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now do the actual call. Pseudocode:
|
// Now do the actual call. Pseudocode:
|
||||||
@@ -308,24 +300,9 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
|
|||||||
// Note that SetLastError/GetLastError could be replaced with direct
|
// Note that SetLastError/GetLastError could be replaced with direct
|
||||||
// access to the thread control block, which is probably smaller and
|
// access to the thread control block, which is probably smaller and
|
||||||
// faster. The Go runtime does this in assembly.
|
// faster. The Go runtime does this in assembly.
|
||||||
// On windows/386, we also need to save/restore the stack pointer. I'm
|
b.CreateCall(setLastError.GlobalValueType(), setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, "")
|
||||||
// not entirely sure why this is needed, but without it these calls
|
|
||||||
// change the stack pointer leading to a crash soon after.
|
|
||||||
setLastErrorCall := b.CreateCall(setLastError.GlobalValueType(), setLastError, []llvm.Value{llvm.ConstNull(b.ctx.Int32Type())}, "")
|
|
||||||
var sp llvm.Value
|
|
||||||
if isI386 {
|
|
||||||
setLastErrorCall.SetInstructionCallConv(llvm.X86StdcallCallConv)
|
|
||||||
sp = b.readStackPointer()
|
|
||||||
}
|
|
||||||
syscallResult := b.CreateCall(llvmType, fnPtr, params, "")
|
syscallResult := b.CreateCall(llvmType, fnPtr, params, "")
|
||||||
if isI386 {
|
|
||||||
syscallResult.SetInstructionCallConv(llvm.X86StdcallCallConv)
|
|
||||||
b.writeStackPointer(sp)
|
|
||||||
}
|
|
||||||
errResult := b.CreateCall(getLastError.GlobalValueType(), getLastError, nil, "err")
|
errResult := b.CreateCall(getLastError.GlobalValueType(), getLastError, nil, "err")
|
||||||
if isI386 {
|
|
||||||
errResult.SetInstructionCallConv(llvm.X86StdcallCallConv)
|
|
||||||
}
|
|
||||||
if b.uintptrType != b.ctx.Int32Type() {
|
if b.uintptrType != b.ctx.Int32Type() {
|
||||||
errResult = b.CreateZExt(errResult, b.uintptrType, "err.uintptr")
|
errResult = b.CreateZExt(errResult, b.uintptrType, "err.uintptr")
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-40
@@ -10,7 +10,6 @@ import (
|
|||||||
"go/types"
|
"go/types"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -24,11 +23,6 @@ import (
|
|||||||
type Diagnostic struct {
|
type Diagnostic struct {
|
||||||
Pos token.Position
|
Pos token.Position
|
||||||
Msg string
|
Msg string
|
||||||
|
|
||||||
// Start and end position, if available. For many errors these positions are
|
|
||||||
// not available, but for some they are.
|
|
||||||
StartPos token.Position
|
|
||||||
EndPos token.Position
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// One or multiple errors of a particular package.
|
// One or multiple errors of a particular package.
|
||||||
@@ -120,22 +114,12 @@ func createPackageDiagnostic(err error) PackageDiagnostic {
|
|||||||
func createDiagnostics(err error) []Diagnostic {
|
func createDiagnostics(err error) []Diagnostic {
|
||||||
switch err := err.(type) {
|
switch err := err.(type) {
|
||||||
case types.Error:
|
case types.Error:
|
||||||
diag := Diagnostic{
|
return []Diagnostic{
|
||||||
Pos: err.Fset.Position(err.Pos),
|
{
|
||||||
Msg: err.Msg,
|
Pos: err.Fset.Position(err.Pos),
|
||||||
|
Msg: err.Msg,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
// There is a special unexported API since Go 1.16 that provides the
|
|
||||||
// range (start and end position) where the type error exists.
|
|
||||||
// There is no promise of backwards compatibility in future Go versions
|
|
||||||
// so we have to be extra careful here to be resilient.
|
|
||||||
v := reflect.ValueOf(err)
|
|
||||||
start := v.FieldByName("go116start")
|
|
||||||
end := v.FieldByName("go116end")
|
|
||||||
if start.IsValid() && end.IsValid() && start.Int() != end.Int() {
|
|
||||||
diag.StartPos = err.Fset.Position(token.Pos(start.Int()))
|
|
||||||
diag.EndPos = err.Fset.Position(token.Pos(end.Int()))
|
|
||||||
}
|
|
||||||
return []Diagnostic{diag}
|
|
||||||
case scanner.Error:
|
case scanner.Error:
|
||||||
return []Diagnostic{
|
return []Diagnostic{
|
||||||
{
|
{
|
||||||
@@ -204,29 +188,25 @@ func (diag Diagnostic) WriteTo(w io.Writer, wd string) {
|
|||||||
fmt.Fprintln(w, diag.Msg)
|
fmt.Fprintln(w, diag.Msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pos := RelativePosition(diag.Pos, wd)
|
pos := diag.Pos // make a copy
|
||||||
|
if !strings.HasPrefix(pos.Filename, filepath.Join(goenv.Get("GOROOT"), "src")) && !strings.HasPrefix(pos.Filename, filepath.Join(goenv.Get("TINYGOROOT"), "src")) {
|
||||||
|
// This file is not from the standard library (either the GOROOT or the
|
||||||
|
// TINYGOROOT). Make the path relative, for easier reading. Ignore any
|
||||||
|
// errors in the process (falling back to the absolute path).
|
||||||
|
pos.Filename = tryToMakePathRelative(pos.Filename, wd)
|
||||||
|
}
|
||||||
fmt.Fprintf(w, "%s: %s\n", pos, diag.Msg)
|
fmt.Fprintf(w, "%s: %s\n", pos, diag.Msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the position in pos (assumed to have an absolute path) into a
|
// try to make the path relative to the current working directory. If any error
|
||||||
// relative path if possible. Paths inside GOROOT/TINYGOROOT will remain
|
// occurs, this error is ignored and the absolute path is returned instead.
|
||||||
// absolute.
|
func tryToMakePathRelative(dir, wd string) string {
|
||||||
func RelativePosition(pos token.Position, wd string) token.Position {
|
|
||||||
// Check whether we even have a working directory.
|
|
||||||
if wd == "" {
|
if wd == "" {
|
||||||
return pos
|
return dir // working directory not found
|
||||||
}
|
}
|
||||||
|
relpath, err := filepath.Rel(wd, dir)
|
||||||
// Paths inside GOROOT should be printed in full.
|
if err != nil {
|
||||||
if strings.HasPrefix(pos.Filename, filepath.Join(goenv.Get("GOROOT"), "src")) || strings.HasPrefix(pos.Filename, filepath.Join(goenv.Get("TINYGOROOT"), "src")) {
|
return dir
|
||||||
return pos
|
|
||||||
}
|
}
|
||||||
|
return relpath
|
||||||
// Make the path relative, for easier reading. Ignore any errors in the
|
|
||||||
// process (falling back to the absolute path).
|
|
||||||
relpath, err := filepath.Rel(wd, pos.Filename)
|
|
||||||
if err == nil {
|
|
||||||
pos.Filename = relpath
|
|
||||||
}
|
|
||||||
return pos
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-6
@@ -8,7 +8,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tinygo-org/tinygo/builder"
|
|
||||||
"github.com/tinygo-org/tinygo/compileopts"
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
"github.com/tinygo-org/tinygo/diagnostics"
|
"github.com/tinygo-org/tinygo/diagnostics"
|
||||||
)
|
)
|
||||||
@@ -65,11 +64,7 @@ func testErrorMessages(t *testing.T, filename string, options *compileopts.Optio
|
|||||||
|
|
||||||
// Try to build a binary (this should fail with an error).
|
// Try to build a binary (this should fail with an error).
|
||||||
tmpdir := t.TempDir()
|
tmpdir := t.TempDir()
|
||||||
config, err := builder.NewConfig(options)
|
err := Build(filename, tmpdir+"/out", options)
|
||||||
if err != nil {
|
|
||||||
t.Fatal("expected to get a compiler error")
|
|
||||||
}
|
|
||||||
err = Build(filename, tmpdir+"/out", config)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected to get a compiler error")
|
t.Fatal("expected to get a compiler error")
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+4
-4
@@ -20,16 +20,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1747953325,
|
"lastModified": 1728500571,
|
||||||
"narHash": "sha256-y2ZtlIlNTuVJUZCqzZAhIw5rrKP4DOSklev6c8PyCkQ=",
|
"narHash": "sha256-dOymOQ3AfNI4Z337yEwHGohrVQb4yPODCW9MDUyAc4w=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "55d1f923c480dadce40f5231feb472e81b0bab48",
|
"rev": "d51c28603def282a24fa034bcb007e2bcb5b5dd0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"id": "nixpkgs",
|
||||||
"ref": "nixos-25.05",
|
"ref": "nixos-24.05",
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
# make llvm-source # fetch compiler-rt
|
# make llvm-source # fetch compiler-rt
|
||||||
# git submodule update --init # fetch lots of other libraries and SVD files
|
# git submodule update --init # fetch lots of other libraries and SVD files
|
||||||
# make gen-device -j4 # build src/device/*/*.go 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
|
# With this, you should have an environment that can compile anything - except
|
||||||
# for the Xtensa architecture (ESP8266/ESP32) because support for that lives in
|
# for the Xtensa architecture (ESP8266/ESP32) because support for that lives in
|
||||||
@@ -34,7 +35,7 @@
|
|||||||
inputs = {
|
inputs = {
|
||||||
# Use a recent stable release, but fix the version to make it reproducible.
|
# Use a recent stable release, but fix the version to make it reproducible.
|
||||||
# This version should be updated from time to time.
|
# This version should be updated from time to time.
|
||||||
nixpkgs.url = "nixpkgs/nixos-25.05";
|
nixpkgs.url = "nixpkgs/nixos-24.05";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
outputs = { self, nixpkgs, flake-utils }:
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
@@ -48,11 +49,11 @@
|
|||||||
buildInputs = [
|
buildInputs = [
|
||||||
# These dependencies are required for building tinygo (go install).
|
# These dependencies are required for building tinygo (go install).
|
||||||
go
|
go
|
||||||
llvmPackages_20.llvm
|
llvmPackages_18.llvm
|
||||||
llvmPackages_20.libclang
|
llvmPackages_18.libclang
|
||||||
# Additional dependencies needed at runtime, for building and/or
|
# Additional dependencies needed at runtime, for building and/or
|
||||||
# flashing.
|
# flashing.
|
||||||
llvmPackages_20.lld
|
llvmPackages_18.lld
|
||||||
avrdude
|
avrdude
|
||||||
binaryen
|
binaryen
|
||||||
# Additional dependencies needed for on-chip debugging.
|
# Additional dependencies needed for on-chip debugging.
|
||||||
@@ -63,12 +64,20 @@
|
|||||||
#openocd
|
#openocd
|
||||||
];
|
];
|
||||||
shellHook= ''
|
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-18 -resource-dir ${llvmPackages_18.clang.cc.lib}/lib/clang/18"
|
||||||
|
export LLVM_AR=llvm-ar
|
||||||
|
export LLVM_NM=llvm-nm
|
||||||
|
|
||||||
# Make `make smoketest` work (the default is `md5`, while Nix only
|
# Make `make smoketest` work (the default is `md5`, while Nix only
|
||||||
# has `md5sum`).
|
# has `md5sum`).
|
||||||
export MD5SUM=md5sum
|
export MD5SUM=md5sum
|
||||||
|
|
||||||
# Ugly hack to make the Clang resources directory available.
|
# Ugly hack to make the Clang resources directory available.
|
||||||
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_20.clang.cc.lib}/lib/clang/20\" -tags=llvm20"
|
export GOFLAGS="\"-ldflags=-X github.com/tinygo-org/tinygo/goenv.clangResourceDir=${llvmPackages_18.clang.cc.lib}/lib/clang/18\" -tags=llvm18"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
module github.com/tinygo-org/tinygo
|
module github.com/tinygo-org/tinygo
|
||||||
|
|
||||||
go 1.22.0
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139
|
github.com/aykevl/go-wasm v0.0.2-0.20240825160117-b76c3f9f0982
|
||||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
|
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2
|
||||||
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee
|
github.com/chromedp/cdproto v0.0.0-20220113222801-0725d94bb6ee
|
||||||
github.com/chromedp/chromedp v0.7.6
|
github.com/chromedp/chromedp v0.7.6
|
||||||
@@ -16,11 +16,11 @@ require (
|
|||||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
|
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3
|
||||||
github.com/tetratelabs/wazero v1.6.0
|
github.com/tetratelabs/wazero v1.6.0
|
||||||
go.bug.st/serial v1.6.0
|
go.bug.st/serial v1.6.0
|
||||||
golang.org/x/net v0.35.0
|
golang.org/x/net v0.26.0
|
||||||
golang.org/x/sys v0.30.0
|
golang.org/x/sys v0.21.0
|
||||||
golang.org/x/tools v0.30.0
|
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74
|
tinygo.org/x/go-llvm v0.0.0-20250119132755-9dca92dfb4f9
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -33,5 +33,5 @@ require (
|
|||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/stretchr/testify v1.8.4 // indirect
|
github.com/stretchr/testify v1.8.4 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.16.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139 h1:2O/WuAt8J5id3khcAtVB90czG80m+v0sfkLE07GrCVg=
|
github.com/aykevl/go-wasm v0.0.2-0.20240825160117-b76c3f9f0982 h1:cD7QfvrJdYmBw2tFP/VyKPT8ZESlcrwSwo7SvH9Y4dc=
|
||||||
github.com/aykevl/go-wasm v0.0.2-0.20250317121156-42b86c494139/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=
|
github.com/aykevl/go-wasm v0.0.2-0.20240825160117-b76c3f9f0982/go.mod h1:7sXyiaA0WtSogCu67R2252fQpVmJMh9JWJ9ddtGkpWw=
|
||||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI=
|
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 h1:oMCHnXa6CCCafdPDbMh/lWRhRByN0VFLvv+g+ayx1SI=
|
||||||
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||||
github.com/chromedp/cdproto v0.0.0-20211126220118-81fa0469ad77/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
|
github.com/chromedp/cdproto v0.0.0-20211126220118-81fa0469ad77/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
|
||||||
@@ -12,7 +12,6 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA
|
|||||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
||||||
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||||
@@ -45,7 +44,6 @@ github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3px
|
|||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
||||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
|
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
|
||||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
@@ -54,12 +52,10 @@ github.com/tetratelabs/wazero v1.6.0 h1:z0H1iikCdP8t+q341xqepY4EWvHEw8Es7tlqiVzl
|
|||||||
github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
|
github.com/tetratelabs/wazero v1.6.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
|
||||||
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.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-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=
|
||||||
@@ -67,17 +63,16 @@ golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504 h1:MMsD8mMfluf/578+3wrTn22pjI/Xkzm+gPW47SYfspY=
|
||||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
golang.org/x/tools v0.22.1-0.20240621165957-db513b091504/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||||
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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
tinygo.org/x/go-llvm v0.0.0-20250119132755-9dca92dfb4f9 h1:rMvEzuCYjyiR+pmdiCVWTQw3L6VqiSIXoL19I3lYufE=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74 h1:ovavgTdIBWCH8YWlcfq9gkpoyT1+IxMKSn+Df27QwE8=
|
tinygo.org/x/go-llvm v0.0.0-20250119132755-9dca92dfb4f9/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||||
tinygo.org/x/go-llvm v0.0.0-20250422114502-b8f170971e74/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
// Version of TinyGo.
|
// Version of TinyGo.
|
||||||
// Update this value before release of new version of software.
|
// Update this value before release of new version of software.
|
||||||
const version = "0.39.0"
|
const version = "0.36.0"
|
||||||
|
|
||||||
// Return TinyGo version, either in the form 0.30.0 or as a development version
|
// Return TinyGo version, either in the form 0.30.0 or as a development version
|
||||||
// (like 0.30.0-dev-abcd012).
|
// (like 0.30.0-dev-abcd012).
|
||||||
|
|||||||
@@ -1,22 +1,18 @@
|
|||||||
module github.com/tinygo-org/tinygo/internal/wasm-tools
|
module github.com/tinygo-org/tinygo/internal/tools
|
||||||
|
|
||||||
go 1.23.0
|
go 1.22.4
|
||||||
|
|
||||||
require (
|
require github.com/bytecodealliance/wasm-tools-go v0.3.1
|
||||||
go.bytecodealliance.org v0.6.2
|
|
||||||
go.bytecodealliance.org/cm v0.2.2
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/coreos/go-semver v0.3.1 // indirect
|
github.com/coreos/go-semver v0.3.1 // indirect
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/regclient/regclient v0.8.2 // indirect
|
github.com/regclient/regclient v0.7.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/tetratelabs/wazero v1.9.0 // indirect
|
|
||||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||||
github.com/urfave/cli/v3 v3.0.0-beta1 // indirect
|
github.com/urfave/cli/v3 v3.0.0-alpha9.2 // indirect
|
||||||
golang.org/x/mod v0.24.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
+18
-22
@@ -1,3 +1,5 @@
|
|||||||
|
github.com/bytecodealliance/wasm-tools-go v0.3.1 h1:9Q9PjSzkbiVmkUvZ7nYCfJ02mcQDBalxycA3s8g7kR4=
|
||||||
|
github.com/bytecodealliance/wasm-tools-go v0.3.1/go.mod h1:vNAQ8DAEp6xvvk+TUHah5DslLEa76f4H6e737OeaxuY=
|
||||||
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -5,16 +7,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/olareg/olareg v0.1.1 h1:Ui7q93zjcoF+U9U71sgqgZWByDoZOpqHitUXEu2xV+g=
|
github.com/olareg/olareg v0.1.0 h1:1dXBOgPrig5N7zoXyIZVQqU0QBo6sD9pbL6UYjY75CA=
|
||||||
github.com/olareg/olareg v0.1.1/go.mod h1:w8NP4SWrHHtxsFaUiv1lnCnYPm4sN1seCd2h7FK/dc0=
|
github.com/olareg/olareg v0.1.0/go.mod h1:RBuU7JW7SoIIxZKzLRhq8sVtQeAHzCAtRrXEBx2KlM4=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/regclient/regclient v0.8.2 h1:23BQ3jWgKYHHIXUhp/S9laVJDHDoOQaQCzXMJ4undVE=
|
github.com/regclient/regclient v0.7.1 h1:qEsJrTmZd98fZKjueAbrZCSNGU+ifnr6xjlSAs3WOPs=
|
||||||
github.com/regclient/regclient v0.8.2/go.mod h1:uGyetv0o6VLyRDjtfeBqp/QBwRLJ3Hcn07/+8QbhNcM=
|
github.com/regclient/regclient v0.7.1/go.mod h1:+w/BFtJuw0h0nzIw/z2+1FuA2/dVXBzDq4rYmziJpMc=
|
||||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
@@ -23,25 +25,19 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
|
|
||||||
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
|
|
||||||
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||||
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/urfave/cli/v3 v3.0.0-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=
|
github.com/urfave/cli/v3 v3.0.0-alpha9.2 h1:CL8llQj3dGRLVQQzHxS+ZYRLanOuhyK1fXgLKD+qV+Y=
|
||||||
github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
|
github.com/urfave/cli/v3 v3.0.0-alpha9.2/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
|
||||||
go.bytecodealliance.org v0.6.2 h1:Jy4u5DVmSkXgsnwojBhJ+AD/YsJsR3VzVnxF0xRCqTQ=
|
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||||
go.bytecodealliance.org v0.6.2/go.mod h1:gqjTJm0y9NSksG4py/lSjIQ/SNuIlOQ+hCIEPQwtJgA=
|
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
go.bytecodealliance.org/cm v0.2.2 h1:M9iHS6qs884mbQbIjtLX1OifgyPG9DuMs2iwz8G4WQA=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
go.bytecodealliance.org/cm v0.2.2/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
|
||||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
|
||||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
|
||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||||
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.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
package tools
|
package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "go.bytecodealliance.org/cm"
|
_ "github.com/bytecodealliance/wasm-tools-go/cmd/wit-bindgen-go"
|
||||||
_ "go.bytecodealliance.org/cmd/wit-bindgen-go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go install go.bytecodealliance.org/cmd/wit-bindgen-go
|
//go:generate go install github.com/bytecodealliance/wasm-tools-go/cmd/wit-bindgen-go
|
||||||
|
|||||||
+1
-14
@@ -364,22 +364,9 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
nBytes := uint32(n * elemSize)
|
nBytes := uint32(n * elemSize)
|
||||||
srcObj := mem.get(src.index())
|
|
||||||
dstObj := mem.getWritable(dst.index())
|
dstObj := mem.getWritable(dst.index())
|
||||||
if srcObj.buffer == nil || dstObj.buffer == nil {
|
|
||||||
// If the buffer is nil, it means the slice is external.
|
|
||||||
// This can happen for example when copying data out of
|
|
||||||
// a //go:embed slice, which is not available at interp
|
|
||||||
// time.
|
|
||||||
// See: https://github.com/tinygo-org/tinygo/issues/4895
|
|
||||||
err := r.runAtRuntime(fn, inst, locals, &mem, indent)
|
|
||||||
if err != nil {
|
|
||||||
return nil, mem, err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dstBuf := dstObj.buffer.asRawValue(r)
|
dstBuf := dstObj.buffer.asRawValue(r)
|
||||||
srcBuf := srcObj.buffer.asRawValue(r)
|
srcBuf := mem.get(src.index()).buffer.asRawValue(r)
|
||||||
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
||||||
dstObj.buffer = dstBuf
|
dstObj.buffer = dstBuf
|
||||||
mem.put(dst.index(), dstObj)
|
mem.put(dst.index(), dstObj)
|
||||||
|
|||||||
@@ -824,6 +824,19 @@ func (v rawValue) rawLLVMValue(mem *memoryView) (llvm.Value, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return llvm.Value{}, err
|
return llvm.Value{}, err
|
||||||
}
|
}
|
||||||
|
if !field.IsAGlobalVariable().IsNil() {
|
||||||
|
elementType := field.GlobalValueType()
|
||||||
|
if elementType.TypeKind() == llvm.StructTypeKind {
|
||||||
|
// There are some special pointer types that should be used
|
||||||
|
// as a ptrtoint, so that they can be used in certain
|
||||||
|
// optimizations.
|
||||||
|
name := elementType.StructName()
|
||||||
|
if name == "runtime.funcValueWithSignature" {
|
||||||
|
uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8)
|
||||||
|
field = llvm.ConstPtrToInt(field, uintptrType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
structFields = append(structFields, field)
|
structFields = append(structFields, field)
|
||||||
i += mem.r.pointerSize
|
i += mem.r.pointerSize
|
||||||
continue
|
continue
|
||||||
|
|||||||
Vendored
-18
@@ -11,10 +11,6 @@ target triple = "x86_64--linux"
|
|||||||
@main.sliceDstUntaint.buf = internal global [2 x i8] zeroinitializer
|
@main.sliceDstUntaint.buf = internal global [2 x i8] zeroinitializer
|
||||||
@main.sliceSrcTaint.buf = internal global [2 x i8] c"cd"
|
@main.sliceSrcTaint.buf = internal global [2 x i8] c"cd"
|
||||||
@main.sliceDstTaint.buf = internal global [2 x i8] zeroinitializer
|
@main.sliceDstTaint.buf = internal global [2 x i8] zeroinitializer
|
||||||
@main.sliceSrcExternal1.buf = external global [2 x i8]
|
|
||||||
@main.sliceDstExternal1.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceSrcExternal2.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceDstExternal2.buf = external global [2 x i8]
|
|
||||||
|
|
||||||
declare i64 @runtime.sliceCopy(ptr %dst, ptr %src, i64 %dstLen, i64 %srcLen, i64 %elemSize) unnamed_addr
|
declare i64 @runtime.sliceCopy(ptr %dst, ptr %src, i64 %dstLen, i64 %srcLen, i64 %elemSize) unnamed_addr
|
||||||
|
|
||||||
@@ -62,14 +58,6 @@ entry:
|
|||||||
%sliceDstTaint.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstTaint.buf, i32 0)
|
%sliceDstTaint.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstTaint.buf, i32 0)
|
||||||
call void @runtime.printuint8(i8 %sliceDstTaint.val)
|
call void @runtime.printuint8(i8 %sliceDstTaint.val)
|
||||||
|
|
||||||
; print(sliceDstExternal1[0])
|
|
||||||
%sliceDstExternal1.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstExternal1.buf, i32 0)
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstExternal1.val)
|
|
||||||
|
|
||||||
; print(sliceDstExternal2[0])
|
|
||||||
%sliceDstExternal2.val = load i8, ptr getelementptr inbounds (i8, ptr @main.sliceDstExternal2.buf, i32 0)
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstExternal2.val)
|
|
||||||
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,11 +102,5 @@ entry:
|
|||||||
call void @use(ptr @main.sliceSrcTaint.buf)
|
call void @use(ptr @main.sliceSrcTaint.buf)
|
||||||
%copy.n4 = call i64 @runtime.sliceCopy(ptr @main.sliceDstTaint.buf, ptr @main.sliceSrcTaint.buf, i64 2, i64 2, i64 1)
|
%copy.n4 = call i64 @runtime.sliceCopy(ptr @main.sliceDstTaint.buf, ptr @main.sliceSrcTaint.buf, i64 2, i64 2, i64 1)
|
||||||
|
|
||||||
; Test that copying from or into external buffers works correctly.
|
|
||||||
; These copy operations must be done at runtime.
|
|
||||||
; https://github.com/tinygo-org/tinygo/issues/4895
|
|
||||||
%copy.n5 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal1.buf, ptr @main.sliceSrcExternal1.buf, i64 2, i64 2, i64 1)
|
|
||||||
%copy.n6 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal2.buf, ptr @main.sliceSrcExternal2.buf, i64 2, i64 2, i64 1)
|
|
||||||
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-10
@@ -3,10 +3,6 @@ target triple = "x86_64--linux"
|
|||||||
|
|
||||||
@main.sliceSrcTaint.buf = internal global [2 x i8] c"cd"
|
@main.sliceSrcTaint.buf = internal global [2 x i8] c"cd"
|
||||||
@main.sliceDstTaint.buf = internal global [2 x i8] zeroinitializer
|
@main.sliceDstTaint.buf = internal global [2 x i8] zeroinitializer
|
||||||
@main.sliceSrcExternal1.buf = external global [2 x i8]
|
|
||||||
@main.sliceDstExternal1.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceSrcExternal2.buf = internal global [2 x i8] zeroinitializer
|
|
||||||
@main.sliceDstExternal2.buf = external global [2 x i8]
|
|
||||||
|
|
||||||
declare i64 @runtime.sliceCopy(ptr, ptr, i64, i64, i64) unnamed_addr
|
declare i64 @runtime.sliceCopy(ptr, ptr, i64, i64, i64) unnamed_addr
|
||||||
|
|
||||||
@@ -20,8 +16,6 @@ define void @runtime.initAll() unnamed_addr {
|
|||||||
entry:
|
entry:
|
||||||
call void @use(ptr @main.sliceSrcTaint.buf)
|
call void @use(ptr @main.sliceSrcTaint.buf)
|
||||||
%copy.n4 = call i64 @runtime.sliceCopy(ptr @main.sliceDstTaint.buf, ptr @main.sliceSrcTaint.buf, i64 2, i64 2, i64 1)
|
%copy.n4 = call i64 @runtime.sliceCopy(ptr @main.sliceDstTaint.buf, ptr @main.sliceSrcTaint.buf, i64 2, i64 2, i64 1)
|
||||||
%copy.n5 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal1.buf, ptr @main.sliceSrcExternal1.buf, i64 2, i64 2, i64 1)
|
|
||||||
%copy.n6 = call i64 @runtime.sliceCopy(ptr @main.sliceDstExternal2.buf, ptr @main.sliceSrcExternal2.buf, i64 2, i64 2, i64 1)
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,9 +28,5 @@ entry:
|
|||||||
call void @runtime.printuint8(i8 97)
|
call void @runtime.printuint8(i8 97)
|
||||||
%sliceDstTaint.val = load i8, ptr @main.sliceDstTaint.buf, align 1
|
%sliceDstTaint.val = load i8, ptr @main.sliceDstTaint.buf, align 1
|
||||||
call void @runtime.printuint8(i8 %sliceDstTaint.val)
|
call void @runtime.printuint8(i8 %sliceDstTaint.val)
|
||||||
%sliceDstExternal1.val = load i8, ptr @main.sliceDstExternal1.buf, align 1
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstExternal1.val)
|
|
||||||
%sliceDstExternal2.val = load i8, ptr @main.sliceDstExternal2.buf, align 1
|
|
||||||
call void @runtime.printuint8(i8 %sliceDstExternal2.val)
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|||||||
-1
Submodule lib/bdwgc deleted from 1166f11f7d
+1
-1
Submodule lib/macos-minimal-sdk updated: e7c72156ea...9b69407cb5
+1
-3
@@ -8,9 +8,7 @@ import (
|
|||||||
//
|
//
|
||||||
// The program must already be parsed and type-checked with the .Parse() method.
|
// The program must already be parsed and type-checked with the .Parse() method.
|
||||||
func (p *Program) LoadSSA() *ssa.Program {
|
func (p *Program) LoadSSA() *ssa.Program {
|
||||||
// TODO: re-enable SanityCheckFunctions when x/tools is upgraded to
|
prog := ssa.NewProgram(p.fset, ssa.SanityCheckFunctions|ssa.BareInits|ssa.GlobalDebug|ssa.InstantiateGenerics)
|
||||||
// a version with a fix for https://golang.org/issues/73594.
|
|
||||||
prog := ssa.NewProgram(p.fset /*ssa.SanityCheckFunctions|*/, ssa.BareInits|ssa.GlobalDebug|ssa.InstantiateGenerics)
|
|
||||||
|
|
||||||
for _, pkg := range p.sorted {
|
for _, pkg := range p.sorted {
|
||||||
prog.CreatePackage(pkg.Pkg, pkg.Files, &pkg.info, true)
|
prog.CreatePackage(pkg.Pkg, pkg.Files, &pkg.info, true)
|
||||||
|
|||||||
@@ -138,13 +138,27 @@ func printCommand(cmd string, args ...string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build compiles and links the given package and writes it to outpath.
|
// Build compiles and links the given package and writes it to outpath.
|
||||||
func Build(pkgName, outpath string, config *compileopts.Config) error {
|
func Build(pkgName, outpath string, options *compileopts.Options) error {
|
||||||
|
config, err := builder.NewConfig(options)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.PrintJSON {
|
||||||
|
b, err := json.MarshalIndent(config, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
handleCompilerError(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", string(b))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Create a temporary directory for intermediary files.
|
// Create a temporary directory for intermediary files.
|
||||||
tmpdir, err := os.MkdirTemp("", "tinygo")
|
tmpdir, err := os.MkdirTemp("", "tinygo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !config.Options.Work {
|
if !options.Work {
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,8 +305,7 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
|||||||
})
|
})
|
||||||
|
|
||||||
if testConfig.CompileOnly {
|
if testConfig.CompileOnly {
|
||||||
// Return the compiler error, if there is one.
|
return true, nil
|
||||||
return true, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
importPath := strings.TrimSuffix(result.ImportPath, ".test")
|
importPath := strings.TrimSuffix(result.ImportPath, ".test")
|
||||||
@@ -340,17 +353,8 @@ func dirsToModuleRootAbs(maindir, modroot string) []string {
|
|||||||
return dirs
|
return dirs
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateOutputFormat checks if the output file extension matches the expected format
|
|
||||||
func validateOutputFormat(outpath, expectedExt string) error {
|
|
||||||
actualExt := filepath.Ext(outpath)
|
|
||||||
if actualExt != expectedExt {
|
|
||||||
return fmt.Errorf("output format %s does not match target format %s", actualExt, expectedExt)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flash builds and flashes the built binary to the given serial port.
|
// Flash builds and flashes the built binary to the given serial port.
|
||||||
func Flash(pkgName, port, outpath string, options *compileopts.Options) error {
|
func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||||
config, err := builder.NewConfig(options)
|
config, err := builder.NewConfig(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -399,24 +403,13 @@ func Flash(pkgName, port, outpath string, options *compileopts.Options) error {
|
|||||||
if !options.Work {
|
if !options.Work {
|
||||||
defer os.RemoveAll(tmpdir)
|
defer os.RemoveAll(tmpdir)
|
||||||
}
|
}
|
||||||
// Validate output format before building
|
|
||||||
if outpath != "" {
|
|
||||||
if err := validateOutputFormat(outpath, fileExt); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Build the binary.
|
// Build the binary.
|
||||||
result, err := builder.Build(pkgName, fileExt, tmpdir, config)
|
result, err := builder.Build(pkgName, fileExt, tmpdir, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save output file if specified (after build, before flashing)
|
|
||||||
if outpath != "" {
|
|
||||||
if err := copyFile(result.Binary, outpath); err != nil {
|
|
||||||
return fmt.Errorf("failed to save output file: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// do we need port reset to put MCU into bootloader mode?
|
// do we need port reset to put MCU into bootloader mode?
|
||||||
if config.Target.PortReset == "true" && flashMethod != "openocd" {
|
if config.Target.PortReset == "true" && flashMethod != "openocd" {
|
||||||
port, err := getDefaultPort(port, config.Target.SerialPort)
|
port, err := getDefaultPort(port, config.Target.SerialPort)
|
||||||
@@ -1034,50 +1027,15 @@ func findFATMounts(options *compileopts.Options) ([]mountPoint, error) {
|
|||||||
return nil, fmt.Errorf("could not list mount points: %w", err)
|
return nil, fmt.Errorf("could not list mount points: %w", err)
|
||||||
}
|
}
|
||||||
for _, elem := range list {
|
for _, elem := range list {
|
||||||
volumePath := filepath.Join("/Volumes", elem.Name())
|
// TODO: find a way to check for the filesystem type.
|
||||||
if _, err := os.Stat(volumePath); err != nil {
|
// (Only return FAT filesystems).
|
||||||
continue
|
points = append(points, mountPoint{
|
||||||
}
|
name: elem.Name(),
|
||||||
|
path: filepath.Join("/Volumes", elem.Name()),
|
||||||
cmd := exec.Command("diskutil", "info", volumePath)
|
})
|
||||||
var out bytes.Buffer
|
|
||||||
cmd.Stdout = &out
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
continue // skip if diskutil failed
|
|
||||||
}
|
|
||||||
|
|
||||||
diskInfo := map[string]string{}
|
|
||||||
scanner := bufio.NewScanner(&out)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
parts := strings.SplitN(line, ":", 2)
|
|
||||||
if len(parts) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key := strings.TrimSpace(parts[0])
|
|
||||||
value := strings.TrimSpace(parts[1])
|
|
||||||
diskInfo[key] = value
|
|
||||||
}
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
volName, okv := diskInfo["Volume Name"]
|
|
||||||
fsType, okf := diskInfo["File System Personality"]
|
|
||||||
if !okv || !okf {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if a filesystem type is FAT-based
|
|
||||||
if strings.Contains(strings.ToUpper(fsType), "FAT") {
|
|
||||||
points = append(points, mountPoint{
|
|
||||||
name: volName,
|
|
||||||
path: volumePath,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sort.Slice(points, func(i, j int) bool {
|
sort.Slice(points, func(i, j int) bool {
|
||||||
return points[i].path < points[j].path
|
return points[i].path < points[j].name
|
||||||
})
|
})
|
||||||
return points, nil
|
return points, nil
|
||||||
case "linux":
|
case "linux":
|
||||||
@@ -1318,11 +1276,6 @@ extension at all.`
|
|||||||
(https://tinygo.org/docs/reference/microcontrollers/).
|
(https://tinygo.org/docs/reference/microcontrollers/).
|
||||||
Examples: "arduino-nano", "d1mini", "xiao".
|
Examples: "arduino-nano", "d1mini", "xiao".
|
||||||
|
|
||||||
-o={filename}:
|
|
||||||
Save the built binary to the specified output file. The file
|
|
||||||
format must match the target's expected format (e.g., .hex,
|
|
||||||
.uf2). Both flashing and saving will be performed.
|
|
||||||
|
|
||||||
-monitor:
|
-monitor:
|
||||||
Start the serial monitor (see below) immediately after
|
Start the serial monitor (see below) immediately after
|
||||||
flashing. However, some microcontrollers need a split second
|
flashing. However, some microcontrollers need a split second
|
||||||
@@ -1443,68 +1396,6 @@ func usage(command string) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print diagnostics very similar to the -json flag in Go.
|
|
||||||
func printBuildOutput(err error, jsonDiagnostics bool) {
|
|
||||||
if err == nil {
|
|
||||||
return // nothing to report
|
|
||||||
}
|
|
||||||
|
|
||||||
if jsonDiagnostics {
|
|
||||||
workingDir, getwdErr := os.Getwd()
|
|
||||||
if getwdErr != nil {
|
|
||||||
workingDir = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type jsonDiagnosticOutput struct {
|
|
||||||
ImportPath string
|
|
||||||
Action string
|
|
||||||
Output string `json:",omitempty"`
|
|
||||||
StartPos string `json:",omitempty"` // non-standard
|
|
||||||
EndPos string `json:",omitempty"` // non-standard
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, diags := range diagnostics.CreateDiagnostics(err) {
|
|
||||||
if diags.ImportPath != "" {
|
|
||||||
output, _ := json.Marshal(jsonDiagnosticOutput{
|
|
||||||
ImportPath: diags.ImportPath,
|
|
||||||
Action: "build-output",
|
|
||||||
Output: "# " + diags.ImportPath + "\n",
|
|
||||||
})
|
|
||||||
os.Stdout.Write(append(output, '\n'))
|
|
||||||
}
|
|
||||||
for _, diag := range diags.Diagnostics {
|
|
||||||
w := &bytes.Buffer{}
|
|
||||||
diag.WriteTo(w, workingDir)
|
|
||||||
data := jsonDiagnosticOutput{
|
|
||||||
ImportPath: diags.ImportPath,
|
|
||||||
Action: "build-output",
|
|
||||||
Output: w.String(),
|
|
||||||
}
|
|
||||||
if diag.StartPos.IsValid() && diag.EndPos.IsValid() {
|
|
||||||
// Include the non-standard StartPos/EndPos values. These
|
|
||||||
// are useful for the TinyGo Playground to show better error
|
|
||||||
// messages.
|
|
||||||
data.StartPos = diagnostics.RelativePosition(diag.StartPos, workingDir).String()
|
|
||||||
data.EndPos = diagnostics.RelativePosition(diag.EndPos, workingDir).String()
|
|
||||||
}
|
|
||||||
output, _ := json.Marshal(data)
|
|
||||||
os.Stdout.Write(append(output, '\n'))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit the "Action":"build-fail" JSON.
|
|
||||||
output, _ := json.Marshal(jsonDiagnosticOutput{
|
|
||||||
ImportPath: diags.ImportPath,
|
|
||||||
Action: "build-fail",
|
|
||||||
})
|
|
||||||
os.Stdout.Write(append(output, '\n'))
|
|
||||||
}
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regular diagnostic handling.
|
|
||||||
handleCompilerError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleCompilerError(err error) {
|
func handleCompilerError(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wd, getwdErr := os.Getwd()
|
wd, getwdErr := os.Getwd()
|
||||||
@@ -1601,9 +1492,9 @@ func main() {
|
|||||||
command := os.Args[1]
|
command := os.Args[1]
|
||||||
|
|
||||||
opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z")
|
opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z")
|
||||||
gc := flag.String("gc", "", "garbage collector to use (none, leaking, conservative, custom, precise, boehm)")
|
gc := flag.String("gc", "", "garbage collector to use (none, leaking, conservative)")
|
||||||
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
||||||
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, cores, threads, asyncify)")
|
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
|
||||||
serial := flag.String("serial", "", "which serial output to use (none, uart, usb, rtt)")
|
serial := flag.String("serial", "", "which serial output to use (none, uart, usb, rtt)")
|
||||||
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
|
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
|
||||||
interpTimeout := flag.Duration("interp-timeout", 180*time.Second, "interp optimization pass timeout")
|
interpTimeout := flag.Duration("interp-timeout", 180*time.Second, "interp optimization pass timeout")
|
||||||
@@ -1621,10 +1512,8 @@ func main() {
|
|||||||
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
|
||||||
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
printAllocsString := flag.String("print-allocs", "", "regular expression of functions for which heap allocations should be printed")
|
||||||
printCommands := flag.Bool("x", false, "Print commands")
|
printCommands := flag.Bool("x", false, "Print commands")
|
||||||
flagJSON := flag.Bool("json", false, "print output in JSON format")
|
|
||||||
parallelism := flag.Int("p", runtime.GOMAXPROCS(0), "the number of build jobs that can run in parallel")
|
parallelism := flag.Int("p", runtime.GOMAXPROCS(0), "the number of build jobs that can run in parallel")
|
||||||
nodebug := flag.Bool("no-debug", false, "strip debug information")
|
nodebug := flag.Bool("no-debug", false, "strip debug information")
|
||||||
nobounds := flag.Bool("nobounds", false, "do not emit bounds checks")
|
|
||||||
ocdCommandsString := flag.String("ocd-commands", "", "OpenOCD commands, overriding target spec (can specify multiple separated by commas)")
|
ocdCommandsString := flag.String("ocd-commands", "", "OpenOCD commands, overriding target spec (can specify multiple separated by commas)")
|
||||||
ocdOutput := flag.Bool("ocd-output", false, "print OCD daemon output during debug")
|
ocdOutput := flag.Bool("ocd-output", false, "print OCD daemon output during debug")
|
||||||
port := flag.String("port", "", "flash port (can specify multiple candidates separated by commas)")
|
port := flag.String("port", "", "flash port (can specify multiple candidates separated by commas)")
|
||||||
@@ -1647,13 +1536,16 @@ func main() {
|
|||||||
// development it can be useful to not emit debug information at all.
|
// development it can be useful to not emit debug information at all.
|
||||||
skipDwarf := flag.Bool("internal-nodwarf", false, "internal flag, use -no-debug instead")
|
skipDwarf := flag.Bool("internal-nodwarf", false, "internal flag, use -no-debug instead")
|
||||||
|
|
||||||
var flagDeps, flagTest bool
|
var flagJSON, flagDeps, flagTest bool
|
||||||
|
if command == "help" || command == "list" || command == "info" || command == "build" {
|
||||||
|
flag.BoolVar(&flagJSON, "json", false, "print data in JSON format")
|
||||||
|
}
|
||||||
if command == "help" || command == "list" {
|
if command == "help" || command == "list" {
|
||||||
flag.BoolVar(&flagDeps, "deps", false, "supply -deps flag to go list")
|
flag.BoolVar(&flagDeps, "deps", false, "supply -deps flag to go list")
|
||||||
flag.BoolVar(&flagTest, "test", false, "supply -test flag to go list")
|
flag.BoolVar(&flagTest, "test", false, "supply -test flag to go list")
|
||||||
}
|
}
|
||||||
var outpath string
|
var outpath string
|
||||||
if command == "help" || command == "build" || command == "test" || command == "flash" {
|
if command == "help" || command == "build" || command == "test" {
|
||||||
flag.StringVar(&outpath, "o", "", "output filename")
|
flag.StringVar(&outpath, "o", "", "output filename")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1733,7 +1625,6 @@ func main() {
|
|||||||
SkipDWARF: *skipDwarf,
|
SkipDWARF: *skipDwarf,
|
||||||
Semaphore: make(chan struct{}, *parallelism),
|
Semaphore: make(chan struct{}, *parallelism),
|
||||||
Debug: !*nodebug,
|
Debug: !*nodebug,
|
||||||
Nobounds: *nobounds,
|
|
||||||
PrintSizes: *printSize,
|
PrintSizes: *printSize,
|
||||||
PrintStacks: *printStacks,
|
PrintStacks: *printStacks,
|
||||||
PrintAllocs: printAllocs,
|
PrintAllocs: printAllocs,
|
||||||
@@ -1743,6 +1634,7 @@ func main() {
|
|||||||
Programmer: *programmer,
|
Programmer: *programmer,
|
||||||
OpenOCDCommands: ocdCommands,
|
OpenOCDCommands: ocdCommands,
|
||||||
LLVMFeatures: *llvmFeatures,
|
LLVMFeatures: *llvmFeatures,
|
||||||
|
PrintJSON: flagJSON,
|
||||||
Monitor: *monitor,
|
Monitor: *monitor,
|
||||||
BaudRate: *baudrate,
|
BaudRate: *baudrate,
|
||||||
Timeout: *timeout,
|
Timeout: *timeout,
|
||||||
@@ -1792,20 +1684,33 @@ func main() {
|
|||||||
usage(command)
|
usage(command)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if filepath.Ext(outpath) == ".wasm" && options.GOARCH != "wasm" && options.Target == "" {
|
if options.Target == "" {
|
||||||
fmt.Fprintln(os.Stderr, "you appear to want to build a wasm file, but have not specified either a target flag, or the GOARCH/GOOS to use.")
|
switch {
|
||||||
os.Exit(1)
|
case options.GOARCH == "wasm":
|
||||||
|
switch options.GOOS {
|
||||||
|
case "js":
|
||||||
|
options.Target = "wasm"
|
||||||
|
case "wasip1":
|
||||||
|
options.Target = "wasip1"
|
||||||
|
case "wasip2":
|
||||||
|
options.Target = "wasip2"
|
||||||
|
default:
|
||||||
|
fmt.Fprintln(os.Stderr, "GOARCH=wasm but GOOS is not set correctly. Please set GOOS to wasm, wasip1, or wasip2.")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
case filepath.Ext(outpath) == ".wasm":
|
||||||
|
fmt.Fprintln(os.Stderr, "you appear to want to build a wasm file, but have not specified either a target flag, or the GOARCH/GOOS to use.")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := builder.NewConfig(options)
|
err := Build(pkgName, outpath, options)
|
||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
err = Build(pkgName, outpath, config)
|
|
||||||
printBuildOutput(err, *flagJSON)
|
|
||||||
case "flash", "gdb", "lldb":
|
case "flash", "gdb", "lldb":
|
||||||
pkgName := filepath.ToSlash(flag.Arg(0))
|
pkgName := filepath.ToSlash(flag.Arg(0))
|
||||||
if command == "flash" {
|
if command == "flash" {
|
||||||
err := Flash(pkgName, *port, outpath, options)
|
err := Flash(pkgName, *port, options)
|
||||||
printBuildOutput(err, *flagJSON)
|
handleCompilerError(err)
|
||||||
} else {
|
} else {
|
||||||
if !options.Debug {
|
if !options.Debug {
|
||||||
fmt.Fprintln(os.Stderr, "Debug disabled while running debugger?")
|
fmt.Fprintln(os.Stderr, "Debug disabled while running debugger?")
|
||||||
@@ -1813,7 +1718,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
err := Debug(command, pkgName, *ocdOutput, options)
|
err := Debug(command, pkgName, *ocdOutput, options)
|
||||||
printBuildOutput(err, *flagJSON)
|
handleCompilerError(err)
|
||||||
}
|
}
|
||||||
case "run":
|
case "run":
|
||||||
if flag.NArg() < 1 {
|
if flag.NArg() < 1 {
|
||||||
@@ -1823,7 +1728,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
pkgName := filepath.ToSlash(flag.Arg(0))
|
pkgName := filepath.ToSlash(flag.Arg(0))
|
||||||
err := Run(pkgName, options, flag.Args()[1:])
|
err := Run(pkgName, options, flag.Args()[1:])
|
||||||
printBuildOutput(err, *flagJSON)
|
handleCompilerError(err)
|
||||||
case "test":
|
case "test":
|
||||||
var pkgNames []string
|
var pkgNames []string
|
||||||
for i := 0; i < flag.NArg(); i++ {
|
for i := 0; i < flag.NArg(); i++ {
|
||||||
@@ -1890,7 +1795,6 @@ func main() {
|
|||||||
wd = ""
|
wd = ""
|
||||||
}
|
}
|
||||||
diagnostics.CreateDiagnostics(err).WriteTo(os.Stderr, wd)
|
diagnostics.CreateDiagnostics(err).WriteTo(os.Stderr, wd)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
if !passed {
|
if !passed {
|
||||||
select {
|
select {
|
||||||
@@ -1952,13 +1856,16 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
config.GoMinorVersion = 0 // this avoids creating the list of Go1.x build tags.
|
config.GoMinorVersion = 0 // this avoids creating the list of Go1.x build tags.
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
cachedGOROOT, err := loader.GetCachedGoroot(config)
|
cachedGOROOT, err := loader.GetCachedGoroot(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if *flagJSON {
|
if flagJSON {
|
||||||
json, _ := json.MarshalIndent(struct {
|
json, _ := json.MarshalIndent(struct {
|
||||||
Target *compileopts.TargetSpec `json:"target"`
|
Target *compileopts.TargetSpec `json:"target"`
|
||||||
GOROOT string `json:"goroot"`
|
GOROOT string `json:"goroot"`
|
||||||
@@ -2000,7 +1907,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
var extraArgs []string
|
var extraArgs []string
|
||||||
if *flagJSON {
|
if flagJSON {
|
||||||
extraArgs = append(extraArgs, "-json")
|
extraArgs = append(extraArgs, "-json")
|
||||||
}
|
}
|
||||||
if flagDeps {
|
if flagDeps {
|
||||||
|
|||||||
+24
-60
@@ -35,8 +35,6 @@ const TESTDATA = "testdata"
|
|||||||
|
|
||||||
var testTarget = flag.String("target", "", "override test target")
|
var testTarget = flag.String("target", "", "override test target")
|
||||||
|
|
||||||
var testOnlyCurrentOS = flag.Bool("only-current-os", false, "")
|
|
||||||
|
|
||||||
var supportedLinuxArches = map[string]string{
|
var supportedLinuxArches = map[string]string{
|
||||||
"AMD64Linux": "linux/amd64",
|
"AMD64Linux": "linux/amd64",
|
||||||
"X86Linux": "linux/386",
|
"X86Linux": "linux/386",
|
||||||
@@ -160,51 +158,20 @@ func TestBuild(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !*testOnlyCurrentOS {
|
t.Run("EmulatedCortexM3", func(t *testing.T) {
|
||||||
t.Run("EmulatedCortexM3", func(t *testing.T) {
|
t.Parallel()
|
||||||
t.Parallel()
|
runPlatTests(optionsFromTarget("cortex-m-qemu", sema), tests, t)
|
||||||
runPlatTests(optionsFromTarget("cortex-m-qemu", sema), tests, t)
|
})
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("EmulatedRISCV", func(t *testing.T) {
|
t.Run("EmulatedRISCV", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runPlatTests(optionsFromTarget("riscv-qemu", sema), tests, t)
|
runPlatTests(optionsFromTarget("riscv-qemu", sema), tests, t)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("AVR", func(t *testing.T) {
|
t.Run("AVR", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
runPlatTests(optionsFromTarget("simavr", sema), tests, t)
|
runPlatTests(optionsFromTarget("simavr", sema), tests, t)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("WebAssembly", func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
runPlatTests(optionsFromTarget("wasm", sema), tests, t)
|
|
||||||
// Test with -gc=boehm.
|
|
||||||
t.Run("gc.go-boehm", func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
optionsBoehm := optionsFromTarget("wasm", sema)
|
|
||||||
optionsBoehm.GC = "boehm"
|
|
||||||
runTest("gc.go", optionsBoehm, t, nil, nil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
t.Run("WASIp1", func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
runPlatTests(optionsFromTarget("wasip1", sema), tests, t)
|
|
||||||
|
|
||||||
// Test with -gc=boehm.
|
|
||||||
t.Run("gc.go-boehm", func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
optionsBoehm := optionsFromTarget("wasip1", sema)
|
|
||||||
optionsBoehm.GC = "boehm"
|
|
||||||
runTest("gc.go", optionsBoehm, t, nil, nil)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
t.Run("WASIp2", func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
runPlatTests(optionsFromTarget("wasip2", sema), tests, t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
for name, osArch := range supportedLinuxArches {
|
for name, osArch := range supportedLinuxArches {
|
||||||
@@ -224,13 +191,18 @@ func TestBuild(t *testing.T) {
|
|||||||
options := optionsFromOSARCH("linux/mipsle/softfloat", sema)
|
options := optionsFromOSARCH("linux/mipsle/softfloat", sema)
|
||||||
runTest("cgo/", options, t, nil, nil)
|
runTest("cgo/", options, t, nil, nil)
|
||||||
})
|
})
|
||||||
} else if runtime.GOOS == "windows" {
|
t.Run("WebAssembly", func(t *testing.T) {
|
||||||
if runtime.GOARCH != "386" {
|
t.Parallel()
|
||||||
t.Run("Windows386", func(t *testing.T) {
|
runPlatTests(optionsFromTarget("wasm", sema), tests, t)
|
||||||
t.Parallel()
|
})
|
||||||
runPlatTests(optionsFromOSARCH("windows/386", sema), tests, t)
|
t.Run("WASI", func(t *testing.T) {
|
||||||
})
|
t.Parallel()
|
||||||
}
|
runPlatTests(optionsFromTarget("wasip1", sema), tests, t)
|
||||||
|
})
|
||||||
|
t.Run("WASIp2", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
runPlatTests(optionsFromTarget("wasip2", sema), tests, t)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,12 +396,10 @@ func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runTest(name string, options compileopts.Options, t *testing.T, cmdArgs, environmentVars []string) {
|
func runTest(name string, options compileopts.Options, t *testing.T, cmdArgs, environmentVars []string) {
|
||||||
t.Helper()
|
|
||||||
runTestWithConfig(name, t, options, cmdArgs, environmentVars)
|
runTestWithConfig(name, t, options, cmdArgs, environmentVars)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runTestWithConfig(name string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string) {
|
func runTestWithConfig(name string, t *testing.T, options compileopts.Options, cmdArgs, environmentVars []string) {
|
||||||
t.Helper()
|
|
||||||
// Get the expected output for this test.
|
// Get the expected output for this test.
|
||||||
// Note: not using filepath.Join as it strips the path separator at the end
|
// Note: not using filepath.Join as it strips the path separator at the end
|
||||||
// of the path.
|
// of the path.
|
||||||
@@ -705,10 +675,6 @@ func TestWasmExport(t *testing.T) {
|
|||||||
// again.
|
// again.
|
||||||
checkResult("reentrantCall(2, 3)", mustCall(mod.ExportedFunction("reentrantCall").Call(ctx, 2, 3)), []uint64{5})
|
checkResult("reentrantCall(2, 3)", mustCall(mod.ExportedFunction("reentrantCall").Call(ctx, 2, 3)), []uint64{5})
|
||||||
checkResult("reentrantCall(1, 8)", mustCall(mod.ExportedFunction("reentrantCall").Call(ctx, 1, 8)), []uint64{9})
|
checkResult("reentrantCall(1, 8)", mustCall(mod.ExportedFunction("reentrantCall").Call(ctx, 1, 8)), []uint64{9})
|
||||||
|
|
||||||
// Check that goroutines started inside //go:wasmexport don't
|
|
||||||
// block the called function from returning.
|
|
||||||
checkResult("goroutineExit()", mustCall(mod.ExportedFunction("goroutineExit").Call(ctx)), nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add wasip1 module.
|
// Add wasip1 module.
|
||||||
@@ -878,7 +844,6 @@ func TestWasmExit(t *testing.T) {
|
|||||||
|
|
||||||
// Check whether the output of a test equals the expected output.
|
// Check whether the output of a test equals the expected output.
|
||||||
func checkOutput(t *testing.T, filename string, actual []byte) {
|
func checkOutput(t *testing.T, filename string, actual []byte) {
|
||||||
t.Helper()
|
|
||||||
expectedOutput, err := os.ReadFile(filename)
|
expectedOutput, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("could not read output file:", err)
|
t.Fatal("could not read output file:", err)
|
||||||
@@ -887,7 +852,6 @@ func checkOutput(t *testing.T, filename string, actual []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkOutputData(t *testing.T, expectedOutput, actual []byte) {
|
func checkOutputData(t *testing.T, expectedOutput, actual []byte) {
|
||||||
t.Helper()
|
|
||||||
expectedOutput = bytes.ReplaceAll(expectedOutput, []byte("\r\n"), []byte("\n"))
|
expectedOutput = bytes.ReplaceAll(expectedOutput, []byte("\r\n"), []byte("\n"))
|
||||||
actual = bytes.ReplaceAll(actual, []byte("\r\n"), []byte("\n"))
|
actual = bytes.ReplaceAll(actual, []byte("\r\n"), []byte("\n"))
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package rand
|
package rand
|
||||||
|
|
||||||
import (
|
import "errors"
|
||||||
"errors"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Reader = &reader{}
|
Reader = &reader{}
|
||||||
@@ -19,22 +16,28 @@ func (r *reader) Read(b []byte) (n int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the old RtlGenRandom, introduced in Windows XP.
|
var randomByte uint32
|
||||||
// Even though the documentation says it is deprecated, it is widely used
|
for i := range b {
|
||||||
// and probably won't go away anytime soon.
|
// Call rand_s every four bytes because it's a C int (always 32-bit in
|
||||||
// See for example: https://github.com/golang/go/issues/33542
|
// Windows).
|
||||||
// For Windows 7 and newer, we might switch to ProcessPrng in the future
|
if i%4 == 0 {
|
||||||
// (which is a documented function and might be a tiny bit faster).
|
errCode := libc_rand_s(&randomByte)
|
||||||
ok := libc_RtlGenRandom(unsafe.Pointer(&b[0]), len(b))
|
if errCode != 0 {
|
||||||
if !ok {
|
// According to the documentation, it can return an error.
|
||||||
return 0, errRandom
|
return n, errRandom
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
randomByte >>= 8
|
||||||
|
}
|
||||||
|
b[i] = byte(randomByte)
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is part of advapi32.dll, and is called SystemFunction036 for
|
// Cryptographically secure random number generator.
|
||||||
// some reason. It's available on Windows XP and newer.
|
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rand-s?view=msvc-170
|
||||||
// See: https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
|
// errno_t rand_s(unsigned int* randomValue);
|
||||||
//
|
//
|
||||||
//export SystemFunction036
|
//export rand_s
|
||||||
func libc_RtlGenRandom(buf unsafe.Pointer, len int) bool
|
func libc_rand_s(randomValue *uint32) int32
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ func SecCertificateCopyData(cert CFRef) ([]byte, error) {
|
|||||||
return nil, errors.New("not implemented")
|
return nil, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func SecTrustCopyCertificateChain(trustObj CFRef) (CFRef, error) {
|
|
||||||
return 0, errors.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
|
func SecTrustEvaluateWithError(trustObj CFRef) (int, error) {
|
||||||
return 0, errors.New("not implemented")
|
return 0, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,11 +146,6 @@ const (
|
|||||||
SYST_CALIB_NOREF = 0x80000000 // Bit NOREF.
|
SYST_CALIB_NOREF = 0x80000000 // Bit NOREF.
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClearPendingIRQ clears the pending status of the interrupt.
|
|
||||||
func ClearPendingIRQ(irq uint32) {
|
|
||||||
NVIC.ICPR[irq>>5].Set(1 << (irq & 0x1F))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable the given interrupt number.
|
// Enable the given interrupt number.
|
||||||
func EnableIRQ(irq uint32) {
|
func EnableIRQ(irq uint32) {
|
||||||
NVIC.ISER[irq>>5].Set(1 << (irq & 0x1F))
|
NVIC.ISER[irq>>5].Set(1 << (irq & 0x1F))
|
||||||
|
|||||||
@@ -275,61 +275,3 @@ const (
|
|||||||
DPC CSR = 0x7B1 // Debug PC.
|
DPC CSR = 0x7B1 // Debug PC.
|
||||||
DSCRATCH CSR = 0x7B2 // Debug scratch register.
|
DSCRATCH CSR = 0x7B2 // Debug scratch register.
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bitfields for the CSR registers above.
|
|
||||||
const (
|
|
||||||
// MSTATUS (common bits between RV32 and RV64)
|
|
||||||
MSTATUS_SIE = 1 << 1
|
|
||||||
MSTATUS_MIE = 1 << 3
|
|
||||||
MSTATUS_SPIE = 1 << 5
|
|
||||||
MSTATUS_UBE = 1 << 6
|
|
||||||
MSTATUS_MPIE = 1 << 7
|
|
||||||
MSTATUS_SPP = 1 << 8
|
|
||||||
MSTATUS_MPRV = 1 << 17
|
|
||||||
MSTATUS_SUM = 1 << 18
|
|
||||||
MSTATUS_MXR = 1 << 19
|
|
||||||
MSTATUS_TVM = 1 << 20
|
|
||||||
MSTATUS_TW = 1 << 21
|
|
||||||
MSTATUS_TSR = 1 << 22
|
|
||||||
|
|
||||||
MIE_SSIE = 1 << 1
|
|
||||||
MIE_MSIE = 1 << 3
|
|
||||||
MIE_STIE = 1 << 5
|
|
||||||
MIE_MTIE = 1 << 7
|
|
||||||
MIE_SEIE = 1 << 9
|
|
||||||
MIE_MEIE = 1 << 11
|
|
||||||
|
|
||||||
MIP_SSIP = 1 << 1
|
|
||||||
MIP_MSIP = 1 << 3
|
|
||||||
MIP_STIP = 1 << 5
|
|
||||||
MIP_MTIP = 1 << 7
|
|
||||||
MIP_SEIP = 1 << 9
|
|
||||||
MIP_MEIP = 1 << 11
|
|
||||||
)
|
|
||||||
|
|
||||||
// Interrupt constants
|
|
||||||
const (
|
|
||||||
// MCAUSE values with the topmost bit (interrupt bit) set.
|
|
||||||
SupervisorSoftwareInterrupt = 1
|
|
||||||
MachineSoftwareInterrupt = 3
|
|
||||||
SupervisorTimerInterrupt = 5
|
|
||||||
MachineTimerInterrupt = 7
|
|
||||||
SupervisorExternalInterrupt = 9
|
|
||||||
MachineExternalInterrupt = 11
|
|
||||||
|
|
||||||
// MCAUSE values with the topmost bit (interrupt bit) clear.
|
|
||||||
InstructionAddressMisaligned = 0
|
|
||||||
InstructionAccessFault = 1
|
|
||||||
IllegalInstruction = 2
|
|
||||||
Breakpoint = 3
|
|
||||||
LoadAddressMisaligned = 4
|
|
||||||
LoadAccessFault = 5
|
|
||||||
StoreOrAMOAddressMisaligned = 6
|
|
||||||
StoreOrAMOAccessFault = 7
|
|
||||||
EnvironmentCallFromUMode = 8
|
|
||||||
EnvironmentCallFromSMode = 9
|
|
||||||
EnvironmentCallFromMMode = 11
|
|
||||||
InstructionPageFault = 12
|
|
||||||
LoadPageFault = 13
|
|
||||||
StoreOrAMOPageFault = 15
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -3,47 +3,8 @@
|
|||||||
.type _start,@function
|
.type _start,@function
|
||||||
|
|
||||||
_start:
|
_start:
|
||||||
// If we're on a multicore system, we need to wait for hart 0 to wake us up.
|
|
||||||
#if TINYGO_CORES > 1
|
|
||||||
csrr a0, mhartid
|
|
||||||
|
|
||||||
// Hart 0 stack
|
|
||||||
bnez a0, 1f
|
|
||||||
la sp, _stack_top
|
|
||||||
|
|
||||||
1:
|
|
||||||
// Hart 1 stack
|
|
||||||
li a1, 1
|
|
||||||
bne a0, a1, 2f
|
|
||||||
la sp, _stack1_top
|
|
||||||
|
|
||||||
2:
|
|
||||||
// Hart 2 stack
|
|
||||||
#if TINYGO_CORES >= 3
|
|
||||||
li a1, 2
|
|
||||||
bne a0, a1, 3f
|
|
||||||
la sp, _stack2_top
|
|
||||||
#endif
|
|
||||||
|
|
||||||
3:
|
|
||||||
// Hart 3 stack
|
|
||||||
#if TINYGO_CORES >= 4
|
|
||||||
li a1, 3
|
|
||||||
bne a0, a1, 4f
|
|
||||||
la sp, _stack3_top
|
|
||||||
#endif
|
|
||||||
|
|
||||||
4:
|
|
||||||
// done
|
|
||||||
|
|
||||||
#if TINYGO_CORES > 4
|
|
||||||
#error only up to 4 cores are supported at the moment!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
// Load the stack pointer.
|
// Load the stack pointer.
|
||||||
la sp, _stack_top
|
la sp, _stack_top
|
||||||
#endif
|
|
||||||
|
|
||||||
// Load the globals pointer. The program will load pointers relative to this
|
// Load the globals pointer. The program will load pointers relative to this
|
||||||
// register, so it must be set to the right value on startup.
|
// register, so it must be set to the right value on startup.
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
// Hand created file. DO NOT DELETE.
|
|
||||||
// Definitions that are missing in src/device/rp/rp2040.go generated from SVDs
|
|
||||||
|
|
||||||
//go:build rp && rp2040
|
|
||||||
|
|
||||||
package rp
|
|
||||||
|
|
||||||
// DMA: 2.5.3.1. System DREQ Table from RP2040 Datasheet
|
|
||||||
// https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
|
|
||||||
const (
|
|
||||||
DREQ_PIO0_TX0 = 0
|
|
||||||
DREQ_PIO0_TX1 = 1
|
|
||||||
DREQ_PIO0_TX2 = 2
|
|
||||||
DREQ_PIO0_TX3 = 3
|
|
||||||
DREQ_PIO0_RX0 = 4
|
|
||||||
DREQ_PIO0_RX1 = 5
|
|
||||||
DREQ_PIO0_RX2 = 6
|
|
||||||
DREQ_PIO0_RX3 = 7
|
|
||||||
DREQ_PIO1_TX0 = 8
|
|
||||||
DREQ_PIO1_TX1 = 9
|
|
||||||
DREQ_PIO1_TX2 = 10
|
|
||||||
DREQ_PIO1_TX3 = 11
|
|
||||||
DREQ_PIO1_RX0 = 12
|
|
||||||
DREQ_PIO1_RX1 = 13
|
|
||||||
DREQ_PIO1_RX2 = 14
|
|
||||||
DREQ_PIO1_RX3 = 15
|
|
||||||
DREQ_SPI0_TX = 16
|
|
||||||
DREQ_SPI0_RX = 17
|
|
||||||
DREQ_SPI1_TX = 18
|
|
||||||
DREQ_SPI1_RX = 19
|
|
||||||
DREQ_UART0_TX = 20
|
|
||||||
DREQ_UART0_RX = 21
|
|
||||||
DREQ_UART1_TX = 22
|
|
||||||
DREQ_UART1_RX = 23
|
|
||||||
DREQ_PWM_WRAP0 = 24
|
|
||||||
DREQ_PWM_WRAP1 = 25
|
|
||||||
DREQ_PWM_WRAP2 = 26
|
|
||||||
DREQ_PWM_WRAP3 = 27
|
|
||||||
DREQ_PWM_WRAP4 = 28
|
|
||||||
DREQ_PWM_WRAP5 = 29
|
|
||||||
DREQ_PWM_WRAP6 = 30
|
|
||||||
DREQ_PWM_WRAP7 = 31
|
|
||||||
DREQ_I2C0_TX = 32
|
|
||||||
DREQ_I2C0_RX = 33
|
|
||||||
DREQ_I2C1_TX = 34
|
|
||||||
DREQ_I2C1_RX = 35
|
|
||||||
DREQ_ADC = 36
|
|
||||||
DREQ_XIP_STREAM = 37
|
|
||||||
DREQ_XIP_SSITX = 38
|
|
||||||
DREQ_XIP_SSIRX = 39
|
|
||||||
)
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
// Hand created file. DO NOT DELETE.
|
|
||||||
// Definitions that are missing in src/device/rp/rp2350.go generated from SVDs
|
|
||||||
|
|
||||||
//go:build rp && rp2350
|
|
||||||
|
|
||||||
package rp
|
|
||||||
|
|
||||||
// DMA: 12.6.4.1. System DREQ Table from RP2350 Datasheet
|
|
||||||
// https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf
|
|
||||||
const (
|
|
||||||
DREQ_PIO0_TX0 = 0
|
|
||||||
DREQ_PIO0_TX1 = 1
|
|
||||||
DREQ_PIO0_TX2 = 2
|
|
||||||
DREQ_PIO0_TX3 = 3
|
|
||||||
DREQ_PIO0_RX0 = 4
|
|
||||||
DREQ_PIO0_RX1 = 5
|
|
||||||
DREQ_PIO0_RX2 = 6
|
|
||||||
DREQ_PIO0_RX3 = 7
|
|
||||||
DREQ_PIO1_TX0 = 8
|
|
||||||
DREQ_PIO1_TX1 = 9
|
|
||||||
DREQ_PIO1_TX2 = 10
|
|
||||||
DREQ_PIO1_TX3 = 11
|
|
||||||
DREQ_PIO1_RX0 = 12
|
|
||||||
DREQ_PIO1_RX1 = 13
|
|
||||||
DREQ_PIO1_RX2 = 14
|
|
||||||
DREQ_PIO1_RX3 = 15
|
|
||||||
DREQ_PIO2_TX0 = 16
|
|
||||||
DREQ_PIO2_TX1 = 17
|
|
||||||
DREQ_PIO2_TX2 = 18
|
|
||||||
DREQ_PIO2_TX3 = 19
|
|
||||||
DREQ_PIO2_RX0 = 20
|
|
||||||
DREQ_PIO2_RX1 = 21
|
|
||||||
DREQ_PIO2_RX2 = 22
|
|
||||||
DREQ_PIO2_RX3 = 23
|
|
||||||
DREQ_SPI0_TX = 24
|
|
||||||
DREQ_SPI0_RX = 25
|
|
||||||
DREQ_SPI1_TX = 26
|
|
||||||
DREQ_SPI1_RX = 27
|
|
||||||
DREQ_UART0_TX = 28
|
|
||||||
DREQ_UART0_RX = 29
|
|
||||||
DREQ_UART1_TX = 30
|
|
||||||
DREQ_UART1_RX = 31
|
|
||||||
DREQ_PWM_WRAP0 = 32
|
|
||||||
DREQ_PWM_WRAP1 = 33
|
|
||||||
DREQ_PWM_WRAP2 = 34
|
|
||||||
DREQ_PWM_WRAP3 = 35
|
|
||||||
DREQ_PWM_WRAP4 = 36
|
|
||||||
DREQ_PWM_WRAP5 = 37
|
|
||||||
DREQ_PWM_WRAP6 = 38
|
|
||||||
DREQ_PWM_WRAP7 = 39
|
|
||||||
DREQ_PWM_WRAP8 = 40
|
|
||||||
DREQ_PWM_WRAP9 = 41
|
|
||||||
DREQ_PWM_WRAP10 = 42
|
|
||||||
DREQ_PWM_WRAP11 = 43
|
|
||||||
DREQ_I2C0_TX = 44
|
|
||||||
DREQ_I2C0_RX = 45
|
|
||||||
DREQ_I2C1_TX = 46
|
|
||||||
DREQ_I2C1_RX = 47
|
|
||||||
DREQ_ADC = 48
|
|
||||||
DREQ_XIP_STREAM = 49
|
|
||||||
DREQ_XIP_QMITX = 50
|
|
||||||
DREQ_XIP_QMIRX = 51
|
|
||||||
DREQ_HSTX = 52
|
|
||||||
DREQ_CORESIGHT = 53
|
|
||||||
DREQ_SHA256 = 54
|
|
||||||
)
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"machine"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const N = 500000
|
|
||||||
const Ngoro = 4
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
start := time.Now()
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(Ngoro)
|
|
||||||
for i := 0; i < Ngoro; i++ {
|
|
||||||
go adder(&wg, N)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
elapsed := time.Since(start)
|
|
||||||
goroutineCtxSwitchOverhead := (elapsed / (Ngoro * N)).String()
|
|
||||||
|
|
||||||
elapsedstr := elapsed.String()
|
|
||||||
machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
||||||
for {
|
|
||||||
println("bench:", elapsedstr, "goroutine ctx switch:", goroutineCtxSwitchOverhead)
|
|
||||||
machine.LED.High()
|
|
||||||
time.Sleep(elapsed)
|
|
||||||
machine.LED.Low()
|
|
||||||
time.Sleep(elapsed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func adder(wg *sync.WaitGroup, num int) {
|
|
||||||
for i := 0; i < num; i++ {
|
|
||||||
runtime.Gosched()
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"machine"
|
|
||||||
"machine/usb/msc"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
msc.Port(machine.Flash)
|
|
||||||
|
|
||||||
for {
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,10 +8,3 @@ import "unsafe"
|
|||||||
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
func NoEscape(p unsafe.Pointer) unsafe.Pointer {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func Escape[T any](x T) T {
|
|
||||||
// This function is either implemented in the compiler, or left undefined
|
|
||||||
// for some variation of T. The body of this function should not be compiled
|
|
||||||
// as-is.
|
|
||||||
panic("internal/abi.Escape: unreachable (implemented in the compiler)")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
package cm
|
|
||||||
|
|
||||||
// CaseUnmarshaler returns an function that can unmarshal text into
|
|
||||||
// [variant] or [enum] case T.
|
|
||||||
//
|
|
||||||
// [enum]: https://component-model.bytecodealliance.org/design/wit.html#enums
|
|
||||||
// [variant]: https://component-model.bytecodealliance.org/design/wit.html#variants
|
|
||||||
func CaseUnmarshaler[T ~uint8 | ~uint16 | ~uint32](cases []string) func(v *T, text []byte) error {
|
|
||||||
if len(cases) <= linearScanThreshold {
|
|
||||||
return func(v *T, text []byte) error {
|
|
||||||
if len(text) == 0 {
|
|
||||||
return &emptyTextError{}
|
|
||||||
}
|
|
||||||
s := string(text)
|
|
||||||
for i := 0; i < len(cases); i++ {
|
|
||||||
if cases[i] == s {
|
|
||||||
*v = T(i)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &noMatchingCaseError{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m := make(map[string]T, len(cases))
|
|
||||||
for i, v := range cases {
|
|
||||||
m[v] = T(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(v *T, text []byte) error {
|
|
||||||
if len(text) == 0 {
|
|
||||||
return &emptyTextError{}
|
|
||||||
}
|
|
||||||
c, ok := m[string(text)]
|
|
||||||
if !ok {
|
|
||||||
return &noMatchingCaseError{}
|
|
||||||
}
|
|
||||||
*v = c
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const linearScanThreshold = 16
|
|
||||||
|
|
||||||
type emptyTextError struct{}
|
|
||||||
|
|
||||||
func (*emptyTextError) Error() string { return "empty text" }
|
|
||||||
|
|
||||||
type noMatchingCaseError struct{}
|
|
||||||
|
|
||||||
func (*noMatchingCaseError) Error() string { return "no matching case" }
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Package cm provides types and functions for interfacing with the WebAssembly Component Model.
|
// Package cm contains types and functions for interfacing with the WebAssembly Component Model.
|
||||||
//
|
//
|
||||||
// The types in this package (such as [List], [Option], [Result], and [Variant]) are designed to match the memory layout
|
// The types in this package (such as [List], [Option], [Result], and [Variant]) are designed to match the memory layout
|
||||||
// of [Component Model] types as specified in the [Canonical ABI].
|
// of [Component Model] types as specified in the [Canonical ABI].
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
// This file exists for testing this package without WebAssembly,
|
|
||||||
// allowing empty function bodies with a //go:wasmimport directive.
|
|
||||||
// See https://pkg.go.dev/cmd/compile for more information.
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package cm
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// ErrorContext represents the Component Model [error-context] type,
|
|
||||||
// an immutable, non-deterministic, host-defined value meant to aid in debugging.
|
|
||||||
//
|
|
||||||
// [error-context]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#error-context-type
|
|
||||||
type ErrorContext struct {
|
|
||||||
_ HostLayout
|
|
||||||
errorContext
|
|
||||||
}
|
|
||||||
|
|
||||||
type errorContext uint32
|
|
||||||
|
|
||||||
// Error implements the [error] interface. It returns the debug message associated with err.
|
|
||||||
func (err errorContext) Error() string {
|
|
||||||
return err.DebugMessage()
|
|
||||||
}
|
|
||||||
|
|
||||||
// String implements [fmt.Stringer].
|
|
||||||
func (err errorContext) String() string {
|
|
||||||
return err.DebugMessage()
|
|
||||||
}
|
|
||||||
|
|
||||||
// DebugMessage represents the Canonical ABI [error-context.debug-message] function.
|
|
||||||
//
|
|
||||||
// [error-context.debug-message]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#error-contextdebug-message
|
|
||||||
func (err errorContext) DebugMessage() string {
|
|
||||||
var s string
|
|
||||||
wasmimport_errorContextDebugMessage(err, unsafe.Pointer(&s))
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drop represents the Canonical ABI [error-context.drop] function.
|
|
||||||
//
|
|
||||||
// [error-context.drop]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#error-contextdrop
|
|
||||||
func (err errorContext) Drop() {
|
|
||||||
wasmimport_errorContextDrop(err)
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package cm
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// msg uses unsafe.Pointer for compatibility with go1.23 and lower.
|
|
||||||
//
|
|
||||||
//go:wasmimport canon error-context.debug-message
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_errorContextDebugMessage(err errorContext, msg unsafe.Pointer)
|
|
||||||
|
|
||||||
//go:wasmimport canon error-context.drop
|
|
||||||
//go:noescape
|
|
||||||
func wasmimport_errorContextDrop(err errorContext)
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package cm
|
|
||||||
|
|
||||||
// Future represents the Component Model [future] type.
|
|
||||||
// A future is a special case of stream. In non-error cases,
|
|
||||||
// a future delivers exactly one value before being automatically closed.
|
|
||||||
//
|
|
||||||
// [future]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#asynchronous-value-types
|
|
||||||
type Future[T any] struct {
|
|
||||||
_ HostLayout
|
|
||||||
future[T]
|
|
||||||
}
|
|
||||||
|
|
||||||
type future[T any] uint32
|
|
||||||
|
|
||||||
// TODO: implement methods on type future
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package cm
|
package cm
|
||||||
|
|
||||||
import (
|
import "unsafe"
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// List represents a Component Model list.
|
// List represents a Component Model list.
|
||||||
// The binary representation of list<T> is similar to a Go slice minus the cap field.
|
// The binary representation of list<T> is similar to a Go slice minus the cap field.
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package cm
|
|
||||||
|
|
||||||
// Stream represents the Component Model [stream] type.
|
|
||||||
// A stream is a special case of stream. In non-error cases,
|
|
||||||
// a stream delivers exactly one value before being automatically closed.
|
|
||||||
//
|
|
||||||
// [stream]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md#asynchronous-value-types
|
|
||||||
type Stream[T any] struct {
|
|
||||||
_ HostLayout
|
|
||||||
stream[T]
|
|
||||||
}
|
|
||||||
|
|
||||||
type stream[T any] uint32
|
|
||||||
|
|
||||||
// TODO: implement methods on type stream
|
|
||||||
@@ -3,9 +3,10 @@ package cm
|
|||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
// Discriminant is the set of types that can represent the tag or discriminator of a variant.
|
// Discriminant is the set of types that can represent the tag or discriminator of a variant.
|
||||||
// Use uint8 where there are 256 or fewer cases, uint16 for up to 65,536 cases, or uint32 for anything greater.
|
// Use bool for 2-case variant types, result<T>, or option<T> types, uint8 where there are 256 or
|
||||||
|
// fewer cases, uint16 for up to 65,536 cases, or uint32 for anything greater.
|
||||||
type Discriminant interface {
|
type Discriminant interface {
|
||||||
uint8 | uint16 | uint32
|
bool | uint8 | uint16 | uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variant represents a loosely-typed Component Model variant.
|
// Variant represents a loosely-typed Component Model variant.
|
||||||
|
|||||||
@@ -5,20 +5,29 @@ import "unsafe"
|
|||||||
// Internal constants for gc layout
|
// Internal constants for gc layout
|
||||||
// See runtime/gc_precise.go
|
// See runtime/gc_precise.go
|
||||||
|
|
||||||
type Layout uintptr
|
var (
|
||||||
|
NoPtrs unsafe.Pointer
|
||||||
const (
|
Pointer unsafe.Pointer
|
||||||
// 16-bit int => bits = 4
|
String unsafe.Pointer
|
||||||
// 32-bit int => bits = 5
|
Slice unsafe.Pointer
|
||||||
// 64-bit int => bits = 6
|
|
||||||
sizeBits = 4 + unsafe.Sizeof(uintptr(0))/4
|
|
||||||
|
|
||||||
sizeShift = sizeBits + 1
|
|
||||||
|
|
||||||
NoPtrs = Layout(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
|
||||||
Pointer = Layout(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
|
||||||
String = Layout(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
|
|
||||||
Slice = Layout(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l Layout) AsPtr() unsafe.Pointer { return unsafe.Pointer(l) }
|
func init() {
|
||||||
|
var sizeBits uintptr
|
||||||
|
|
||||||
|
switch unsafe.Sizeof(uintptr(0)) {
|
||||||
|
case 8:
|
||||||
|
sizeBits = 6
|
||||||
|
case 4:
|
||||||
|
sizeBits = 5
|
||||||
|
case 2:
|
||||||
|
sizeBits = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
var sizeShift = sizeBits + 1
|
||||||
|
|
||||||
|
NoPtrs = unsafe.Pointer(uintptr(0b0<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
||||||
|
Pointer = unsafe.Pointer(uintptr(0b1<<sizeShift) | uintptr(0b1<<1) | uintptr(1))
|
||||||
|
String = unsafe.Pointer(uintptr(0b01<<sizeShift) | uintptr(0b10<<1) | uintptr(1))
|
||||||
|
Slice = unsafe.Pointer(uintptr(0b001<<sizeShift) | uintptr(0b11<<1) | uintptr(1))
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,196 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// Deep equality test via reflection
|
|
||||||
|
|
||||||
package reflectlite
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// During deepValueEqual, must keep track of checks that are
|
|
||||||
// in progress. The comparison algorithm assumes that all
|
|
||||||
// checks in progress are true when it reencounters them.
|
|
||||||
// Visited comparisons are stored in a map indexed by visit.
|
|
||||||
type visit struct {
|
|
||||||
a1 unsafe.Pointer
|
|
||||||
a2 unsafe.Pointer
|
|
||||||
typ *RawType
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests for deep equality using reflected types. The map argument tracks
|
|
||||||
// comparisons that have already been seen, which allows short circuiting on
|
|
||||||
// recursive types.
|
|
||||||
func deepValueEqual(v1, v2 Value, visited map[visit]struct{}) bool {
|
|
||||||
if !v1.IsValid() || !v2.IsValid() {
|
|
||||||
return v1.IsValid() == v2.IsValid()
|
|
||||||
}
|
|
||||||
if v1.typecode != v2.typecode {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to avoid putting more in the visited map than we need to.
|
|
||||||
// For any possible reference cycle that might be encountered,
|
|
||||||
// hard(v1, v2) needs to return true for at least one of the types in the cycle,
|
|
||||||
// and it's safe and valid to get Value's internal pointer.
|
|
||||||
hard := func(v1, v2 Value) bool {
|
|
||||||
switch v1.Kind() {
|
|
||||||
case Map, Slice, Ptr, Interface:
|
|
||||||
// Nil pointers cannot be cyclic. Avoid putting them in the visited map.
|
|
||||||
return !v1.IsNil() && !v2.IsNil()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if hard(v1, v2) {
|
|
||||||
addr1 := v1.pointer()
|
|
||||||
addr2 := v2.pointer()
|
|
||||||
if uintptr(addr1) > uintptr(addr2) {
|
|
||||||
// Canonicalize order to reduce number of entries in visited.
|
|
||||||
// Assumes non-moving garbage collector.
|
|
||||||
addr1, addr2 = addr2, addr1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Short circuit if references are already seen.
|
|
||||||
v := visit{addr1, addr2, v1.typecode}
|
|
||||||
if _, ok := visited[v]; ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember for later.
|
|
||||||
visited[v] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v1.Kind() {
|
|
||||||
case Array:
|
|
||||||
for i := 0; i < v1.Len(); i++ {
|
|
||||||
if !deepValueEqual(v1.Index(i), v2.Index(i), visited) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case Slice:
|
|
||||||
if v1.IsNil() != v2.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if v1.Len() != v2.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if v1.UnsafePointer() == v2.UnsafePointer() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
for i := 0; i < v1.Len(); i++ {
|
|
||||||
if !deepValueEqual(v1.Index(i), v2.Index(i), visited) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case Interface:
|
|
||||||
if v1.IsNil() || v2.IsNil() {
|
|
||||||
return v1.IsNil() == v2.IsNil()
|
|
||||||
}
|
|
||||||
return deepValueEqual(v1.Elem(), v2.Elem(), visited)
|
|
||||||
case Ptr:
|
|
||||||
if v1.UnsafePointer() == v2.UnsafePointer() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return deepValueEqual(v1.Elem(), v2.Elem(), visited)
|
|
||||||
case Struct:
|
|
||||||
for i, n := 0, v1.NumField(); i < n; i++ {
|
|
||||||
if !deepValueEqual(v1.Field(i), v2.Field(i), visited) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case Map:
|
|
||||||
if v1.IsNil() != v2.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if v1.Len() != v2.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if v1.UnsafePointer() == v2.UnsafePointer() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
for _, k := range v1.MapKeys() {
|
|
||||||
val1 := v1.MapIndex(k)
|
|
||||||
val2 := v2.MapIndex(k)
|
|
||||||
if !val1.IsValid() || !val2.IsValid() || !deepValueEqual(val1, val2, visited) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case Func:
|
|
||||||
if v1.IsNil() && v2.IsNil() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Can't do better than this:
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
// Normal equality suffices
|
|
||||||
return valueInterfaceUnsafe(v1) == valueInterfaceUnsafe(v2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepEqual reports whether x and y are “deeply equal”, defined as follows.
|
|
||||||
// Two values of identical type are deeply equal if one of the following cases applies.
|
|
||||||
// Values of distinct types are never deeply equal.
|
|
||||||
//
|
|
||||||
// Array values are deeply equal when their corresponding elements are deeply equal.
|
|
||||||
//
|
|
||||||
// Struct values are deeply equal if their corresponding fields,
|
|
||||||
// both exported and unexported, are deeply equal.
|
|
||||||
//
|
|
||||||
// Func values are deeply equal if both are nil; otherwise they are not deeply equal.
|
|
||||||
//
|
|
||||||
// Interface values are deeply equal if they hold deeply equal concrete values.
|
|
||||||
//
|
|
||||||
// Map values are deeply equal when all of the following are true:
|
|
||||||
// they are both nil or both non-nil, they have the same length,
|
|
||||||
// and either they are the same map object or their corresponding keys
|
|
||||||
// (matched using Go equality) map to deeply equal values.
|
|
||||||
//
|
|
||||||
// Pointer values are deeply equal if they are equal using Go's == operator
|
|
||||||
// or if they point to deeply equal values.
|
|
||||||
//
|
|
||||||
// Slice values are deeply equal when all of the following are true:
|
|
||||||
// they are both nil or both non-nil, they have the same length,
|
|
||||||
// and either they point to the same initial entry of the same underlying array
|
|
||||||
// (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal.
|
|
||||||
// Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil))
|
|
||||||
// are not deeply equal.
|
|
||||||
//
|
|
||||||
// Other values - numbers, bools, strings, and channels - are deeply equal
|
|
||||||
// if they are equal using Go's == operator.
|
|
||||||
//
|
|
||||||
// In general DeepEqual is a recursive relaxation of Go's == operator.
|
|
||||||
// However, this idea is impossible to implement without some inconsistency.
|
|
||||||
// Specifically, it is possible for a value to be unequal to itself,
|
|
||||||
// either because it is of func type (uncomparable in general)
|
|
||||||
// or because it is a floating-point NaN value (not equal to itself in floating-point comparison),
|
|
||||||
// or because it is an array, struct, or interface containing
|
|
||||||
// such a value.
|
|
||||||
// On the other hand, pointer values are always equal to themselves,
|
|
||||||
// even if they point at or contain such problematic values,
|
|
||||||
// because they compare equal using Go's == operator, and that
|
|
||||||
// is a sufficient condition to be deeply equal, regardless of content.
|
|
||||||
// DeepEqual has been defined so that the same short-cut applies
|
|
||||||
// to slices and maps: if x and y are the same slice or the same map,
|
|
||||||
// they are deeply equal regardless of content.
|
|
||||||
//
|
|
||||||
// As DeepEqual traverses the data values it may find a cycle. The
|
|
||||||
// second and subsequent times that DeepEqual compares two pointer
|
|
||||||
// values that have been compared before, it treats the values as
|
|
||||||
// equal rather than examining the values to which they point.
|
|
||||||
// This ensures that DeepEqual terminates.
|
|
||||||
func DeepEqual(x, y interface{}) bool {
|
|
||||||
if x == nil || y == nil {
|
|
||||||
return x == y
|
|
||||||
}
|
|
||||||
v1 := ValueOf(x)
|
|
||||||
v2 := ValueOf(y)
|
|
||||||
if v1.typecode != v2.typecode {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return deepValueEqual(v1, v2, make(map[visit]struct{}))
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package reflectlite
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
func Swapper(slice interface{}) func(i, j int) {
|
||||||
|
return reflect.Swapper(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Kind = reflect.Kind
|
||||||
|
type Type = reflect.Type
|
||||||
|
type Value = reflect.Value
|
||||||
|
|
||||||
|
const (
|
||||||
|
Invalid Kind = reflect.Invalid
|
||||||
|
Bool Kind = reflect.Bool
|
||||||
|
Int Kind = reflect.Int
|
||||||
|
Int8 Kind = reflect.Int8
|
||||||
|
Int16 Kind = reflect.Int16
|
||||||
|
Int32 Kind = reflect.Int32
|
||||||
|
Int64 Kind = reflect.Int64
|
||||||
|
Uint Kind = reflect.Uint
|
||||||
|
Uint8 Kind = reflect.Uint8
|
||||||
|
Uint16 Kind = reflect.Uint16
|
||||||
|
Uint32 Kind = reflect.Uint32
|
||||||
|
Uint64 Kind = reflect.Uint64
|
||||||
|
Uintptr Kind = reflect.Uintptr
|
||||||
|
Float32 Kind = reflect.Float32
|
||||||
|
Float64 Kind = reflect.Float64
|
||||||
|
Complex64 Kind = reflect.Complex64
|
||||||
|
Complex128 Kind = reflect.Complex128
|
||||||
|
Array Kind = reflect.Array
|
||||||
|
Chan Kind = reflect.Chan
|
||||||
|
Func Kind = reflect.Func
|
||||||
|
Interface Kind = reflect.Interface
|
||||||
|
Map Kind = reflect.Map
|
||||||
|
Ptr Kind = reflect.Ptr
|
||||||
|
Slice Kind = reflect.Slice
|
||||||
|
String Kind = reflect.String
|
||||||
|
Struct Kind = reflect.Struct
|
||||||
|
UnsafePointer Kind = reflect.UnsafePointer
|
||||||
|
)
|
||||||
|
|
||||||
|
func ValueOf(i interface{}) reflect.Value {
|
||||||
|
return reflect.ValueOf(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TypeOf(i interface{}) reflect.Type {
|
||||||
|
return reflect.TypeOf(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValueError = reflect.ValueError
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package reflectlite
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// Some of code here has been copied from the Go sources:
|
|
||||||
// https://github.com/golang/go/blob/go1.15.2/src/reflect/swapper.go
|
|
||||||
// It has the following copyright note:
|
|
||||||
//
|
|
||||||
// Copyright 2016 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.
|
|
||||||
|
|
||||||
func Swapper(slice interface{}) func(i, j int) {
|
|
||||||
v := ValueOf(slice)
|
|
||||||
if v.Kind() != Slice {
|
|
||||||
panic(&ValueError{Method: "Swapper"})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just return Nop func if nothing to swap.
|
|
||||||
if v.Len() < 2 {
|
|
||||||
return func(i, j int) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
typ := v.typecode.Elem()
|
|
||||||
size := typ.Size()
|
|
||||||
|
|
||||||
header := (*sliceHeader)(v.value)
|
|
||||||
tmp := unsafe.Pointer(&make([]byte, size)[0])
|
|
||||||
|
|
||||||
return func(i, j int) {
|
|
||||||
if uint(i) >= uint(header.len) || uint(j) >= uint(header.len) {
|
|
||||||
panic("reflect: slice index out of range")
|
|
||||||
}
|
|
||||||
val1 := unsafe.Add(header.data, uintptr(i)*size)
|
|
||||||
val2 := unsafe.Add(header.data, uintptr(j)*size)
|
|
||||||
memcpy(tmp, val1, size)
|
|
||||||
memcpy(val1, val2, size)
|
|
||||||
memcpy(val2, tmp, size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,105 +0,0 @@
|
|||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package reflectlite
|
|
||||||
|
|
||||||
// VisibleFields returns all the visible fields in t, which must be a
|
|
||||||
// struct type. A field is defined as visible if it's accessible
|
|
||||||
// directly with a FieldByName call. The returned fields include fields
|
|
||||||
// inside anonymous struct members and unexported fields. They follow
|
|
||||||
// the same order found in the struct, with anonymous fields followed
|
|
||||||
// immediately by their promoted fields.
|
|
||||||
//
|
|
||||||
// For each element e of the returned slice, the corresponding field
|
|
||||||
// can be retrieved from a value v of type t by calling v.FieldByIndex(e.Index).
|
|
||||||
func VisibleFields(t Type) []StructField {
|
|
||||||
if t == nil {
|
|
||||||
panic("reflect: VisibleFields(nil)")
|
|
||||||
}
|
|
||||||
if t.Kind() != Struct {
|
|
||||||
panic("reflect.VisibleFields of non-struct type")
|
|
||||||
}
|
|
||||||
w := &visibleFieldsWalker{
|
|
||||||
byName: make(map[string]int),
|
|
||||||
visiting: make(map[Type]bool),
|
|
||||||
fields: make([]StructField, 0, t.NumField()),
|
|
||||||
index: make([]int, 0, 2),
|
|
||||||
}
|
|
||||||
w.walk(t)
|
|
||||||
// Remove all the fields that have been hidden.
|
|
||||||
// Use an in-place removal that avoids copying in
|
|
||||||
// the common case that there are no hidden fields.
|
|
||||||
j := 0
|
|
||||||
for i := range w.fields {
|
|
||||||
f := &w.fields[i]
|
|
||||||
if f.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i != j {
|
|
||||||
// A field has been removed. We need to shuffle
|
|
||||||
// all the subsequent elements up.
|
|
||||||
w.fields[j] = *f
|
|
||||||
}
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
return w.fields[:j]
|
|
||||||
}
|
|
||||||
|
|
||||||
type visibleFieldsWalker struct {
|
|
||||||
byName map[string]int
|
|
||||||
visiting map[Type]bool
|
|
||||||
fields []StructField
|
|
||||||
index []int
|
|
||||||
}
|
|
||||||
|
|
||||||
// walk walks all the fields in the struct type t, visiting
|
|
||||||
// fields in index preorder and appending them to w.fields
|
|
||||||
// (this maintains the required ordering).
|
|
||||||
// Fields that have been overridden have their
|
|
||||||
// Name field cleared.
|
|
||||||
func (w *visibleFieldsWalker) walk(t Type) {
|
|
||||||
if w.visiting[t] {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.visiting[t] = true
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
w.index = append(w.index, i)
|
|
||||||
add := true
|
|
||||||
if oldIndex, ok := w.byName[f.Name]; ok {
|
|
||||||
old := &w.fields[oldIndex]
|
|
||||||
if len(w.index) == len(old.Index) {
|
|
||||||
// Fields with the same name at the same depth
|
|
||||||
// cancel one another out. Set the field name
|
|
||||||
// to empty to signify that has happened, and
|
|
||||||
// there's no need to add this field.
|
|
||||||
old.Name = ""
|
|
||||||
add = false
|
|
||||||
} else if len(w.index) < len(old.Index) {
|
|
||||||
// The old field loses because it's deeper than the new one.
|
|
||||||
old.Name = ""
|
|
||||||
} else {
|
|
||||||
// The old field wins because it's shallower than the new one.
|
|
||||||
add = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if add {
|
|
||||||
// Copy the index so that it's not overwritten
|
|
||||||
// by the other appends.
|
|
||||||
f.Index = append([]int(nil), w.index...)
|
|
||||||
w.byName[f.Name] = len(w.fields)
|
|
||||||
w.fields = append(w.fields, f)
|
|
||||||
}
|
|
||||||
if f.Anonymous {
|
|
||||||
if f.Type.Kind() == Pointer {
|
|
||||||
f.Type = f.Type.Elem()
|
|
||||||
}
|
|
||||||
if f.Type.Kind() == Struct {
|
|
||||||
w.walk(f.Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.index = w.index[:len(w.index)-1]
|
|
||||||
}
|
|
||||||
delete(w.visiting, t)
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build tinygo.unicore
|
|
||||||
|
|
||||||
package task
|
package task
|
||||||
|
|
||||||
// Atomics implementation for cooperative systems. The atomic types here aren't
|
// Atomics implementation for cooperative systems. The atomic types here aren't
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
//go:build !tinygo.unicore
|
|
||||||
|
|
||||||
package task
|
|
||||||
|
|
||||||
// Atomics implementation for non-cooperative systems (multithreaded, etc).
|
|
||||||
// These atomic types use real atomic instructions.
|
|
||||||
|
|
||||||
import "sync/atomic"
|
|
||||||
|
|
||||||
type (
|
|
||||||
Uintptr = atomic.Uintptr
|
|
||||||
Uint32 = atomic.Uint32
|
|
||||||
Uint64 = atomic.Uint64
|
|
||||||
)
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
//go:build darwin
|
|
||||||
|
|
||||||
package task
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// MacOS uses a pointer so unsafe.Pointer should be fine:
|
|
||||||
//
|
|
||||||
// typedef struct _opaque_pthread_t *__darwin_pthread_t;
|
|
||||||
// typedef __darwin_pthread_t pthread_t;
|
|
||||||
type threadID unsafe.Pointer
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build tinygo.unicore
|
|
||||||
|
|
||||||
package task
|
package task
|
||||||
|
|
||||||
// A futex is a way for userspace to wait with the pointer as the key, and for
|
// A futex is a way for userspace to wait with the pointer as the key, and for
|
||||||
|
|||||||
@@ -1,64 +0,0 @@
|
|||||||
//go:build scheduler.cores
|
|
||||||
|
|
||||||
package task
|
|
||||||
|
|
||||||
import "runtime/interrupt"
|
|
||||||
|
|
||||||
// A futex is a way for userspace to wait with the pointer as the key, and for
|
|
||||||
// another thread to wake one or all waiting threads keyed on the same pointer.
|
|
||||||
//
|
|
||||||
// A futex does not change the underlying value, it only reads it before to prevent
|
|
||||||
// lost wake-ups.
|
|
||||||
type Futex struct {
|
|
||||||
Uint32
|
|
||||||
|
|
||||||
waiters Stack
|
|
||||||
}
|
|
||||||
|
|
||||||
// Atomically check for cmp to still be equal to the futex value and if so, go
|
|
||||||
// to sleep. Return true if we were definitely awoken by a call to Wake or
|
|
||||||
// WakeAll, and false if we can't be sure of that.
|
|
||||||
func (f *Futex) Wait(cmp uint32) (awoken bool) {
|
|
||||||
mask := lockFutex()
|
|
||||||
|
|
||||||
if f.Uint32.Load() != cmp {
|
|
||||||
unlockFutex(mask)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the current goroutine onto the waiter stack.
|
|
||||||
f.waiters.Push(Current())
|
|
||||||
|
|
||||||
unlockFutex(mask)
|
|
||||||
|
|
||||||
// Pause until this task is awoken by Wake/WakeAll.
|
|
||||||
Pause()
|
|
||||||
|
|
||||||
// We were awoken by a call to Wake or WakeAll. There is no chance for
|
|
||||||
// spurious wakeups.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wake a single waiter.
|
|
||||||
func (f *Futex) Wake() {
|
|
||||||
mask := lockFutex()
|
|
||||||
if t := f.waiters.Pop(); t != nil {
|
|
||||||
scheduleTask(t)
|
|
||||||
}
|
|
||||||
unlockFutex(mask)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wake all waiters.
|
|
||||||
func (f *Futex) WakeAll() {
|
|
||||||
mask := lockFutex()
|
|
||||||
for t := f.waiters.Pop(); t != nil; t = f.waiters.Pop() {
|
|
||||||
scheduleTask(t)
|
|
||||||
}
|
|
||||||
unlockFutex(mask)
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname lockFutex runtime.lockFutex
|
|
||||||
func lockFutex() interrupt.State
|
|
||||||
|
|
||||||
//go:linkname unlockFutex runtime.unlockFutex
|
|
||||||
func unlockFutex(interrupt.State)
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
//go:build scheduler.threads
|
|
||||||
|
|
||||||
package task
|
|
||||||
|
|
||||||
import "internal/futex"
|
|
||||||
|
|
||||||
type Futex = futex.Futex
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
//go:build linux && !baremetal
|
|
||||||
|
|
||||||
package task
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// Musl uses a pointer (or unsigned long for C++) so unsafe.Pointer should be
|
|
||||||
// fine.
|
|
||||||
type threadID unsafe.Pointer
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build tinygo.unicore
|
|
||||||
|
|
||||||
package task
|
package task
|
||||||
|
|
||||||
type Mutex struct {
|
type Mutex struct {
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
//go:build !tinygo.unicore
|
|
||||||
|
|
||||||
package task
|
|
||||||
|
|
||||||
// Futex-based mutex.
|
|
||||||
// This is largely based on the paper "Futexes are Tricky" by Ulrich Drepper.
|
|
||||||
// It describes a few ways to implement mutexes using a futex, and how some
|
|
||||||
// seemingly-obvious implementations don't exactly work as intended.
|
|
||||||
// Unfortunately, Go atomic operations work slightly differently so we can't
|
|
||||||
// copy the algorithm verbatim.
|
|
||||||
//
|
|
||||||
// The implementation works like this. The futex can have 3 different values,
|
|
||||||
// depending on the state:
|
|
||||||
//
|
|
||||||
// - 0: the futex is currently unlocked.
|
|
||||||
// - 1: the futex is locked, but is uncontended. There is one special case: if
|
|
||||||
// a contended futex is unlocked, it is set to 0. It is possible for another
|
|
||||||
// thread to lock the futex before the next waiter is woken. But because a
|
|
||||||
// waiter will be woken (if there is one), it will always change to 2
|
|
||||||
// regardless. So this is not a problem.
|
|
||||||
// - 2: the futex is locked, and is contended. At least one thread is trying
|
|
||||||
// to obtain the lock (and is in the contended loop, see below).
|
|
||||||
//
|
|
||||||
// For the paper, see:
|
|
||||||
// https://dept-info.labri.fr/~denis/Enseignement/2008-IR/Articles/01-futex.pdf)
|
|
||||||
|
|
||||||
type Mutex struct {
|
|
||||||
futex Futex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mutex) Lock() {
|
|
||||||
// Fast path: try to take an uncontended lock.
|
|
||||||
if m.futex.CompareAndSwap(0, 1) {
|
|
||||||
// We obtained the mutex.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// The futex is contended, so we enter the contended loop.
|
|
||||||
// If we manage to change the futex from 0 to 2, we managed to take the
|
|
||||||
// lock. Else, we have to wait until a call to Unlock unlocks this mutex.
|
|
||||||
// (Unlock will wake one waiter when it finds the futex is set to 2 when
|
|
||||||
// unlocking).
|
|
||||||
for m.futex.Swap(2) != 0 {
|
|
||||||
// Wait until we get resumed in Unlock.
|
|
||||||
m.futex.Wait(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mutex) Unlock() {
|
|
||||||
if old := m.futex.Swap(0); old == 0 {
|
|
||||||
// Mutex wasn't locked before.
|
|
||||||
panic("sync: unlock of unlocked Mutex")
|
|
||||||
} else if old == 2 {
|
|
||||||
// Mutex was a contended lock, so we need to wake the next waiter.
|
|
||||||
m.futex.Wake()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TryLock tries to lock m and reports whether it succeeded.
|
|
||||||
//
|
|
||||||
// Note that while correct uses of TryLock do exist, they are rare,
|
|
||||||
// and use of TryLock is often a sign of a deeper problem
|
|
||||||
// in a particular use of mutexes.
|
|
||||||
func (m *Mutex) TryLock() bool {
|
|
||||||
// Fast path: try to take an uncontended lock.
|
|
||||||
if m.futex.CompareAndSwap(0, 1) {
|
|
||||||
// We obtained the mutex.
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build tinygo.unicore
|
|
||||||
|
|
||||||
package task
|
package task
|
||||||
|
|
||||||
// PMutex is a real mutex on systems that can be either preemptive or threaded,
|
// PMutex is a real mutex on systems that can be either preemptive or threaded,
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
//go:build !tinygo.unicore
|
|
||||||
|
|
||||||
package task
|
|
||||||
|
|
||||||
// PMutex is a real mutex on systems that can be either preemptive or threaded,
|
|
||||||
// and a dummy lock on other (purely cooperative) systems.
|
|
||||||
//
|
|
||||||
// It is mainly useful for short operations that need a lock when threading may
|
|
||||||
// be involved, but which do not need a lock with a purely cooperative
|
|
||||||
// scheduler.
|
|
||||||
type PMutex = Mutex
|
|
||||||
+17
-30
@@ -12,9 +12,9 @@ type Queue struct {
|
|||||||
|
|
||||||
// Push a task onto the queue.
|
// Push a task onto the queue.
|
||||||
func (q *Queue) Push(t *Task) {
|
func (q *Queue) Push(t *Task) {
|
||||||
mask := lockAtomics()
|
i := interrupt.Disable()
|
||||||
if asserts && t.Next != nil {
|
if asserts && t.Next != nil {
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
panic("runtime: pushing a task to a queue with a non-nil Next pointer")
|
panic("runtime: pushing a task to a queue with a non-nil Next pointer")
|
||||||
}
|
}
|
||||||
if q.tail != nil {
|
if q.tail != nil {
|
||||||
@@ -25,15 +25,15 @@ func (q *Queue) Push(t *Task) {
|
|||||||
if q.head == nil {
|
if q.head == nil {
|
||||||
q.head = t
|
q.head = t
|
||||||
}
|
}
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop a task off of the queue.
|
// Pop a task off of the queue.
|
||||||
func (q *Queue) Pop() *Task {
|
func (q *Queue) Pop() *Task {
|
||||||
mask := lockAtomics()
|
i := interrupt.Disable()
|
||||||
t := q.head
|
t := q.head
|
||||||
if t == nil {
|
if t == nil {
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
q.head = t.Next
|
q.head = t.Next
|
||||||
@@ -41,13 +41,13 @@ func (q *Queue) Pop() *Task {
|
|||||||
q.tail = nil
|
q.tail = nil
|
||||||
}
|
}
|
||||||
t.Next = nil
|
t.Next = nil
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append pops the contents of another queue and pushes them onto the end of this queue.
|
// Append pops the contents of another queue and pushes them onto the end of this queue.
|
||||||
func (q *Queue) Append(other *Queue) {
|
func (q *Queue) Append(other *Queue) {
|
||||||
mask := lockAtomics()
|
i := interrupt.Disable()
|
||||||
if q.head == nil {
|
if q.head == nil {
|
||||||
q.head = other.head
|
q.head = other.head
|
||||||
} else {
|
} else {
|
||||||
@@ -55,14 +55,14 @@ func (q *Queue) Append(other *Queue) {
|
|||||||
}
|
}
|
||||||
q.tail = other.tail
|
q.tail = other.tail
|
||||||
other.head, other.tail = nil, nil
|
other.head, other.tail = nil, nil
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty checks if the queue is empty.
|
// Empty checks if the queue is empty.
|
||||||
func (q *Queue) Empty() bool {
|
func (q *Queue) Empty() bool {
|
||||||
mask := lockAtomics()
|
i := interrupt.Disable()
|
||||||
empty := q.head == nil
|
empty := q.head == nil
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
return empty
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,24 +75,24 @@ type Stack struct {
|
|||||||
|
|
||||||
// Push a task onto the stack.
|
// Push a task onto the stack.
|
||||||
func (s *Stack) Push(t *Task) {
|
func (s *Stack) Push(t *Task) {
|
||||||
mask := lockAtomics()
|
i := interrupt.Disable()
|
||||||
if asserts && t.Next != nil {
|
if asserts && t.Next != nil {
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
panic("runtime: pushing a task to a stack with a non-nil Next pointer")
|
panic("runtime: pushing a task to a stack with a non-nil Next pointer")
|
||||||
}
|
}
|
||||||
s.top, t.Next = t, s.top
|
s.top, t.Next = t, s.top
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop a task off of the stack.
|
// Pop a task off of the stack.
|
||||||
func (s *Stack) Pop() *Task {
|
func (s *Stack) Pop() *Task {
|
||||||
mask := lockAtomics()
|
i := interrupt.Disable()
|
||||||
t := s.top
|
t := s.top
|
||||||
if t != nil {
|
if t != nil {
|
||||||
s.top = t.Next
|
s.top = t.Next
|
||||||
t.Next = nil
|
t.Next = nil
|
||||||
}
|
}
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,26 +112,13 @@ func (t *Task) tail() *Task {
|
|||||||
// Queue moves the contents of the stack into a queue.
|
// Queue moves the contents of the stack into a queue.
|
||||||
// Elements can be popped from the queue in the same order that they would be popped from the stack.
|
// Elements can be popped from the queue in the same order that they would be popped from the stack.
|
||||||
func (s *Stack) Queue() Queue {
|
func (s *Stack) Queue() Queue {
|
||||||
mask := lockAtomics()
|
i := interrupt.Disable()
|
||||||
head := s.top
|
head := s.top
|
||||||
s.top = nil
|
s.top = nil
|
||||||
q := Queue{
|
q := Queue{
|
||||||
head: head,
|
head: head,
|
||||||
tail: head.tail(),
|
tail: head.tail(),
|
||||||
}
|
}
|
||||||
unlockAtomics(mask)
|
interrupt.Restore(i)
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use runtime.lockAtomics and runtime.unlockAtomics so that Queue and Stack
|
|
||||||
// work correctly even on multicore systems. These functions are normally used
|
|
||||||
// to implement atomic operations, but the same spinlock can also be used for
|
|
||||||
// Queue/Stack operations which are very fast.
|
|
||||||
// These functions are just plain old interrupt disable/restore on non-multicore
|
|
||||||
// systems.
|
|
||||||
|
|
||||||
//go:linkname lockAtomics runtime.lockAtomics
|
|
||||||
func lockAtomics() interrupt.State
|
|
||||||
|
|
||||||
//go:linkname unlockAtomics runtime.unlockAtomics
|
|
||||||
func unlockAtomics(mask interrupt.State)
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user