mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-27 15:18:41 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 907d90105a |
+13
-4
@@ -112,17 +112,26 @@ commands:
|
||||
- /go/pkg/mod
|
||||
|
||||
jobs:
|
||||
test-llvm14-go118:
|
||||
test-llvm13-go116:
|
||||
docker:
|
||||
- image: golang:1.18-buster
|
||||
- image: golang:1.16-buster
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "13"
|
||||
test-llvm14-go119:
|
||||
docker:
|
||||
- image: golang:1.19beta1-buster
|
||||
steps:
|
||||
- test-linux:
|
||||
llvm: "14"
|
||||
resource_class: large
|
||||
fmt-check: false
|
||||
|
||||
workflows:
|
||||
test-all:
|
||||
jobs:
|
||||
# This tests our lowest supported versions of Go and LLVM, to make sure at
|
||||
# least the smoke tests still pass.
|
||||
- test-llvm14-go118
|
||||
- test-llvm13-go116
|
||||
# This tests a beta version of Go. It should be removed once regular
|
||||
# release builds are built using this version.
|
||||
- test-llvm14-go119
|
||||
|
||||
@@ -16,6 +16,10 @@ jobs:
|
||||
name: build-macos
|
||||
runs-on: macos-11
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
- name: Install Dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -31,13 +35,8 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-macos-v1
|
||||
@@ -51,7 +50,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-macos-v1
|
||||
@@ -69,7 +68,7 @@ jobs:
|
||||
make llvm-build
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
- name: Cache wasi-libc sysroot
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-v4
|
||||
@@ -101,22 +100,3 @@ jobs:
|
||||
- name: Smoke tests
|
||||
shell: bash
|
||||
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0
|
||||
test-macos-homebrew:
|
||||
name: homebrew-install
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Install LLVM
|
||||
shell: bash
|
||||
run: |
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@14
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
- name: Build TinyGo
|
||||
run: go install
|
||||
- name: Check binary
|
||||
run: tinygo version
|
||||
|
||||
+52
-33
@@ -18,13 +18,14 @@ jobs:
|
||||
# statically linked binary.
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: golang:1.19-alpine
|
||||
image: alpine:3.16
|
||||
steps:
|
||||
- name: Install apk dependencies
|
||||
# tar: needed for actions/cache@v3
|
||||
# tar: needed for actions/cache@v2
|
||||
# git+openssh: needed for checkout (I think?)
|
||||
# gcompat: needed for go binary
|
||||
# ruby: needed to install fpm
|
||||
run: apk add tar git openssh make g++ ruby
|
||||
run: apk add tar git openssh gcompat make g++ ruby
|
||||
- name: Work around CVE-2022-24765
|
||||
# We're not on a multi-user machine, so this is safe.
|
||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
@@ -32,15 +33,19 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
- name: Cache Go
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-alpine-v1
|
||||
@@ -54,7 +59,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-alpine-v1
|
||||
@@ -72,7 +77,7 @@ jobs:
|
||||
# Remove unnecessary object files (to reduce cache size).
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
- name: Cache Binaryen
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-alpine-v1
|
||||
@@ -83,7 +88,7 @@ jobs:
|
||||
apk add cmake samurai python3
|
||||
make binaryen STATIC=1
|
||||
- name: Cache wasi-libc
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-linux-alpine-v1
|
||||
@@ -93,7 +98,6 @@ jobs:
|
||||
run: make wasi-libc
|
||||
- name: Install fpm
|
||||
run: |
|
||||
gem install --version 4.0.7 public_suffix
|
||||
gem install --version 2.7.6 dotenv
|
||||
gem install --no-document fpm
|
||||
- name: Build TinyGo release
|
||||
@@ -116,10 +120,9 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
go-version: '1.18.1'
|
||||
- name: Install wasmtime
|
||||
run: |
|
||||
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||
@@ -169,10 +172,9 @@ jobs:
|
||||
simavr \
|
||||
ninja-build
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
go-version: '1.18.1'
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
@@ -181,8 +183,15 @@ jobs:
|
||||
run: |
|
||||
curl https://wasmtime.dev/install.sh -sSf | bash
|
||||
echo "$HOME/.wasmtime/bin" >> $GITHUB_PATH
|
||||
- name: Cache Go
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
key: go-cache-linux-asserts-v1-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-asserts-v2
|
||||
@@ -196,7 +205,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-asserts-v1
|
||||
@@ -212,7 +221,7 @@ jobs:
|
||||
# Remove unnecessary object files (to reduce cache size).
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
- name: Cache Binaryen
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-asserts-v1
|
||||
@@ -221,7 +230,7 @@ jobs:
|
||||
if: steps.cache-binaryen.outputs.cache-hit != 'true'
|
||||
run: make binaryen
|
||||
- name: Cache wasi-libc
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-linux-asserts-v5
|
||||
@@ -269,12 +278,18 @@ jobs:
|
||||
g++-arm-linux-gnueabihf \
|
||||
libc6-dev-armhf-cross
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
go-version: '1.18.1'
|
||||
- name: Cache Go
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
key: go-cache-linux-arm-v2-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-v2
|
||||
@@ -288,7 +303,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-arm-v1
|
||||
@@ -306,7 +321,7 @@ jobs:
|
||||
# Remove unnecessary object files (to reduce cache size).
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
- name: Cache Binaryen
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-arm-v1
|
||||
@@ -319,7 +334,6 @@ jobs:
|
||||
make CROSS=arm-linux-gnueabihf binaryen
|
||||
- name: Install fpm
|
||||
run: |
|
||||
sudo gem install --version 4.0.7 public_suffix
|
||||
sudo gem install --version 2.7.6 dotenv
|
||||
sudo gem install --no-document fpm
|
||||
- name: Build TinyGo binary
|
||||
@@ -369,12 +383,18 @@ jobs:
|
||||
libc6-dev-arm64-cross \
|
||||
ninja-build
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
go-version: '1.18.1'
|
||||
- name: Cache Go
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
key: go-cache-linux-arm64-v2-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-linux-v1
|
||||
@@ -388,7 +408,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-linux-arm64-v1
|
||||
@@ -404,7 +424,7 @@ jobs:
|
||||
# Remove unnecessary object files (to reduce cache size).
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
- name: Cache Binaryen
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-binaryen
|
||||
with:
|
||||
key: binaryen-linux-arm64-v1
|
||||
@@ -416,7 +436,6 @@ jobs:
|
||||
make CROSS=aarch64-linux-gnu binaryen
|
||||
- name: Install fpm
|
||||
run: |
|
||||
sudo gem install --version 4.0.7 public_suffix
|
||||
sudo gem install --version 2.7.6 dotenv
|
||||
sudo gem install --no-document fpm
|
||||
- name: Build TinyGo binary
|
||||
|
||||
@@ -15,6 +15,10 @@ jobs:
|
||||
build-windows:
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.18.1'
|
||||
- uses: brechtm/setup-scoop@v2
|
||||
with:
|
||||
scoop_update: 'false'
|
||||
@@ -26,13 +30,15 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
- name: Cache Go
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
go-version: '1.19'
|
||||
cache: true
|
||||
key: go-cache-windows-v1-${{ hashFiles('go.mod') }}
|
||||
path: |
|
||||
~/AppData/Local/go-build
|
||||
~/go/pkg/mod
|
||||
- name: Cache LLVM source
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-source
|
||||
with:
|
||||
key: llvm-source-14-windows-v2
|
||||
@@ -46,7 +52,7 @@ jobs:
|
||||
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
|
||||
run: make llvm-source
|
||||
- name: Cache LLVM build
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-llvm-build
|
||||
with:
|
||||
key: llvm-build-14-windows-v2
|
||||
@@ -63,7 +69,7 @@ jobs:
|
||||
# Remove unnecessary object files (to reduce cache size).
|
||||
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
|
||||
- name: Cache wasi-libc sysroot
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
id: cache-wasi-libc
|
||||
with:
|
||||
key: wasi-libc-sysroot-v4
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ tarball. If you want to help with development of TinyGo itself, you should follo
|
||||
LLVM, Clang and LLD are quite light on dependencies, requiring only standard
|
||||
build tools to be built. Go is of course necessary to build TinyGo itself.
|
||||
|
||||
* Go (1.18+)
|
||||
* Go (1.16+)
|
||||
* Standard build tools (gcc/clang)
|
||||
* git
|
||||
* CMake
|
||||
|
||||
@@ -1,58 +1,3 @@
|
||||
0.25.0
|
||||
---
|
||||
|
||||
* **command line**
|
||||
- change to ignore PortReset failures
|
||||
* **compiler**
|
||||
- `compiler`: darwin/arm64 is aarch64, not arm
|
||||
- `compiler`: don't clobber X18 and FP registers on darwin/arm64
|
||||
- `compiler`: fix issue with methods on generic structs
|
||||
- `compiler`: do not try to build generic functions
|
||||
- `compiler`: fix type names for generic named structs
|
||||
- `compiler`: fix multiple defined function issue for generic functions
|
||||
- `compiler`: implement `unsafe.Alignof` and `unsafe.Sizeof` for generic code
|
||||
* **standard library**
|
||||
- `machine`: add DTR and RTS to Serialer interface
|
||||
- `machine`: reorder pin definitions to improve pin list on tinygo.org
|
||||
- `machine/usb`: add support for MIDI
|
||||
- `machine/usb`: adjust buffer alignment (samd21, samd51, nrf52840)
|
||||
- `machine/usb/midi`: add `NoteOn`, `NoteOff`, and `SendCC` methods
|
||||
- `machine/usb/midi`: add definition of MIDI note number
|
||||
- `runtime`: add benchmarks for memhash
|
||||
- `runtime`: add support for printing slices via print/println
|
||||
* **targets**
|
||||
- `avr`: fix some apparent mistake in atmega1280/atmega2560 pin constants
|
||||
- `esp32`: provide hardware pin constants
|
||||
- `esp32`: fix WDT reset on the MCH2022 badge
|
||||
- `esp32`: optimize SPI transmit
|
||||
- `esp32c3`: provide hardware pin constants
|
||||
- `esp8266`: provide hardware pin constants like `GPIO2`
|
||||
- `nrf51`: define and use `P0_xx` constants
|
||||
- `nrf52840`, `samd21`, `samd51`: unify bootloader entry process
|
||||
- `nrf52840`, `samd21`, `samd51`: change usbSetup and sendZlp to public
|
||||
- `nrf52840`, `samd21`, `samd51`: refactor handleStandardSetup and initEndpoint
|
||||
- `nrf52840`, `samd21`, `samd51`: improve usb-device initialization
|
||||
- `nrf52840`, `samd21`, `samd51`: move usbcdc to machine/usb/cdc
|
||||
- `rp2040`: add usb serial vendor/product ID
|
||||
- `rp2040`: add support for usb
|
||||
- `rp2040`: change default for serial to usb
|
||||
- `rp2040`: add support for `machine.EnterBootloader`
|
||||
- `rp2040`: turn off pullup/down when input type is not specified
|
||||
- `rp2040`: make picoprobe default openocd interface
|
||||
- `samd51`: add support for `DAC1`
|
||||
- `samd51`: improve TRNG
|
||||
- `wasm`: stub `runtime.buffered`, `runtime.getchar`
|
||||
- `wasi`: make leveldb runtime hash the default
|
||||
* **boards**
|
||||
- add Challenger RP2040 LoRa
|
||||
- add MCH2022 badge
|
||||
- add XIAO RP2040
|
||||
- `clue`: remove pins `D21`..`D28`
|
||||
- `feather-rp2040`, `macropad-rp2040`: fix qspi-flash settings
|
||||
- `xiao-ble`: add support for flash-1200-bps-reset
|
||||
- `gopherbot`, `gopherbot2`: add these aliases to simplify for newer users
|
||||
|
||||
|
||||
0.24.0
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# tinygo-llvm stage obtains the llvm source for TinyGo
|
||||
FROM golang:1.19 AS tinygo-llvm
|
||||
FROM golang:1.18 AS tinygo-llvm
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y apt-utils make cmake clang-11 binutils-avr gcc-avr avr-libc ninja-build
|
||||
|
||||
@@ -280,6 +280,7 @@ TEST_PACKAGES_FAST = \
|
||||
container/list \
|
||||
container/ring \
|
||||
crypto/des \
|
||||
crypto/elliptic/internal/fiat \
|
||||
crypto/internal/subtle \
|
||||
crypto/md5 \
|
||||
crypto/rc4 \
|
||||
@@ -316,24 +317,13 @@ TEST_PACKAGES_FAST = \
|
||||
unicode \
|
||||
unicode/utf16 \
|
||||
unicode/utf8 \
|
||||
$(nil)
|
||||
|
||||
# Assume this will go away before Go2, so only check minor version.
|
||||
ifeq ($(filter $(shell $(GO) env GOVERSION | cut -f 2 -d.), 16 17 18), )
|
||||
TEST_PACKAGES_FAST += crypto/internal/nistec/fiat
|
||||
else
|
||||
TEST_PACKAGES_FAST += crypto/elliptic/internal/fiat
|
||||
endif
|
||||
|
||||
# archive/zip requires os.ReadAt, which is not yet supported on windows
|
||||
# compress/flate appears to hang on wasi
|
||||
# compress/lzw appears to hang on wasi
|
||||
# crypto/hmac fails on wasi, it exits with a "slice out of range" panic
|
||||
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows
|
||||
# io/ioutil requires os.ReadDir, which is not yet supported on windows or wasi
|
||||
# strconv requires recover() which is not yet supported on wasi
|
||||
# text/template/parse requires recover(), which is not yet supported on wasi
|
||||
# io/fs requires os.ReadDir, which is not yet supported on windows or wasi
|
||||
# testing/fstest requires os.ReadDir, which is not yet supported on windows or wasi
|
||||
# compress/flate fails windows go 1.18, https://github.com/tinygo-org/tinygo/issues/2762
|
||||
# compress/lzw fails windows go 1.18 wasi, https://github.com/tinygo-org/tinygo/issues/2762
|
||||
|
||||
# Additional standard library packages that pass tests on individual platforms
|
||||
TEST_PACKAGES_LINUX := \
|
||||
@@ -343,6 +333,7 @@ TEST_PACKAGES_LINUX := \
|
||||
crypto/hmac \
|
||||
debug/dwarf \
|
||||
debug/plan9obj \
|
||||
io/fs \
|
||||
io/ioutil \
|
||||
strconv \
|
||||
testing/fstest \
|
||||
@@ -351,12 +342,7 @@ TEST_PACKAGES_LINUX := \
|
||||
TEST_PACKAGES_DARWIN := $(TEST_PACKAGES_LINUX)
|
||||
|
||||
TEST_PACKAGES_WINDOWS := \
|
||||
compress/flate \
|
||||
compress/lzw \
|
||||
crypto/hmac \
|
||||
strconv \
|
||||
text/template/parse \
|
||||
$(nil)
|
||||
compress/lzw
|
||||
|
||||
# Report platforms on which each standard library package is known to pass tests
|
||||
jointmp := $(shell echo /tmp/join.$$$$)
|
||||
@@ -371,15 +357,12 @@ report-stdlib-tests-pass:
|
||||
# Standard library packages that pass tests quickly on the current platform
|
||||
ifeq ($(shell uname),Darwin)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_DARWIN)
|
||||
TEST_IOFS := true
|
||||
endif
|
||||
ifeq ($(shell uname),Linux)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_LINUX)
|
||||
TEST_IOFS := true
|
||||
endif
|
||||
ifeq ($(OS),Windows_NT)
|
||||
TEST_PACKAGES_HOST := $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_WINDOWS)
|
||||
TEST_IOFS := false
|
||||
endif
|
||||
|
||||
# Test known-working standard library packages.
|
||||
@@ -387,12 +370,6 @@ endif
|
||||
.PHONY: tinygo-test
|
||||
tinygo-test:
|
||||
$(TINYGO) test $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
|
||||
@# io/fs requires os.ReadDir, not yet supported on windows or wasi. It also
|
||||
@# requires a large stack-size. Hence, io/fs is only run conditionally.
|
||||
@# For more details, see the comments on issue #3143.
|
||||
ifeq ($(TEST_IOFS),true)
|
||||
$(TINYGO) test -stack-size=6MB io/fs
|
||||
endif
|
||||
tinygo-test-fast:
|
||||
$(TINYGO) test $(TEST_PACKAGES_HOST)
|
||||
tinygo-bench:
|
||||
@@ -402,9 +379,9 @@ tinygo-bench-fast:
|
||||
|
||||
# Same thing, except for wasi rather than the current platform.
|
||||
tinygo-test-wasi:
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-test-wasi-fast:
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST) ./tests/runtime_wasi
|
||||
$(TINYGO) test -target wasi $(TEST_PACKAGES_FAST)
|
||||
tinygo-bench-wasi:
|
||||
$(TINYGO) test -target wasi -bench . $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)
|
||||
tinygo-bench-wasi-fast:
|
||||
@@ -426,7 +403,6 @@ tinygo-baremetal:
|
||||
.PHONY: smoketest
|
||||
smoketest:
|
||||
$(TINYGO) version
|
||||
$(TINYGO) targets > /dev/null
|
||||
# regression test for #2892
|
||||
cd tests/testing/recurse && ($(TINYGO) test ./... > recurse.log && cat recurse.log && test $$(wc -l < recurse.log) = 2 && rm recurse.log)
|
||||
# compile-only platform-independent examples
|
||||
@@ -536,8 +512,6 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=feather-m4 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=matrixportal-m4 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=pybadge examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=metro-m4-airlift examples/blinky1
|
||||
@@ -604,22 +578,16 @@ endif
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=qtpy-rp2040 examples/echo
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=macropad-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=badger2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=tufty2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=thingplus-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=xiao-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/temp
|
||||
@$(MD5SUM) test.hex
|
||||
# test pwm
|
||||
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
|
||||
@$(MD5SUM) test.hex
|
||||
@@ -700,16 +668,14 @@ ifneq ($(XTENSA), 0)
|
||||
$(TINYGO) build -size short -o test.bin -target mch2022 examples/serial
|
||||
@$(MD5SUM) test.bin
|
||||
endif
|
||||
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
|
||||
@$(MD5SUM) test.bin
|
||||
$(TINYGO) build -size short -o test.bin -target=esp32c3-12f examples/serial
|
||||
$(TINYGO) build -size short -o test.bin -target=esp32c3 examples/serial
|
||||
@$(MD5SUM) test.bin
|
||||
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
|
||||
@$(MD5SUM) test.bin
|
||||
$(TINYGO) build -size short -o test.bin -target=xiao-esp32c3 examples/serial
|
||||
@$(MD5SUM) test.bin
|
||||
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=hifive1-qemu examples/serial
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
ifneq ($(WASM), 0)
|
||||
@@ -782,7 +748,6 @@ endif
|
||||
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
|
||||
@cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src
|
||||
@cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src
|
||||
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
|
||||
@cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src
|
||||
@cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src
|
||||
@cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src
|
||||
@@ -801,7 +766,6 @@ endif
|
||||
@cp -rp lib/picolibc/newlib/libc/string build/release/tinygo/lib/picolibc/newlib/libc
|
||||
@cp -rp lib/picolibc/newlib/libc/tinystdio build/release/tinygo/lib/picolibc/newlib/libc
|
||||
@cp -rp lib/picolibc/newlib/libm/common build/release/tinygo/lib/picolibc/newlib/libm
|
||||
@cp -rp lib/picolibc/newlib/libm/math build/release/tinygo/lib/picolibc/newlib/libm
|
||||
@cp -rp lib/picolibc-stdio.c build/release/tinygo/lib
|
||||
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
|
||||
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
|
||||
|
||||
@@ -43,7 +43,7 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
|
||||
|
||||
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
|
||||
|
||||
The following 91 microcontroller boards are currently supported:
|
||||
The following 88 microcontroller boards are currently supported:
|
||||
|
||||
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
|
||||
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
|
||||
@@ -66,9 +66,7 @@ The following 91 microcontroller boards are currently supported:
|
||||
* [Adafruit PyGamer](https://www.adafruit.com/product/4242)
|
||||
* [Adafruit PyPortal](https://www.adafruit.com/product/4116)
|
||||
* [Adafruit QT Py](https://www.adafruit.com/product/4600)
|
||||
* [Adafruit QT Py RP2040](https://www.adafruit.com/product/4900)
|
||||
* [Adafruit Trinket M0](https://www.adafruit.com/product/3500)
|
||||
* [Adafruit Trinkey QT2040](https://adafruit.com/product/5056)
|
||||
* [Arduino Mega 1280](https://www.arduino.cc/en/Main/arduinoBoardMega/)
|
||||
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
|
||||
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
|
||||
@@ -110,7 +108,6 @@ The following 91 microcontroller boards are currently supported:
|
||||
* [Particle Xenon](https://docs.particle.io/datasheets/discontinued/xenon-datasheet/)
|
||||
* [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/)
|
||||
* [Pimoroni Badger2040](https://shop.pimoroni.com/products/badger-2040)
|
||||
* [Pimoroni Tufty2040](https://shop.pimoroni.com/products/tufty-2040)
|
||||
* [PineTime DevKit](https://www.pine64.org/pinetime/)
|
||||
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
|
||||
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
|
||||
@@ -120,12 +117,11 @@ The following 91 microcontroller boards are currently supported:
|
||||
* [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199)
|
||||
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
|
||||
* [Seeed XIAO BLE](https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html)
|
||||
* [Seeed XIAO ESP32C3](https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html)
|
||||
* [Seeed XIAO RP2040](https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html)
|
||||
* [Seeed LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html)
|
||||
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
|
||||
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
|
||||
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1-rev-b)
|
||||
* [SiFIve HiFive1 Rev B](https://www.sifive.com/boards/hifive1)
|
||||
* [Sparkfun Thing Plus RP2040](https://www.sparkfun.com/products/17745)
|
||||
* [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
|
||||
* [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import (
|
||||
// makeArchive creates an arcive for static linking from a list of object files
|
||||
// given as a parameter. It is equivalent to the following command:
|
||||
//
|
||||
// ar -rcs <archivePath> <objs...>
|
||||
// ar -rcs <archivePath> <objs...>
|
||||
func makeArchive(arfile *os.File, objs []string) error {
|
||||
// Open the archive file.
|
||||
arwriter := ar.NewWriter(arfile)
|
||||
|
||||
+29
-19
@@ -14,7 +14,7 @@ import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"hash/crc32"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"math/bits"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -103,7 +103,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
}
|
||||
|
||||
// Create a temporary directory for intermediary files.
|
||||
dir, err := os.MkdirTemp("", "tinygo")
|
||||
dir, err := ioutil.TempDir("", "tinygo")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -148,7 +148,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
libcDependencies = append(libcDependencies, libcJob)
|
||||
case "wasi-libc":
|
||||
path := filepath.Join(root, "lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a")
|
||||
if _, err := os.Stat(path); errors.Is(err, fs.ErrNotExist) {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?")
|
||||
}
|
||||
libcDependencies = append(libcDependencies, dummyCompileJob(path))
|
||||
@@ -178,7 +178,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
|
||||
Scheduler: config.Scheduler(),
|
||||
AutomaticStackSize: config.AutomaticStackSize(),
|
||||
DefaultStackSize: config.StackSize(),
|
||||
DefaultStackSize: config.Target.DefaultStackSize,
|
||||
NeedsStackObjects: config.NeedsStackObjects(),
|
||||
Debug: true,
|
||||
}
|
||||
@@ -370,7 +370,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
// Packages are compiled independently anyway.
|
||||
for _, cgoHeader := range pkg.CGoHeaders {
|
||||
// Store the header text in a temporary file.
|
||||
f, err := os.CreateTemp(dir, "cgosnippet-*.c")
|
||||
f, err := ioutil.TempFile(dir, "cgosnippet-*.c")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -431,7 +431,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
if pkgInit.IsNil() {
|
||||
panic("init not found for " + pkg.Pkg.Path())
|
||||
}
|
||||
err := interp.RunFunc(pkgInit, config.Options.InterpTimeout, config.DumpSSA())
|
||||
err := interp.RunFunc(pkgInit, config.DumpSSA())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -445,7 +445,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
// Write to a temporary path that is renamed to the destination
|
||||
// file to avoid race conditions with other TinyGo invocatiosn
|
||||
// that might also be compiling this package at the same time.
|
||||
f, err := os.CreateTemp(filepath.Dir(job.result), filepath.Base(job.result))
|
||||
f, err := ioutil.TempFile(filepath.Dir(job.result), filepath.Base(job.result))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -589,7 +589,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
return err
|
||||
}
|
||||
defer llvmBuf.Dispose()
|
||||
return os.WriteFile(outpath, llvmBuf.Bytes(), 0666)
|
||||
return ioutil.WriteFile(outpath, llvmBuf.Bytes(), 0666)
|
||||
case ".bc":
|
||||
var buf llvm.MemoryBuffer
|
||||
if config.UseThinLTO() {
|
||||
@@ -598,10 +598,10 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
buf = llvm.WriteBitcodeToMemoryBuffer(mod)
|
||||
}
|
||||
defer buf.Dispose()
|
||||
return os.WriteFile(outpath, buf.Bytes(), 0666)
|
||||
return ioutil.WriteFile(outpath, buf.Bytes(), 0666)
|
||||
case ".ll":
|
||||
data := []byte(mod.String())
|
||||
return os.WriteFile(outpath, data, 0666)
|
||||
return ioutil.WriteFile(outpath, data, 0666)
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
@@ -629,7 +629,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
|
||||
}
|
||||
}
|
||||
defer llvmBuf.Dispose()
|
||||
return os.WriteFile(objfile, llvmBuf.Bytes(), 0666)
|
||||
return ioutil.WriteFile(objfile, llvmBuf.Bytes(), 0666)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1055,7 +1055,7 @@ func createEmbedObjectFile(data, hexSum, sourceFile, sourceDir, tmpdir string, c
|
||||
// needed to convert a program to its final form. Some transformations are not
|
||||
// optional and must be run as the compiler expects them to run.
|
||||
func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
|
||||
err := interp.Run(mod, config.Options.InterpTimeout, config.DumpSSA())
|
||||
err := interp.Run(mod, config.DumpSSA())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1228,10 +1228,15 @@ func determineStackSizes(mod llvm.Module, executable string) ([]string, map[stri
|
||||
// Goroutines need to be started and finished and take up some stack space
|
||||
// that way. This can be measured by measuing the stack size of
|
||||
// tinygo_startTask.
|
||||
if numFuncs := len(functions["tinygo_startTask"]); numFuncs != 1 {
|
||||
return nil, nil, fmt.Errorf("expected exactly one definition of tinygo_startTask, got %d", numFuncs)
|
||||
var baseStackSize uint64
|
||||
var baseStackSizeType stacksize.SizeType
|
||||
var baseStackSizeFailedAt *stacksize.CallNode
|
||||
if len(gowrappers) != 0 {
|
||||
if numFuncs := len(functions["tinygo_startTask"]); numFuncs != 1 {
|
||||
return nil, nil, fmt.Errorf("expected exactly one definition of tinygo_startTask, got %d", numFuncs)
|
||||
}
|
||||
baseStackSize, baseStackSizeType, baseStackSizeFailedAt = functions["tinygo_startTask"][0].StackSize()
|
||||
}
|
||||
baseStackSize, baseStackSizeType, baseStackSizeFailedAt := functions["tinygo_startTask"][0].StackSize()
|
||||
|
||||
sizes := make(map[string]functionStackSize)
|
||||
|
||||
@@ -1303,6 +1308,11 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if data == nil {
|
||||
// The .tinygo_stacksizes section doesn't exist, so assume this
|
||||
// modification isn't needed.
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(stackSizeLoads)*4 != len(data) {
|
||||
// Note: while AVR should use 2 byte stack sizes, even 64-bit platforms
|
||||
@@ -1367,10 +1377,10 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
|
||||
//
|
||||
// It might print something like the following:
|
||||
//
|
||||
// function stack usage (in bytes)
|
||||
// Reset_Handler 316
|
||||
// examples/blinky2.led1 92
|
||||
// runtime.run$1 300
|
||||
// function stack usage (in bytes)
|
||||
// Reset_Handler 316
|
||||
// examples/blinky2.led1 92
|
||||
// runtime.run$1 300
|
||||
func printStacks(calculatedStacks []string, stackSizes map[string]functionStackSize) {
|
||||
// Print the sizes of all stacks.
|
||||
fmt.Printf("%-32s %s\n", "function", "stack usage (in bytes)")
|
||||
|
||||
@@ -2,6 +2,7 @@ package builder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -89,7 +90,7 @@ func testClangAttributes(t *testing.T, options *compileopts.Options) {
|
||||
|
||||
// Create a very simple C input file.
|
||||
srcpath := filepath.Join(testDir, "test.c")
|
||||
err = os.WriteFile(srcpath, []byte("int add(int a, int b) { return a + b; }"), 0o666)
|
||||
err = ioutil.WriteFile(srcpath, []byte("int add(int a, int b) { return a + b; }"), 0o666)
|
||||
if err != nil {
|
||||
t.Fatalf("could not write target file %s: %s", srcpath, err)
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ func ReadBuildID() ([]byte, error) {
|
||||
defer f.Close()
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "linux", "freebsd", "android":
|
||||
case "linux", "freebsd":
|
||||
// Read the GNU build id section. (Not sure about FreeBSD though...)
|
||||
file, err := elf.NewFile(f)
|
||||
if err != nil {
|
||||
|
||||
+36
-37
@@ -10,7 +10,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
@@ -33,29 +33,29 @@ import (
|
||||
// Because of this complexity, every file has in fact two cached build outputs:
|
||||
// the file itself, and the list of dependencies. Its operation is as follows:
|
||||
//
|
||||
// depfile = hash(path, compiler, cflags, ...)
|
||||
// if depfile exists:
|
||||
// outfile = hash of all files and depfile name
|
||||
// if outfile exists:
|
||||
// # cache hit
|
||||
// return outfile
|
||||
// # cache miss
|
||||
// tmpfile = compile file
|
||||
// read dependencies (side effect of compile)
|
||||
// write depfile
|
||||
// outfile = hash of all files and depfile name
|
||||
// rename tmpfile to outfile
|
||||
// depfile = hash(path, compiler, cflags, ...)
|
||||
// if depfile exists:
|
||||
// outfile = hash of all files and depfile name
|
||||
// if outfile exists:
|
||||
// # cache hit
|
||||
// return outfile
|
||||
// # cache miss
|
||||
// tmpfile = compile file
|
||||
// read dependencies (side effect of compile)
|
||||
// write depfile
|
||||
// outfile = hash of all files and depfile name
|
||||
// rename tmpfile to outfile
|
||||
//
|
||||
// There are a few edge cases that are not handled:
|
||||
// - If a file is added to an include path, that file may be included instead of
|
||||
// some other file. This would be fixed by also including lookup failures in the
|
||||
// dependencies file, but I'm not aware of a compiler which does that.
|
||||
// - The Makefile syntax that compilers output has issues, see readDepFile for
|
||||
// details.
|
||||
// - A header file may be changed to add/remove an include. This invalidates the
|
||||
// depfile but without invalidating its name. For this reason, the depfile is
|
||||
// written on each new compilation (even when it seems unnecessary). However, it
|
||||
// could in rare cases lead to a stale file fetched from the cache.
|
||||
// - If a file is added to an include path, that file may be included instead of
|
||||
// some other file. This would be fixed by also including lookup failures in the
|
||||
// dependencies file, but I'm not aware of a compiler which does that.
|
||||
// - The Makefile syntax that compilers output has issues, see readDepFile for
|
||||
// details.
|
||||
// - A header file may be changed to add/remove an include. This invalidates the
|
||||
// depfile but without invalidating its name. For this reason, the depfile is
|
||||
// written on each new compilation (even when it seems unnecessary). However, it
|
||||
// could in rare cases lead to a stale file fetched from the cache.
|
||||
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool, printCommands func(string, ...string)) (string, error) {
|
||||
// Hash input file.
|
||||
fileHash, err := hashFile(abspath)
|
||||
@@ -93,7 +93,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||
// Load dependencies file, if possible.
|
||||
depfileName := "dep-" + depfileNameHash + ".json"
|
||||
depfileCachePath := filepath.Join(goenv.Get("GOCACHE"), depfileName)
|
||||
depfileBuf, err := os.ReadFile(depfileCachePath)
|
||||
depfileBuf, err := ioutil.ReadFile(depfileCachePath)
|
||||
var dependencies []string // sorted list of dependency paths
|
||||
if err == nil {
|
||||
// There is a dependency file, that's great!
|
||||
@@ -108,21 +108,21 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||
if err == nil {
|
||||
if _, err := os.Stat(outpath); err == nil {
|
||||
return outpath, nil
|
||||
} else if !errors.Is(err, fs.ErrNotExist) {
|
||||
} else if !os.IsNotExist(err) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
} else if !errors.Is(err, fs.ErrNotExist) {
|
||||
} else if !os.IsNotExist(err) {
|
||||
// expected either nil or IsNotExist
|
||||
return "", err
|
||||
}
|
||||
|
||||
objTmpFile, err := os.CreateTemp(goenv.Get("GOCACHE"), "tmp-*"+ext)
|
||||
objTmpFile, err := ioutil.TempFile(goenv.Get("GOCACHE"), "tmp-*"+ext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
objTmpFile.Close()
|
||||
depTmpFile, err := os.CreateTemp(tmpdir, "dep-*.d")
|
||||
depTmpFile, err := ioutil.TempFile(tmpdir, "dep-*.d")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -166,7 +166,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
|
||||
sort.Strings(dependencySlice)
|
||||
|
||||
// Write dependencies file.
|
||||
f, err := os.CreateTemp(filepath.Dir(depfileCachePath), depfileName)
|
||||
f, err := ioutil.TempFile(filepath.Dir(depfileCachePath), depfileName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -252,14 +252,13 @@ func hashFile(path string) (string, error) {
|
||||
// file is assumed to have a single target named deps.
|
||||
//
|
||||
// There are roughly three make syntax variants:
|
||||
// - BSD make, which doesn't support any escaping. This means that many special
|
||||
// characters are not supported in file names.
|
||||
// - GNU make, which supports escaping using a backslash but when it fails to
|
||||
// find a file it tries to fall back with the literal path name (to match BSD
|
||||
// make).
|
||||
// - NMake (Visual Studio) and Jom, which simply quote the string if there are
|
||||
// any weird characters.
|
||||
//
|
||||
// - BSD make, which doesn't support any escaping. This means that many special
|
||||
// characters are not supported in file names.
|
||||
// - GNU make, which supports escaping using a backslash but when it fails to
|
||||
// find a file it tries to fall back with the literal path name (to match BSD
|
||||
// make).
|
||||
// - NMake (Visual Studio) and Jom, which simply quote the string if there are
|
||||
// any weird characters.
|
||||
// Clang supports two variants: a format that's a compromise between BSD and GNU
|
||||
// make (and is buggy to match GCC which is equally buggy), and NMake/Jom, which
|
||||
// is at least somewhat sane. This last format isn't perfect either: it does not
|
||||
@@ -267,7 +266,7 @@ func hashFile(path string) (string, error) {
|
||||
// allowed on Windows, but of course can be used on POSIX like systems. Still,
|
||||
// it's the most sane of any of the formats so readDepFile will use that format.
|
||||
func readDepFile(filename string) ([]string, error) {
|
||||
buf, err := os.ReadFile(filename)
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+2
-2
@@ -33,8 +33,8 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
|
||||
}
|
||||
if major != 1 || minor < 18 || minor > 19 {
|
||||
return nil, fmt.Errorf("requires go version 1.18 through 1.19, got go%d.%d", major, minor)
|
||||
if major != 1 || minor < 16 || minor > 19 {
|
||||
return nil, fmt.Errorf("requires go version 1.16 through 1.19, got go%d.%d", major, minor)
|
||||
}
|
||||
|
||||
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ func getElfSectionData(executable string, sectionName string) ([]byte, elf.FileH
|
||||
|
||||
section := elfFile.Section(sectionName)
|
||||
if section == nil {
|
||||
return nil, elf.FileHeader{}, fmt.Errorf("could not find %s section", sectionName)
|
||||
return nil, elf.FileHeader{}, nil
|
||||
}
|
||||
|
||||
data, err := section.Data()
|
||||
|
||||
+2
-4
@@ -1,8 +1,6 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -19,13 +17,13 @@ import (
|
||||
func getClangHeaderPath(TINYGOROOT string) string {
|
||||
// Check whether we're running from the source directory.
|
||||
path := filepath.Join(TINYGOROOT, "llvm-project", "clang", "lib", "Headers")
|
||||
if _, err := os.Stat(path); !errors.Is(err, fs.ErrNotExist) {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
return path
|
||||
}
|
||||
|
||||
// Check whether we're running from the installation directory.
|
||||
path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
|
||||
if _, err := os.Stat(path); !errors.Is(err, fs.ErrNotExist) {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
return path
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ import (
|
||||
"debug/elf"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
@@ -189,5 +189,5 @@ func makeESPFirmareImage(infile, outfile, format string) error {
|
||||
}
|
||||
|
||||
// Write the image to the output file.
|
||||
return os.WriteFile(outfile, outf.Bytes(), 0666)
|
||||
return ioutil.WriteFile(outfile, outf.Bytes(), 0666)
|
||||
}
|
||||
|
||||
+7
-12
@@ -1,8 +1,7 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -95,7 +94,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
target := config.Triple()
|
||||
if l.makeHeaders != nil {
|
||||
if _, err = os.Stat(headerPath); err != nil {
|
||||
temporaryHeaderPath, err := os.MkdirTemp(outdir, "include.tmp*")
|
||||
temporaryHeaderPath, err := ioutil.TempDir(outdir, "include.tmp*")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -111,10 +110,10 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
err = os.Rename(temporaryHeaderPath, headerPath)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, fs.ErrExist):
|
||||
case os.IsExist(err):
|
||||
// Another invocation of TinyGo also seems to have already created the headers.
|
||||
|
||||
case runtime.GOOS == "windows" && errors.Is(err, fs.ErrPermission):
|
||||
case runtime.GOOS == "windows" && os.IsPermission(err):
|
||||
// On Windows, a rename with a destination directory that already
|
||||
// exists does not result in an IsExist error, but rather in an
|
||||
// access denied error. To be sure, check for this case by checking
|
||||
@@ -156,11 +155,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
|
||||
if strings.Split(target, "-")[2] == "linux" {
|
||||
args = append(args, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||
} else {
|
||||
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||
}
|
||||
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
|
||||
}
|
||||
if strings.HasPrefix(target, "avr") {
|
||||
// AVR defaults to C float and double both being 32-bit. This deviates
|
||||
@@ -194,7 +189,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
defer once.Do(unlock)
|
||||
|
||||
// Create an archive of all object files.
|
||||
f, err := os.CreateTemp(outdir, "libc.a.tmp*")
|
||||
f, err := ioutil.TempFile(outdir, "libc.a.tmp*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -255,7 +250,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
|
||||
run: func(*compileJob) error {
|
||||
var compileArgs []string
|
||||
compileArgs = append(compileArgs, args...)
|
||||
tmpfile, err := os.CreateTemp(outdir, "crt1.o.tmp*")
|
||||
tmpfile, err := ioutil.TempFile(outdir, "crt1.o.tmp*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func makeMinGWExtraLibs(tmpdir string) []*compileJob {
|
||||
// .in files need to be preprocessed by a preprocessor (-E)
|
||||
// first.
|
||||
defpath = outpath + ".def"
|
||||
err := runCCompiler("-E", "-x", "c", "-Wp,-w", "-P", "-DDEF_X64", "-DDATA", "-o", defpath, inpath, "-I"+goenv.Get("TINYGOROOT")+"/lib/mingw-w64/mingw-w64-crt/def-include/")
|
||||
err := runCCompiler("-E", "-x", "c", "-Wp,-w", "-P", "-DDEF_X64", "-o", defpath, inpath, "-I"+goenv.Get("TINYGOROOT")+"/lib/mingw-w64/mingw-w64-crt/def-include/")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+3
-4
@@ -3,6 +3,7 @@ package builder
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@@ -34,7 +35,7 @@ var Musl = Library{
|
||||
filepath.Join(muslDir, "include", "alltypes.h.in"),
|
||||
}
|
||||
for _, infile := range infiles {
|
||||
data, err := os.ReadFile(infile)
|
||||
data, err := ioutil.ReadFile(infile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -62,7 +63,7 @@ var Musl = Library{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := os.ReadFile(filepath.Join(muslDir, "arch", arch, "bits", "syscall.h.in"))
|
||||
data, err := ioutil.ReadFile(filepath.Join(muslDir, "arch", arch, "bits", "syscall.h.in"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -89,7 +90,6 @@ var Musl = Library{
|
||||
"-Wno-shift-op-parentheses",
|
||||
"-Wno-ignored-attributes",
|
||||
"-Wno-string-plus-int",
|
||||
"-Wno-ignored-pragmas",
|
||||
"-Qunused-arguments",
|
||||
// Select include dirs. Don't include standard library includes
|
||||
// (that would introduce host dependencies and other complications),
|
||||
@@ -118,7 +118,6 @@ var Musl = Library{
|
||||
"legacy/*.c",
|
||||
"malloc/*.c",
|
||||
"mman/*.c",
|
||||
"math/*.c",
|
||||
"signal/*.c",
|
||||
"stdio/*.c",
|
||||
"string/*.c",
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ package builder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
@@ -18,7 +18,7 @@ func makeDFUFirmwareImage(options *compileopts.Options, infile, outfile string)
|
||||
}
|
||||
|
||||
cmd := exec.Command(cmdLine[0], cmdLine[1:]...)
|
||||
cmd.Stdout = io.Discard
|
||||
cmd.Stdout = ioutil.Discard
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not run nrfutil pkg generate: %w", err)
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ package builder
|
||||
|
||||
import (
|
||||
"debug/elf"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
@@ -87,7 +87,7 @@ func extractROM(path string) (uint64, []byte, error) {
|
||||
// Pad the difference
|
||||
rom = append(rom, make([]byte, diff)...)
|
||||
}
|
||||
data, err := io.ReadAll(prog.Open())
|
||||
data, err := ioutil.ReadAll(prog.Open())
|
||||
if err != nil {
|
||||
return 0, nil, objcopyError{"failed to extract segment from ELF file: " + path, err}
|
||||
}
|
||||
|
||||
+204
-380
@@ -19,7 +19,7 @@ var Picolibc = Library{
|
||||
return f.Close()
|
||||
},
|
||||
cflags: func(target, headerPath string) []string {
|
||||
newlibDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib")
|
||||
picolibcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc")
|
||||
return []string{
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
@@ -27,395 +27,219 @@ var Picolibc = Library{
|
||||
"-D_COMPILING_NEWLIB",
|
||||
"-DHAVE_ALIAS_ATTRIBUTE",
|
||||
"-DTINY_STDIO",
|
||||
"-D_IEEE_LIBM",
|
||||
"-D__OBSOLETE_MATH_FLOAT=1", // use old math code that doesn't expect a FPU
|
||||
"-D__OBSOLETE_MATH_DOUBLE=0",
|
||||
"-nostdlibinc",
|
||||
"-isystem", newlibDir + "/libc/include",
|
||||
"-I" + newlibDir + "/libc/tinystdio",
|
||||
"-I" + newlibDir + "/libm/common",
|
||||
"-isystem", picolibcDir + "/include",
|
||||
"-I" + picolibcDir + "/tinystdio",
|
||||
"-I" + headerPath,
|
||||
}
|
||||
},
|
||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib") },
|
||||
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc") },
|
||||
librarySources: func(target string) []string {
|
||||
return picolibcSources
|
||||
},
|
||||
}
|
||||
|
||||
var picolibcSources = []string{
|
||||
"../../picolibc-stdio.c",
|
||||
"../../../picolibc-stdio.c",
|
||||
|
||||
"libc/tinystdio/asprintf.c",
|
||||
"libc/tinystdio/atod_engine.c",
|
||||
"libc/tinystdio/atod_ryu.c",
|
||||
"libc/tinystdio/atof_engine.c",
|
||||
"libc/tinystdio/atof_ryu.c",
|
||||
//"libc/tinystdio/atold_engine.c", // have_long_double and not long_double_equals_double
|
||||
"libc/tinystdio/clearerr.c",
|
||||
"libc/tinystdio/compare_exchange.c",
|
||||
"libc/tinystdio/dtoa_data.c",
|
||||
"libc/tinystdio/dtoa_engine.c",
|
||||
"libc/tinystdio/dtoa_ryu.c",
|
||||
"libc/tinystdio/ecvtbuf.c",
|
||||
"libc/tinystdio/ecvt.c",
|
||||
"libc/tinystdio/ecvt_data.c",
|
||||
"libc/tinystdio/ecvtfbuf.c",
|
||||
"libc/tinystdio/ecvtf.c",
|
||||
"libc/tinystdio/ecvtf_data.c",
|
||||
"libc/tinystdio/exchange.c",
|
||||
//"libc/tinystdio/fclose.c", // posix-io
|
||||
"libc/tinystdio/fcvtbuf.c",
|
||||
"libc/tinystdio/fcvt.c",
|
||||
"libc/tinystdio/fcvtfbuf.c",
|
||||
"libc/tinystdio/fcvtf.c",
|
||||
"libc/tinystdio/fdevopen.c",
|
||||
//"libc/tinystdio/fdopen.c", // posix-io
|
||||
"libc/tinystdio/feof.c",
|
||||
"libc/tinystdio/ferror.c",
|
||||
"libc/tinystdio/fflush.c",
|
||||
"libc/tinystdio/fgetc.c",
|
||||
"libc/tinystdio/fgets.c",
|
||||
"libc/tinystdio/fileno.c",
|
||||
"libc/tinystdio/filestrget.c",
|
||||
"libc/tinystdio/filestrputalloc.c",
|
||||
"libc/tinystdio/filestrput.c",
|
||||
//"libc/tinystdio/fopen.c", // posix-io
|
||||
"libc/tinystdio/fprintf.c",
|
||||
"libc/tinystdio/fputc.c",
|
||||
"libc/tinystdio/fputs.c",
|
||||
"libc/tinystdio/fread.c",
|
||||
"libc/tinystdio/fscanf.c",
|
||||
"libc/tinystdio/fseek.c",
|
||||
"libc/tinystdio/ftell.c",
|
||||
"libc/tinystdio/ftoa_data.c",
|
||||
"libc/tinystdio/ftoa_engine.c",
|
||||
"libc/tinystdio/ftoa_ryu.c",
|
||||
"libc/tinystdio/fwrite.c",
|
||||
"libc/tinystdio/gcvtbuf.c",
|
||||
"libc/tinystdio/gcvt.c",
|
||||
"libc/tinystdio/gcvtfbuf.c",
|
||||
"libc/tinystdio/gcvtf.c",
|
||||
"libc/tinystdio/getchar.c",
|
||||
"libc/tinystdio/gets.c",
|
||||
"libc/tinystdio/matchcaseprefix.c",
|
||||
"libc/tinystdio/perror.c",
|
||||
//"libc/tinystdio/posixiob.c", // posix-io
|
||||
//"libc/tinystdio/posixio.c", // posix-io
|
||||
"libc/tinystdio/printf.c",
|
||||
"libc/tinystdio/putchar.c",
|
||||
"libc/tinystdio/puts.c",
|
||||
"libc/tinystdio/ryu_divpow2.c",
|
||||
"libc/tinystdio/ryu_log10.c",
|
||||
"libc/tinystdio/ryu_log2pow5.c",
|
||||
"libc/tinystdio/ryu_pow5bits.c",
|
||||
"libc/tinystdio/ryu_table.c",
|
||||
"libc/tinystdio/ryu_umul128.c",
|
||||
"libc/tinystdio/scanf.c",
|
||||
"libc/tinystdio/setbuf.c",
|
||||
"libc/tinystdio/setvbuf.c",
|
||||
//"libc/tinystdio/sflags.c", // posix-io
|
||||
"libc/tinystdio/snprintf.c",
|
||||
"libc/tinystdio/snprintfd.c",
|
||||
"libc/tinystdio/snprintff.c",
|
||||
"libc/tinystdio/sprintf.c",
|
||||
"libc/tinystdio/sprintfd.c",
|
||||
"libc/tinystdio/sprintff.c",
|
||||
"libc/tinystdio/sscanf.c",
|
||||
"libc/tinystdio/strfromd.c",
|
||||
"libc/tinystdio/strfromf.c",
|
||||
"libc/tinystdio/strtod.c",
|
||||
"libc/tinystdio/strtod_l.c",
|
||||
"libc/tinystdio/strtof.c",
|
||||
//"libc/tinystdio/strtold.c", // have_long_double and not long_double_equals_double
|
||||
//"libc/tinystdio/strtold_l.c", // have_long_double and not long_double_equals_double
|
||||
"libc/tinystdio/ungetc.c",
|
||||
"libc/tinystdio/vasprintf.c",
|
||||
"libc/tinystdio/vfiprintf.c",
|
||||
"libc/tinystdio/vfiscanf.c",
|
||||
"libc/tinystdio/vfprintf.c",
|
||||
"libc/tinystdio/vfprintff.c",
|
||||
"libc/tinystdio/vfscanf.c",
|
||||
"libc/tinystdio/vfscanff.c",
|
||||
"libc/tinystdio/vprintf.c",
|
||||
"libc/tinystdio/vscanf.c",
|
||||
"libc/tinystdio/vsnprintf.c",
|
||||
"libc/tinystdio/vsprintf.c",
|
||||
"libc/tinystdio/vsscanf.c",
|
||||
"tinystdio/asprintf.c",
|
||||
"tinystdio/atod_engine.c",
|
||||
"tinystdio/atod_ryu.c",
|
||||
"tinystdio/atof_engine.c",
|
||||
"tinystdio/atof_ryu.c",
|
||||
//"tinystdio/atold_engine.c", // have_long_double and not long_double_equals_double
|
||||
"tinystdio/clearerr.c",
|
||||
"tinystdio/compare_exchange.c",
|
||||
"tinystdio/dtoa_data.c",
|
||||
"tinystdio/dtoa_engine.c",
|
||||
"tinystdio/dtoa_ryu.c",
|
||||
"tinystdio/ecvtbuf.c",
|
||||
"tinystdio/ecvt.c",
|
||||
"tinystdio/ecvt_data.c",
|
||||
"tinystdio/ecvtfbuf.c",
|
||||
"tinystdio/ecvtf.c",
|
||||
"tinystdio/ecvtf_data.c",
|
||||
"tinystdio/exchange.c",
|
||||
//"tinystdio/fclose.c", // posix-io
|
||||
"tinystdio/fcvtbuf.c",
|
||||
"tinystdio/fcvt.c",
|
||||
"tinystdio/fcvtfbuf.c",
|
||||
"tinystdio/fcvtf.c",
|
||||
"tinystdio/fdevopen.c",
|
||||
//"tinystdio/fdopen.c", // posix-io
|
||||
"tinystdio/feof.c",
|
||||
"tinystdio/ferror.c",
|
||||
"tinystdio/fflush.c",
|
||||
"tinystdio/fgetc.c",
|
||||
"tinystdio/fgets.c",
|
||||
"tinystdio/fileno.c",
|
||||
"tinystdio/filestrget.c",
|
||||
"tinystdio/filestrputalloc.c",
|
||||
"tinystdio/filestrput.c",
|
||||
//"tinystdio/fopen.c", // posix-io
|
||||
"tinystdio/fprintf.c",
|
||||
"tinystdio/fputc.c",
|
||||
"tinystdio/fputs.c",
|
||||
"tinystdio/fread.c",
|
||||
"tinystdio/fscanf.c",
|
||||
"tinystdio/fseek.c",
|
||||
"tinystdio/ftell.c",
|
||||
"tinystdio/ftoa_data.c",
|
||||
"tinystdio/ftoa_engine.c",
|
||||
"tinystdio/ftoa_ryu.c",
|
||||
"tinystdio/fwrite.c",
|
||||
"tinystdio/gcvtbuf.c",
|
||||
"tinystdio/gcvt.c",
|
||||
"tinystdio/gcvtfbuf.c",
|
||||
"tinystdio/gcvtf.c",
|
||||
"tinystdio/getchar.c",
|
||||
"tinystdio/gets.c",
|
||||
"tinystdio/matchcaseprefix.c",
|
||||
"tinystdio/perror.c",
|
||||
//"tinystdio/posixiob.c", // posix-io
|
||||
//"tinystdio/posixio.c", // posix-io
|
||||
"tinystdio/printf.c",
|
||||
"tinystdio/putchar.c",
|
||||
"tinystdio/puts.c",
|
||||
"tinystdio/ryu_divpow2.c",
|
||||
"tinystdio/ryu_log10.c",
|
||||
"tinystdio/ryu_log2pow5.c",
|
||||
"tinystdio/ryu_pow5bits.c",
|
||||
"tinystdio/ryu_table.c",
|
||||
"tinystdio/ryu_umul128.c",
|
||||
"tinystdio/scanf.c",
|
||||
"tinystdio/setbuf.c",
|
||||
"tinystdio/setvbuf.c",
|
||||
//"tinystdio/sflags.c", // posix-io
|
||||
"tinystdio/snprintf.c",
|
||||
"tinystdio/snprintfd.c",
|
||||
"tinystdio/snprintff.c",
|
||||
"tinystdio/sprintf.c",
|
||||
"tinystdio/sprintfd.c",
|
||||
"tinystdio/sprintff.c",
|
||||
"tinystdio/sscanf.c",
|
||||
"tinystdio/strfromd.c",
|
||||
"tinystdio/strfromf.c",
|
||||
"tinystdio/strtod.c",
|
||||
"tinystdio/strtod_l.c",
|
||||
"tinystdio/strtof.c",
|
||||
//"tinystdio/strtold.c", // have_long_double and not long_double_equals_double
|
||||
//"tinystdio/strtold_l.c", // have_long_double and not long_double_equals_double
|
||||
"tinystdio/ungetc.c",
|
||||
"tinystdio/vasprintf.c",
|
||||
"tinystdio/vfiprintf.c",
|
||||
"tinystdio/vfiscanf.c",
|
||||
"tinystdio/vfprintf.c",
|
||||
"tinystdio/vfprintff.c",
|
||||
"tinystdio/vfscanf.c",
|
||||
"tinystdio/vfscanff.c",
|
||||
"tinystdio/vprintf.c",
|
||||
"tinystdio/vscanf.c",
|
||||
"tinystdio/vsnprintf.c",
|
||||
"tinystdio/vsprintf.c",
|
||||
"tinystdio/vsscanf.c",
|
||||
|
||||
"libc/string/bcmp.c",
|
||||
"libc/string/bcopy.c",
|
||||
"libc/string/bzero.c",
|
||||
"libc/string/explicit_bzero.c",
|
||||
"libc/string/ffsl.c",
|
||||
"libc/string/ffsll.c",
|
||||
"libc/string/fls.c",
|
||||
"libc/string/flsl.c",
|
||||
"libc/string/flsll.c",
|
||||
"libc/string/gnu_basename.c",
|
||||
"libc/string/index.c",
|
||||
"libc/string/memccpy.c",
|
||||
"libc/string/memchr.c",
|
||||
"libc/string/memcmp.c",
|
||||
"libc/string/memcpy.c",
|
||||
"libc/string/memmem.c",
|
||||
"libc/string/memmove.c",
|
||||
"libc/string/mempcpy.c",
|
||||
"libc/string/memrchr.c",
|
||||
"libc/string/memset.c",
|
||||
"libc/string/rawmemchr.c",
|
||||
"libc/string/rindex.c",
|
||||
"libc/string/stpcpy.c",
|
||||
"libc/string/stpncpy.c",
|
||||
"libc/string/strcasecmp.c",
|
||||
"libc/string/strcasecmp_l.c",
|
||||
"libc/string/strcasestr.c",
|
||||
"libc/string/strcat.c",
|
||||
"libc/string/strchr.c",
|
||||
"libc/string/strchrnul.c",
|
||||
"libc/string/strcmp.c",
|
||||
"libc/string/strcoll.c",
|
||||
"libc/string/strcoll_l.c",
|
||||
"libc/string/strcpy.c",
|
||||
"libc/string/strcspn.c",
|
||||
"libc/string/strdup.c",
|
||||
"libc/string/strerror.c",
|
||||
"libc/string/strerror_r.c",
|
||||
"libc/string/strlcat.c",
|
||||
"libc/string/strlcpy.c",
|
||||
"libc/string/strlen.c",
|
||||
"libc/string/strlwr.c",
|
||||
"libc/string/strncasecmp.c",
|
||||
"libc/string/strncasecmp_l.c",
|
||||
"libc/string/strncat.c",
|
||||
"libc/string/strncmp.c",
|
||||
"libc/string/strncpy.c",
|
||||
"libc/string/strndup.c",
|
||||
"libc/string/strnlen.c",
|
||||
"libc/string/strnstr.c",
|
||||
"libc/string/strpbrk.c",
|
||||
"libc/string/strrchr.c",
|
||||
"libc/string/strsep.c",
|
||||
"libc/string/strsignal.c",
|
||||
"libc/string/strspn.c",
|
||||
"libc/string/strstr.c",
|
||||
"libc/string/strtok.c",
|
||||
"libc/string/strtok_r.c",
|
||||
"libc/string/strupr.c",
|
||||
"libc/string/strverscmp.c",
|
||||
"libc/string/strxfrm.c",
|
||||
"libc/string/strxfrm_l.c",
|
||||
"libc/string/swab.c",
|
||||
"libc/string/timingsafe_bcmp.c",
|
||||
"libc/string/timingsafe_memcmp.c",
|
||||
"libc/string/u_strerr.c",
|
||||
"libc/string/wcpcpy.c",
|
||||
"libc/string/wcpncpy.c",
|
||||
"libc/string/wcscasecmp.c",
|
||||
"libc/string/wcscasecmp_l.c",
|
||||
"libc/string/wcscat.c",
|
||||
"libc/string/wcschr.c",
|
||||
"libc/string/wcscmp.c",
|
||||
"libc/string/wcscoll.c",
|
||||
"libc/string/wcscoll_l.c",
|
||||
"libc/string/wcscpy.c",
|
||||
"libc/string/wcscspn.c",
|
||||
"libc/string/wcsdup.c",
|
||||
"libc/string/wcslcat.c",
|
||||
"libc/string/wcslcpy.c",
|
||||
"libc/string/wcslen.c",
|
||||
"libc/string/wcsncasecmp.c",
|
||||
"libc/string/wcsncasecmp_l.c",
|
||||
"libc/string/wcsncat.c",
|
||||
"libc/string/wcsncmp.c",
|
||||
"libc/string/wcsncpy.c",
|
||||
"libc/string/wcsnlen.c",
|
||||
"libc/string/wcspbrk.c",
|
||||
"libc/string/wcsrchr.c",
|
||||
"libc/string/wcsspn.c",
|
||||
"libc/string/wcsstr.c",
|
||||
"libc/string/wcstok.c",
|
||||
"libc/string/wcswidth.c",
|
||||
"libc/string/wcsxfrm.c",
|
||||
"libc/string/wcsxfrm_l.c",
|
||||
"libc/string/wcwidth.c",
|
||||
"libc/string/wmemchr.c",
|
||||
"libc/string/wmemcmp.c",
|
||||
"libc/string/wmemcpy.c",
|
||||
"libc/string/wmemmove.c",
|
||||
"libc/string/wmempcpy.c",
|
||||
"libc/string/wmemset.c",
|
||||
"libc/string/xpg_strerror_r.c",
|
||||
|
||||
"libm/common/sf_finite.c",
|
||||
"libm/common/sf_copysign.c",
|
||||
"libm/common/sf_modf.c",
|
||||
"libm/common/sf_scalbn.c",
|
||||
"libm/common/sf_cbrt.c",
|
||||
"libm/common/sf_exp10.c",
|
||||
"libm/common/sf_expm1.c",
|
||||
"libm/common/sf_ilogb.c",
|
||||
"libm/common/sf_infinity.c",
|
||||
"libm/common/sf_isinf.c",
|
||||
"libm/common/sf_isinff.c",
|
||||
"libm/common/sf_isnan.c",
|
||||
"libm/common/sf_isnanf.c",
|
||||
"libm/common/sf_issignaling.c",
|
||||
"libm/common/sf_log1p.c",
|
||||
"libm/common/sf_nan.c",
|
||||
"libm/common/sf_nextafter.c",
|
||||
"libm/common/sf_pow10.c",
|
||||
"libm/common/sf_rint.c",
|
||||
"libm/common/sf_logb.c",
|
||||
"libm/common/sf_fdim.c",
|
||||
"libm/common/sf_fma.c",
|
||||
"libm/common/sf_fmax.c",
|
||||
"libm/common/sf_fmin.c",
|
||||
"libm/common/sf_fpclassify.c",
|
||||
"libm/common/sf_lrint.c",
|
||||
"libm/common/sf_llrint.c",
|
||||
"libm/common/sf_lround.c",
|
||||
"libm/common/sf_llround.c",
|
||||
"libm/common/sf_nearbyint.c",
|
||||
"libm/common/sf_remquo.c",
|
||||
"libm/common/sf_round.c",
|
||||
"libm/common/sf_scalbln.c",
|
||||
"libm/common/sf_trunc.c",
|
||||
"libm/common/sf_exp.c",
|
||||
"libm/common/sf_exp2.c",
|
||||
"libm/common/sf_exp2_data.c",
|
||||
"libm/common/sf_log.c",
|
||||
"libm/common/sf_log_data.c",
|
||||
"libm/common/sf_log2.c",
|
||||
"libm/common/sf_log2_data.c",
|
||||
"libm/common/sf_pow_log2_data.c",
|
||||
"libm/common/sf_pow.c",
|
||||
|
||||
"libm/common/s_finite.c",
|
||||
"libm/common/s_copysign.c",
|
||||
"libm/common/s_modf.c",
|
||||
"libm/common/s_scalbn.c",
|
||||
"libm/common/s_cbrt.c",
|
||||
"libm/common/s_exp10.c",
|
||||
"libm/common/s_expm1.c",
|
||||
"libm/common/s_ilogb.c",
|
||||
"libm/common/s_infinity.c",
|
||||
"libm/common/s_isinf.c",
|
||||
"libm/common/s_isinfd.c",
|
||||
"libm/common/s_isnan.c",
|
||||
"libm/common/s_isnand.c",
|
||||
"libm/common/s_issignaling.c",
|
||||
"libm/common/s_log1p.c",
|
||||
"libm/common/s_nan.c",
|
||||
"libm/common/s_nextafter.c",
|
||||
"libm/common/s_pow10.c",
|
||||
"libm/common/s_rint.c",
|
||||
"libm/common/s_logb.c",
|
||||
"libm/common/s_log2.c",
|
||||
"libm/common/s_fdim.c",
|
||||
"libm/common/s_fma.c",
|
||||
"libm/common/s_fmax.c",
|
||||
"libm/common/s_fmin.c",
|
||||
"libm/common/s_fpclassify.c",
|
||||
"libm/common/s_lrint.c",
|
||||
"libm/common/s_llrint.c",
|
||||
"libm/common/s_lround.c",
|
||||
"libm/common/s_llround.c",
|
||||
"libm/common/s_nearbyint.c",
|
||||
"libm/common/s_remquo.c",
|
||||
"libm/common/s_round.c",
|
||||
"libm/common/s_scalbln.c",
|
||||
"libm/common/s_signbit.c",
|
||||
"libm/common/s_trunc.c",
|
||||
"libm/common/exp.c",
|
||||
"libm/common/exp2.c",
|
||||
"libm/common/exp_data.c",
|
||||
"libm/common/math_err_with_errno.c",
|
||||
"libm/common/math_err_xflow.c",
|
||||
"libm/common/math_err_uflow.c",
|
||||
"libm/common/math_err_oflow.c",
|
||||
"libm/common/math_err_divzero.c",
|
||||
"libm/common/math_err_invalid.c",
|
||||
"libm/common/math_err_may_uflow.c",
|
||||
"libm/common/math_err_check_uflow.c",
|
||||
"libm/common/math_err_check_oflow.c",
|
||||
"libm/common/log.c",
|
||||
"libm/common/log_data.c",
|
||||
"libm/common/log2.c",
|
||||
"libm/common/log2_data.c",
|
||||
"libm/common/pow.c",
|
||||
"libm/common/pow_log_data.c",
|
||||
|
||||
"libm/math/e_acos.c",
|
||||
"libm/math/e_acosh.c",
|
||||
"libm/math/e_asin.c",
|
||||
"libm/math/e_atan2.c",
|
||||
"libm/math/e_atanh.c",
|
||||
"libm/math/e_cosh.c",
|
||||
"libm/math/e_exp.c",
|
||||
"libm/math/ef_acos.c",
|
||||
"libm/math/ef_acosh.c",
|
||||
"libm/math/ef_asin.c",
|
||||
"libm/math/ef_atan2.c",
|
||||
"libm/math/ef_atanh.c",
|
||||
"libm/math/ef_cosh.c",
|
||||
"libm/math/ef_exp.c",
|
||||
"libm/math/ef_fmod.c",
|
||||
"libm/math/ef_hypot.c",
|
||||
"libm/math/ef_j0.c",
|
||||
"libm/math/ef_j1.c",
|
||||
"libm/math/ef_jn.c",
|
||||
"libm/math/ef_lgamma.c",
|
||||
"libm/math/ef_log10.c",
|
||||
"libm/math/ef_log.c",
|
||||
"libm/math/e_fmod.c",
|
||||
"libm/math/ef_pow.c",
|
||||
"libm/math/ef_remainder.c",
|
||||
"libm/math/ef_rem_pio2.c",
|
||||
"libm/math/ef_scalb.c",
|
||||
"libm/math/ef_sinh.c",
|
||||
"libm/math/ef_sqrt.c",
|
||||
"libm/math/ef_tgamma.c",
|
||||
"libm/math/e_hypot.c",
|
||||
"libm/math/e_j0.c",
|
||||
"libm/math/e_j1.c",
|
||||
"libm/math/e_jn.c",
|
||||
"libm/math/e_lgamma.c",
|
||||
"libm/math/e_log10.c",
|
||||
"libm/math/e_log.c",
|
||||
"libm/math/e_pow.c",
|
||||
"libm/math/e_remainder.c",
|
||||
"libm/math/e_rem_pio2.c",
|
||||
"libm/math/erf_lgamma.c",
|
||||
"libm/math/er_lgamma.c",
|
||||
"libm/math/e_scalb.c",
|
||||
"libm/math/e_sinh.c",
|
||||
"libm/math/e_sqrt.c",
|
||||
"libm/math/e_tgamma.c",
|
||||
"libm/math/s_asinh.c",
|
||||
"libm/math/s_atan.c",
|
||||
"libm/math/s_ceil.c",
|
||||
"libm/math/s_cos.c",
|
||||
"libm/math/s_erf.c",
|
||||
"libm/math/s_fabs.c",
|
||||
"libm/math/sf_asinh.c",
|
||||
"libm/math/sf_atan.c",
|
||||
"libm/math/sf_ceil.c",
|
||||
"libm/math/sf_cos.c",
|
||||
"libm/math/sf_erf.c",
|
||||
"libm/math/sf_fabs.c",
|
||||
"libm/math/sf_floor.c",
|
||||
"libm/math/sf_frexp.c",
|
||||
"libm/math/sf_ldexp.c",
|
||||
"libm/math/s_floor.c",
|
||||
"libm/math/s_frexp.c",
|
||||
"libm/math/sf_signif.c",
|
||||
"libm/math/sf_sin.c",
|
||||
"libm/math/sf_tan.c",
|
||||
"libm/math/sf_tanh.c",
|
||||
"libm/math/s_ldexp.c",
|
||||
"libm/math/s_signif.c",
|
||||
"libm/math/s_sin.c",
|
||||
"libm/math/s_tan.c",
|
||||
"libm/math/s_tanh.c",
|
||||
"string/bcmp.c",
|
||||
"string/bcopy.c",
|
||||
"string/bzero.c",
|
||||
"string/explicit_bzero.c",
|
||||
"string/ffsl.c",
|
||||
"string/ffsll.c",
|
||||
"string/fls.c",
|
||||
"string/flsl.c",
|
||||
"string/flsll.c",
|
||||
"string/gnu_basename.c",
|
||||
"string/index.c",
|
||||
"string/memccpy.c",
|
||||
"string/memchr.c",
|
||||
"string/memcmp.c",
|
||||
"string/memcpy.c",
|
||||
"string/memmem.c",
|
||||
"string/memmove.c",
|
||||
"string/mempcpy.c",
|
||||
"string/memrchr.c",
|
||||
"string/memset.c",
|
||||
"string/rawmemchr.c",
|
||||
"string/rindex.c",
|
||||
"string/stpcpy.c",
|
||||
"string/stpncpy.c",
|
||||
"string/strcasecmp.c",
|
||||
"string/strcasecmp_l.c",
|
||||
"string/strcasestr.c",
|
||||
"string/strcat.c",
|
||||
"string/strchr.c",
|
||||
"string/strchrnul.c",
|
||||
"string/strcmp.c",
|
||||
"string/strcoll.c",
|
||||
"string/strcoll_l.c",
|
||||
"string/strcpy.c",
|
||||
"string/strcspn.c",
|
||||
"string/strdup.c",
|
||||
"string/strerror.c",
|
||||
"string/strerror_r.c",
|
||||
"string/strlcat.c",
|
||||
"string/strlcpy.c",
|
||||
"string/strlen.c",
|
||||
"string/strlwr.c",
|
||||
"string/strncasecmp.c",
|
||||
"string/strncasecmp_l.c",
|
||||
"string/strncat.c",
|
||||
"string/strncmp.c",
|
||||
"string/strncpy.c",
|
||||
"string/strndup.c",
|
||||
"string/strnlen.c",
|
||||
"string/strnstr.c",
|
||||
"string/strpbrk.c",
|
||||
"string/strrchr.c",
|
||||
"string/strsep.c",
|
||||
"string/strsignal.c",
|
||||
"string/strspn.c",
|
||||
"string/strstr.c",
|
||||
"string/strtok.c",
|
||||
"string/strtok_r.c",
|
||||
"string/strupr.c",
|
||||
"string/strverscmp.c",
|
||||
"string/strxfrm.c",
|
||||
"string/strxfrm_l.c",
|
||||
"string/swab.c",
|
||||
"string/timingsafe_bcmp.c",
|
||||
"string/timingsafe_memcmp.c",
|
||||
"string/u_strerr.c",
|
||||
"string/wcpcpy.c",
|
||||
"string/wcpncpy.c",
|
||||
"string/wcscasecmp.c",
|
||||
"string/wcscasecmp_l.c",
|
||||
"string/wcscat.c",
|
||||
"string/wcschr.c",
|
||||
"string/wcscmp.c",
|
||||
"string/wcscoll.c",
|
||||
"string/wcscoll_l.c",
|
||||
"string/wcscpy.c",
|
||||
"string/wcscspn.c",
|
||||
"string/wcsdup.c",
|
||||
"string/wcslcat.c",
|
||||
"string/wcslcpy.c",
|
||||
"string/wcslen.c",
|
||||
"string/wcsncasecmp.c",
|
||||
"string/wcsncasecmp_l.c",
|
||||
"string/wcsncat.c",
|
||||
"string/wcsncmp.c",
|
||||
"string/wcsncpy.c",
|
||||
"string/wcsnlen.c",
|
||||
"string/wcspbrk.c",
|
||||
"string/wcsrchr.c",
|
||||
"string/wcsspn.c",
|
||||
"string/wcsstr.c",
|
||||
"string/wcstok.c",
|
||||
"string/wcswidth.c",
|
||||
"string/wcsxfrm.c",
|
||||
"string/wcsxfrm_l.c",
|
||||
"string/wcwidth.c",
|
||||
"string/wmemchr.c",
|
||||
"string/wmemcmp.c",
|
||||
"string/wmemcpy.c",
|
||||
"string/wmemmove.c",
|
||||
"string/wmempcpy.c",
|
||||
"string/wmemset.c",
|
||||
"string/xpg_strerror_r.c",
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ package builder
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ func convertELFFileToUF2File(infile, outfile string, uf2FamilyID string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(outfile, output, 0644)
|
||||
return ioutil.WriteFile(outfile, output, 0644)
|
||||
}
|
||||
|
||||
// convertBinToUF2 converts the binary bytes in input to UF2 formatted data.
|
||||
|
||||
+31
-72
@@ -32,7 +32,6 @@ type cgoPackage struct {
|
||||
errors []error
|
||||
currentDir string // current working directory
|
||||
packageDir string // full path to the package to process
|
||||
importPath string
|
||||
fset *token.FileSet
|
||||
tokenFiles map[string]*token.File
|
||||
definedGlobally map[string]ast.Node
|
||||
@@ -40,15 +39,12 @@ type cgoPackage struct {
|
||||
cflags []string // CFlags from #cgo lines
|
||||
ldflags []string // LDFlags from #cgo lines
|
||||
visitedFiles map[string][]byte
|
||||
cgoHeaders []string
|
||||
}
|
||||
|
||||
// cgoFile holds information only for a single Go file (with one or more
|
||||
// `import "C"` statements).
|
||||
type cgoFile struct {
|
||||
*cgoPackage
|
||||
file *ast.File
|
||||
index int
|
||||
defined map[string]ast.Node
|
||||
names map[string]clangCursor
|
||||
}
|
||||
@@ -162,10 +158,9 @@ func GoBytes(ptr unsafe.Pointer, length C.int) []byte {
|
||||
// functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file
|
||||
// hashes of the accessed C header files. If there is one or more error, it
|
||||
// returns these in the []error slice but still modifies the AST.
|
||||
func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
||||
func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string, clangHeaders string) (*ast.File, []string, []string, []string, map[string][]byte, []error) {
|
||||
p := &cgoPackage{
|
||||
currentDir: dir,
|
||||
importPath: importPath,
|
||||
fset: fset,
|
||||
tokenFiles: map[string]*token.File{},
|
||||
definedGlobally: map[string]ast.Node{},
|
||||
@@ -215,13 +210,13 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
||||
}
|
||||
}
|
||||
// Patch some types, for example *C.char in C.CString.
|
||||
cf := p.newCGoFile(nil, -1) // dummy *cgoFile for the walker
|
||||
cf := p.newCGoFile()
|
||||
astutil.Apply(p.generated, func(cursor *astutil.Cursor) bool {
|
||||
return cf.walker(cursor, nil)
|
||||
}, nil)
|
||||
|
||||
// Find `import "C"` C fragments in the file.
|
||||
p.cgoHeaders = make([]string, len(files)) // combined CGo header fragment for each file
|
||||
cgoHeaders := make([]string, len(files)) // combined CGo header fragment for each file
|
||||
for i, f := range files {
|
||||
var cgoHeader string
|
||||
for i := 0; i < len(f.Decls); i++ {
|
||||
@@ -280,7 +275,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
||||
cgoHeader += fragment
|
||||
}
|
||||
|
||||
p.cgoHeaders[i] = cgoHeader
|
||||
cgoHeaders[i] = cgoHeader
|
||||
}
|
||||
|
||||
// Define CFlags that will be used while parsing the package.
|
||||
@@ -294,7 +289,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
||||
}
|
||||
|
||||
// Retrieve types such as C.int, C.longlong, etc from C.
|
||||
p.newCGoFile(nil, -1).readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
|
||||
p.newCGoFile().readNames(builtinAliasTypedefs, cflagsForCGo, "", func(names map[string]clangCursor) {
|
||||
gen := &ast.GenDecl{
|
||||
TokPos: token.NoPos,
|
||||
Tok: token.TYPE,
|
||||
@@ -308,8 +303,8 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
||||
|
||||
// Process CGo imports for each file.
|
||||
for i, f := range files {
|
||||
cf := p.newCGoFile(f, i)
|
||||
cf.readNames(p.cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
||||
cf := p.newCGoFile()
|
||||
cf.readNames(cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
||||
for _, name := range builtinAliases {
|
||||
// Names such as C.int should not be obtained from C.
|
||||
// This works around an issue in picolibc that has `#define int`
|
||||
@@ -325,14 +320,12 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
||||
// Print the newly generated in-memory AST, for debugging.
|
||||
//ast.Print(fset, p.generated)
|
||||
|
||||
return p.generated, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
||||
return p.generated, cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors
|
||||
}
|
||||
|
||||
func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile {
|
||||
func (p *cgoPackage) newCGoFile() *cgoFile {
|
||||
return &cgoFile{
|
||||
cgoPackage: p,
|
||||
file: file,
|
||||
index: index,
|
||||
defined: make(map[string]ast.Node),
|
||||
names: make(map[string]clangCursor),
|
||||
}
|
||||
@@ -500,15 +493,15 @@ func (p *cgoPackage) makeUnionField(typ *elaboratedTypeInfo) *ast.StructType {
|
||||
// createUnionAccessor creates a function that returns a typed pointer to a
|
||||
// union field for each field in a union. For example:
|
||||
//
|
||||
// func (union *C.union_1) unionfield_d() *float64 {
|
||||
// return (*float64)(unsafe.Pointer(&union.$union))
|
||||
// }
|
||||
// func (union *C.union_1) unionfield_d() *float64 {
|
||||
// return (*float64)(unsafe.Pointer(&union.$union))
|
||||
// }
|
||||
//
|
||||
// Where C.union_1 is defined as:
|
||||
//
|
||||
// type C.union_1 struct{
|
||||
// $union uint64
|
||||
// }
|
||||
// type C.union_1 struct{
|
||||
// $union uint64
|
||||
// }
|
||||
//
|
||||
// The returned pointer can be used to get or set the field, or get the pointer
|
||||
// to a subfield.
|
||||
@@ -624,9 +617,9 @@ func (p *cgoPackage) createUnionAccessor(field *ast.Field, typeName string) {
|
||||
|
||||
// createBitfieldGetter creates a bitfield getter function like the following:
|
||||
//
|
||||
// func (s *C.struct_foo) bitfield_b() byte {
|
||||
// return (s.__bitfield_1 >> 5) & 0x1
|
||||
// }
|
||||
// func (s *C.struct_foo) bitfield_b() byte {
|
||||
// return (s.__bitfield_1 >> 5) & 0x1
|
||||
// }
|
||||
func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string) {
|
||||
// The value to return from the getter.
|
||||
// Not complete: this is just an expression to get the complete field.
|
||||
@@ -736,15 +729,15 @@ func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string
|
||||
|
||||
// createBitfieldSetter creates a bitfield setter function like the following:
|
||||
//
|
||||
// func (s *C.struct_foo) set_bitfield_b(value byte) {
|
||||
// s.__bitfield_1 = s.__bitfield_1 ^ 0x60 | ((value & 1) << 5)
|
||||
// }
|
||||
// func (s *C.struct_foo) set_bitfield_b(value byte) {
|
||||
// s.__bitfield_1 = s.__bitfield_1 ^ 0x60 | ((value & 1) << 5)
|
||||
// }
|
||||
//
|
||||
// Or the following:
|
||||
//
|
||||
// func (s *C.struct_foo) set_bitfield_c(value byte) {
|
||||
// s.__bitfield_1 = s.__bitfield_1 & 0x3f | (value << 6)
|
||||
// }
|
||||
// func (s *C.struct_foo) set_bitfield_c(value byte) {
|
||||
// s.__bitfield_1 = s.__bitfield_1 & 0x3f | (value << 6)
|
||||
// }
|
||||
func (p *cgoPackage) createBitfieldSetter(bitfield bitfieldInfo, typeName string) {
|
||||
// The full field with all bitfields.
|
||||
var field ast.Expr = &ast.SelectorExpr{
|
||||
@@ -1124,11 +1117,8 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
|
||||
return alias
|
||||
}
|
||||
node := f.getASTDeclNode(name, found, iscall)
|
||||
if node, ok := node.(*ast.FuncDecl); ok {
|
||||
if !iscall {
|
||||
return node.Name.Name + "$funcaddr"
|
||||
}
|
||||
return node.Name.Name
|
||||
if _, ok := node.(*ast.FuncDecl); ok && !iscall {
|
||||
return "C." + name + "$funcaddr"
|
||||
}
|
||||
return "C." + name
|
||||
}
|
||||
@@ -1152,7 +1142,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
||||
// Original cgo reports an error like
|
||||
// cgo: inconsistent definitions for C.myint
|
||||
// which is far less helpful.
|
||||
f.addError(getPos(node), name+" defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
|
||||
f.addError(getPos(node), "defined previously at "+f.fset.Position(getPos(newNode)).String()+" with a different type")
|
||||
}
|
||||
f.defined[name] = node
|
||||
return node
|
||||
@@ -1160,39 +1150,11 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
|
||||
|
||||
// The declaration has no AST node. Create it now.
|
||||
f.defined[name] = nil
|
||||
node, extra := f.createASTNode(name, found)
|
||||
node, elaboratedType := f.createASTNode(name, found)
|
||||
f.defined[name] = node
|
||||
f.definedGlobally[name] = node
|
||||
switch node := node.(type) {
|
||||
case *ast.FuncDecl:
|
||||
if strings.HasPrefix(node.Doc.List[0].Text, "//export _Cgo_static_") {
|
||||
// Static function. Only accessible in the current Go file.
|
||||
globalName := strings.TrimPrefix(node.Doc.List[0].Text, "//export ")
|
||||
// Make an alias. Normally this is done using the alias function
|
||||
// attribute, but MacOS for some reason doesn't support this (even
|
||||
// though the linker has support for aliases in the form of N_INDR).
|
||||
// Therefore, create an actual function for MacOS.
|
||||
var params []string
|
||||
for _, param := range node.Type.Params.List {
|
||||
params = append(params, param.Names[0].Name)
|
||||
}
|
||||
callInst := fmt.Sprintf("%s(%s);", name, strings.Join(params, ", "))
|
||||
if node.Type.Results != nil {
|
||||
callInst = "return " + callInst
|
||||
}
|
||||
aliasDeclaration := fmt.Sprintf(`
|
||||
#ifdef __APPLE__
|
||||
%s {
|
||||
%s
|
||||
}
|
||||
#else
|
||||
extern __typeof(%s) %s __attribute__((alias(%#v)));
|
||||
#endif
|
||||
`, extra.(string), callInst, name, globalName, name)
|
||||
f.cgoHeaders[f.index] += "\n\n" + aliasDeclaration
|
||||
} else {
|
||||
// Regular (non-static) function.
|
||||
f.definedGlobally[name] = node
|
||||
}
|
||||
f.generated.Decls = append(f.generated.Decls, node)
|
||||
// Also add a declaration like the following:
|
||||
// var C.foo$funcaddr unsafe.Pointer
|
||||
@@ -1200,7 +1162,7 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
|
||||
Tok: token.VAR,
|
||||
Specs: []ast.Spec{
|
||||
&ast.ValueSpec{
|
||||
Names: []*ast.Ident{{Name: node.Name.Name + "$funcaddr"}},
|
||||
Names: []*ast.Ident{{Name: "C." + name + "$funcaddr"}},
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "unsafe"},
|
||||
Sel: &ast.Ident{Name: "Pointer"},
|
||||
@@ -1209,10 +1171,8 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
|
||||
},
|
||||
})
|
||||
case *ast.GenDecl:
|
||||
f.definedGlobally[name] = node
|
||||
f.generated.Decls = append(f.generated.Decls, node)
|
||||
case *ast.TypeSpec:
|
||||
f.definedGlobally[name] = node
|
||||
f.generated.Decls = append(f.generated.Decls, &ast.GenDecl{
|
||||
Tok: token.TYPE,
|
||||
Specs: []ast.Spec{node},
|
||||
@@ -1226,8 +1186,7 @@ extern __typeof(%s) %s __attribute__((alias(%#v)));
|
||||
|
||||
// If this is a struct or union it may need bitfields or union accessor
|
||||
// methods.
|
||||
switch elaboratedType := extra.(type) {
|
||||
case *elaboratedTypeInfo:
|
||||
if elaboratedType != nil {
|
||||
// Add struct bitfields.
|
||||
for _, bitfield := range elaboratedType.bitfields {
|
||||
f.createBitfieldGetter(bitfield, "C."+name)
|
||||
|
||||
+19
-4
@@ -5,11 +5,12 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
@@ -39,6 +40,20 @@ func TestCGo(t *testing.T) {
|
||||
} {
|
||||
name := name // avoid a race condition
|
||||
t.Run(name, func(t *testing.T) {
|
||||
// Skip tests that require specific Go version.
|
||||
if name == "errors" {
|
||||
ok := false
|
||||
for _, version := range build.Default.ReleaseTags {
|
||||
if version == "go1.16" {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
t.Skip("Results for errors test are only valid for Go 1.16+")
|
||||
}
|
||||
}
|
||||
|
||||
// Read the AST in memory.
|
||||
path := filepath.Join("testdata", name+".go")
|
||||
fset := token.NewFileSet()
|
||||
@@ -48,7 +63,7 @@ func TestCGo(t *testing.T) {
|
||||
}
|
||||
|
||||
// Process the AST with CGo.
|
||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags, "")
|
||||
cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags, "")
|
||||
|
||||
// Check the AST for type errors.
|
||||
var typecheckErrors []error
|
||||
@@ -92,7 +107,7 @@ func TestCGo(t *testing.T) {
|
||||
|
||||
// Read the file with the expected output, to compare against.
|
||||
outfile := filepath.Join("testdata", name+".out.go")
|
||||
expectedBytes, err := os.ReadFile(outfile)
|
||||
expectedBytes, err := ioutil.ReadFile(outfile)
|
||||
if err != nil {
|
||||
t.Fatalf("could not read expected output: %v", err)
|
||||
}
|
||||
@@ -103,7 +118,7 @@ func TestCGo(t *testing.T) {
|
||||
// It is not. Test failed.
|
||||
if *flagUpdate {
|
||||
// Update the file with the expected data.
|
||||
err := os.WriteFile(outfile, []byte(actual), 0666)
|
||||
err := ioutil.WriteFile(outfile, []byte(actual), 0666)
|
||||
if err != nil {
|
||||
t.Error("could not write updated output file:", err)
|
||||
}
|
||||
|
||||
+4
-33
@@ -4,9 +4,7 @@ package cgo
|
||||
// modification. It does not touch the AST itself.
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/scanner"
|
||||
@@ -45,8 +43,6 @@ typedef struct {
|
||||
GoCXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu);
|
||||
unsigned tinygo_clang_visitChildren(GoCXCursor parent, CXCursorVisitor visitor, CXClientData client_data);
|
||||
CXString tinygo_clang_getCursorSpelling(GoCXCursor c);
|
||||
CXString tinygo_clang_getCursorPrettyPrinted(GoCXCursor c, CXPrintingPolicy Policy);
|
||||
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(GoCXCursor c);
|
||||
enum CXCursorKind tinygo_clang_getCursorKind(GoCXCursor c);
|
||||
CXType tinygo_clang_getCursorType(GoCXCursor c);
|
||||
GoCXCursor tinygo_clang_getTypeDeclaration(CXType t);
|
||||
@@ -54,7 +50,6 @@ CXType tinygo_clang_getTypedefDeclUnderlyingType(GoCXCursor c);
|
||||
CXType tinygo_clang_getCursorResultType(GoCXCursor c);
|
||||
int tinygo_clang_Cursor_getNumArguments(GoCXCursor c);
|
||||
GoCXCursor tinygo_clang_Cursor_getArgument(GoCXCursor c, unsigned i);
|
||||
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(GoCXCursor c);
|
||||
CXSourceLocation tinygo_clang_getCursorLocation(GoCXCursor c);
|
||||
CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c);
|
||||
CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);
|
||||
@@ -194,7 +189,7 @@ func (f *cgoFile) readNames(fragment string, cflags []string, filename string, c
|
||||
|
||||
// Convert the AST node under the given Clang cursor to a Go AST node and return
|
||||
// it.
|
||||
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
|
||||
func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, *elaboratedTypeInfo) {
|
||||
kind := C.tinygo_clang_getCursorKind(c)
|
||||
pos := f.getCursorPosition(c)
|
||||
switch kind {
|
||||
@@ -205,43 +200,19 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
|
||||
Kind: ast.Fun,
|
||||
Name: "C." + name,
|
||||
}
|
||||
exportName := name
|
||||
localName := name
|
||||
var stringSignature string
|
||||
if C.tinygo_clang_Cursor_getStorageClass(c) == C.CX_SC_Static {
|
||||
// A static function is assigned a globally unique symbol name based
|
||||
// on the file path (like _Cgo_static_2d09198adbf58f4f4655_foo) and
|
||||
// has a different Go name in the form of C.foo!symbols.go instead
|
||||
// of just C.foo.
|
||||
path := f.importPath + "/" + filepath.Base(f.fset.File(f.file.Pos()).Name())
|
||||
staticIDBuf := sha256.Sum256([]byte(path))
|
||||
staticID := hex.EncodeToString(staticIDBuf[:10])
|
||||
exportName = "_Cgo_static_" + staticID + "_" + name
|
||||
localName = name + "!" + filepath.Base(path)
|
||||
|
||||
// Create a signature. This is necessary for MacOS to forward the
|
||||
// call, because MacOS doesn't support aliases like ELF and PE do.
|
||||
// (There is N_INDR but __attribute__((alias("..."))) doesn't work).
|
||||
policy := C.tinygo_clang_getCursorPrintingPolicy(c)
|
||||
defer C.clang_PrintingPolicy_dispose(policy)
|
||||
C.clang_PrintingPolicy_setProperty(policy, C.CXPrintingPolicy_TerseOutput, 1)
|
||||
stringSignature = getString(C.tinygo_clang_getCursorPrettyPrinted(c, policy))
|
||||
stringSignature = strings.Replace(stringSignature, " "+name+"(", " "+exportName+"(", 1)
|
||||
stringSignature = strings.TrimPrefix(stringSignature, "static ")
|
||||
}
|
||||
args := make([]*ast.Field, numArgs)
|
||||
decl := &ast.FuncDecl{
|
||||
Doc: &ast.CommentGroup{
|
||||
List: []*ast.Comment{
|
||||
{
|
||||
Slash: pos - 1,
|
||||
Text: "//export " + exportName,
|
||||
Text: "//export " + name,
|
||||
},
|
||||
},
|
||||
},
|
||||
Name: &ast.Ident{
|
||||
NamePos: pos,
|
||||
Name: "C." + localName,
|
||||
Name: "C." + name,
|
||||
Obj: obj,
|
||||
},
|
||||
Type: &ast.FuncType{
|
||||
@@ -292,7 +263,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
|
||||
}
|
||||
}
|
||||
obj.Decl = decl
|
||||
return decl, stringSignature
|
||||
return decl, nil
|
||||
case C.CXCursor_StructDecl, C.CXCursor_UnionDecl:
|
||||
typ := f.makeASTRecordType(c, pos)
|
||||
typeName := "C." + name
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//go:build !byollvm && llvm13
|
||||
// +build !byollvm,llvm13
|
||||
|
||||
package cgo
|
||||
|
||||
/*
|
||||
#cgo linux CFLAGS: -I/usr/lib/llvm-13/include
|
||||
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@13/include
|
||||
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@13/include
|
||||
#cgo freebsd CFLAGS: -I/usr/local/llvm13/include
|
||||
#cgo linux LDFLAGS: -L/usr/lib/llvm-13/lib -lclang
|
||||
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@13/lib -lclang -lffi
|
||||
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@13/lib -lclang -lffi
|
||||
#cgo freebsd LDFLAGS: -L/usr/local/llvm13/lib -lclang
|
||||
*/
|
||||
import "C"
|
||||
@@ -1,5 +1,5 @@
|
||||
//go:build !byollvm
|
||||
// +build !byollvm
|
||||
//go:build !byollvm && !llvm13
|
||||
// +build !byollvm,!llvm13
|
||||
|
||||
package cgo
|
||||
|
||||
|
||||
@@ -17,14 +17,6 @@ CXString tinygo_clang_getCursorSpelling(CXCursor c) {
|
||||
return clang_getCursorSpelling(c);
|
||||
}
|
||||
|
||||
CXString tinygo_clang_getCursorPrettyPrinted(CXCursor c, CXPrintingPolicy policy) {
|
||||
return clang_getCursorPrettyPrinted(c, policy);
|
||||
}
|
||||
|
||||
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(CXCursor c) {
|
||||
return clang_getCursorPrintingPolicy(c);
|
||||
}
|
||||
|
||||
enum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) {
|
||||
return clang_getCursorKind(c);
|
||||
}
|
||||
@@ -53,10 +45,6 @@ CXCursor tinygo_clang_Cursor_getArgument(CXCursor c, unsigned i) {
|
||||
return clang_Cursor_getArgument(c, i);
|
||||
}
|
||||
|
||||
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(CXCursor c) {
|
||||
return clang_Cursor_getStorageClass(c);
|
||||
}
|
||||
|
||||
CXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) {
|
||||
return clang_getCursorLocation(c);
|
||||
}
|
||||
|
||||
Vendored
-2
@@ -5,7 +5,6 @@ package main
|
||||
int foo(int a, int b);
|
||||
void variadic0();
|
||||
void variadic2(int x, int y, ...);
|
||||
static void staticfunc(int x);
|
||||
|
||||
// Global variable signatures.
|
||||
extern int someValue;
|
||||
@@ -17,7 +16,6 @@ func accessFunctions() {
|
||||
C.foo(3, 4)
|
||||
C.variadic0()
|
||||
C.variadic2(3, 5)
|
||||
C.staticfunc(3)
|
||||
}
|
||||
|
||||
func accessGlobals() {
|
||||
|
||||
Vendored
-5
@@ -55,10 +55,5 @@ func C.variadic2(x C.int, y C.int)
|
||||
|
||||
var C.variadic2$funcaddr unsafe.Pointer
|
||||
|
||||
//export _Cgo_static_173c95a79b6df1980521_staticfunc
|
||||
func C.staticfunc!symbols.go(x C.int)
|
||||
|
||||
var C.staticfunc!symbols.go$funcaddr unsafe.Pointer
|
||||
|
||||
//go:extern someValue
|
||||
var C.someValue C.int
|
||||
|
||||
+6
-20
@@ -73,7 +73,9 @@ func (c *Config) BuildTags() []string {
|
||||
for i := 1; i <= c.GoMinorVersion; i++ {
|
||||
tags = append(tags, fmt.Sprintf("go1.%d", i))
|
||||
}
|
||||
tags = append(tags, c.Options.Tags...)
|
||||
if extraTags := strings.Fields(c.Options.Tags); len(extraTags) != 0 {
|
||||
tags = append(tags, extraTags...)
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
@@ -175,15 +177,6 @@ func (c *Config) AutomaticStackSize() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// StackSize returns the default stack size to be used for goroutines, if the
|
||||
// stack size could not be determined automatically at compile time.
|
||||
func (c *Config) StackSize() uint64 {
|
||||
if c.Options.StackSize != 0 {
|
||||
return c.Options.StackSize
|
||||
}
|
||||
return c.Target.DefaultStackSize
|
||||
}
|
||||
|
||||
// UseThinLTO returns whether ThinLTO should be used for the given target. Some
|
||||
// targets (such as wasm) are not yet supported.
|
||||
// We should try and remove as many exceptions as possible in the future, so
|
||||
@@ -449,13 +442,13 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
|
||||
if openocdInterface == "" {
|
||||
return nil, errors.New("OpenOCD programmer not set")
|
||||
}
|
||||
if !regexp.MustCompile(`^[\p{L}0-9_-]+$`).MatchString(openocdInterface) {
|
||||
if !regexp.MustCompile("^[\\p{L}0-9_-]+$").MatchString(openocdInterface) {
|
||||
return nil, fmt.Errorf("OpenOCD programmer has an invalid name: %#v", openocdInterface)
|
||||
}
|
||||
if c.Target.OpenOCDTarget == "" {
|
||||
return nil, errors.New("OpenOCD chip not set")
|
||||
}
|
||||
if !regexp.MustCompile(`^[\p{L}0-9_-]+$`).MatchString(c.Target.OpenOCDTarget) {
|
||||
if !regexp.MustCompile("^[\\p{L}0-9_-]+$").MatchString(c.Target.OpenOCDTarget) {
|
||||
return nil, fmt.Errorf("OpenOCD target has an invalid name: %#v", c.Target.OpenOCDTarget)
|
||||
}
|
||||
if c.Target.OpenOCDTransport != "" && c.Target.OpenOCDTransport != "swd" {
|
||||
@@ -466,14 +459,7 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
|
||||
args = append(args, "-c", cmd)
|
||||
}
|
||||
if c.Target.OpenOCDTransport != "" {
|
||||
transport := c.Target.OpenOCDTransport
|
||||
if transport == "swd" {
|
||||
switch openocdInterface {
|
||||
case "stlink-dap":
|
||||
transport = "dapdirect_swd"
|
||||
}
|
||||
}
|
||||
args = append(args, "-c", "transport select "+transport)
|
||||
args = append(args, "-c", "transport select "+c.Target.OpenOCDTransport)
|
||||
}
|
||||
args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
|
||||
return args, nil
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -28,10 +27,8 @@ type Options struct {
|
||||
GC string
|
||||
PanicStrategy string
|
||||
Scheduler string
|
||||
StackSize uint64 // goroutine stack size (if none could be automatically determined)
|
||||
Serial string
|
||||
Work bool // -work flag to print temporary build directory
|
||||
InterpTimeout time.Duration
|
||||
PrintIR bool
|
||||
DumpSSA bool
|
||||
VerifyIR bool
|
||||
@@ -41,7 +38,7 @@ type Options struct {
|
||||
PrintSizes string
|
||||
PrintAllocs *regexp.Regexp // regexp string
|
||||
PrintStacks bool
|
||||
Tags []string
|
||||
Tags string
|
||||
WasmAbi string
|
||||
GlobalValues map[string]map[string]string // map[pkgpath]map[varname]value
|
||||
TestConfig TestConfig
|
||||
@@ -50,8 +47,6 @@ type Options struct {
|
||||
LLVMFeatures string
|
||||
Directory string
|
||||
PrintJSON bool
|
||||
Monitor bool
|
||||
BaudRate int
|
||||
}
|
||||
|
||||
// Verify performs a validation on the given options, raising an error if options are not valid.
|
||||
|
||||
+13
-28
@@ -65,7 +65,7 @@ type TargetSpec struct {
|
||||
}
|
||||
|
||||
// overrideProperties overrides all properties that are set in child into itself using reflection.
|
||||
func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
|
||||
func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
|
||||
specType := reflect.TypeOf(spec).Elem()
|
||||
specValue := reflect.ValueOf(spec).Elem()
|
||||
childValue := reflect.ValueOf(child).Elem()
|
||||
@@ -88,22 +88,12 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
|
||||
if !src.IsNil() {
|
||||
dst.Set(src)
|
||||
}
|
||||
case reflect.Slice: // for slices, append the field and check for duplicates
|
||||
case reflect.Slice: // for slices, append the field
|
||||
dst.Set(reflect.AppendSlice(dst, src))
|
||||
for i := 0; i < dst.Len(); i++ {
|
||||
v := dst.Index(i).String()
|
||||
for j := i + 1; j < dst.Len(); j++ {
|
||||
w := dst.Index(j).String()
|
||||
if v == w {
|
||||
return fmt.Errorf("duplicate value '%s' in field %s", v, field.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown field type: %s", kind)
|
||||
panic("unknown field type : " + kind.String())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// load reads a target specification from the JSON in the given io.Reader. It
|
||||
@@ -118,10 +108,10 @@ func (spec *TargetSpec) load(r io.Reader) error {
|
||||
}
|
||||
|
||||
// loadFromGivenStr loads the TargetSpec from the given string that could be:
|
||||
// - targets/ directory inside the compiler sources
|
||||
// - a relative or absolute path to custom (project specific) target specification .json file;
|
||||
// the Inherits[] could contain the files from target folder (ex. stm32f4disco)
|
||||
// as well as path to custom files (ex. myAwesomeProject.json)
|
||||
// - targets/ directory inside the compiler sources
|
||||
// - a relative or absolute path to custom (project specific) target specification .json file;
|
||||
// the Inherits[] could contain the files from target folder (ex. stm32f4disco)
|
||||
// as well as path to custom files (ex. myAwesomeProject.json)
|
||||
func (spec *TargetSpec) loadFromGivenStr(str string) error {
|
||||
path := ""
|
||||
if strings.HasSuffix(str, ".json") {
|
||||
@@ -151,17 +141,11 @@ func (spec *TargetSpec) resolveInherits() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = newSpec.overrideProperties(subtarget)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newSpec.overrideProperties(subtarget)
|
||||
}
|
||||
|
||||
// When all properties are loaded, make sure they are properly inherited.
|
||||
err := newSpec.overrideProperties(spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newSpec.overrideProperties(spec)
|
||||
*spec = *newSpec
|
||||
|
||||
return nil
|
||||
@@ -209,10 +193,11 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
|
||||
// triples for historical reasons) have the form:
|
||||
// arch-vendor-os-environment
|
||||
target := llvmarch + "-unknown-" + llvmos
|
||||
if options.GOARCH == "arm" {
|
||||
target += "-gnueabihf"
|
||||
}
|
||||
if options.GOOS == "windows" {
|
||||
target += "-gnu"
|
||||
} else if options.GOARCH == "arm" {
|
||||
target += "-gnueabihf"
|
||||
}
|
||||
return defaultTarget(options.GOOS, options.GOARCH, target)
|
||||
}
|
||||
@@ -228,7 +213,7 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
|
||||
// it includes all parents as specified in the "inherits" key.
|
||||
err = spec.resolveInherits()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s : %w", options.Target, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if spec.Scheduler == "asyncify" {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package compileopts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
@@ -18,7 +17,7 @@ func TestLoadTarget(t *testing.T) {
|
||||
t.Error("LoadTarget should have failed with non existing target")
|
||||
}
|
||||
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
if !os.IsNotExist(err) {
|
||||
t.Error("LoadTarget failed for wrong reason:", err)
|
||||
}
|
||||
}
|
||||
|
||||
+43
-2
@@ -16,8 +16,6 @@ import "tinygo.org/x/go-llvm"
|
||||
|
||||
var stdlibAliases = map[string]string{
|
||||
// crypto packages
|
||||
"crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric",
|
||||
"crypto/ed25519/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric",
|
||||
"crypto/md5.block": "crypto/md5.blockGeneric",
|
||||
"crypto/sha1.block": "crypto/sha1.blockGeneric",
|
||||
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
|
||||
@@ -25,10 +23,53 @@ var stdlibAliases = map[string]string{
|
||||
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
|
||||
|
||||
// math package
|
||||
"math.Asin": "math.asin",
|
||||
"math.Asinh": "math.asinh",
|
||||
"math.Acos": "math.acos",
|
||||
"math.Acosh": "math.acosh",
|
||||
"math.Atan": "math.atan",
|
||||
"math.Atanh": "math.atanh",
|
||||
"math.Atan2": "math.atan2",
|
||||
"math.Cbrt": "math.cbrt",
|
||||
"math.Ceil": "math.ceil",
|
||||
"math.archCeil": "math.ceil",
|
||||
"math.Cos": "math.cos",
|
||||
"math.Cosh": "math.cosh",
|
||||
"math.Erf": "math.erf",
|
||||
"math.Erfc": "math.erfc",
|
||||
"math.Exp": "math.exp",
|
||||
"math.archExp": "math.exp",
|
||||
"math.Expm1": "math.expm1",
|
||||
"math.Exp2": "math.exp2",
|
||||
"math.archExp2": "math.exp2",
|
||||
"math.Floor": "math.floor",
|
||||
"math.archFloor": "math.floor",
|
||||
"math.Frexp": "math.frexp",
|
||||
"math.Hypot": "math.hypot",
|
||||
"math.archHypot": "math.hypot",
|
||||
"math.Ldexp": "math.ldexp",
|
||||
"math.Log": "math.log",
|
||||
"math.archLog": "math.log",
|
||||
"math.Log1p": "math.log1p",
|
||||
"math.Log10": "math.log10",
|
||||
"math.Log2": "math.log2",
|
||||
"math.Max": "math.max",
|
||||
"math.archMax": "math.max",
|
||||
"math.Min": "math.min",
|
||||
"math.archMin": "math.min",
|
||||
"math.Mod": "math.mod",
|
||||
"math.Modf": "math.modf",
|
||||
"math.archModf": "math.modf",
|
||||
"math.Pow": "math.pow",
|
||||
"math.Remainder": "math.remainder",
|
||||
"math.Sin": "math.sin",
|
||||
"math.Sinh": "math.sinh",
|
||||
"math.Sqrt": "math.sqrt",
|
||||
"math.archSqrt": "math.sqrt",
|
||||
"math.Tan": "math.tan",
|
||||
"math.Tanh": "math.tanh",
|
||||
"math.Trunc": "math.trunc",
|
||||
"math.archTrunc": "math.trunc",
|
||||
}
|
||||
|
||||
// createAlias implements the function (in the builder) as a call to the alias
|
||||
|
||||
+24
-32
@@ -22,6 +22,10 @@ import (
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
var typeParamUnderlyingType = func(t types.Type) types.Type {
|
||||
return t
|
||||
}
|
||||
|
||||
func init() {
|
||||
llvm.InitializeAllTargets()
|
||||
llvm.InitializeAllTargetMCs()
|
||||
@@ -341,6 +345,7 @@ func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
|
||||
// makeLLVMType creates a LLVM type for a Go type. Don't call this, use
|
||||
// getLLVMType instead.
|
||||
func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
|
||||
goType = typeParamUnderlyingType(goType)
|
||||
switch typ := goType.(type) {
|
||||
case *types.Array:
|
||||
elemType := c.getLLVMType(typ.Elem())
|
||||
@@ -415,8 +420,6 @@ func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
|
||||
members[i] = c.getLLVMType(typ.Field(i).Type())
|
||||
}
|
||||
return c.ctx.StructType(members, false)
|
||||
case *types.TypeParam:
|
||||
return c.getLLVMType(typ.Underlying())
|
||||
case *types.Tuple:
|
||||
members := make([]llvm.Type, typ.Len())
|
||||
for i := 0; i < typ.Len(); i++ {
|
||||
@@ -452,6 +455,7 @@ func (c *compilerContext) getDIType(typ types.Type) llvm.Metadata {
|
||||
// createDIType creates a new DWARF type. Don't call this function directly,
|
||||
// call getDIType instead.
|
||||
func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
||||
typ = typeParamUnderlyingType(typ)
|
||||
llvmType := c.getLLVMType(typ)
|
||||
sizeInBytes := c.targetData.TypeAllocSize(llvmType)
|
||||
switch typ := typ.(type) {
|
||||
@@ -615,8 +619,6 @@ func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
||||
})
|
||||
temporaryMDNode.ReplaceAllUsesWith(md)
|
||||
return md
|
||||
case *types.TypeParam:
|
||||
return c.getDIType(typ.Underlying())
|
||||
default:
|
||||
panic("unknown type while generating DWARF debug type: " + typ.String())
|
||||
}
|
||||
@@ -686,7 +688,7 @@ func (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata {
|
||||
Name: param.Name(),
|
||||
File: b.getDIFile(pos.Filename),
|
||||
Line: pos.Line,
|
||||
Type: b.getDIType(param.Type()),
|
||||
Type: b.getDIType(variable.Type()),
|
||||
AlwaysPreserve: true,
|
||||
ArgNo: i + 1,
|
||||
})
|
||||
@@ -790,12 +792,6 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
|
||||
}
|
||||
// Create the function definition.
|
||||
b := newBuilder(c, irbuilder, member)
|
||||
if _, ok := mathToLLVMMapping[member.RelString(nil)]; ok {
|
||||
// The body of this function (if there is one) is ignored and
|
||||
// replaced with a LLVM intrinsic call.
|
||||
b.defineMathOp()
|
||||
continue
|
||||
}
|
||||
if member.Blocks == nil {
|
||||
// Try to define this as an intrinsic function.
|
||||
b.defineIntrinsicFunction()
|
||||
@@ -1030,7 +1026,7 @@ func (c *compilerContext) getEmbedFileString(file *loader.EmbedFile) llvm.Value
|
||||
// parameters, create basic blocks, and set up debug information.
|
||||
// This is separated out from createFunction() so that it is also usable to
|
||||
// define compiler intrinsics like the atomic operations in sync/atomic.
|
||||
func (b *builder) createFunctionStart(intrinsic bool) {
|
||||
func (b *builder) createFunctionStart() {
|
||||
if b.DumpSSA {
|
||||
fmt.Printf("\nfunc %s:\n", b.fn)
|
||||
}
|
||||
@@ -1043,17 +1039,9 @@ func (b *builder) createFunctionStart(intrinsic bool) {
|
||||
b.addError(b.fn.Pos(), errValue)
|
||||
return
|
||||
}
|
||||
|
||||
b.addStandardDefinedAttributes(b.llvmFn)
|
||||
if !b.info.exported {
|
||||
// Do not set visibility for local linkage (internal or private).
|
||||
// Otherwise a "local linkage requires default visibility"
|
||||
// assertion error in llvm-project/llvm/include/llvm/IR/GlobalValue.h:236
|
||||
// is thrown.
|
||||
if b.llvmFn.Linkage() != llvm.InternalLinkage &&
|
||||
b.llvmFn.Linkage() != llvm.PrivateLinkage {
|
||||
b.llvmFn.SetVisibility(llvm.HiddenVisibility)
|
||||
}
|
||||
b.llvmFn.SetVisibility(llvm.HiddenVisibility)
|
||||
b.llvmFn.SetUnnamedAddr(true)
|
||||
}
|
||||
if b.info.section != "" {
|
||||
@@ -1103,20 +1091,20 @@ func (b *builder) createFunctionStart(intrinsic bool) {
|
||||
}
|
||||
|
||||
// Pre-create all basic blocks in the function.
|
||||
for _, block := range b.fn.DomPreorder() {
|
||||
llvmBlock := b.ctx.AddBasicBlock(b.llvmFn, block.Comment)
|
||||
b.blockEntries[block] = llvmBlock
|
||||
b.blockExits[block] = llvmBlock
|
||||
}
|
||||
var entryBlock llvm.BasicBlock
|
||||
if intrinsic {
|
||||
if len(b.fn.Blocks) != 0 {
|
||||
// Normal functions have an entry block.
|
||||
entryBlock = b.blockEntries[b.fn.Blocks[0]]
|
||||
} else {
|
||||
// This function isn't defined in Go SSA. It is probably a compiler
|
||||
// intrinsic (like an atomic operation). Create the entry block
|
||||
// manually.
|
||||
entryBlock = b.ctx.AddBasicBlock(b.llvmFn, "entry")
|
||||
} else {
|
||||
for _, block := range b.fn.DomPreorder() {
|
||||
llvmBlock := b.ctx.AddBasicBlock(b.llvmFn, block.Comment)
|
||||
b.blockEntries[block] = llvmBlock
|
||||
b.blockExits[block] = llvmBlock
|
||||
}
|
||||
// Normal functions have an entry block.
|
||||
entryBlock = b.blockEntries[b.fn.Blocks[0]]
|
||||
}
|
||||
b.SetInsertPointAtEnd(entryBlock)
|
||||
|
||||
@@ -1198,7 +1186,7 @@ func (b *builder) createFunctionStart(intrinsic bool) {
|
||||
// function must not yet be defined, otherwise this function will create a
|
||||
// diagnostic.
|
||||
func (b *builder) createFunction() {
|
||||
b.createFunctionStart(false)
|
||||
b.createFunctionStart()
|
||||
|
||||
// Fill blocks with instructions.
|
||||
for _, block := range b.fn.DomPreorder() {
|
||||
@@ -1277,7 +1265,6 @@ func (b *builder) createFunction() {
|
||||
// Create anonymous functions (closures etc.).
|
||||
for _, sub := range b.fn.AnonFuncs {
|
||||
b := newBuilder(b.compilerContext, b.Builder, sub)
|
||||
b.llvmFn.SetLinkage(llvm.InternalLinkage)
|
||||
b.createFunction()
|
||||
}
|
||||
}
|
||||
@@ -1660,6 +1647,11 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
||||
// applied) function call. If it is anonymous, it may be a closure.
|
||||
name := fn.RelString(nil)
|
||||
switch {
|
||||
case name == "math.Ceil" || name == "math.Floor" || name == "math.Sqrt" || name == "math.Trunc":
|
||||
result, ok := b.createMathOp(instr)
|
||||
if ok {
|
||||
return result, nil
|
||||
}
|
||||
case name == "device.Asm" || name == "device/arm.Asm" || name == "device/arm64.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm":
|
||||
return b.createInlineAsm(instr.Args)
|
||||
case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package compiler
|
||||
|
||||
// Workaround for Go 1.17 support. Should be removed once we drop Go 1.17
|
||||
// support.
|
||||
|
||||
import "go/types"
|
||||
|
||||
func init() {
|
||||
typeParamUnderlyingType = func(t types.Type) types.Type {
|
||||
if t, ok := t.(*types.TypeParam); ok {
|
||||
return t.Underlying()
|
||||
}
|
||||
return t
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,13 @@ package compiler
|
||||
import (
|
||||
"flag"
|
||||
"go/types"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
"github.com/tinygo-org/tinygo/loader"
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
@@ -27,6 +28,18 @@ type testCase struct {
|
||||
func TestCompiler(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Determine LLVM version.
|
||||
llvmMajor, err := strconv.Atoi(strings.SplitN(llvm.Version, ".", 2)[0])
|
||||
if err != nil {
|
||||
t.Fatal("could not parse LLVM version:", llvm.Version)
|
||||
}
|
||||
|
||||
// Determine Go minor version (e.g. 16 in go1.16.3).
|
||||
_, goMinor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
|
||||
if err != nil {
|
||||
t.Fatal("could not read Go version:", err)
|
||||
}
|
||||
|
||||
// Determine which tests to run, depending on the Go and LLVM versions.
|
||||
tests := []testCase{
|
||||
{"basic.go", "", ""},
|
||||
@@ -41,8 +54,20 @@ func TestCompiler(t *testing.T) {
|
||||
{"goroutine.go", "wasm", "asyncify"},
|
||||
{"goroutine.go", "cortex-m-qemu", "tasks"},
|
||||
{"channel.go", "", ""},
|
||||
{"intrinsics.go", "cortex-m-qemu", ""},
|
||||
{"intrinsics.go", "wasm", ""},
|
||||
{"gc.go", "", ""},
|
||||
}
|
||||
if llvmMajor >= 12 {
|
||||
tests = append(tests, testCase{"intrinsics.go", "cortex-m-qemu", ""})
|
||||
tests = append(tests, testCase{"intrinsics.go", "wasm", ""})
|
||||
}
|
||||
if goMinor >= 17 {
|
||||
tests = append(tests, testCase{"go1.17.go", "", ""})
|
||||
}
|
||||
if goMinor >= 18 {
|
||||
tests = append(tests, testCase{"generics.go", "", ""})
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
name := tc.file
|
||||
@@ -79,7 +104,7 @@ func TestCompiler(t *testing.T) {
|
||||
RelocationModel: config.RelocationModel(),
|
||||
Scheduler: config.Scheduler(),
|
||||
AutomaticStackSize: config.AutomaticStackSize(),
|
||||
DefaultStackSize: config.StackSize(),
|
||||
DefaultStackSize: config.Target.DefaultStackSize,
|
||||
NeedsStackObjects: config.NeedsStackObjects(),
|
||||
}
|
||||
machine, err := NewTargetMachine(compilerConfig)
|
||||
@@ -137,14 +162,14 @@ func TestCompiler(t *testing.T) {
|
||||
|
||||
// Update test if needed. Do not check the result.
|
||||
if *flagUpdate {
|
||||
err := os.WriteFile(outPath, []byte(mod.String()), 0666)
|
||||
err := ioutil.WriteFile(outPath, []byte(mod.String()), 0666)
|
||||
if err != nil {
|
||||
t.Error("failed to write updated output file:", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
expected, err := os.ReadFile(outPath)
|
||||
expected, err := ioutil.ReadFile(outPath)
|
||||
if err != nil {
|
||||
t.Fatal("failed to read golden file:", err)
|
||||
}
|
||||
|
||||
@@ -120,16 +120,16 @@ func (b *builder) createGo(instr *ssa.Go) {
|
||||
// createGoroutineStartWrapper creates a wrapper for the task-based
|
||||
// implementation of goroutines. For example, to call a function like this:
|
||||
//
|
||||
// func add(x, y int) int { ... }
|
||||
// func add(x, y int) int { ... }
|
||||
//
|
||||
// It creates a wrapper like this:
|
||||
//
|
||||
// func add$gowrapper(ptr *unsafe.Pointer) {
|
||||
// args := (*struct{
|
||||
// x, y int
|
||||
// })(ptr)
|
||||
// add(args.x, args.y)
|
||||
// }
|
||||
// func add$gowrapper(ptr *unsafe.Pointer) {
|
||||
// args := (*struct{
|
||||
// x, y int
|
||||
// })(ptr)
|
||||
// add(args.x, args.y)
|
||||
// }
|
||||
//
|
||||
// This is useful because the task-based goroutine start implementation only
|
||||
// allows a single (pointer) argument to the newly started goroutine. Also, it
|
||||
|
||||
+22
-22
@@ -17,7 +17,7 @@ import (
|
||||
// operands or return values. It is useful for trivial instructions, like wfi in
|
||||
// ARM or sleep in AVR.
|
||||
//
|
||||
// func Asm(asm string)
|
||||
// func Asm(asm string)
|
||||
//
|
||||
// The provided assembly must be a constant.
|
||||
func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
|
||||
@@ -31,17 +31,17 @@ func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) {
|
||||
// This is a compiler builtin, which allows assembly to be called in a flexible
|
||||
// way.
|
||||
//
|
||||
// func AsmFull(asm string, regs map[string]interface{}) uintptr
|
||||
// func AsmFull(asm string, regs map[string]interface{}) uintptr
|
||||
//
|
||||
// The asm parameter must be a constant string. The regs parameter must be
|
||||
// provided immediately. For example:
|
||||
//
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) {
|
||||
asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)
|
||||
registers := map[string]llvm.Value{}
|
||||
@@ -132,11 +132,11 @@ func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error)
|
||||
// This is a compiler builtin which emits an inline SVCall instruction. It can
|
||||
// be one of:
|
||||
//
|
||||
// func SVCall0(num uintptr) uintptr
|
||||
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||
// func SVCall0(num uintptr) uintptr
|
||||
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||
//
|
||||
// The num parameter must be a constant. All other parameters may be any scalar
|
||||
// value supported by LLVM inline assembly.
|
||||
@@ -169,11 +169,11 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) {
|
||||
// This is a compiler builtin which emits an inline SVCall instruction. It can
|
||||
// be one of:
|
||||
//
|
||||
// func SVCall0(num uintptr) uintptr
|
||||
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||
// func SVCall0(num uintptr) uintptr
|
||||
// func SVCall1(num uintptr, a1 interface{}) uintptr
|
||||
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr
|
||||
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
|
||||
// func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
|
||||
//
|
||||
// The num parameter must be a constant. All other parameters may be any scalar
|
||||
// value supported by LLVM inline assembly.
|
||||
@@ -206,10 +206,10 @@ func (b *builder) emitSV64Call(args []ssa.Value) (llvm.Value, error) {
|
||||
|
||||
// This is a compiler builtin which emits CSR instructions. It can be one of:
|
||||
//
|
||||
// func (csr CSR) Get() uintptr
|
||||
// func (csr CSR) Set(uintptr)
|
||||
// func (csr CSR) SetBits(uintptr) uintptr
|
||||
// func (csr CSR) ClearBits(uintptr) uintptr
|
||||
// func (csr CSR) Get() uintptr
|
||||
// func (csr CSR) Set(uintptr)
|
||||
// func (csr CSR) SetBits(uintptr) uintptr
|
||||
// func (csr CSR) ClearBits(uintptr) uintptr
|
||||
//
|
||||
// The csr parameter (method receiver) must be a constant. Other parameter can
|
||||
// be any value.
|
||||
|
||||
@@ -550,8 +550,8 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFn llv
|
||||
// internally to match interfaces and to call the correct method on an
|
||||
// interface. Examples:
|
||||
//
|
||||
// String() string
|
||||
// Read([]byte) (int, error)
|
||||
// String() string
|
||||
// Read([]byte) (int, error)
|
||||
func methodSignature(method *types.Func) string {
|
||||
return method.Name() + signature(method.Type().(*types.Signature))
|
||||
}
|
||||
@@ -559,8 +559,8 @@ func methodSignature(method *types.Func) string {
|
||||
// Make a readable version of a function (pointer) signature.
|
||||
// Examples:
|
||||
//
|
||||
// () string
|
||||
// (string, int) (int, error)
|
||||
// () string
|
||||
// (string, int) (int, error)
|
||||
func signature(sig *types.Signature) string {
|
||||
s := ""
|
||||
if sig.Params().Len() == 0 {
|
||||
|
||||
+42
-30
@@ -7,6 +7,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
|
||||
@@ -28,7 +29,7 @@ func (b *builder) defineIntrinsicFunction() {
|
||||
case strings.HasPrefix(name, "runtime/volatile.Store"):
|
||||
b.createVolatileStore()
|
||||
case strings.HasPrefix(name, "sync/atomic.") && token.IsExported(b.fn.Name()):
|
||||
b.createFunctionStart(true)
|
||||
b.createFunctionStart()
|
||||
returnValue := b.createAtomicOp(b.fn.Name())
|
||||
if !returnValue.IsNil() {
|
||||
b.CreateRet(returnValue)
|
||||
@@ -43,7 +44,7 @@ func (b *builder) defineIntrinsicFunction() {
|
||||
// specially by optimization passes possibly resulting in better generated code,
|
||||
// and will otherwise be lowered to regular libc memcpy/memmove calls.
|
||||
func (b *builder) createMemoryCopyImpl() {
|
||||
b.createFunctionStart(true)
|
||||
b.createFunctionStart()
|
||||
fnName := "llvm." + b.fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
||||
llvmFn := b.mod.NamedFunction(fnName)
|
||||
if llvmFn.IsNil() {
|
||||
@@ -63,7 +64,7 @@ func (b *builder) createMemoryCopyImpl() {
|
||||
// memory, declaring the function if needed. These calls will be lowered to
|
||||
// regular libc memset calls if they aren't optimized out in a different way.
|
||||
func (b *builder) createMemoryZeroImpl() {
|
||||
b.createFunctionStart(true)
|
||||
b.createFunctionStart()
|
||||
fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
|
||||
llvmFn := b.mod.NamedFunction(fnName)
|
||||
if llvmFn.IsNil() {
|
||||
@@ -81,44 +82,55 @@ func (b *builder) createMemoryZeroImpl() {
|
||||
}
|
||||
|
||||
var mathToLLVMMapping = map[string]string{
|
||||
"math.Ceil": "llvm.ceil.f64",
|
||||
"math.Exp": "llvm.exp.f64",
|
||||
"math.Exp2": "llvm.exp2.f64",
|
||||
"math.Floor": "llvm.floor.f64",
|
||||
"math.Log": "llvm.log.f64",
|
||||
"math.Sqrt": "llvm.sqrt.f64",
|
||||
"math.Floor": "llvm.floor.f64",
|
||||
"math.Ceil": "llvm.ceil.f64",
|
||||
"math.Trunc": "llvm.trunc.f64",
|
||||
}
|
||||
|
||||
// defineMathOp defines a math function body as a call to a LLVM intrinsic,
|
||||
// instead of the regular Go implementation. This allows LLVM to reason about
|
||||
// the math operation and (depending on the architecture) allows it to lower the
|
||||
// operation to very fast floating point instructions. If this is not possible,
|
||||
// LLVM will emit a call to a libm function that implements the same operation.
|
||||
//
|
||||
// One example of an optimization that LLVM can do is to convert
|
||||
// float32(math.Sqrt(float64(v))) to a 32-bit floating point operation, which is
|
||||
// beneficial on architectures where 64-bit floating point operations are (much)
|
||||
// more expensive than 32-bit ones.
|
||||
func (b *builder) defineMathOp() {
|
||||
b.createFunctionStart(true)
|
||||
llvmName := mathToLLVMMapping[b.fn.RelString(nil)]
|
||||
if llvmName == "" {
|
||||
panic("unreachable: unknown math operation") // sanity check
|
||||
// createMathOp tries to lower the given call as a LLVM math intrinsic, if
|
||||
// possible. It returns the call result if possible, and a boolean whether it
|
||||
// succeeded. If it doesn't succeed, the architecture doesn't support the given
|
||||
// intrinsic.
|
||||
func (b *builder) createMathOp(call *ssa.CallCommon) (llvm.Value, bool) {
|
||||
// Check whether this intrinsic is supported on the given GOARCH.
|
||||
// If it is unsupported, this can have two reasons:
|
||||
//
|
||||
// 1. LLVM can expand the intrinsic inline (using float instructions), but
|
||||
// the result doesn't pass the tests of the math package.
|
||||
// 2. LLVM cannot expand the intrinsic inline, will therefore lower it as a
|
||||
// libm function call, but the libm function call also fails the math
|
||||
// package tests.
|
||||
//
|
||||
// Whatever the implementation, it must pass the tests in the math package
|
||||
// so unfortunately only the below intrinsic+architecture combinations are
|
||||
// supported.
|
||||
name := call.StaticCallee().RelString(nil)
|
||||
switch name {
|
||||
case "math.Ceil", "math.Floor", "math.Trunc":
|
||||
if b.GOARCH != "wasm" && b.GOARCH != "arm64" {
|
||||
return llvm.Value{}, false
|
||||
}
|
||||
case "math.Sqrt":
|
||||
if b.GOARCH != "wasm" && b.GOARCH != "amd64" && b.GOARCH != "386" {
|
||||
return llvm.Value{}, false
|
||||
}
|
||||
default:
|
||||
return llvm.Value{}, false // only the above functions are supported.
|
||||
}
|
||||
llvmFn := b.mod.NamedFunction(llvmName)
|
||||
|
||||
llvmFn := b.mod.NamedFunction(mathToLLVMMapping[name])
|
||||
if llvmFn.IsNil() {
|
||||
// The intrinsic doesn't exist yet, so declare it.
|
||||
// At the moment, all supported intrinsics have the form "double
|
||||
// foo(double %x)" so we can hardcode the signature here.
|
||||
llvmType := llvm.FunctionType(b.ctx.DoubleType(), []llvm.Type{b.ctx.DoubleType()}, false)
|
||||
llvmFn = llvm.AddFunction(b.mod, llvmName, llvmType)
|
||||
llvmFn = llvm.AddFunction(b.mod, mathToLLVMMapping[name], llvmType)
|
||||
}
|
||||
// Create a call to the intrinsic.
|
||||
args := make([]llvm.Value, len(b.fn.Params))
|
||||
for i, param := range b.fn.Params {
|
||||
args[i] = b.getValue(param)
|
||||
args := make([]llvm.Value, len(call.Args))
|
||||
for i, arg := range call.Args {
|
||||
args[i] = b.getValue(arg)
|
||||
}
|
||||
result := b.CreateCall(llvmFn, args, "")
|
||||
b.CreateRet(result)
|
||||
return b.CreateCall(llvmFn, args, ""), true
|
||||
}
|
||||
|
||||
+1
-1
@@ -152,7 +152,7 @@ func (s *stdSizes) Sizeof(T types.Type) int64 {
|
||||
return align(offsets[n-1]+s.Sizeof(fields[n-1].Type()), maxAlign)
|
||||
case *types.Interface:
|
||||
return s.PtrSize * 2
|
||||
case *types.Pointer, *types.Chan, *types.Map:
|
||||
case *types.Pointer:
|
||||
return s.PtrSize
|
||||
case *types.Signature:
|
||||
// Func values in TinyGo are two words in size.
|
||||
|
||||
+10
-12
@@ -163,20 +163,18 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value {
|
||||
// External/exported functions may not retain pointer values.
|
||||
// https://golang.org/cmd/cgo/#hdr-Passing_pointers
|
||||
if info.exported {
|
||||
if c.archFamily() == "wasm32" {
|
||||
// We need to add the wasm-import-module and the wasm-import-name
|
||||
// attributes.
|
||||
module := info.module
|
||||
if module == "" {
|
||||
module = "env"
|
||||
}
|
||||
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-module", module))
|
||||
// Set the wasm-import-module attribute if the function's module is set.
|
||||
if info.module != "" {
|
||||
|
||||
name := info.importName
|
||||
if name == "" {
|
||||
name = info.linkName
|
||||
// We need to add the wasm-import-module and the wasm-import-name
|
||||
wasmImportModuleAttr := c.ctx.CreateStringAttribute("wasm-import-module", info.module)
|
||||
llvmFn.AddFunctionAttr(wasmImportModuleAttr)
|
||||
|
||||
// Add the Wasm Import Name, if we are a named wasm import
|
||||
if info.importName != "" {
|
||||
wasmImportNameAttr := c.ctx.CreateStringAttribute("wasm-import-name", info.importName)
|
||||
llvmFn.AddFunctionAttr(wasmImportNameAttr)
|
||||
}
|
||||
llvmFn.AddFunctionAttr(c.ctx.CreateStringAttribute("wasm-import-name", name))
|
||||
}
|
||||
nocaptureKind := llvm.AttributeKindID("nocapture")
|
||||
nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0)
|
||||
|
||||
Vendored
+1
-1
@@ -196,7 +196,7 @@ entry:
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @"main.foo$1"(%main.kv.0* dereferenceable_or_null(1) %b, i8* %context) unnamed_addr #1 {
|
||||
define hidden void @"main.foo$1"(%main.kv.0* dereferenceable_or_null(1) %b, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
+3
-3
@@ -115,7 +115,7 @@ declare i8* @llvm.stacksave() #2
|
||||
declare void @runtime.setupDeferFrame(%runtime.deferFrame* dereferenceable_or_null(24), i8*, i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @"main.deferSimple$1"(i8* %context) unnamed_addr #1 {
|
||||
define hidden void @"main.deferSimple$1"(i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
call void @runtime.printint32(i32 3, i8* undef) #3
|
||||
ret void
|
||||
@@ -246,14 +246,14 @@ rundefers.end9: ; preds = %rundefers.loophead1
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @"main.deferMultiple$1"(i8* %context) unnamed_addr #1 {
|
||||
define hidden void @"main.deferMultiple$1"(i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
call void @runtime.printint32(i32 3, i8* undef) #3
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @"main.deferMultiple$2"(i8* %context) unnamed_addr #1 {
|
||||
define hidden void @"main.deferMultiple$2"(i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
call void @runtime.printint32(i32 5, i8* undef) #3
|
||||
ret void
|
||||
|
||||
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
// Test changes to the language introduced in Go 1.17.
|
||||
// For details, see: https://tip.golang.org/doc/go1.17#language
|
||||
// These tests should be merged into the regular slice tests once Go 1.17 is the
|
||||
// minimun Go version for TinyGo.
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func Add32(p unsafe.Pointer, len int) unsafe.Pointer {
|
||||
return unsafe.Add(p, len)
|
||||
}
|
||||
|
||||
func Add64(p unsafe.Pointer, len int64) unsafe.Pointer {
|
||||
return unsafe.Add(p, len)
|
||||
}
|
||||
|
||||
func SliceToArray(s []int) *[4]int {
|
||||
return (*[4]int)(s)
|
||||
}
|
||||
|
||||
func SliceToArrayConst() *[4]int {
|
||||
s := make([]int, 6)
|
||||
return (*[4]int)(s)
|
||||
}
|
||||
|
||||
func SliceInt(ptr *int, len int) []int {
|
||||
return unsafe.Slice(ptr, len)
|
||||
}
|
||||
|
||||
func SliceUint16(ptr *byte, len uint16) []byte {
|
||||
return unsafe.Slice(ptr, len)
|
||||
}
|
||||
|
||||
func SliceUint64(ptr *int, len uint64) []int {
|
||||
return unsafe.Slice(ptr, len)
|
||||
}
|
||||
|
||||
func SliceInt64(ptr *int, len int64) []int {
|
||||
return unsafe.Slice(ptr, len)
|
||||
}
|
||||
Vendored
+161
@@ -0,0 +1,161 @@
|
||||
; ModuleID = 'go1.17.go'
|
||||
source_filename = "go1.17.go"
|
||||
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
|
||||
target triple = "wasm32-unknown-wasi"
|
||||
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
|
||||
|
||||
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.init(i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden i8* @main.Add32(i8* %p, i32 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = getelementptr i8, i8* %p, i32 %len
|
||||
call void @runtime.trackPointer(i8* %0, i8* undef) #2
|
||||
ret i8* %0
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden i8* @main.Add64(i8* %p, i64 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = trunc i64 %len to i32
|
||||
%1 = getelementptr i8, i8* %p, i32 %0
|
||||
call void @runtime.trackPointer(i8* %1, i8* undef) #2
|
||||
ret i8* %1
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden [4 x i32]* @main.SliceToArray(i32* %s.data, i32 %s.len, i32 %s.cap, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp ult i32 %s.len, 4
|
||||
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
|
||||
|
||||
slicetoarray.next: ; preds = %entry
|
||||
%1 = bitcast i32* %s.data to [4 x i32]*
|
||||
ret [4 x i32]* %1
|
||||
|
||||
slicetoarray.throw: ; preds = %entry
|
||||
call void @runtime.sliceToArrayPointerPanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
declare void @runtime.sliceToArrayPointerPanic(i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%makeslice = call i8* @runtime.alloc(i32 24, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2
|
||||
call void @runtime.trackPointer(i8* nonnull %makeslice, i8* undef) #2
|
||||
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
|
||||
|
||||
slicetoarray.next: ; preds = %entry
|
||||
%0 = bitcast i8* %makeslice to [4 x i32]*
|
||||
ret [4 x i32]* %0
|
||||
|
||||
slicetoarray.throw: ; preds = %entry
|
||||
unreachable
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden { i32*, i32, i32 } @main.SliceInt(i32* dereferenceable_or_null(4) %ptr, i32 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp ugt i32 %len, 1073741823
|
||||
%1 = icmp eq i32* %ptr, null
|
||||
%2 = icmp ne i32 %len, 0
|
||||
%3 = and i1 %1, %2
|
||||
%4 = or i1 %3, %0
|
||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||
|
||||
unsafe.Slice.next: ; preds = %entry
|
||||
%5 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||
%6 = insertvalue { i32*, i32, i32 } %5, i32 %len, 1
|
||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %len, 2
|
||||
%8 = bitcast i32* %ptr to i8*
|
||||
call void @runtime.trackPointer(i8* %8, i8* undef) #2
|
||||
ret { i32*, i32, i32 } %7
|
||||
|
||||
unsafe.Slice.throw: ; preds = %entry
|
||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
declare void @runtime.unsafeSlicePanic(i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden { i8*, i32, i32 } @main.SliceUint16(i8* dereferenceable_or_null(1) %ptr, i16 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp eq i8* %ptr, null
|
||||
%1 = icmp ne i16 %len, 0
|
||||
%2 = and i1 %0, %1
|
||||
br i1 %2, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||
|
||||
unsafe.Slice.next: ; preds = %entry
|
||||
%3 = zext i16 %len to i32
|
||||
%4 = insertvalue { i8*, i32, i32 } undef, i8* %ptr, 0
|
||||
%5 = insertvalue { i8*, i32, i32 } %4, i32 %3, 1
|
||||
%6 = insertvalue { i8*, i32, i32 } %5, i32 %3, 2
|
||||
call void @runtime.trackPointer(i8* %ptr, i8* undef) #2
|
||||
ret { i8*, i32, i32 } %6
|
||||
|
||||
unsafe.Slice.throw: ; preds = %entry
|
||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden { i32*, i32, i32 } @main.SliceUint64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp ugt i64 %len, 1073741823
|
||||
%1 = icmp eq i32* %ptr, null
|
||||
%2 = icmp ne i64 %len, 0
|
||||
%3 = and i1 %1, %2
|
||||
%4 = or i1 %3, %0
|
||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||
|
||||
unsafe.Slice.next: ; preds = %entry
|
||||
%5 = trunc i64 %len to i32
|
||||
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
|
||||
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
|
||||
%9 = bitcast i32* %ptr to i8*
|
||||
call void @runtime.trackPointer(i8* %9, i8* undef) #2
|
||||
ret { i32*, i32, i32 } %8
|
||||
|
||||
unsafe.Slice.throw: ; preds = %entry
|
||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden { i32*, i32, i32 } @main.SliceInt64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp ugt i64 %len, 1073741823
|
||||
%1 = icmp eq i32* %ptr, null
|
||||
%2 = icmp ne i64 %len, 0
|
||||
%3 = and i1 %1, %2
|
||||
%4 = or i1 %3, %0
|
||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||
|
||||
unsafe.Slice.next: ; preds = %entry
|
||||
%5 = trunc i64 %len to i32
|
||||
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
|
||||
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
|
||||
%9 = bitcast i32* %ptr to i8*
|
||||
call void @runtime.trackPointer(i8* %9, i8* undef) #2
|
||||
ret { i32*, i32, i32 } %8
|
||||
|
||||
unsafe.Slice.throw: ; preds = %entry
|
||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #2 = { nounwind }
|
||||
+2
-2
@@ -51,7 +51,7 @@ entry:
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 {
|
||||
define hidden void @"main.inlineFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
@@ -84,7 +84,7 @@ entry:
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 {
|
||||
define hidden void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%unpack.ptr = bitcast i8* %context to i32*
|
||||
store i32 7, i32* %unpack.ptr, align 4
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ entry:
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @"main.inlineFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 {
|
||||
define hidden void @"main.inlineFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
@@ -90,7 +90,7 @@ entry:
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define internal void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 {
|
||||
define hidden void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%unpack.ptr = bitcast i8* %context to i32*
|
||||
store i32 7, i32* %unpack.ptr, align 4
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
; ModuleID = 'intrinsics.go'
|
||||
source_filename = "intrinsics.go"
|
||||
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
|
||||
target triple = "thumbv7m-unknown-unknown-eabi"
|
||||
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.init(i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden double @main.mySqrt(double %x, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = call double @math.Sqrt(double %x, i8* undef) #2
|
||||
ret double %0
|
||||
}
|
||||
|
||||
declare double @math.Sqrt(double, i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden double @main.myTrunc(double %x, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = call double @math.Trunc(double %x, i8* undef) #2
|
||||
ret double %0
|
||||
}
|
||||
|
||||
declare double @math.Trunc(double, i8*) #0
|
||||
|
||||
attributes #0 = { "target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
|
||||
attributes #1 = { nounwind "target-features"="+armv7-m,+hwdiv,+soft-float,+strict-align,+thumb-mode,-aes,-bf16,-cdecp0,-cdecp1,-cdecp2,-cdecp3,-cdecp4,-cdecp5,-cdecp6,-cdecp7,-crc,-crypto,-d32,-dotprod,-dsp,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-hwdiv-arm,-i8mm,-lob,-mve,-mve.fp,-neon,-pacbti,-ras,-sb,-sha2,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" }
|
||||
attributes #2 = { nounwind }
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
; ModuleID = 'intrinsics.go'
|
||||
source_filename = "intrinsics.go"
|
||||
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
|
||||
target triple = "wasm32-unknown-wasi"
|
||||
|
||||
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*) #0
|
||||
|
||||
declare void @runtime.trackPointer(i8* nocapture readonly, i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden void @main.init(i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden double @main.mySqrt(double %x, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = call double @llvm.sqrt.f64(double %x)
|
||||
ret double %0
|
||||
}
|
||||
|
||||
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
|
||||
declare double @llvm.sqrt.f64(double) #2
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden double @main.myTrunc(double %x, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = call double @llvm.trunc.f64(double %x)
|
||||
ret double %0
|
||||
}
|
||||
|
||||
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
|
||||
declare double @llvm.trunc.f64(double) #2
|
||||
|
||||
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #2 = { nofree nosync nounwind readnone speculatable willreturn }
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
// Test how intrinsics are lowered: either as regular calls to the math
|
||||
// functions or as LLVM builtins (such as llvm.sqrt.f64).
|
||||
|
||||
import "math"
|
||||
|
||||
func mySqrt(x float64) float64 {
|
||||
return math.Sqrt(x)
|
||||
}
|
||||
|
||||
func myTrunc(x float64) float64 {
|
||||
return math.Trunc(x)
|
||||
}
|
||||
Vendored
-10
@@ -3,53 +3,44 @@ package main
|
||||
import _ "unsafe"
|
||||
|
||||
// Creates an external global with name extern_global.
|
||||
//
|
||||
//go:extern extern_global
|
||||
var externGlobal [0]byte
|
||||
|
||||
// Creates a
|
||||
//
|
||||
//go:align 32
|
||||
var alignedGlobal [4]uint32
|
||||
|
||||
// Test conflicting pragmas (the last one counts).
|
||||
//
|
||||
//go:align 64
|
||||
//go:align 16
|
||||
var alignedGlobal16 [4]uint32
|
||||
|
||||
// Test exported functions.
|
||||
//
|
||||
//export extern_func
|
||||
func externFunc() {
|
||||
}
|
||||
|
||||
// Define a function in a different package using go:linkname.
|
||||
//
|
||||
//go:linkname withLinkageName1 somepkg.someFunction1
|
||||
func withLinkageName1() {
|
||||
}
|
||||
|
||||
// Import a function from a different package using go:linkname.
|
||||
//
|
||||
//go:linkname withLinkageName2 somepkg.someFunction2
|
||||
func withLinkageName2()
|
||||
|
||||
// Function has an 'inline hint', similar to the inline keyword in C.
|
||||
//
|
||||
//go:inline
|
||||
func inlineFunc() {
|
||||
}
|
||||
|
||||
// Function should never be inlined, equivalent to GCC
|
||||
// __attribute__((noinline)).
|
||||
//
|
||||
//go:noinline
|
||||
func noinlineFunc() {
|
||||
}
|
||||
|
||||
// This function should have the specified section.
|
||||
//
|
||||
//go:section .special_function_section
|
||||
func functionInSection() {
|
||||
}
|
||||
@@ -60,7 +51,6 @@ func exportedFunctionInSection() {
|
||||
}
|
||||
|
||||
// This function should not: it's only a declaration and not a definition.
|
||||
//
|
||||
//go:section .special_function_section
|
||||
func undefinedFunctionNotInSection()
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -62,7 +62,7 @@ declare void @main.undefinedFunctionNotInSection(i8*) #0
|
||||
|
||||
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" "wasm-import-module"="env" "wasm-import-name"="extern_func" }
|
||||
attributes #2 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="extern_func" }
|
||||
attributes #3 = { inlinehint nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #4 = { noinline nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" "wasm-import-module"="env" "wasm-import-name"="exportedFunctionInSection" }
|
||||
attributes #5 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" "wasm-export-name"="exportedFunctionInSection" }
|
||||
|
||||
Vendored
-35
@@ -1,7 +1,5 @@
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func sliceLen(ints []int) int {
|
||||
return len(ints)
|
||||
}
|
||||
@@ -43,36 +41,3 @@ func makeArraySlice(len int) [][3]byte {
|
||||
func makeInt32Slice(len int) []int32 {
|
||||
return make([]int32, len)
|
||||
}
|
||||
|
||||
func Add32(p unsafe.Pointer, len int) unsafe.Pointer {
|
||||
return unsafe.Add(p, len)
|
||||
}
|
||||
|
||||
func Add64(p unsafe.Pointer, len int64) unsafe.Pointer {
|
||||
return unsafe.Add(p, len)
|
||||
}
|
||||
|
||||
func SliceToArray(s []int) *[4]int {
|
||||
return (*[4]int)(s)
|
||||
}
|
||||
|
||||
func SliceToArrayConst() *[4]int {
|
||||
s := make([]int, 6)
|
||||
return (*[4]int)(s)
|
||||
}
|
||||
|
||||
func SliceInt(ptr *int, len int) []int {
|
||||
return unsafe.Slice(ptr, len)
|
||||
}
|
||||
|
||||
func SliceUint16(ptr *byte, len uint16) []byte {
|
||||
return unsafe.Slice(ptr, len)
|
||||
}
|
||||
|
||||
func SliceUint64(ptr *int, len uint64) []int {
|
||||
return unsafe.Slice(ptr, len)
|
||||
}
|
||||
|
||||
func SliceInt64(ptr *int, len int64) []int {
|
||||
return unsafe.Slice(ptr, len)
|
||||
}
|
||||
|
||||
Vendored
-143
@@ -183,149 +183,6 @@ slice.throw: ; preds = %entry
|
||||
unreachable
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden i8* @main.Add32(i8* %p, i32 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = getelementptr i8, i8* %p, i32 %len
|
||||
call void @runtime.trackPointer(i8* %0, i8* undef) #2
|
||||
ret i8* %0
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden i8* @main.Add64(i8* %p, i64 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = trunc i64 %len to i32
|
||||
%1 = getelementptr i8, i8* %p, i32 %0
|
||||
call void @runtime.trackPointer(i8* %1, i8* undef) #2
|
||||
ret i8* %1
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden [4 x i32]* @main.SliceToArray(i32* %s.data, i32 %s.len, i32 %s.cap, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp ult i32 %s.len, 4
|
||||
br i1 %0, label %slicetoarray.throw, label %slicetoarray.next
|
||||
|
||||
slicetoarray.next: ; preds = %entry
|
||||
%1 = bitcast i32* %s.data to [4 x i32]*
|
||||
ret [4 x i32]* %1
|
||||
|
||||
slicetoarray.throw: ; preds = %entry
|
||||
call void @runtime.sliceToArrayPointerPanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
declare void @runtime.sliceToArrayPointerPanic(i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden [4 x i32]* @main.SliceToArrayConst(i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%makeslice = call i8* @runtime.alloc(i32 24, i8* nonnull inttoptr (i32 3 to i8*), i8* undef) #2
|
||||
call void @runtime.trackPointer(i8* nonnull %makeslice, i8* undef) #2
|
||||
br i1 false, label %slicetoarray.throw, label %slicetoarray.next
|
||||
|
||||
slicetoarray.next: ; preds = %entry
|
||||
%0 = bitcast i8* %makeslice to [4 x i32]*
|
||||
ret [4 x i32]* %0
|
||||
|
||||
slicetoarray.throw: ; preds = %entry
|
||||
unreachable
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden { i32*, i32, i32 } @main.SliceInt(i32* dereferenceable_or_null(4) %ptr, i32 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp ugt i32 %len, 1073741823
|
||||
%1 = icmp eq i32* %ptr, null
|
||||
%2 = icmp ne i32 %len, 0
|
||||
%3 = and i1 %1, %2
|
||||
%4 = or i1 %3, %0
|
||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||
|
||||
unsafe.Slice.next: ; preds = %entry
|
||||
%5 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||
%6 = insertvalue { i32*, i32, i32 } %5, i32 %len, 1
|
||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %len, 2
|
||||
%8 = bitcast i32* %ptr to i8*
|
||||
call void @runtime.trackPointer(i8* %8, i8* undef) #2
|
||||
ret { i32*, i32, i32 } %7
|
||||
|
||||
unsafe.Slice.throw: ; preds = %entry
|
||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
declare void @runtime.unsafeSlicePanic(i8*) #0
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden { i8*, i32, i32 } @main.SliceUint16(i8* dereferenceable_or_null(1) %ptr, i16 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp eq i8* %ptr, null
|
||||
%1 = icmp ne i16 %len, 0
|
||||
%2 = and i1 %0, %1
|
||||
br i1 %2, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||
|
||||
unsafe.Slice.next: ; preds = %entry
|
||||
%3 = zext i16 %len to i32
|
||||
%4 = insertvalue { i8*, i32, i32 } undef, i8* %ptr, 0
|
||||
%5 = insertvalue { i8*, i32, i32 } %4, i32 %3, 1
|
||||
%6 = insertvalue { i8*, i32, i32 } %5, i32 %3, 2
|
||||
call void @runtime.trackPointer(i8* %ptr, i8* undef) #2
|
||||
ret { i8*, i32, i32 } %6
|
||||
|
||||
unsafe.Slice.throw: ; preds = %entry
|
||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden { i32*, i32, i32 } @main.SliceUint64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp ugt i64 %len, 1073741823
|
||||
%1 = icmp eq i32* %ptr, null
|
||||
%2 = icmp ne i64 %len, 0
|
||||
%3 = and i1 %1, %2
|
||||
%4 = or i1 %3, %0
|
||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||
|
||||
unsafe.Slice.next: ; preds = %entry
|
||||
%5 = trunc i64 %len to i32
|
||||
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
|
||||
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
|
||||
%9 = bitcast i32* %ptr to i8*
|
||||
call void @runtime.trackPointer(i8* %9, i8* undef) #2
|
||||
ret { i32*, i32, i32 } %8
|
||||
|
||||
unsafe.Slice.throw: ; preds = %entry
|
||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define hidden { i32*, i32, i32 } @main.SliceInt64(i32* dereferenceable_or_null(4) %ptr, i64 %len, i8* %context) unnamed_addr #1 {
|
||||
entry:
|
||||
%0 = icmp ugt i64 %len, 1073741823
|
||||
%1 = icmp eq i32* %ptr, null
|
||||
%2 = icmp ne i64 %len, 0
|
||||
%3 = and i1 %1, %2
|
||||
%4 = or i1 %3, %0
|
||||
br i1 %4, label %unsafe.Slice.throw, label %unsafe.Slice.next
|
||||
|
||||
unsafe.Slice.next: ; preds = %entry
|
||||
%5 = trunc i64 %len to i32
|
||||
%6 = insertvalue { i32*, i32, i32 } undef, i32* %ptr, 0
|
||||
%7 = insertvalue { i32*, i32, i32 } %6, i32 %5, 1
|
||||
%8 = insertvalue { i32*, i32, i32 } %7, i32 %5, 2
|
||||
%9 = bitcast i32* %ptr to i8*
|
||||
call void @runtime.trackPointer(i8* %9, i8* undef) #2
|
||||
ret { i32*, i32, i32 } %8
|
||||
|
||||
unsafe.Slice.throw: ; preds = %entry
|
||||
call void @runtime.unsafeSlicePanic(i8* undef) #2
|
||||
unreachable
|
||||
}
|
||||
|
||||
attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
|
||||
attributes #2 = { nounwind }
|
||||
|
||||
@@ -6,7 +6,7 @@ package compiler
|
||||
// createVolatileLoad is the implementation of the intrinsic function
|
||||
// runtime/volatile.LoadT().
|
||||
func (b *builder) createVolatileLoad() {
|
||||
b.createFunctionStart(true)
|
||||
b.createFunctionStart()
|
||||
addr := b.getValue(b.fn.Params[0])
|
||||
b.createNilCheck(b.fn.Params[0], addr, "deref")
|
||||
val := b.CreateLoad(addr, "")
|
||||
@@ -17,7 +17,7 @@ func (b *builder) createVolatileLoad() {
|
||||
// createVolatileStore is the implementation of the intrinsic function
|
||||
// runtime/volatile.StoreT().
|
||||
func (b *builder) createVolatileStore() {
|
||||
b.createFunctionStart(true)
|
||||
b.createFunctionStart()
|
||||
addr := b.getValue(b.fn.Params[0])
|
||||
val := b.getValue(b.fn.Params[1])
|
||||
b.createNilCheck(b.fn.Params[0], addr, "deref")
|
||||
|
||||
+2
-5
@@ -8,7 +8,6 @@ import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/buildutil"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
@@ -112,11 +111,9 @@ func TestCorpus(t *testing.T) {
|
||||
|
||||
opts := optionsFromTarget(target, sema)
|
||||
opts.Directory = dir
|
||||
var tags buildutil.TagsFlag
|
||||
tags.Set(repo.Tags)
|
||||
opts.Tags = []string(tags)
|
||||
opts.Tags = repo.Tags
|
||||
|
||||
passed, err := Test(path, out, out, &opts, false, testing.Verbose(), false, "", "", "", false, "")
|
||||
passed, err := Test(path, out, out, &opts, false, testing.Verbose(), false, "", "", "", "")
|
||||
if err != nil {
|
||||
t.Errorf("test error: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/tinygo-org/tinygo
|
||||
|
||||
go 1.18
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/aykevl/go-wasm v0.0.2-0.20220616010729-4a0a888aebdc
|
||||
@@ -9,25 +9,11 @@ require (
|
||||
github.com/chromedp/chromedp v0.7.6
|
||||
github.com/gofrs/flock v0.8.1
|
||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
|
||||
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
|
||||
github.com/mattn/go-colorable v0.1.8
|
||||
github.com/mattn/go-tty v0.0.4
|
||||
go.bug.st/serial v1.3.5
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
||||
go.bug.st/serial v1.1.3
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
|
||||
golang.org/x/tools v0.1.11
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||
github.com/creack/goselect v0.1.2 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ 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/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
@@ -22,47 +23,61 @@ github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
|
||||
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
|
||||
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s=
|
||||
github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 h1:6J+qramlHVLmiBOgRiBOnQkno8uprqG6YFFQTt6uYIw=
|
||||
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892/go.mod h1:Pb6XcsXyropB9LNHhnqaknG/vEwYztLkQzVCHv8sQ3M=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-tty v0.0.4 h1:NVikla9X8MN0SQAqCYzpGyXv0jY7MNl3HOWD2dkle7E=
|
||||
github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3pxse28=
|
||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
|
||||
github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE=
|
||||
go.bug.st/serial v1.3.5/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.bug.st/serial v1.1.3 h1:YEBxJa9pKS9Wdg46B/jiaKbvvbUrjhZZZITfJHEJhaE=
|
||||
go.bug.st/serial v1.1.3/go.mod h1:8TT7u/SwwNIpJ8QaG4s+HTjFt9ReXs2cdOU7ZEk50Dk=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
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-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
|
||||
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887 h1:k+Y1DU/WoBDkTkRJGF149yk3S2K2VhNglN435DXDS5s=
|
||||
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
|
||||
|
||||
+4
-9
@@ -6,7 +6,6 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
@@ -42,14 +41,10 @@ var TINYGOROOT string
|
||||
func Get(name string) string {
|
||||
switch name {
|
||||
case "GOOS":
|
||||
goos := os.Getenv("GOOS")
|
||||
if goos == "" {
|
||||
goos = runtime.GOOS
|
||||
if dir := os.Getenv("GOOS"); dir != "" {
|
||||
return dir
|
||||
}
|
||||
if goos == "android" {
|
||||
goos = "linux"
|
||||
}
|
||||
return goos
|
||||
return runtime.GOOS
|
||||
case "GOARCH":
|
||||
if dir := os.Getenv("GOARCH"); dir != "" {
|
||||
return dir
|
||||
@@ -127,7 +122,7 @@ func findWasmOpt() string {
|
||||
}
|
||||
|
||||
_, err := os.Stat(path)
|
||||
if err != nil && errors.Is(err, fs.ErrNotExist) {
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// Version of TinyGo.
|
||||
// Update this value before release of new version of software.
|
||||
const Version = "0.26.0-dev"
|
||||
const Version = "0.25.0-dev"
|
||||
|
||||
var (
|
||||
// This variable is set at build time using -ldflags parameters.
|
||||
@@ -54,10 +54,10 @@ func GetGorootVersion(goroot string) (major, minor int, err error) {
|
||||
// toolchain for the given GOROOT path. It is usually of the form `go1.x.y` but
|
||||
// can have some variations (for beta releases, for example).
|
||||
func GorootVersionString(goroot string) (string, error) {
|
||||
if data, err := os.ReadFile(filepath.Join(goroot, "VERSION")); err == nil {
|
||||
if data, err := ioutil.ReadFile(filepath.Join(goroot, "VERSION")); err == nil {
|
||||
return string(data), nil
|
||||
|
||||
} else if data, err := os.ReadFile(filepath.Join(
|
||||
} else if data, err := ioutil.ReadFile(filepath.Join(
|
||||
goroot, "src", "internal", "buildcfg", "zbootstrap.go")); err == nil {
|
||||
|
||||
r := regexp.MustCompile("const version = `(.*)`")
|
||||
|
||||
+5
-7
@@ -30,11 +30,10 @@ type runner struct {
|
||||
objects []object // slice of objects in memory
|
||||
globals map[llvm.Value]int // map from global to index in objects slice
|
||||
start time.Time
|
||||
timeout time.Duration
|
||||
callsExecuted uint64
|
||||
}
|
||||
|
||||
func newRunner(mod llvm.Module, timeout time.Duration, debug bool) *runner {
|
||||
func newRunner(mod llvm.Module, debug bool) *runner {
|
||||
r := runner{
|
||||
mod: mod,
|
||||
targetData: llvm.NewTargetData(mod.DataLayout()),
|
||||
@@ -43,7 +42,6 @@ func newRunner(mod llvm.Module, timeout time.Duration, debug bool) *runner {
|
||||
objects: []object{{}},
|
||||
globals: make(map[llvm.Value]int),
|
||||
start: time.Now(),
|
||||
timeout: timeout,
|
||||
}
|
||||
r.pointerSize = uint32(r.targetData.PointerSize())
|
||||
r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0)
|
||||
@@ -60,8 +58,8 @@ func (r *runner) dispose() {
|
||||
|
||||
// Run evaluates runtime.initAll function as much as possible at compile time.
|
||||
// Set debug to true if it should print output while running.
|
||||
func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
|
||||
r := newRunner(mod, timeout, debug)
|
||||
func Run(mod llvm.Module, debug bool) error {
|
||||
r := newRunner(mod, debug)
|
||||
defer r.dispose()
|
||||
|
||||
initAll := mod.NamedFunction("runtime.initAll")
|
||||
@@ -201,10 +199,10 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
|
||||
|
||||
// RunFunc evaluates a single package initializer at compile time.
|
||||
// Set debug to true if it should print output while running.
|
||||
func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error {
|
||||
func RunFunc(fn llvm.Value, debug bool) error {
|
||||
// Create and initialize *runner object.
|
||||
mod := fn.GlobalParent()
|
||||
r := newRunner(mod, timeout, debug)
|
||||
r := newRunner(mod, debug)
|
||||
defer r.dispose()
|
||||
initName := fn.Name()
|
||||
if !strings.HasSuffix(initName, ".init") {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package interp
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"tinygo.org/x/go-llvm"
|
||||
)
|
||||
@@ -53,7 +53,7 @@ func runTest(t *testing.T, pathPrefix string) {
|
||||
defer mod.Dispose()
|
||||
|
||||
// Perform the transform.
|
||||
err = Run(mod, 10*time.Minute, false)
|
||||
err = Run(mod, false)
|
||||
if err != nil {
|
||||
if err, match := err.(*Error); match {
|
||||
println(err.Error())
|
||||
@@ -87,7 +87,7 @@ func runTest(t *testing.T, pathPrefix string) {
|
||||
pm.Run(mod)
|
||||
|
||||
// Read the expected output IR.
|
||||
out, err := os.ReadFile(pathPrefix + ".out.ll")
|
||||
out, err := ioutil.ReadFile(pathPrefix + ".out.ll")
|
||||
if err != nil {
|
||||
t.Fatalf("could not read output file %s: %v", pathPrefix+".out.ll", err)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
||||
locals := make([]value, len(fn.locals))
|
||||
r.callsExecuted++
|
||||
|
||||
t0 := time.Since(r.start)
|
||||
|
||||
// Parameters are considered a kind of local values.
|
||||
for i, param := range params {
|
||||
locals[i] = param
|
||||
@@ -141,10 +143,11 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
||||
}
|
||||
switch inst.opcode {
|
||||
case llvm.Ret:
|
||||
if time.Since(r.start) > r.timeout {
|
||||
// Running for more than the allowed timeout; This shouldn't happen, but it does.
|
||||
const maxInterpSeconds = 180
|
||||
if t0 > maxInterpSeconds*time.Second {
|
||||
// Running for more than maxInterpSeconds seconds. This should never happen, but does.
|
||||
// See github.com/tinygo-org/tinygo/issues/2124
|
||||
return nil, mem, r.errorAt(fn.blocks[0].instructions[0], fmt.Errorf("interp: running for more than %s, timing out (executed calls: %d)", r.timeout, r.callsExecuted))
|
||||
return nil, mem, r.errorAt(fn.blocks[0].instructions[0], fmt.Errorf("interp: running for more than %d seconds, timing out (executed calls: %d)", maxInterpSeconds, r.callsExecuted))
|
||||
}
|
||||
|
||||
if len(operands) != 0 {
|
||||
@@ -369,11 +372,6 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
|
||||
nBytes := uint32(operands[3].Uint())
|
||||
dstObj := mem.getWritable(dst.index())
|
||||
dstBuf := dstObj.buffer.asRawValue(r)
|
||||
if mem.get(src.index()).buffer == nil {
|
||||
// Looks like the source buffer is not defined.
|
||||
// This can happen with //extern or //go:embed.
|
||||
return nil, mem, r.errorAt(inst, errUnsupportedRuntimeInst)
|
||||
}
|
||||
srcBuf := mem.get(src.index()).buffer.asRawValue(r)
|
||||
copy(dstBuf.buf[dst.offset():dst.offset()+nBytes], srcBuf.buf[src.offset():])
|
||||
dstObj.buffer = dstBuf
|
||||
|
||||
+6
-13
@@ -17,7 +17,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -46,7 +45,7 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
|
||||
}
|
||||
|
||||
// Find the overrides needed for the goroot.
|
||||
overrides := pathsToOverride(config.GoMinorVersion, needsSyscallPackage(config.BuildTags()))
|
||||
overrides := pathsToOverride(needsSyscallPackage(config.BuildTags()))
|
||||
|
||||
// Resolve the merge links within the goroot.
|
||||
merge, err := listGorootMergeLinks(goroot, tinygoroot, overrides)
|
||||
@@ -84,7 +83,7 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
|
||||
}
|
||||
|
||||
// Create a temporary directory to construct the goroot within.
|
||||
tmpgoroot, err := os.MkdirTemp(goenv.Get("GOCACHE"), cachedGorootName+".tmp")
|
||||
tmpgoroot, err := ioutil.TempDir(goenv.Get("GOCACHE"), cachedGorootName+".tmp")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -123,13 +122,13 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
|
||||
// Rename the new merged gorooot into place.
|
||||
err = os.Rename(tmpgoroot, cachedgoroot)
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrExist) {
|
||||
if os.IsExist(err) {
|
||||
// Another invocation of TinyGo also seems to have created a GOROOT.
|
||||
// Use that one instead. Our new GOROOT will be automatically
|
||||
// deleted by the defer above.
|
||||
return cachedgoroot, nil
|
||||
}
|
||||
if runtime.GOOS == "windows" && errors.Is(err, fs.ErrPermission) {
|
||||
if runtime.GOOS == "windows" && os.IsPermission(err) {
|
||||
// On Windows, a rename with a destination directory that already
|
||||
// exists does not result in an IsExist error, but rather in an
|
||||
// access denied error. To be sure, check for this case by checking
|
||||
@@ -223,7 +222,7 @@ func needsSyscallPackage(buildTags []string) bool {
|
||||
|
||||
// The boolean indicates whether to merge the subdirs. True means merge, false
|
||||
// means use the TinyGo version.
|
||||
func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
||||
func pathsToOverride(needsSyscallPackage bool) map[string]bool {
|
||||
paths := map[string]bool{
|
||||
"": true,
|
||||
"crypto/": true,
|
||||
@@ -235,6 +234,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
||||
"internal/bytealg/": false,
|
||||
"internal/reflectlite/": false,
|
||||
"internal/task/": false,
|
||||
"internal/itoa/": false, // TODO: Remove when we drop support for go 1.16
|
||||
"machine/": false,
|
||||
"net/": true,
|
||||
"os/": true,
|
||||
@@ -243,13 +243,6 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
|
||||
"sync/": true,
|
||||
"testing/": true,
|
||||
}
|
||||
|
||||
if goMinor >= 19 {
|
||||
paths["crypto/internal/"] = true
|
||||
paths["crypto/internal/boring/"] = true
|
||||
paths["crypto/internal/boring/sig/"] = false
|
||||
}
|
||||
|
||||
if needsSyscallPackage {
|
||||
paths["syscall/"] = true // include syscall/js
|
||||
}
|
||||
|
||||
+9
-4
@@ -13,6 +13,7 @@ import (
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
@@ -27,6 +28,8 @@ import (
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
)
|
||||
|
||||
var addInstances func(*types.Info)
|
||||
|
||||
// Program holds all packages and some metadata about the program as a whole.
|
||||
type Program struct {
|
||||
config *compileopts.Config
|
||||
@@ -156,7 +159,6 @@ func Load(config *compileopts.Config, inputPkg string, clangHeaders string, type
|
||||
EmbedGlobals: make(map[string][]*EmbedFile),
|
||||
info: types.Info{
|
||||
Types: make(map[ast.Expr]types.TypeAndValue),
|
||||
Instances: make(map[*ast.Ident]types.Instance),
|
||||
Defs: make(map[*ast.Ident]types.Object),
|
||||
Uses: make(map[*ast.Ident]types.Object),
|
||||
Implicits: make(map[ast.Node]types.Object),
|
||||
@@ -164,6 +166,9 @@ func Load(config *compileopts.Config, inputPkg string, clangHeaders string, type
|
||||
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
||||
},
|
||||
}
|
||||
if addInstances != nil {
|
||||
addInstances(&pkg.info)
|
||||
}
|
||||
err := decoder.Decode(&pkg.PackageJSON)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
@@ -264,7 +269,7 @@ func (p *Program) getOriginalPath(path string) string {
|
||||
originalPath = realgorootPath
|
||||
}
|
||||
maybeInTinyGoRoot := false
|
||||
for prefix := range pathsToOverride(p.config.GoMinorVersion, needsSyscallPackage(p.config.BuildTags())) {
|
||||
for prefix := range pathsToOverride(needsSyscallPackage(p.config.BuildTags())) {
|
||||
if runtime.GOOS == "windows" {
|
||||
prefix = strings.ReplaceAll(prefix, "/", "\\")
|
||||
}
|
||||
@@ -330,7 +335,7 @@ func (p *Package) OriginalDir() string {
|
||||
// parseFile is a wrapper around parser.ParseFile.
|
||||
func (p *Package) parseFile(path string, mode parser.Mode) (*ast.File, error) {
|
||||
originalPath := p.program.getOriginalPath(path)
|
||||
data, err := os.ReadFile(path)
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -440,7 +445,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) {
|
||||
var initialCFlags []string
|
||||
initialCFlags = append(initialCFlags, p.program.config.CFlags()...)
|
||||
initialCFlags = append(initialCFlags, "-I"+p.Dir)
|
||||
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.ImportPath, p.program.fset, initialCFlags, p.program.clangHeaders)
|
||||
generated, headerCode, cflags, ldflags, accessedFiles, errs := cgo.Process(files, p.program.workingDir, p.program.fset, initialCFlags, p.program.clangHeaders)
|
||||
p.CFlags = append(initialCFlags, cflags...)
|
||||
p.CGoHeaders = headerCode
|
||||
for path, hash := range accessedFiles {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package loader
|
||||
|
||||
// Workaround for Go 1.17 support. Should be removed once we drop Go 1.17
|
||||
// support.
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
addInstances = func(info *types.Info) {
|
||||
info.Instances = make(map[*ast.Ident]types.Instance)
|
||||
}
|
||||
}
|
||||
@@ -26,14 +26,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/shlex"
|
||||
"github.com/inhies/go-bytesize"
|
||||
"github.com/mattn/go-colorable"
|
||||
"github.com/tinygo-org/tinygo/builder"
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
"github.com/tinygo-org/tinygo/goenv"
|
||||
"github.com/tinygo-org/tinygo/interp"
|
||||
"github.com/tinygo-org/tinygo/loader"
|
||||
"golang.org/x/tools/go/buildutil"
|
||||
"tinygo.org/x/go-llvm"
|
||||
|
||||
"go.bug.st/serial"
|
||||
@@ -196,7 +194,7 @@ func Build(pkgName, outpath string, options *compileopts.Options) error {
|
||||
|
||||
// Test runs the tests in the given package. Returns whether the test passed and
|
||||
// possibly an error if the test failed to run.
|
||||
func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options, testCompileOnly, testVerbose, testShort bool, testRunRegexp string, testBenchRegexp string, testBenchTime string, testBenchMem bool, outpath string) (bool, error) {
|
||||
func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options, testCompileOnly, testVerbose, testShort bool, testRunRegexp string, testBenchRegexp string, testBenchTime string, outpath string) (bool, error) {
|
||||
options.TestConfig.CompileTestBinary = true
|
||||
config, err := builder.NewConfig(options)
|
||||
if err != nil {
|
||||
@@ -220,9 +218,6 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
||||
if testBenchTime != "" {
|
||||
flags = append(flags, "-test.benchtime="+testBenchTime)
|
||||
}
|
||||
if testBenchMem {
|
||||
flags = append(flags, "-test.benchmem")
|
||||
}
|
||||
|
||||
passed := false
|
||||
err = buildAndRun(pkgName, config, os.Stdout, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
|
||||
@@ -244,37 +239,18 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
||||
// Tests are always run in the package directory.
|
||||
cmd.Dir = result.MainDir
|
||||
|
||||
// wasmtime is the default emulator used for `-target=wasi`. wasmtime
|
||||
// is a WebAssembly runtime CLI with WASI enabled by default. However,
|
||||
// only stdio are allowed by default. For example, while STDOUT routes
|
||||
// to the host, other files don't. It also does not inherit environment
|
||||
// variables from the host. Some tests read testdata files, often from
|
||||
// outside the package directory. Other tests require temporary
|
||||
// writeable directories. We allow this by adding wasmtime flags below.
|
||||
// Wasmtime needs a few extra flags to work.
|
||||
if config.EmulatorName() == "wasmtime" {
|
||||
// At this point, The current working directory is at the package
|
||||
// directory. Ex. $GOROOT/src/compress/flate for compress/flate.
|
||||
// buildAndRun has already added arguments for wasmtime, that allow
|
||||
// read-access to files such as "testdata/huffman-zero.in".
|
||||
//
|
||||
// Ex. main(.wasm) --dir=. -- -test.v
|
||||
|
||||
// Below adds additional wasmtime flags in case a test reads files
|
||||
// outside its directory, like "../testdata/e.txt". This allows any
|
||||
// relative directory up to the module root, even if the test never
|
||||
// reads any files.
|
||||
//
|
||||
// Ex. --dir=.. --dir=../.. --dir=../../..
|
||||
// Add directories to the module root, but skip the current working
|
||||
// directory which is already added by buildAndRun.
|
||||
dirs := dirsToModuleRoot(result.MainDir, result.ModuleRoot)
|
||||
var args []string
|
||||
for _, d := range dirs[1:] {
|
||||
args = append(args, "--dir="+d)
|
||||
}
|
||||
|
||||
// Some tests create temp directories using os.MkdirTemp or via
|
||||
// t.TempDir(). Create a writeable directory and map it to the
|
||||
// default tempDir environment variable: TMPDIR.
|
||||
tmpdir, err := os.MkdirTemp("", "tinygotmp")
|
||||
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
|
||||
tmpdir, err := ioutil.TempDir("", "tinygotmp")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temporary directory: %w", err)
|
||||
}
|
||||
@@ -282,8 +258,7 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
|
||||
// TODO: add option to not delete temp dir for debugging?
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
// The below re-organizes the arguments so that the current
|
||||
// directory is added last.
|
||||
// Insert new argments at the front of the command line argments.
|
||||
args = append(args, cmd.Args[1:]...)
|
||||
cmd.Args = append(cmd.Args[:1:1], args...)
|
||||
}
|
||||
@@ -423,6 +398,7 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
case "msd":
|
||||
switch fileExt {
|
||||
case ".uf2":
|
||||
@@ -430,11 +406,13 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
case ".hex":
|
||||
err := flashHexUsingMSD(config.Target.FlashVolume, result.Binary, config.Options)
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return errors.New("mass storage device flashing currently only supports uf2 and hex")
|
||||
}
|
||||
@@ -455,6 +433,7 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
case "bmp":
|
||||
gdb, err := config.Target.LookupGDB()
|
||||
if err != nil {
|
||||
@@ -473,13 +452,10 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
|
||||
if err != nil {
|
||||
return &commandError{"failed to flash", result.Binary, err}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unknown flash method: %s", flashMethod)
|
||||
}
|
||||
if options.Monitor {
|
||||
return Monitor("", options)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1039,6 +1015,18 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
||||
// available in the system.
|
||||
ports = secondaryPorts
|
||||
}
|
||||
|
||||
if len(ports) == 0 {
|
||||
// fallback
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
ports, err = filepath.Glob("/dev/cu.usb*")
|
||||
case "linux":
|
||||
ports, err = filepath.Glob("/dev/ttyACM*")
|
||||
case "windows":
|
||||
ports, err = serial.GetPortsList()
|
||||
}
|
||||
}
|
||||
default:
|
||||
return "", errors.New("unable to search for a default USB device to be flashed on this OS")
|
||||
}
|
||||
@@ -1052,9 +1040,7 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
|
||||
}
|
||||
|
||||
if len(portCandidates) == 0 {
|
||||
if len(usbInterfaces) > 0 {
|
||||
return "", errors.New("unable to search for a default USB device - use -port flag, available ports are " + strings.Join(ports, ", "))
|
||||
} else if len(ports) == 1 {
|
||||
if len(ports) == 1 {
|
||||
return ports[0], nil
|
||||
} else {
|
||||
return "", errors.New("multiple serial ports available - use -port flag, available ports are " + strings.Join(ports, ", "))
|
||||
@@ -1119,7 +1105,6 @@ func usage(command string) {
|
||||
fmt.Fprintln(os.Stderr, " flash: compile and flash to the device")
|
||||
fmt.Fprintln(os.Stderr, " gdb: run/flash and immediately enter GDB")
|
||||
fmt.Fprintln(os.Stderr, " lldb: run/flash and immediately enter LLDB")
|
||||
fmt.Fprintln(os.Stderr, " monitor: open communication port")
|
||||
fmt.Fprintln(os.Stderr, " env: list environment variables used during build")
|
||||
fmt.Fprintln(os.Stderr, " list: run go list using the TinyGo root")
|
||||
fmt.Fprintln(os.Stderr, " clean: empty cache directory ("+goenv.Get("GOCACHE")+")")
|
||||
@@ -1309,19 +1294,11 @@ func main() {
|
||||
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
|
||||
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
|
||||
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit")
|
||||
interpTimeout := flag.Duration("interp-timeout", 180*time.Second, "interp optimization pass timeout")
|
||||
printIR := flag.Bool("printir", false, "print LLVM IR")
|
||||
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
||||
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
||||
var tags buildutil.TagsFlag
|
||||
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
|
||||
tags := flag.String("tags", "", "a space-separated list of extra build tags")
|
||||
target := flag.String("target", "", "chip/board name or JSON target specification file")
|
||||
var stackSize uint64
|
||||
flag.Func("stack-size", "goroutine stack size (if unknown at compile time)", func(s string) error {
|
||||
size, err := bytesize.Parse(s)
|
||||
stackSize = uint64(size)
|
||||
return err
|
||||
})
|
||||
printSize := flag.String("size", "", "print sizes (none, short, full)")
|
||||
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")
|
||||
@@ -1336,8 +1313,6 @@ func main() {
|
||||
wasmAbi := flag.String("wasm-abi", "", "WebAssembly ABI conventions: js (no i64 params) or generic")
|
||||
llvmFeatures := flag.String("llvm-features", "", "comma separated LLVM features to enable")
|
||||
cpuprofile := flag.String("cpuprofile", "", "cpuprofile output")
|
||||
monitor := flag.Bool("monitor", false, "enable serial monitor")
|
||||
baudrate := flag.Int("baudrate", 115200, "baudrate of serial monitor")
|
||||
|
||||
var flagJSON, flagDeps, flagTest bool
|
||||
if command == "help" || command == "list" || command == "info" || command == "build" {
|
||||
@@ -1355,7 +1330,6 @@ func main() {
|
||||
var testBenchRegexp *string
|
||||
var testBenchTime *string
|
||||
var testRunRegexp *string
|
||||
var testBenchMem *bool
|
||||
if command == "help" || command == "test" {
|
||||
testCompileOnlyFlag = flag.Bool("c", false, "compile the test binary but do not run it")
|
||||
testVerboseFlag = flag.Bool("v", false, "verbose: print additional output")
|
||||
@@ -1363,7 +1337,6 @@ func main() {
|
||||
testRunRegexp = flag.String("run", "", "run: regexp of tests to run")
|
||||
testBenchRegexp = flag.String("bench", "", "run: regexp of benchmarks to run")
|
||||
testBenchTime = flag.String("benchtime", "", "run each benchmark for duration `d`")
|
||||
testBenchMem = flag.Bool("benchmem", false, "show memory stats for benchmarks")
|
||||
}
|
||||
|
||||
// Early command processing, before commands are interpreted by the Go flag
|
||||
@@ -1404,14 +1377,12 @@ func main() {
|
||||
GOARCH: goenv.Get("GOARCH"),
|
||||
GOARM: goenv.Get("GOARM"),
|
||||
Target: *target,
|
||||
StackSize: stackSize,
|
||||
Opt: *opt,
|
||||
GC: *gc,
|
||||
PanicStrategy: *panicStrategy,
|
||||
Scheduler: *scheduler,
|
||||
Serial: *serial,
|
||||
Work: *work,
|
||||
InterpTimeout: *interpTimeout,
|
||||
PrintIR: *printIR,
|
||||
DumpSSA: *dumpSSA,
|
||||
VerifyIR: *verifyIR,
|
||||
@@ -1420,15 +1391,13 @@ func main() {
|
||||
PrintSizes: *printSize,
|
||||
PrintStacks: *printStacks,
|
||||
PrintAllocs: printAllocs,
|
||||
Tags: []string(tags),
|
||||
Tags: *tags,
|
||||
GlobalValues: globalVarValues,
|
||||
WasmAbi: *wasmAbi,
|
||||
Programmer: *programmer,
|
||||
OpenOCDCommands: ocdCommands,
|
||||
LLVMFeatures: *llvmFeatures,
|
||||
PrintJSON: flagJSON,
|
||||
Monitor: *monitor,
|
||||
BaudRate: *baudrate,
|
||||
}
|
||||
if *printCommands {
|
||||
options.PrintCommands = printCommand
|
||||
@@ -1496,7 +1465,7 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "Unknown library: %s\n", name)
|
||||
os.Exit(1)
|
||||
}
|
||||
tmpdir, err := os.MkdirTemp("", "tinygo*")
|
||||
tmpdir, err := ioutil.TempDir("", "tinygo*")
|
||||
if err != nil {
|
||||
handleCompilerError(err)
|
||||
}
|
||||
@@ -1597,7 +1566,7 @@ func main() {
|
||||
defer close(buf.done)
|
||||
stdout := (*testStdout)(buf)
|
||||
stderr := (*testStderr)(buf)
|
||||
passed, err := Test(pkgName, stdout, stderr, options, *testCompileOnlyFlag, *testVerboseFlag, *testShortFlag, *testRunRegexp, *testBenchRegexp, *testBenchTime, *testBenchMem, outpath)
|
||||
passed, err := Test(pkgName, stdout, stderr, options, *testCompileOnlyFlag, *testVerboseFlag, *testShortFlag, *testRunRegexp, *testBenchRegexp, *testBenchTime, outpath)
|
||||
if err != nil {
|
||||
printCompilerError(func(args ...interface{}) {
|
||||
fmt.Fprintln(stderr, args...)
|
||||
@@ -1619,9 +1588,6 @@ func main() {
|
||||
fmt.Println("FAIL")
|
||||
os.Exit(1)
|
||||
}
|
||||
case "monitor":
|
||||
err := Monitor(*port, options)
|
||||
handleCompilerError(err)
|
||||
case "targets":
|
||||
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
|
||||
entries, err := ioutil.ReadDir(dir)
|
||||
@@ -1700,6 +1666,7 @@ func main() {
|
||||
fmt.Printf("LLVM triple: %s\n", config.Triple())
|
||||
fmt.Printf("GOOS: %s\n", config.GOOS())
|
||||
fmt.Printf("GOARCH: %s\n", config.GOARCH())
|
||||
fmt.Printf("GOARM: %s\n", config.GOARM())
|
||||
fmt.Printf("build tags: %s\n", strings.Join(config.BuildTags(), " "))
|
||||
fmt.Printf("garbage collector: %s\n", config.GC())
|
||||
fmt.Printf("scheduler: %s\n", config.Scheduler())
|
||||
|
||||
+36
-41
@@ -10,6 +10,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
@@ -51,7 +52,6 @@ func TestBuild(t *testing.T) {
|
||||
"embed/",
|
||||
"float.go",
|
||||
"gc.go",
|
||||
"generics.go",
|
||||
"goroutines.go",
|
||||
"init.go",
|
||||
"init_multi.go",
|
||||
@@ -66,10 +66,21 @@ func TestBuild(t *testing.T) {
|
||||
"stdlib.go",
|
||||
"string.go",
|
||||
"structs.go",
|
||||
"testing.go",
|
||||
"timers.go",
|
||||
"zeroalloc.go",
|
||||
}
|
||||
_, minor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
|
||||
if err != nil {
|
||||
t.Fatal("could not read version from GOROOT:", err)
|
||||
}
|
||||
if minor >= 17 {
|
||||
tests = append(tests, "go1.17.go")
|
||||
}
|
||||
if minor >= 18 {
|
||||
tests = append(tests, "generics.go")
|
||||
tests = append(tests, "testing_go118.go")
|
||||
} else {
|
||||
tests = append(tests, "testing.go")
|
||||
}
|
||||
|
||||
if *testTarget != "" {
|
||||
// This makes it possible to run one specific test (instead of all),
|
||||
@@ -170,14 +181,6 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
||||
}
|
||||
|
||||
for _, name := range tests {
|
||||
if options.GOOS == "linux" && (options.GOARCH == "arm" || options.GOARCH == "386") {
|
||||
switch name {
|
||||
case "timers.go":
|
||||
// Timer tests do not work because syscall.seek is implemented
|
||||
// as Assembly in mainline Go and causes linker failure
|
||||
continue
|
||||
}
|
||||
}
|
||||
if options.Target == "simavr" {
|
||||
// Not all tests are currently supported on AVR.
|
||||
// Skip the ones that aren't.
|
||||
@@ -190,7 +193,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
||||
// Does not pass due to high mark false positive rate.
|
||||
continue
|
||||
|
||||
case "json.go", "stdlib.go", "testing.go":
|
||||
case "json.go", "stdlib.go", "testing.go", "testing_go118.go":
|
||||
// Breaks interp.
|
||||
continue
|
||||
|
||||
@@ -206,11 +209,6 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
|
||||
// CGo does not work on AVR.
|
||||
continue
|
||||
|
||||
case "timers.go":
|
||||
// Doesn't compile:
|
||||
// panic: compiler: could not store type code number inside interface type code
|
||||
continue
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
@@ -262,11 +260,10 @@ func emuCheck(t *testing.T, options compileopts.Options) {
|
||||
t.Fatal("failed to load target spec:", err)
|
||||
}
|
||||
if spec.Emulator != "" {
|
||||
emulatorCommand := strings.SplitN(spec.Emulator, " ", 2)[0]
|
||||
_, err := exec.LookPath(emulatorCommand)
|
||||
_, err := exec.LookPath(strings.SplitN(spec.Emulator, " ", 2)[0])
|
||||
if err != nil {
|
||||
if errors.Is(err, exec.ErrNotFound) {
|
||||
t.Skipf("emulator not installed: %q", emulatorCommand)
|
||||
t.Skipf("emulator not installed: %q", spec.Emulator[0])
|
||||
}
|
||||
|
||||
t.Errorf("searching for emulator: %v", err)
|
||||
@@ -278,15 +275,14 @@ func emuCheck(t *testing.T, options compileopts.Options) {
|
||||
func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
|
||||
return compileopts.Options{
|
||||
// GOOS/GOARCH are only used if target == ""
|
||||
GOOS: goenv.Get("GOOS"),
|
||||
GOARCH: goenv.Get("GOARCH"),
|
||||
GOARM: goenv.Get("GOARM"),
|
||||
Target: target,
|
||||
Semaphore: sema,
|
||||
InterpTimeout: 180 * time.Second,
|
||||
Debug: true,
|
||||
VerifyIR: true,
|
||||
Opt: "z",
|
||||
GOOS: goenv.Get("GOOS"),
|
||||
GOARCH: goenv.Get("GOARCH"),
|
||||
GOARM: goenv.Get("GOARM"),
|
||||
Target: target,
|
||||
Semaphore: sema,
|
||||
Debug: true,
|
||||
VerifyIR: true,
|
||||
Opt: "z",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,13 +292,12 @@ func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
|
||||
func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options {
|
||||
parts := strings.Split(osarch, "/")
|
||||
options := compileopts.Options{
|
||||
GOOS: parts[0],
|
||||
GOARCH: parts[1],
|
||||
Semaphore: sema,
|
||||
InterpTimeout: 180 * time.Second,
|
||||
Debug: true,
|
||||
VerifyIR: true,
|
||||
Opt: "z",
|
||||
GOOS: parts[0],
|
||||
GOARCH: parts[1],
|
||||
Semaphore: sema,
|
||||
Debug: true,
|
||||
VerifyIR: true,
|
||||
Opt: "z",
|
||||
}
|
||||
if options.GOARCH == "arm" {
|
||||
options.GOARM = parts[2]
|
||||
@@ -324,7 +319,7 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
|
||||
if path[len(path)-1] == '/' {
|
||||
txtpath = path + "out.txt"
|
||||
}
|
||||
expected, err := os.ReadFile(txtpath)
|
||||
expected, err := ioutil.ReadFile(txtpath)
|
||||
if err != nil {
|
||||
t.Fatal("could not read expected output file:", err)
|
||||
}
|
||||
@@ -435,7 +430,7 @@ func TestTest(t *testing.T) {
|
||||
defer out.Close()
|
||||
|
||||
opts := targ.opts
|
||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/pass", out, out, &opts, false, false, false, "", "", "", false, "")
|
||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/pass", out, out, &opts, false, false, false, "", "", "", "")
|
||||
if err != nil {
|
||||
t.Errorf("test error: %v", err)
|
||||
}
|
||||
@@ -456,7 +451,7 @@ func TestTest(t *testing.T) {
|
||||
defer out.Close()
|
||||
|
||||
opts := targ.opts
|
||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/fail", out, out, &opts, false, false, false, "", "", "", false, "")
|
||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/fail", out, out, &opts, false, false, false, "", "", "", "")
|
||||
if err != nil {
|
||||
t.Errorf("test error: %v", err)
|
||||
}
|
||||
@@ -483,7 +478,7 @@ func TestTest(t *testing.T) {
|
||||
|
||||
var output bytes.Buffer
|
||||
opts := targ.opts
|
||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/nothing", io.MultiWriter(&output, out), out, &opts, false, false, false, "", "", "", false, "")
|
||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/nothing", io.MultiWriter(&output, out), out, &opts, false, false, false, "", "", "", "")
|
||||
if err != nil {
|
||||
t.Errorf("test error: %v", err)
|
||||
}
|
||||
@@ -507,7 +502,7 @@ func TestTest(t *testing.T) {
|
||||
defer out.Close()
|
||||
|
||||
opts := targ.opts
|
||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/builderr", out, out, &opts, false, false, false, "", "", "", false, "")
|
||||
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/builderr", out, out, &opts, false, false, false, "", "", "", "")
|
||||
if err == nil {
|
||||
t.Error("test did not error")
|
||||
}
|
||||
|
||||
-106
@@ -1,106 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/mattn/go-tty"
|
||||
"github.com/tinygo-org/tinygo/builder"
|
||||
"github.com/tinygo-org/tinygo/compileopts"
|
||||
"go.bug.st/serial"
|
||||
)
|
||||
|
||||
// Monitor connects to the given port and reads/writes the serial port.
|
||||
func Monitor(port string, options *compileopts.Options) error {
|
||||
config, err := builder.NewConfig(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wait := 300
|
||||
for i := 0; i <= wait; i++ {
|
||||
port, err = getDefaultPort(port, config.Target.SerialPort)
|
||||
if err != nil {
|
||||
if i < wait {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
br := options.BaudRate
|
||||
if br <= 0 {
|
||||
br = 115200
|
||||
}
|
||||
|
||||
wait = 300
|
||||
var p serial.Port
|
||||
for i := 0; i <= wait; i++ {
|
||||
p, err = serial.Open(port, &serial.Mode{BaudRate: br})
|
||||
if err != nil {
|
||||
if i < wait {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
defer p.Close()
|
||||
|
||||
tty, err := tty.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tty.Close()
|
||||
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, os.Interrupt)
|
||||
defer signal.Stop(sig)
|
||||
|
||||
go func() {
|
||||
<-sig
|
||||
tty.Close()
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
fmt.Printf("Connected to %s. Press Ctrl-C to exit.\n", port)
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
buf := make([]byte, 100*1024)
|
||||
for {
|
||||
n, err := p.Read(buf)
|
||||
if err != nil {
|
||||
errCh <- fmt.Errorf("read error: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("%v", string(buf[:n]))
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
r, err := tty.ReadRune()
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
}
|
||||
if r == 0 {
|
||||
continue
|
||||
}
|
||||
p.Write([]byte(string(r)))
|
||||
}
|
||||
}()
|
||||
|
||||
return <-errCh
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// Package sig stubs crypto/internal/boring/sig
|
||||
package sig
|
||||
|
||||
// BoringCrypto indicates that the BoringCrypto module is present.
|
||||
func BoringCrypto() {
|
||||
|
||||
}
|
||||
|
||||
// FIPSOnly indicates that package crypto/tls/fipsonly is present.
|
||||
func FIPSOnly() {
|
||||
|
||||
}
|
||||
|
||||
// StandardCrypto indicates that standard Go crypto is present.
|
||||
func StandardCrypto() {
|
||||
|
||||
}
|
||||
@@ -27,6 +27,5 @@ func (r *reader) Read(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
// void arc4random_buf(void *buf, size_t buflen);
|
||||
//
|
||||
//export arc4random_buf
|
||||
func libc_arc4random_buf(buf unsafe.Pointer, buflen uint)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//go:build nrf || stm32 || (sam && atsamd51) || (sam && atsame5x)
|
||||
// +build nrf stm32 sam,atsamd51 sam,atsame5x
|
||||
//go:build stm32 || (sam && atsamd51) || (sam && atsame5x)
|
||||
// +build stm32 sam,atsamd51 sam,atsame5x
|
||||
|
||||
package rand
|
||||
|
||||
|
||||
@@ -38,6 +38,5 @@ func (r *reader) Read(b []byte) (n int, err error) {
|
||||
// Cryptographically secure random number generator.
|
||||
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rand-s?view=msvc-170
|
||||
// errno_t rand_s(unsigned int* randomValue);
|
||||
//
|
||||
//export rand_s
|
||||
func libc_rand_s(randomValue *uint32) int32
|
||||
|
||||
+29
-29
@@ -2,31 +2,31 @@
|
||||
//
|
||||
// Original copyright:
|
||||
//
|
||||
// Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
// Copyright (c) 2009 - 2015 ARM LIMITED
|
||||
//
|
||||
// All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// - Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// - Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// - Neither the name of ARM nor the names of its contributors may be used
|
||||
// to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
// All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// - Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// - Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// - Neither the name of ARM nor the names of its contributors may be used
|
||||
// to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
package arm
|
||||
|
||||
import (
|
||||
@@ -46,12 +46,12 @@ func Asm(asm string)
|
||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||
// recognizes template values in the form {name}, like so:
|
||||
//
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
//
|
||||
// You can use {} in the asm string (which expands to a register) to set the
|
||||
// return value.
|
||||
|
||||
@@ -60,6 +60,5 @@ const (
|
||||
|
||||
// Call a semihosting function.
|
||||
// TODO: implement it here using inline assembly.
|
||||
//
|
||||
//go:linkname SemihostingCall SemihostingCall
|
||||
func SemihostingCall(num int, arg uintptr) int
|
||||
|
||||
@@ -9,12 +9,12 @@ func Asm(asm string)
|
||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||
// recognizes template values in the form {name}, like so:
|
||||
//
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
//
|
||||
// You can use {} in the asm string (which expands to a register) to set the
|
||||
// return value.
|
||||
|
||||
+6
-6
@@ -9,12 +9,12 @@ func Asm(asm string)
|
||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||
// recognizes template values in the form {name}, like so:
|
||||
//
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
// arm.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
//
|
||||
// You can use {} in the asm string (which expands to a register) to set the
|
||||
// return value.
|
||||
|
||||
@@ -9,12 +9,12 @@ func Asm(asm string)
|
||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||
// recognizes template values in the form {name}, like so:
|
||||
//
|
||||
// avr.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
// avr.AsmFull(
|
||||
// "str {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
//
|
||||
// You can use {} in the asm string (which expands to a register) to set the
|
||||
// return value.
|
||||
|
||||
@@ -9,12 +9,12 @@ func Asm(asm string)
|
||||
// effects, as it would otherwise be optimized away. The inline assembly string
|
||||
// recognizes template values in the form {name}, like so:
|
||||
//
|
||||
// arm.AsmFull(
|
||||
// "st {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
// arm.AsmFull(
|
||||
// "st {value}, {result}",
|
||||
// map[string]interface{}{
|
||||
// "value": 1
|
||||
// "result": &dest,
|
||||
// })
|
||||
//
|
||||
// You can use {} in the asm string (which expands to a register) to set the
|
||||
// return value.
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Reads multiple rp2040 ADC channels concurrently. Including the internal temperature sensor
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"machine"
|
||||
"time"
|
||||
)
|
||||
|
||||
type celsius float32
|
||||
|
||||
func (c celsius) String() string {
|
||||
return fmt.Sprintf("%4.1f℃", c)
|
||||
}
|
||||
|
||||
// rp2040 ADC is 12 bits. Reading are shifted <<4 to fill the 16-bit range.
|
||||
var adcReading [3]uint16
|
||||
|
||||
func readADC(a machine.ADC, w time.Duration, i int) {
|
||||
for {
|
||||
adcReading[i] = a.Get()
|
||||
time.Sleep(w)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
machine.InitADC()
|
||||
a0 := machine.ADC{machine.ADC0} // GPIO26 input
|
||||
a1 := machine.ADC{machine.ADC1} // GPIO27 input
|
||||
a2 := machine.ADC{machine.ADC2} // GPIO28 input
|
||||
t := machine.ADC_TEMP_SENSOR // Internal Temperature sensor
|
||||
// Configure sets the GPIOs to PinAnalog mode
|
||||
a0.Configure(machine.ADCConfig{})
|
||||
a1.Configure(machine.ADCConfig{})
|
||||
a2.Configure(machine.ADCConfig{})
|
||||
// Configure powers on the temperature sensor
|
||||
t.Configure(machine.ADCConfig{})
|
||||
|
||||
// Safe to read concurrently
|
||||
go readADC(a0, 10*time.Millisecond, 0)
|
||||
go readADC(a1, 17*time.Millisecond, 1)
|
||||
go readADC(a2, 29*time.Millisecond, 2)
|
||||
|
||||
for {
|
||||
fmt.Printf("ADC0: %5d ADC1: %5d ADC2: %5d Temp: %v\n\r", adcReading[0], adcReading[1], adcReading[2], celsius(float32(t.ReadTemperature())/1000))
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// Example using the i2s hardware interface on the Adafruit Circuit Playground Express
|
||||
// to read data from the onboard MEMS microphone.
|
||||
//
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// Read the internal temperature sensor of the chip.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"machine"
|
||||
"time"
|
||||
)
|
||||
|
||||
type celsius float32
|
||||
|
||||
func (c celsius) String() string {
|
||||
return fmt.Sprintf("%4.1f℃", c)
|
||||
}
|
||||
|
||||
func main() {
|
||||
for {
|
||||
temp := celsius(float32(machine.ReadTemperature()) / 1000)
|
||||
println("temperature:", temp.String())
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ main: clean wasm_exec
|
||||
cp ./main/index.html ./html/
|
||||
|
||||
wasm_exec:
|
||||
cp `tinygo env TINYGOROOT`/targets/wasm_exec.js ./html/
|
||||
cp ../../../targets/wasm_exec.js ./html/
|
||||
|
||||
clean:
|
||||
rm -rf ./html
|
||||
|
||||
@@ -21,14 +21,12 @@ $ tinygo build -o ./wasm.wasm -target wasm ./main/main.go
|
||||
This creates a `wasm.wasm` file, which we can load in JavaScript and execute in
|
||||
a browser.
|
||||
|
||||
Next, choose which example you want to use:
|
||||
* [callback](callback): Defines and configures callbacks in Wasm.
|
||||
* [export](export): Defines callbacks in Wasm, but configures them in JavaScript.
|
||||
* [invoke](invoke): Invokes a function defined in JavaScript from Wasm.
|
||||
* [main](main): Prints a message to the JavaScript console from Wasm.
|
||||
* [slices](slices): Splits an Array defined in JavaScript from Wasm.
|
||||
This examples folder contains two examples that can be built using `make`:
|
||||
|
||||
```bash
|
||||
$ make export
|
||||
```
|
||||
|
||||
Let's say you chose [main](main), you'd build it like so:
|
||||
```bash
|
||||
$ make main
|
||||
```
|
||||
@@ -44,8 +42,12 @@ Serving ./html on http://localhost:8080
|
||||
|
||||
Use your web browser to visit http://localhost:8080.
|
||||
|
||||
* Tip: Open the browser development tools (e.g. Right-click, Inspect in
|
||||
FireFox) to see console output.
|
||||
* The wasm "export" example displays a simple math equation using HTML, with
|
||||
the result calculated dynamically using WebAssembly. Changing any of the
|
||||
values on the left hand side triggers the exported wasm `update` function to
|
||||
recalculate the result.
|
||||
* The wasm "main" example uses `println` to write to your browser JavaScript
|
||||
console. You may need to open the browser development tools console to see it.
|
||||
|
||||
## How it works
|
||||
|
||||
|
||||
@@ -8,12 +8,10 @@ import (
|
||||
var a, b int
|
||||
|
||||
func main() {
|
||||
wait := make(chan struct{}, 0)
|
||||
document := js.Global().Get("document")
|
||||
document.Call("getElementById", "a").Set("oninput", updater(&a))
|
||||
document.Call("getElementById", "b").Set("oninput", updater(&b))
|
||||
update()
|
||||
<-wait
|
||||
}
|
||||
|
||||
func updater(n *int) js.Func {
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
internal/itoa is new to go as of 1.17.
|
||||
This directory should be removed when tinygo drops support for go 1.16.
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Simple conversions to avoid depending on strconv.
|
||||
|
||||
package itoa
|
||||
|
||||
// Itoa converts val to a decimal string.
|
||||
func Itoa(val int) string {
|
||||
if val < 0 {
|
||||
return "-" + Uitoa(uint(-val))
|
||||
}
|
||||
return Uitoa(uint(val))
|
||||
}
|
||||
|
||||
// Uitoa converts val to a decimal string.
|
||||
func Uitoa(val uint) string {
|
||||
if val == 0 { // avoid string allocation
|
||||
return "0"
|
||||
}
|
||||
var buf [20]byte // big enough for 64bit value base 10
|
||||
i := len(buf) - 1
|
||||
for val >= 10 {
|
||||
q := val / 10
|
||||
buf[i] = byte('0' + val - q*10)
|
||||
i--
|
||||
val = q
|
||||
}
|
||||
// val < 10
|
||||
buf[i] = byte('0' + val)
|
||||
return string(buf[i:])
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package itoa_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/itoa"
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
minInt64 int64 = math.MinInt64
|
||||
maxInt64 int64 = math.MaxInt64
|
||||
maxUint64 uint64 = math.MaxUint64
|
||||
)
|
||||
|
||||
func TestItoa(t *testing.T) {
|
||||
tests := []int{int(minInt64), math.MinInt32, -999, -100, -1, 0, 1, 100, 999, math.MaxInt32, int(maxInt64)}
|
||||
for _, tt := range tests {
|
||||
got := itoa.Itoa(tt)
|
||||
want := fmt.Sprint(tt)
|
||||
if want != got {
|
||||
t.Fatalf("Itoa(%d) = %s, want %s", tt, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUitoa(t *testing.T) {
|
||||
tests := []uint{0, 1, 100, 999, math.MaxUint32, uint(maxUint64)}
|
||||
for _, tt := range tests {
|
||||
got := itoa.Uitoa(tt)
|
||||
want := fmt.Sprint(tt)
|
||||
if want != got {
|
||||
t.Fatalf("Uitoa(%d) = %s, want %s", tt, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,9 +99,9 @@ func Pause() {
|
||||
//export tinygo_unwind
|
||||
func (*stackState) unwind()
|
||||
|
||||
// Resume the task until it pauses or completes.
|
||||
// Switch to this task until it pauses or completes.
|
||||
// This may only be called from the scheduler.
|
||||
func (t *Task) Resume() {
|
||||
func (t *Task) Switch() {
|
||||
// The current task must be saved and restored because this can nest on WASM with JS.
|
||||
prevTask := currentTask
|
||||
t.gcData.swap()
|
||||
@@ -121,9 +121,3 @@ func (t *Task) Resume() {
|
||||
|
||||
//export tinygo_rewind
|
||||
func (*state) rewind()
|
||||
|
||||
// OnSystemStack returns whether the caller is running on the system stack.
|
||||
func OnSystemStack() bool {
|
||||
// If there is not an active goroutine, then this must be running on the system stack.
|
||||
return Current() == nil
|
||||
}
|
||||
|
||||
@@ -2,16 +2,12 @@
|
||||
|
||||
.functype start_unwind (i32) -> ()
|
||||
.import_module start_unwind, asyncify
|
||||
.import_name start_unwind, start_unwind
|
||||
.functype stop_unwind () -> ()
|
||||
.import_module stop_unwind, asyncify
|
||||
.import_name stop_unwind, stop_unwind
|
||||
.functype start_rewind (i32) -> ()
|
||||
.import_module start_rewind, asyncify
|
||||
.import_name start_rewind, start_rewind
|
||||
.functype stop_rewind () -> ()
|
||||
.import_module stop_rewind, asyncify
|
||||
.import_name stop_rewind, stop_rewind
|
||||
|
||||
.global tinygo_unwind
|
||||
.hidden tinygo_unwind
|
||||
|
||||
@@ -28,12 +28,12 @@ func start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
|
||||
|
||||
type state struct{}
|
||||
|
||||
func (t *Task) Resume() {
|
||||
func (t *Task) Switch() {
|
||||
runtimePanic("scheduler is disabled")
|
||||
}
|
||||
|
||||
// OnSystemStack returns whether the caller is running on the system stack.
|
||||
func OnSystemStack() bool {
|
||||
// MainTask returns whether the caller is running in the main goroutine.
|
||||
func MainTask() bool {
|
||||
// This scheduler does not do any stack switching.
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -27,8 +27,12 @@ type state struct {
|
||||
canaryPtr *uintptr
|
||||
}
|
||||
|
||||
// currentTask is the current running task, or nil if currently in the scheduler.
|
||||
var currentTask *Task
|
||||
// The task struct for the main goroutine.
|
||||
var mainTask Task
|
||||
|
||||
// currentTask is the current running task. The default value is the main
|
||||
// goroutine.
|
||||
var currentTask = &mainTask
|
||||
|
||||
// Current returns the current active task.
|
||||
func Current() *Task {
|
||||
@@ -36,29 +40,36 @@ func Current() *Task {
|
||||
}
|
||||
|
||||
// Pause suspends the current task and returns to the scheduler.
|
||||
// This function may only be called when running on a goroutine stack, not when running on the system stack or in an interrupt.
|
||||
// This function may only be called when running on a goroutine stack, not when in an interrupt.
|
||||
func Pause() {
|
||||
// Check whether the canary (the lowest address of the stack) is still
|
||||
// valid. If it is not, a stack overflow has occured.
|
||||
if *currentTask.state.canaryPtr != stackCanary {
|
||||
if currentTask.state.canaryPtr != nil && *currentTask.state.canaryPtr != stackCanary {
|
||||
runtimePanic("goroutine stack overflow")
|
||||
}
|
||||
currentTask.state.pause()
|
||||
scheduler()
|
||||
}
|
||||
|
||||
//go:linkname scheduler runtime.scheduler
|
||||
func scheduler()
|
||||
|
||||
//export tinygo_pause
|
||||
func pause() {
|
||||
Pause()
|
||||
}
|
||||
|
||||
// Resume the task until it pauses or completes.
|
||||
// Switch to the given task until it pauses or completes.
|
||||
// This may only be called from the scheduler.
|
||||
func (t *Task) Resume() {
|
||||
func (t *Task) Switch() {
|
||||
current := currentTask
|
||||
if current == t {
|
||||
// Nothing to switch to: we're already in this task.
|
||||
return
|
||||
}
|
||||
currentTask = t
|
||||
t.gcData.swap()
|
||||
t.state.resume()
|
||||
t.state.switchTo(current)
|
||||
t.gcData.swap()
|
||||
currentTask = nil
|
||||
}
|
||||
|
||||
// initialize the state and prepare to call the specified function with the specified argument bundle.
|
||||
@@ -89,7 +100,6 @@ func swapTask(oldStack uintptr, newStack *uintptr)
|
||||
// startTask is a small wrapper function that sets up the first (and only)
|
||||
// argument to the new goroutine and makes sure it is exited when the goroutine
|
||||
// finishes.
|
||||
//
|
||||
//go:extern tinygo_startTask
|
||||
var startTask [0]uint8
|
||||
|
||||
@@ -104,8 +114,8 @@ func start(fn uintptr, args unsafe.Pointer, stackSize uintptr) {
|
||||
runqueuePushBack(t)
|
||||
}
|
||||
|
||||
// OnSystemStack returns whether the caller is running on the system stack.
|
||||
func OnSystemStack() bool {
|
||||
// MainTask returns whether the caller is running in the main goroutine.
|
||||
func MainTask() bool {
|
||||
// If there is not an active goroutine, then this must be running on the system stack.
|
||||
return Current() == nil
|
||||
return currentTask == &mainTask
|
||||
}
|
||||
|
||||
@@ -20,11 +20,8 @@ tinygo_startTask:
|
||||
// Branch to the "goroutine start" function.
|
||||
calll *%ebx
|
||||
|
||||
// Rebalance the stack (to undo the above push).
|
||||
addl $4, %esp
|
||||
|
||||
// After return, exit this goroutine. This is a tail call.
|
||||
jmp tinygo_pause
|
||||
// After return, exit this goroutine.
|
||||
calll tinygo_pause
|
||||
.cfi_endproc
|
||||
|
||||
.global tinygo_swapTask
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user