Compare commits

..

56 Commits

Author SHA1 Message Date
Isaac Rodman 4223a60823 Add qtpy-rp2040 to TinyGo v0.25.0 2022-09-02 09:26:23 +09:00
Ayke van Laethem e955aa1941 reflect: implement CanInterface and fix string Index()
This commit fixes two related issues:

 1. CanInterface was unimplemented. It now uses the same check as is
    used in Interface() itself.
    This issue led to https://github.com/tinygo-org/tinygo/issues/3033
 2. Allow making an interface out of a string char element.

Doing this in one commit (instead of two) because they are shown to be
correct with the same tests.
2022-09-01 21:42:22 +02:00
sago35 edaf13f951 wioterminal: add UART3 for RTL8720DN 2022-09-01 19:22:01 +02:00
Ayke van Laethem 5f6cf665f5 compileopts: fix windows/arm target triple
This is just a papercut, and not really something important. But I
noticed something weird:

    $ GOOS=windows GOARCH=arm tinygo info ""
    LLVM triple:       armv7-unknown-windows-gnueabihf-gnu
    GOOS:              windows
    GOARCH:            arm

That -gnueabihf-gnu ending is weird, it should pick one of the two. I've
fixed it as follows:

    $ GOOS=windows GOARCH=arm tinygo info ""
    LLVM triple:       armv7-unknown-windows-gnu
    GOOS:              windows
    GOARCH:            arm
    [...]

We're probably never going to support windows/arm (this is 32-bit arm,
not arm64) so it doesn't really matter which one we pick. And this patch
shouldn't affect any other system.
2022-09-01 16:23:24 +02:00
Ayke van Laethem c6db89ff05 main: remove GOARM from tinygo info
I think it is more confusing than helpful because it is only relevant
when compiling an actual linux/arm binary (and in that case, it is also
included in the LLVM triple).

See: https://github.com/tinygo-org/tinygo/issues/3034
2022-09-01 13:17:37 +02:00
deadprogram 61d651c947 flash: update serial package to v1.3.5 for latest bugfixes
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-01 11:40:52 +02:00
Damian Gryski 227a55d891 loader,crypto: fix link error for crypto/internal/boring/sig.StandardCrypto 2022-09-01 09:48:40 +02:00
Ayke van Laethem b485e8bfbd compiler: fix unsafe.Sizeof for chan and map values
These types are simply pointers. For some reason, they were never
implemented.

Fixes https://github.com/tinygo-org/tinygo/issues/3083.
2022-09-01 03:53:27 +02:00
Ayke van Laethem 9e8739bb47 compiler: replace math aliases with intrinsics
This is really a few more-or-less separate changes:

  * Remove all math aliases that were used in Go 1.16 and below (the
    math.[A-Z] aliases).
  * Replace math aliases with an assembly implementation (the math.arch*
    aliases) with a LLVM intrinsic, where one is available.
  * Include missing math functions in picolibc build.

This leaves just four math aliases:

  * math.archHypot and math.archModf do not have a LLVM builtin
    equivalent. They could be replaced with calls to libm, and I think
    that would be a good idea in the long term.
  * math.archMax and math.archMin do have a LLVM builtin equivalent
    (llvm.maximum.f64, llvm.minimum.f64), but unfortunately they crash
    when used. Apparently these exact operations are not yet widely
    supported in hardware and they don't have a libm equivalent either.

There are more LLVM builtins that we could use for the math package
(such as FMA), but I will leave that to a future change. It could
potentially speed up some math operations.
2022-08-30 17:33:16 +02:00
Ayke van Laethem 20a7a6fd54 compiler: replace some math operation bodies with fast intrinsics
Instead of changing the calls, replace the function bodies themselves.
This is useful for a number of reasons, see
https://github.com/tinygo-org/tinygo/pull/2920 for more information.

I have removed the math intrinsics tests because they are no longer
useful. Instead, I think `tinygo test math` should suffice.
2022-08-30 17:33:16 +02:00
Ayke van Laethem 4695da83b7 all: drop support for Go 1.16 and Go 1.17 2022-08-30 12:38:06 +02:00
Yurii Soldak f094e895c5 p1am-100: remove duplicate build tags 2022-08-29 09:44:03 +02:00
Yurii Soldak 55573c6729 targets: fail fast on duplicate values in target field slices 2022-08-29 09:44:03 +02:00
Ayke van Laethem b8a6a1f62b compiler: use the LLVM builtins everywhere
This gives some more optimization opportunities to LLVM, because it
understands these intrinsics. For example, it might convert
llvm.sqrt.f64 to llvm.sqrt.f32 if possible.
2022-08-28 23:37:56 +02:00
Matt Schultz ef912a132d machine: Add support for Adafruit QT2040 board. 2022-08-28 10:16:52 +02:00
Yurii Soldak fb603a471c boards: Add XIAO ESP32C3 board 2022-08-26 12:44:04 +02:00
Joe Shaw f439514703 runtime: implement resetTimer 2022-08-25 11:30:33 +02:00
sago35 303410d3fc main: ignore ports with VID/PID if not candidates 2022-08-24 19:42:49 +02:00
Daniel Esteban aa13b5d83b Add Pimoroni's Tufty2040 board 2022-08-24 13:50:02 +02:00
Kenneth Bell 12d63d9642 runtime: improve reliability of timers test in CI 2022-08-24 11:05:40 +02:00
Kenneth Bell 24b45555bd runtime: add support for time.NewTimer and time.NewTicker
This commit adds support for time.NewTimer and time.NewTicker. It also
adds support for the Stop() method on time.Timer, but doesn't (yet) add
support for the Reset() method.

The implementation has been carefully written so that programs that
don't use these timers will normally not see an increase in RAM or
binary size. None of the examples in the drivers repo change as a result
of this commit. This comes at the cost of slightly more complex code and
possibly slower execution of the timers when they are used.
2022-08-23 12:37:25 +02:00
Damian Gryski 80c17c0f32 testdata: add russross/blackfriday markdown parser to corpus 2022-08-22 23:06:14 +02:00
Ayke van Laethem f6e6aca8d9 compiler: fix incorrect DWARF type in some generic parameters
For some reason, the type of a function parameter can sometimes be of
interface type, while it should be the underlying type. This might be a
bug in the x/tools/go/ssa package but this is a simple workaround.
2022-08-22 10:31:30 +02:00
Damian Gryski c4d99e5297 src/testing: add support for -benchmem 2022-08-20 11:41:20 +02:00
Damian Gryski 697e8c725b runtime: add MemStats.Mallocs and Frees 2022-08-20 11:41:20 +02:00
Damian Gryski a87e5cdbf0 runtime: add MemStats.TotalAlloc 2022-08-20 11:41:20 +02:00
Damian Gryski b56baa7aad runtime: make MemStats available to leaking collector 2022-08-20 11:41:20 +02:00
deadprogram ee94f92ede build: pin public_suffix Ruby gem to version 4.0.7
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-08-20 08:57:47 +02:00
Damian Gryski 0b77e92c50 make interp timeout configurable from command line 2022-08-20 07:40:39 +02:00
Avi a4ee98e0e1 Add aliases for edwards25519/field.feMul and field.feSquare
ed25519vectors_test.go still fails because:
* It relies on "go mod download" which doesn't work, as well as fork/exec.
* It relies on JSON parsing which has problems with reflection.

But, with the vectors hard coded in the test file the tests *do* succeed, so the encryption is working.
2022-08-18 18:57:16 +02:00
Miguel Angel d0808c93f6 runtime/pprof: add WriteHeapProfile
Fixes: #3071
2022-08-16 09:16:55 +02:00
Ayke van Laethem a0407be7b7 goenv: support GOOS=android
TinyGo doesn't currently support Android directly. However, GOOS=linux
works fine on Android. Therefore, force GOOS=linux on Android.
2022-08-13 12:43:38 +02:00
Elliott Sales de Andrade e70dfa4dd6 Fix skip message for missing emulators 2022-08-09 18:10:35 +02:00
Yeicor f34a0d44ca Fix for builds of tinygo using an Android host 2022-08-09 11:14:39 +02:00
Elliott Sales de Andrade df52b500bf Fix tinygo-test with Go 1.19
One of the internal packages used for tests was moved in that version.
2022-08-09 09:18:49 +02:00
Elliott Sales de Andrade c2f437e0b7 Add ErrProcessDone error
This is used in upstream Go's `os` package now.
2022-08-09 09:18:49 +02:00
Yurii Soldak 2365c7cfec nrf52: cleanup s140v7 uf2 targets 2022-08-07 12:58:36 +02:00
Yurii Soldak a5d28bdcca nrf52: cleanup s140v6 uf2 targets 2022-08-07 11:27:49 +02:00
Damian Gryski f12ddfe164 all: update _test.go files for os.IsFoo changes 2022-08-07 10:32:23 +02:00
Damian Gryski f9ba99344a all: update _test.go files for ioutil changes 2022-08-07 10:32:23 +02:00
Damian Gryski 1784bcd728 compileopts: use backticks for regexp to avoid extra escapes 2022-08-07 10:32:23 +02:00
Damian Gryski a2704f1435 all: move from os.IsFoo to errors.Is(err, ErrFoo) 2022-08-07 10:32:23 +02:00
Damian Gryski edbbca5614 all: remove calls to deprecated ioutil package
Fixes produced via semgrep and https://github.com/dgryski/semgrep-go/blob/master/ioutil.yml
2022-08-07 10:32:23 +02:00
Roman Volosatovs 13f21477b1 syscall/darwin: add ENOTCONN
Signed-off-by: Roman Volosatovs <roman@profian.com>
2022-08-07 09:04:57 +02:00
Roman Volosatovs 9d73e6cfe4 os: add SyscallError.Timeout
Signed-off-by: Roman Volosatovs <roman@profian.com>
2022-08-06 12:40:15 +02:00
Roman Volosatovs 9e7667ffae syscall: add WASI {D,R}SYNC, NONBLOCK FD flags
Signed-off-by: Roman Volosatovs <roman@profian.com>
2022-08-06 09:38:00 +02:00
Roman Volosatovs b86467f9c5 syscall: group WASI consts by purpose
Signed-off-by: Roman Volosatovs <roman@profian.com>
2022-08-06 09:38:00 +02:00
Roman Volosatovs 13a16afc2a net: sync net.go with Go 1.18 stdlib
Signed-off-by: Roman Volosatovs <roman@profian.com>
2022-08-06 08:05:29 +02:00
Roman Volosatovs a107b4d459 syscall: ensure correct C prototype WASI function signature
Signed-off-by: Roman Volosatovs <roman@profian.com>
2022-08-05 21:05:46 +02:00
Ayke van Laethem 5c176f80d5 ci: add check that TinyGo can be built using Homebrew LLVM
This is supposed to work, but there was no CI check. Add it to make sure
it continues to work.
2022-08-05 16:21:34 +02:00
Ayke van Laethem c4392d9472 all: rename assembly files to .S extension
The Go tools only consider lowercase .s files to be assembly files. By
renaming these to uppercase .S files they won't be discovered by the Go
toolchain and listed as the SFiles to be assembled.

There is a difference between .s and .S: only uppercase .S will be
passed through the preprocessor. Doing that is normally safe, and
definitely safe in the case of these files.
2022-08-04 15:43:42 +02:00
Ayke van Laethem b6d6efde07 all: remove support for LLVM 13 2022-08-04 14:31:54 +02:00
sago35 8b67282f91 examples/wasm: improve Makefile 2022-08-04 13:10:41 +02:00
Ayke van Laethem c7a23183e8 all: format code according to Go 1.19 rules
Go 1.19 started reformatting code in a way that makes it more obvious
how it will be rendered on pkg.go.dev. It gets it almost right, but not
entirely. Therefore, I had to modify some of the comments so that they
are formatted correctly.
2022-08-04 12:18:32 +02:00
Ayke van Laethem f936125658 main: use tags parser from buildutil
This should add support for things like quotes around tags, if they are
ever needed.

Only making this change now because I happened to stumble across
buildutil.TagsFlag.
2022-08-04 11:17:43 +02:00
sago35 3cfaceeb16 all: update version for next development iteration 2022-08-04 09:11:18 +02:00
240 changed files with 2462 additions and 1719 deletions
+4 -4
View File
@@ -112,12 +112,12 @@ commands:
- /go/pkg/mod - /go/pkg/mod
jobs: jobs:
test-llvm13-go116: test-llvm14-go118:
docker: docker:
- image: golang:1.16-buster - image: golang:1.18-buster
steps: steps:
- test-linux: - test-linux:
llvm: "13" llvm: "14"
test-llvm14-go119: test-llvm14-go119:
docker: docker:
- image: golang:1.19beta1-buster - image: golang:1.19beta1-buster
@@ -131,7 +131,7 @@ workflows:
jobs: jobs:
# This tests our lowest supported versions of Go and LLVM, to make sure at # This tests our lowest supported versions of Go and LLVM, to make sure at
# least the smoke tests still pass. # least the smoke tests still pass.
- test-llvm13-go116 - test-llvm14-go118
# This tests a beta version of Go. It should be removed once regular # This tests a beta version of Go. It should be removed once regular
# release builds are built using this version. # release builds are built using this version.
- test-llvm14-go119 - test-llvm14-go119
+25
View File
@@ -100,3 +100,28 @@ jobs:
- name: Smoke tests - name: Smoke tests
shell: bash shell: bash
run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0 run: make smoketest TINYGO=$(PWD)/build/tinygo AVR=0
test-macos-homebrew:
name: homebrew-install
runs-on: macos-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.18'
- name: Install LLVM
shell: bash
run: |
HOMEBREW_NO_AUTO_UPDATE=1 brew install llvm@14
- name: Checkout
uses: actions/checkout@v2
- name: Cache Go
uses: actions/cache@v2
with:
key: go-cache-macos-homebrew-v1-${{ hashFiles('go.mod') }}
path: |
~/Library/Caches/go-build
~/go/pkg/mod
- name: Build TinyGo
run: go install
- name: Check binary
run: tinygo version
+3
View File
@@ -98,6 +98,7 @@ jobs:
run: make wasi-libc run: make wasi-libc
- name: Install fpm - name: Install fpm
run: | run: |
gem install --version 4.0.7 public_suffix
gem install --version 2.7.6 dotenv gem install --version 2.7.6 dotenv
gem install --no-document fpm gem install --no-document fpm
- name: Build TinyGo release - name: Build TinyGo release
@@ -334,6 +335,7 @@ jobs:
make CROSS=arm-linux-gnueabihf binaryen make CROSS=arm-linux-gnueabihf binaryen
- name: Install fpm - name: Install fpm
run: | run: |
sudo gem install --version 4.0.7 public_suffix
sudo gem install --version 2.7.6 dotenv sudo gem install --version 2.7.6 dotenv
sudo gem install --no-document fpm sudo gem install --no-document fpm
- name: Build TinyGo binary - name: Build TinyGo binary
@@ -436,6 +438,7 @@ jobs:
make CROSS=aarch64-linux-gnu binaryen make CROSS=aarch64-linux-gnu binaryen
- name: Install fpm - name: Install fpm
run: | run: |
sudo gem install --version 4.0.7 public_suffix
sudo gem install --version 2.7.6 dotenv sudo gem install --version 2.7.6 dotenv
sudo gem install --no-document fpm sudo gem install --no-document fpm
- name: Build TinyGo binary - name: Build TinyGo binary
+1 -1
View File
@@ -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 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. build tools to be built. Go is of course necessary to build TinyGo itself.
* Go (1.16+) * Go (1.18+)
* Standard build tools (gcc/clang) * Standard build tools (gcc/clang)
* git * git
* CMake * CMake
+18 -1
View File
@@ -280,7 +280,6 @@ TEST_PACKAGES_FAST = \
container/list \ container/list \
container/ring \ container/ring \
crypto/des \ crypto/des \
crypto/elliptic/internal/fiat \
crypto/internal/subtle \ crypto/internal/subtle \
crypto/md5 \ crypto/md5 \
crypto/rc4 \ crypto/rc4 \
@@ -317,6 +316,14 @@ TEST_PACKAGES_FAST = \
unicode \ unicode \
unicode/utf16 \ unicode/utf16 \
unicode/utf8 \ 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 # archive/zip requires os.ReadAt, which is not yet supported on windows
# debug/plan9obj requires os.ReadAt, which is not yet supported on windows # debug/plan9obj requires os.ReadAt, which is not yet supported on windows
@@ -578,16 +585,22 @@ endif
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=feather-rp2040 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=qtpy-rp2040 examples/echo
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=macropad-rp2040 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=macropad-rp2040 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=badger2040 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=badger2040 examples/blinky1
@$(MD5SUM) test.hex @$(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 $(TINYGO) build -size short -o test.hex -target=thingplus-rp2040 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=xiao-rp2040 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=xiao-rp2040 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/adc_rp2040
@$(MD5SUM) test.hex
# test pwm # test pwm
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm $(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
@@ -672,6 +685,8 @@ endif
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial $(TINYGO) build -size short -o test.bin -target=m5stamp-c3 examples/serial
@$(MD5SUM) test.bin @$(MD5SUM) test.bin
$(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 $(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hifive1-qemu examples/serial $(TINYGO) build -size short -o test.hex -target=hifive1-qemu examples/serial
@@ -748,6 +763,7 @@ endif
@cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src @cp -rp lib/musl/src/internal build/release/tinygo/lib/musl/src
@cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src @cp -rp lib/musl/src/malloc build/release/tinygo/lib/musl/src
@cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src @cp -rp lib/musl/src/mman build/release/tinygo/lib/musl/src
@cp -rp lib/musl/src/math build/release/tinygo/lib/musl/src
@cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src @cp -rp lib/musl/src/signal build/release/tinygo/lib/musl/src
@cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src @cp -rp lib/musl/src/stdio build/release/tinygo/lib/musl/src
@cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src @cp -rp lib/musl/src/string build/release/tinygo/lib/musl/src
@@ -766,6 +782,7 @@ endif
@cp -rp lib/picolibc/newlib/libc/string build/release/tinygo/lib/picolibc/newlib/libc @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/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/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/picolibc-stdio.c build/release/tinygo/lib
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot @cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
@cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins @cp -rp llvm-project/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt-builtins
+5 -1
View File
@@ -43,7 +43,7 @@ See the [getting started instructions](https://tinygo.org/getting-started/) for
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux. You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
The following 88 microcontroller boards are currently supported: The following 91 microcontroller boards are currently supported:
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333) * [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333) * [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
@@ -66,7 +66,9 @@ The following 88 microcontroller boards are currently supported:
* [Adafruit PyGamer](https://www.adafruit.com/product/4242) * [Adafruit PyGamer](https://www.adafruit.com/product/4242)
* [Adafruit PyPortal](https://www.adafruit.com/product/4116) * [Adafruit PyPortal](https://www.adafruit.com/product/4116)
* [Adafruit QT Py](https://www.adafruit.com/product/4600) * [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 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 1280](https://www.arduino.cc/en/Main/arduinoBoardMega/)
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3) * [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi) * [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
@@ -108,6 +110,7 @@ The following 88 microcontroller boards are currently supported:
* [Particle Xenon](https://docs.particle.io/datasheets/discontinued/xenon-datasheet/) * [Particle Xenon](https://docs.particle.io/datasheets/discontinued/xenon-datasheet/)
* [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/) * [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/)
* [Pimoroni Badger2040](https://shop.pimoroni.com/products/badger-2040) * [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/) * [PineTime DevKit](https://www.pine64.org/pinetime/)
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html) * [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html) * [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
@@ -117,6 +120,7 @@ The following 88 microcontroller boards are currently supported:
* [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199) * [Raytac MDBT50Q-RX Dongle (with TinyUF2 bootloader)](https://www.adafruit.com/product/5199)
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html) * [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
* [Seeed XIAO BLE](https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html) * [Seeed 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 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 LoRa-E5 Development Kit](https://www.seeedstudio.com/LoRa-E5-Dev-Kit-p-4868.html)
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html) * [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
+1 -1
View File
@@ -18,7 +18,7 @@ import (
// makeArchive creates an arcive for static linking from a list of object files // makeArchive creates an arcive for static linking from a list of object files
// given as a parameter. It is equivalent to the following command: // 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 { func makeArchive(arfile *os.File, objs []string) error {
// Open the archive file. // Open the archive file.
arwriter := ar.NewWriter(arfile) arwriter := ar.NewWriter(arfile)
+15 -15
View File
@@ -14,7 +14,7 @@ import (
"fmt" "fmt"
"go/types" "go/types"
"hash/crc32" "hash/crc32"
"io/ioutil" "io/fs"
"math/bits" "math/bits"
"os" "os"
"os/exec" "os/exec"
@@ -103,7 +103,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
} }
// Create a temporary directory for intermediary files. // Create a temporary directory for intermediary files.
dir, err := ioutil.TempDir("", "tinygo") dir, err := os.MkdirTemp("", "tinygo")
if err != nil { if err != nil {
return err return err
} }
@@ -148,7 +148,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
libcDependencies = append(libcDependencies, libcJob) libcDependencies = append(libcDependencies, libcJob)
case "wasi-libc": case "wasi-libc":
path := filepath.Join(root, "lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a") path := filepath.Join(root, "lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a")
if _, err := os.Stat(path); os.IsNotExist(err) { if _, err := os.Stat(path); errors.Is(err, fs.ErrNotExist) {
return errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?") return errors.New("could not find wasi-libc, perhaps you need to run `make wasi-libc`?")
} }
libcDependencies = append(libcDependencies, dummyCompileJob(path)) libcDependencies = append(libcDependencies, dummyCompileJob(path))
@@ -370,7 +370,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
// Packages are compiled independently anyway. // Packages are compiled independently anyway.
for _, cgoHeader := range pkg.CGoHeaders { for _, cgoHeader := range pkg.CGoHeaders {
// Store the header text in a temporary file. // Store the header text in a temporary file.
f, err := ioutil.TempFile(dir, "cgosnippet-*.c") f, err := os.CreateTemp(dir, "cgosnippet-*.c")
if err != nil { if err != nil {
return err return err
} }
@@ -431,7 +431,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
if pkgInit.IsNil() { if pkgInit.IsNil() {
panic("init not found for " + pkg.Pkg.Path()) panic("init not found for " + pkg.Pkg.Path())
} }
err := interp.RunFunc(pkgInit, config.DumpSSA()) err := interp.RunFunc(pkgInit, config.Options.InterpTimeout, config.DumpSSA())
if err != nil { if err != nil {
return err 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 // Write to a temporary path that is renamed to the destination
// file to avoid race conditions with other TinyGo invocatiosn // file to avoid race conditions with other TinyGo invocatiosn
// that might also be compiling this package at the same time. // that might also be compiling this package at the same time.
f, err := ioutil.TempFile(filepath.Dir(job.result), filepath.Base(job.result)) f, err := os.CreateTemp(filepath.Dir(job.result), filepath.Base(job.result))
if err != nil { if err != nil {
return err return err
} }
@@ -589,7 +589,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
return err return err
} }
defer llvmBuf.Dispose() defer llvmBuf.Dispose()
return ioutil.WriteFile(outpath, llvmBuf.Bytes(), 0666) return os.WriteFile(outpath, llvmBuf.Bytes(), 0666)
case ".bc": case ".bc":
var buf llvm.MemoryBuffer var buf llvm.MemoryBuffer
if config.UseThinLTO() { if config.UseThinLTO() {
@@ -598,10 +598,10 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
buf = llvm.WriteBitcodeToMemoryBuffer(mod) buf = llvm.WriteBitcodeToMemoryBuffer(mod)
} }
defer buf.Dispose() defer buf.Dispose()
return ioutil.WriteFile(outpath, buf.Bytes(), 0666) return os.WriteFile(outpath, buf.Bytes(), 0666)
case ".ll": case ".ll":
data := []byte(mod.String()) data := []byte(mod.String())
return ioutil.WriteFile(outpath, data, 0666) return os.WriteFile(outpath, data, 0666)
default: default:
panic("unreachable") panic("unreachable")
} }
@@ -629,7 +629,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(Buil
} }
} }
defer llvmBuf.Dispose() defer llvmBuf.Dispose()
return ioutil.WriteFile(objfile, llvmBuf.Bytes(), 0666) return os.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 // needed to convert a program to its final form. Some transformations are not
// optional and must be run as the compiler expects them to run. // optional and must be run as the compiler expects them to run.
func optimizeProgram(mod llvm.Module, config *compileopts.Config) error { func optimizeProgram(mod llvm.Module, config *compileopts.Config) error {
err := interp.Run(mod, config.DumpSSA()) err := interp.Run(mod, config.Options.InterpTimeout, config.DumpSSA())
if err != nil { if err != nil {
return err return err
} }
@@ -1367,10 +1367,10 @@ func modifyStackSizes(executable string, stackSizeLoads []string, stackSizes map
// //
// It might print something like the following: // It might print something like the following:
// //
// function stack usage (in bytes) // function stack usage (in bytes)
// Reset_Handler 316 // Reset_Handler 316
// examples/blinky2.led1 92 // examples/blinky2.led1 92
// runtime.run$1 300 // runtime.run$1 300
func printStacks(calculatedStacks []string, stackSizes map[string]functionStackSize) { func printStacks(calculatedStacks []string, stackSizes map[string]functionStackSize) {
// Print the sizes of all stacks. // Print the sizes of all stacks.
fmt.Printf("%-32s %s\n", "function", "stack usage (in bytes)") fmt.Printf("%-32s %s\n", "function", "stack usage (in bytes)")
+1 -2
View File
@@ -2,7 +2,6 @@ package builder
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@@ -90,7 +89,7 @@ func testClangAttributes(t *testing.T, options *compileopts.Options) {
// Create a very simple C input file. // Create a very simple C input file.
srcpath := filepath.Join(testDir, "test.c") srcpath := filepath.Join(testDir, "test.c")
err = ioutil.WriteFile(srcpath, []byte("int add(int a, int b) { return a + b; }"), 0o666) err = os.WriteFile(srcpath, []byte("int add(int a, int b) { return a + b; }"), 0o666)
if err != nil { if err != nil {
t.Fatalf("could not write target file %s: %s", srcpath, err) t.Fatalf("could not write target file %s: %s", srcpath, err)
} }
+1 -1
View File
@@ -24,7 +24,7 @@ func ReadBuildID() ([]byte, error) {
defer f.Close() defer f.Close()
switch runtime.GOOS { switch runtime.GOOS {
case "linux", "freebsd": case "linux", "freebsd", "android":
// Read the GNU build id section. (Not sure about FreeBSD though...) // Read the GNU build id section. (Not sure about FreeBSD though...)
file, err := elf.NewFile(f) file, err := elf.NewFile(f)
if err != nil { if err != nil {
+37 -36
View File
@@ -10,7 +10,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/fs"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@@ -33,29 +33,29 @@ import (
// Because of this complexity, every file has in fact two cached build outputs: // 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: // the file itself, and the list of dependencies. Its operation is as follows:
// //
// depfile = hash(path, compiler, cflags, ...) // depfile = hash(path, compiler, cflags, ...)
// if depfile exists: // if depfile exists:
// outfile = hash of all files and depfile name // outfile = hash of all files and depfile name
// if outfile exists: // if outfile exists:
// # cache hit // # cache hit
// return outfile // return outfile
// # cache miss // # cache miss
// tmpfile = compile file // tmpfile = compile file
// read dependencies (side effect of compile) // read dependencies (side effect of compile)
// write depfile // write depfile
// outfile = hash of all files and depfile name // outfile = hash of all files and depfile name
// rename tmpfile to outfile // rename tmpfile to outfile
// //
// There are a few edge cases that are not handled: // 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 // - 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 // 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. // dependencies file, but I'm not aware of a compiler which does that.
// - The Makefile syntax that compilers output has issues, see readDepFile for // - The Makefile syntax that compilers output has issues, see readDepFile for
// details. // details.
// - A header file may be changed to add/remove an include. This invalidates the // - 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 // depfile but without invalidating its name. For this reason, the depfile is
// written on each new compilation (even when it seems unnecessary). However, it // written on each new compilation (even when it seems unnecessary). However, it
// could in rare cases lead to a stale file fetched from the cache. // could in rare cases lead to a stale file fetched from the cache.
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool, printCommands func(string, ...string)) (string, error) { func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool, printCommands func(string, ...string)) (string, error) {
// Hash input file. // Hash input file.
fileHash, err := hashFile(abspath) fileHash, err := hashFile(abspath)
@@ -93,7 +93,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
// Load dependencies file, if possible. // Load dependencies file, if possible.
depfileName := "dep-" + depfileNameHash + ".json" depfileName := "dep-" + depfileNameHash + ".json"
depfileCachePath := filepath.Join(goenv.Get("GOCACHE"), depfileName) depfileCachePath := filepath.Join(goenv.Get("GOCACHE"), depfileName)
depfileBuf, err := ioutil.ReadFile(depfileCachePath) depfileBuf, err := os.ReadFile(depfileCachePath)
var dependencies []string // sorted list of dependency paths var dependencies []string // sorted list of dependency paths
if err == nil { if err == nil {
// There is a dependency file, that's great! // 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 == nil {
if _, err := os.Stat(outpath); err == nil { if _, err := os.Stat(outpath); err == nil {
return outpath, nil return outpath, nil
} else if !os.IsNotExist(err) { } else if !errors.Is(err, fs.ErrNotExist) {
return "", err return "", err
} }
} }
} else if !os.IsNotExist(err) { } else if !errors.Is(err, fs.ErrNotExist) {
// expected either nil or IsNotExist // expected either nil or IsNotExist
return "", err return "", err
} }
objTmpFile, err := ioutil.TempFile(goenv.Get("GOCACHE"), "tmp-*"+ext) objTmpFile, err := os.CreateTemp(goenv.Get("GOCACHE"), "tmp-*"+ext)
if err != nil { if err != nil {
return "", err return "", err
} }
objTmpFile.Close() objTmpFile.Close()
depTmpFile, err := ioutil.TempFile(tmpdir, "dep-*.d") depTmpFile, err := os.CreateTemp(tmpdir, "dep-*.d")
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -166,7 +166,7 @@ func compileAndCacheCFile(abspath, tmpdir string, cflags []string, thinlto bool,
sort.Strings(dependencySlice) sort.Strings(dependencySlice)
// Write dependencies file. // Write dependencies file.
f, err := ioutil.TempFile(filepath.Dir(depfileCachePath), depfileName) f, err := os.CreateTemp(filepath.Dir(depfileCachePath), depfileName)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -252,13 +252,14 @@ func hashFile(path string) (string, error) {
// file is assumed to have a single target named deps. // file is assumed to have a single target named deps.
// //
// There are roughly three make syntax variants: // There are roughly three make syntax variants:
// - BSD make, which doesn't support any escaping. This means that many special // - BSD make, which doesn't support any escaping. This means that many special
// characters are not supported in file names. // characters are not supported in file names.
// - GNU make, which supports escaping using a backslash but when it fails to // - 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 // find a file it tries to fall back with the literal path name (to match BSD
// make). // make).
// - NMake (Visual Studio) and Jom, which simply quote the string if there are // - NMake (Visual Studio) and Jom, which simply quote the string if there are
// any weird characters. // any weird characters.
//
// Clang supports two variants: a format that's a compromise between BSD and GNU // 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 // 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 // is at least somewhat sane. This last format isn't perfect either: it does not
@@ -266,7 +267,7 @@ func hashFile(path string) (string, error) {
// allowed on Windows, but of course can be used on POSIX like systems. Still, // 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. // it's the most sane of any of the formats so readDepFile will use that format.
func readDepFile(filename string) ([]string, error) { func readDepFile(filename string) ([]string, error) {
buf, err := ioutil.ReadFile(filename) buf, err := os.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+2 -2
View File
@@ -33,8 +33,8 @@ func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err) return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
} }
if major != 1 || minor < 16 || minor > 19 { if major != 1 || minor < 18 || minor > 19 {
return nil, fmt.Errorf("requires go version 1.16 through 1.19, got go%d.%d", major, minor) return nil, fmt.Errorf("requires go version 1.18 through 1.19, got go%d.%d", major, minor)
} }
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT")) clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
+4 -2
View File
@@ -1,6 +1,8 @@
package builder package builder
import ( import (
"errors"
"io/fs"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
@@ -17,13 +19,13 @@ import (
func getClangHeaderPath(TINYGOROOT string) string { func getClangHeaderPath(TINYGOROOT string) string {
// Check whether we're running from the source directory. // Check whether we're running from the source directory.
path := filepath.Join(TINYGOROOT, "llvm-project", "clang", "lib", "Headers") path := filepath.Join(TINYGOROOT, "llvm-project", "clang", "lib", "Headers")
if _, err := os.Stat(path); !os.IsNotExist(err) { if _, err := os.Stat(path); !errors.Is(err, fs.ErrNotExist) {
return path return path
} }
// Check whether we're running from the installation directory. // Check whether we're running from the installation directory.
path = filepath.Join(TINYGOROOT, "lib", "clang", "include") path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
if _, err := os.Stat(path); !os.IsNotExist(err) { if _, err := os.Stat(path); !errors.Is(err, fs.ErrNotExist) {
return path return path
} }
+2 -2
View File
@@ -13,7 +13,7 @@ import (
"debug/elf" "debug/elf"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io/ioutil" "os"
"sort" "sort"
"strings" "strings"
) )
@@ -189,5 +189,5 @@ func makeESPFirmareImage(infile, outfile, format string) error {
} }
// Write the image to the output file. // Write the image to the output file.
return ioutil.WriteFile(outfile, outf.Bytes(), 0666) return os.WriteFile(outfile, outf.Bytes(), 0666)
} }
+12 -7
View File
@@ -1,7 +1,8 @@
package builder package builder
import ( import (
"io/ioutil" "errors"
"io/fs"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@@ -94,7 +95,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
target := config.Triple() target := config.Triple()
if l.makeHeaders != nil { if l.makeHeaders != nil {
if _, err = os.Stat(headerPath); err != nil { if _, err = os.Stat(headerPath); err != nil {
temporaryHeaderPath, err := ioutil.TempDir(outdir, "include.tmp*") temporaryHeaderPath, err := os.MkdirTemp(outdir, "include.tmp*")
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -110,10 +111,10 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
err = os.Rename(temporaryHeaderPath, headerPath) err = os.Rename(temporaryHeaderPath, headerPath)
if err != nil { if err != nil {
switch { switch {
case os.IsExist(err): case errors.Is(err, fs.ErrExist):
// Another invocation of TinyGo also seems to have already created the headers. // Another invocation of TinyGo also seems to have already created the headers.
case runtime.GOOS == "windows" && os.IsPermission(err): case runtime.GOOS == "windows" && errors.Is(err, fs.ErrPermission):
// On Windows, a rename with a destination directory that already // On Windows, a rename with a destination directory that already
// exists does not result in an IsExist error, but rather in an // exists does not result in an IsExist error, but rather in an
// access denied error. To be sure, check for this case by checking // access denied error. To be sure, check for this case by checking
@@ -155,7 +156,11 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
} }
} }
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") { if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft", "-fno-unwind-tables", "-fno-asynchronous-unwind-tables") 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")
}
} }
if strings.HasPrefix(target, "avr") { if strings.HasPrefix(target, "avr") {
// AVR defaults to C float and double both being 32-bit. This deviates // AVR defaults to C float and double both being 32-bit. This deviates
@@ -189,7 +194,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
defer once.Do(unlock) defer once.Do(unlock)
// Create an archive of all object files. // Create an archive of all object files.
f, err := ioutil.TempFile(outdir, "libc.a.tmp*") f, err := os.CreateTemp(outdir, "libc.a.tmp*")
if err != nil { if err != nil {
return err return err
} }
@@ -250,7 +255,7 @@ func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJ
run: func(*compileJob) error { run: func(*compileJob) error {
var compileArgs []string var compileArgs []string
compileArgs = append(compileArgs, args...) compileArgs = append(compileArgs, args...)
tmpfile, err := ioutil.TempFile(outdir, "crt1.o.tmp*") tmpfile, err := os.CreateTemp(outdir, "crt1.o.tmp*")
if err != nil { if err != nil {
return err return err
} }
+1 -1
View File
@@ -78,7 +78,7 @@ func makeMinGWExtraLibs(tmpdir string) []*compileJob {
// .in files need to be preprocessed by a preprocessor (-E) // .in files need to be preprocessed by a preprocessor (-E)
// first. // first.
defpath = outpath + ".def" defpath = outpath + ".def"
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/") 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/")
if err != nil { if err != nil {
return err return err
} }
+4 -3
View File
@@ -3,7 +3,6 @@ package builder
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
@@ -35,7 +34,7 @@ var Musl = Library{
filepath.Join(muslDir, "include", "alltypes.h.in"), filepath.Join(muslDir, "include", "alltypes.h.in"),
} }
for _, infile := range infiles { for _, infile := range infiles {
data, err := ioutil.ReadFile(infile) data, err := os.ReadFile(infile)
if err != nil { if err != nil {
return err return err
} }
@@ -63,7 +62,7 @@ var Musl = Library{
if err != nil { if err != nil {
return err return err
} }
data, err := ioutil.ReadFile(filepath.Join(muslDir, "arch", arch, "bits", "syscall.h.in")) data, err := os.ReadFile(filepath.Join(muslDir, "arch", arch, "bits", "syscall.h.in"))
if err != nil { if err != nil {
return err return err
} }
@@ -90,6 +89,7 @@ var Musl = Library{
"-Wno-shift-op-parentheses", "-Wno-shift-op-parentheses",
"-Wno-ignored-attributes", "-Wno-ignored-attributes",
"-Wno-string-plus-int", "-Wno-string-plus-int",
"-Wno-ignored-pragmas",
"-Qunused-arguments", "-Qunused-arguments",
// Select include dirs. Don't include standard library includes // Select include dirs. Don't include standard library includes
// (that would introduce host dependencies and other complications), // (that would introduce host dependencies and other complications),
@@ -118,6 +118,7 @@ var Musl = Library{
"legacy/*.c", "legacy/*.c",
"malloc/*.c", "malloc/*.c",
"mman/*.c", "mman/*.c",
"math/*.c",
"signal/*.c", "signal/*.c",
"stdio/*.c", "stdio/*.c",
"string/*.c", "string/*.c",
+2 -2
View File
@@ -2,7 +2,7 @@ package builder
import ( import (
"fmt" "fmt"
"io/ioutil" "io"
"os/exec" "os/exec"
"github.com/tinygo-org/tinygo/compileopts" "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 := exec.Command(cmdLine[0], cmdLine[1:]...)
cmd.Stdout = ioutil.Discard cmd.Stdout = io.Discard
err := cmd.Run() err := cmd.Run()
if err != nil { if err != nil {
return fmt.Errorf("could not run nrfutil pkg generate: %w", err) return fmt.Errorf("could not run nrfutil pkg generate: %w", err)
+2 -2
View File
@@ -2,7 +2,7 @@ package builder
import ( import (
"debug/elf" "debug/elf"
"io/ioutil" "io"
"os" "os"
"sort" "sort"
@@ -87,7 +87,7 @@ func extractROM(path string) (uint64, []byte, error) {
// Pad the difference // Pad the difference
rom = append(rom, make([]byte, diff)...) rom = append(rom, make([]byte, diff)...)
} }
data, err := ioutil.ReadAll(prog.Open()) data, err := io.ReadAll(prog.Open())
if err != nil { if err != nil {
return 0, nil, objcopyError{"failed to extract segment from ELF file: " + path, err} return 0, nil, objcopyError{"failed to extract segment from ELF file: " + path, err}
} }
+380 -204
View File
@@ -19,7 +19,7 @@ var Picolibc = Library{
return f.Close() return f.Close()
}, },
cflags: func(target, headerPath string) []string { cflags: func(target, headerPath string) []string {
picolibcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc") newlibDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib")
return []string{ return []string{
"-Werror", "-Werror",
"-Wall", "-Wall",
@@ -27,219 +27,395 @@ var Picolibc = Library{
"-D_COMPILING_NEWLIB", "-D_COMPILING_NEWLIB",
"-DHAVE_ALIAS_ATTRIBUTE", "-DHAVE_ALIAS_ATTRIBUTE",
"-DTINY_STDIO", "-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", "-nostdlibinc",
"-isystem", picolibcDir + "/include", "-isystem", newlibDir + "/libc/include",
"-I" + picolibcDir + "/tinystdio", "-I" + newlibDir + "/libc/tinystdio",
"-I" + newlibDir + "/libm/common",
"-I" + headerPath, "-I" + headerPath,
} }
}, },
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc") }, sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib") },
librarySources: func(target string) []string { librarySources: func(target string) []string {
return picolibcSources return picolibcSources
}, },
} }
var picolibcSources = []string{ var picolibcSources = []string{
"../../../picolibc-stdio.c", "../../picolibc-stdio.c",
"tinystdio/asprintf.c", "libc/tinystdio/asprintf.c",
"tinystdio/atod_engine.c", "libc/tinystdio/atod_engine.c",
"tinystdio/atod_ryu.c", "libc/tinystdio/atod_ryu.c",
"tinystdio/atof_engine.c", "libc/tinystdio/atof_engine.c",
"tinystdio/atof_ryu.c", "libc/tinystdio/atof_ryu.c",
//"tinystdio/atold_engine.c", // have_long_double and not long_double_equals_double //"libc/tinystdio/atold_engine.c", // have_long_double and not long_double_equals_double
"tinystdio/clearerr.c", "libc/tinystdio/clearerr.c",
"tinystdio/compare_exchange.c", "libc/tinystdio/compare_exchange.c",
"tinystdio/dtoa_data.c", "libc/tinystdio/dtoa_data.c",
"tinystdio/dtoa_engine.c", "libc/tinystdio/dtoa_engine.c",
"tinystdio/dtoa_ryu.c", "libc/tinystdio/dtoa_ryu.c",
"tinystdio/ecvtbuf.c", "libc/tinystdio/ecvtbuf.c",
"tinystdio/ecvt.c", "libc/tinystdio/ecvt.c",
"tinystdio/ecvt_data.c", "libc/tinystdio/ecvt_data.c",
"tinystdio/ecvtfbuf.c", "libc/tinystdio/ecvtfbuf.c",
"tinystdio/ecvtf.c", "libc/tinystdio/ecvtf.c",
"tinystdio/ecvtf_data.c", "libc/tinystdio/ecvtf_data.c",
"tinystdio/exchange.c", "libc/tinystdio/exchange.c",
//"tinystdio/fclose.c", // posix-io //"libc/tinystdio/fclose.c", // posix-io
"tinystdio/fcvtbuf.c", "libc/tinystdio/fcvtbuf.c",
"tinystdio/fcvt.c", "libc/tinystdio/fcvt.c",
"tinystdio/fcvtfbuf.c", "libc/tinystdio/fcvtfbuf.c",
"tinystdio/fcvtf.c", "libc/tinystdio/fcvtf.c",
"tinystdio/fdevopen.c", "libc/tinystdio/fdevopen.c",
//"tinystdio/fdopen.c", // posix-io //"libc/tinystdio/fdopen.c", // posix-io
"tinystdio/feof.c", "libc/tinystdio/feof.c",
"tinystdio/ferror.c", "libc/tinystdio/ferror.c",
"tinystdio/fflush.c", "libc/tinystdio/fflush.c",
"tinystdio/fgetc.c", "libc/tinystdio/fgetc.c",
"tinystdio/fgets.c", "libc/tinystdio/fgets.c",
"tinystdio/fileno.c", "libc/tinystdio/fileno.c",
"tinystdio/filestrget.c", "libc/tinystdio/filestrget.c",
"tinystdio/filestrputalloc.c", "libc/tinystdio/filestrputalloc.c",
"tinystdio/filestrput.c", "libc/tinystdio/filestrput.c",
//"tinystdio/fopen.c", // posix-io //"libc/tinystdio/fopen.c", // posix-io
"tinystdio/fprintf.c", "libc/tinystdio/fprintf.c",
"tinystdio/fputc.c", "libc/tinystdio/fputc.c",
"tinystdio/fputs.c", "libc/tinystdio/fputs.c",
"tinystdio/fread.c", "libc/tinystdio/fread.c",
"tinystdio/fscanf.c", "libc/tinystdio/fscanf.c",
"tinystdio/fseek.c", "libc/tinystdio/fseek.c",
"tinystdio/ftell.c", "libc/tinystdio/ftell.c",
"tinystdio/ftoa_data.c", "libc/tinystdio/ftoa_data.c",
"tinystdio/ftoa_engine.c", "libc/tinystdio/ftoa_engine.c",
"tinystdio/ftoa_ryu.c", "libc/tinystdio/ftoa_ryu.c",
"tinystdio/fwrite.c", "libc/tinystdio/fwrite.c",
"tinystdio/gcvtbuf.c", "libc/tinystdio/gcvtbuf.c",
"tinystdio/gcvt.c", "libc/tinystdio/gcvt.c",
"tinystdio/gcvtfbuf.c", "libc/tinystdio/gcvtfbuf.c",
"tinystdio/gcvtf.c", "libc/tinystdio/gcvtf.c",
"tinystdio/getchar.c", "libc/tinystdio/getchar.c",
"tinystdio/gets.c", "libc/tinystdio/gets.c",
"tinystdio/matchcaseprefix.c", "libc/tinystdio/matchcaseprefix.c",
"tinystdio/perror.c", "libc/tinystdio/perror.c",
//"tinystdio/posixiob.c", // posix-io //"libc/tinystdio/posixiob.c", // posix-io
//"tinystdio/posixio.c", // posix-io //"libc/tinystdio/posixio.c", // posix-io
"tinystdio/printf.c", "libc/tinystdio/printf.c",
"tinystdio/putchar.c", "libc/tinystdio/putchar.c",
"tinystdio/puts.c", "libc/tinystdio/puts.c",
"tinystdio/ryu_divpow2.c", "libc/tinystdio/ryu_divpow2.c",
"tinystdio/ryu_log10.c", "libc/tinystdio/ryu_log10.c",
"tinystdio/ryu_log2pow5.c", "libc/tinystdio/ryu_log2pow5.c",
"tinystdio/ryu_pow5bits.c", "libc/tinystdio/ryu_pow5bits.c",
"tinystdio/ryu_table.c", "libc/tinystdio/ryu_table.c",
"tinystdio/ryu_umul128.c", "libc/tinystdio/ryu_umul128.c",
"tinystdio/scanf.c", "libc/tinystdio/scanf.c",
"tinystdio/setbuf.c", "libc/tinystdio/setbuf.c",
"tinystdio/setvbuf.c", "libc/tinystdio/setvbuf.c",
//"tinystdio/sflags.c", // posix-io //"libc/tinystdio/sflags.c", // posix-io
"tinystdio/snprintf.c", "libc/tinystdio/snprintf.c",
"tinystdio/snprintfd.c", "libc/tinystdio/snprintfd.c",
"tinystdio/snprintff.c", "libc/tinystdio/snprintff.c",
"tinystdio/sprintf.c", "libc/tinystdio/sprintf.c",
"tinystdio/sprintfd.c", "libc/tinystdio/sprintfd.c",
"tinystdio/sprintff.c", "libc/tinystdio/sprintff.c",
"tinystdio/sscanf.c", "libc/tinystdio/sscanf.c",
"tinystdio/strfromd.c", "libc/tinystdio/strfromd.c",
"tinystdio/strfromf.c", "libc/tinystdio/strfromf.c",
"tinystdio/strtod.c", "libc/tinystdio/strtod.c",
"tinystdio/strtod_l.c", "libc/tinystdio/strtod_l.c",
"tinystdio/strtof.c", "libc/tinystdio/strtof.c",
//"tinystdio/strtold.c", // have_long_double and not long_double_equals_double //"libc/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 //"libc/tinystdio/strtold_l.c", // have_long_double and not long_double_equals_double
"tinystdio/ungetc.c", "libc/tinystdio/ungetc.c",
"tinystdio/vasprintf.c", "libc/tinystdio/vasprintf.c",
"tinystdio/vfiprintf.c", "libc/tinystdio/vfiprintf.c",
"tinystdio/vfiscanf.c", "libc/tinystdio/vfiscanf.c",
"tinystdio/vfprintf.c", "libc/tinystdio/vfprintf.c",
"tinystdio/vfprintff.c", "libc/tinystdio/vfprintff.c",
"tinystdio/vfscanf.c", "libc/tinystdio/vfscanf.c",
"tinystdio/vfscanff.c", "libc/tinystdio/vfscanff.c",
"tinystdio/vprintf.c", "libc/tinystdio/vprintf.c",
"tinystdio/vscanf.c", "libc/tinystdio/vscanf.c",
"tinystdio/vsnprintf.c", "libc/tinystdio/vsnprintf.c",
"tinystdio/vsprintf.c", "libc/tinystdio/vsprintf.c",
"tinystdio/vsscanf.c", "libc/tinystdio/vsscanf.c",
"string/bcmp.c", "libc/string/bcmp.c",
"string/bcopy.c", "libc/string/bcopy.c",
"string/bzero.c", "libc/string/bzero.c",
"string/explicit_bzero.c", "libc/string/explicit_bzero.c",
"string/ffsl.c", "libc/string/ffsl.c",
"string/ffsll.c", "libc/string/ffsll.c",
"string/fls.c", "libc/string/fls.c",
"string/flsl.c", "libc/string/flsl.c",
"string/flsll.c", "libc/string/flsll.c",
"string/gnu_basename.c", "libc/string/gnu_basename.c",
"string/index.c", "libc/string/index.c",
"string/memccpy.c", "libc/string/memccpy.c",
"string/memchr.c", "libc/string/memchr.c",
"string/memcmp.c", "libc/string/memcmp.c",
"string/memcpy.c", "libc/string/memcpy.c",
"string/memmem.c", "libc/string/memmem.c",
"string/memmove.c", "libc/string/memmove.c",
"string/mempcpy.c", "libc/string/mempcpy.c",
"string/memrchr.c", "libc/string/memrchr.c",
"string/memset.c", "libc/string/memset.c",
"string/rawmemchr.c", "libc/string/rawmemchr.c",
"string/rindex.c", "libc/string/rindex.c",
"string/stpcpy.c", "libc/string/stpcpy.c",
"string/stpncpy.c", "libc/string/stpncpy.c",
"string/strcasecmp.c", "libc/string/strcasecmp.c",
"string/strcasecmp_l.c", "libc/string/strcasecmp_l.c",
"string/strcasestr.c", "libc/string/strcasestr.c",
"string/strcat.c", "libc/string/strcat.c",
"string/strchr.c", "libc/string/strchr.c",
"string/strchrnul.c", "libc/string/strchrnul.c",
"string/strcmp.c", "libc/string/strcmp.c",
"string/strcoll.c", "libc/string/strcoll.c",
"string/strcoll_l.c", "libc/string/strcoll_l.c",
"string/strcpy.c", "libc/string/strcpy.c",
"string/strcspn.c", "libc/string/strcspn.c",
"string/strdup.c", "libc/string/strdup.c",
"string/strerror.c", "libc/string/strerror.c",
"string/strerror_r.c", "libc/string/strerror_r.c",
"string/strlcat.c", "libc/string/strlcat.c",
"string/strlcpy.c", "libc/string/strlcpy.c",
"string/strlen.c", "libc/string/strlen.c",
"string/strlwr.c", "libc/string/strlwr.c",
"string/strncasecmp.c", "libc/string/strncasecmp.c",
"string/strncasecmp_l.c", "libc/string/strncasecmp_l.c",
"string/strncat.c", "libc/string/strncat.c",
"string/strncmp.c", "libc/string/strncmp.c",
"string/strncpy.c", "libc/string/strncpy.c",
"string/strndup.c", "libc/string/strndup.c",
"string/strnlen.c", "libc/string/strnlen.c",
"string/strnstr.c", "libc/string/strnstr.c",
"string/strpbrk.c", "libc/string/strpbrk.c",
"string/strrchr.c", "libc/string/strrchr.c",
"string/strsep.c", "libc/string/strsep.c",
"string/strsignal.c", "libc/string/strsignal.c",
"string/strspn.c", "libc/string/strspn.c",
"string/strstr.c", "libc/string/strstr.c",
"string/strtok.c", "libc/string/strtok.c",
"string/strtok_r.c", "libc/string/strtok_r.c",
"string/strupr.c", "libc/string/strupr.c",
"string/strverscmp.c", "libc/string/strverscmp.c",
"string/strxfrm.c", "libc/string/strxfrm.c",
"string/strxfrm_l.c", "libc/string/strxfrm_l.c",
"string/swab.c", "libc/string/swab.c",
"string/timingsafe_bcmp.c", "libc/string/timingsafe_bcmp.c",
"string/timingsafe_memcmp.c", "libc/string/timingsafe_memcmp.c",
"string/u_strerr.c", "libc/string/u_strerr.c",
"string/wcpcpy.c", "libc/string/wcpcpy.c",
"string/wcpncpy.c", "libc/string/wcpncpy.c",
"string/wcscasecmp.c", "libc/string/wcscasecmp.c",
"string/wcscasecmp_l.c", "libc/string/wcscasecmp_l.c",
"string/wcscat.c", "libc/string/wcscat.c",
"string/wcschr.c", "libc/string/wcschr.c",
"string/wcscmp.c", "libc/string/wcscmp.c",
"string/wcscoll.c", "libc/string/wcscoll.c",
"string/wcscoll_l.c", "libc/string/wcscoll_l.c",
"string/wcscpy.c", "libc/string/wcscpy.c",
"string/wcscspn.c", "libc/string/wcscspn.c",
"string/wcsdup.c", "libc/string/wcsdup.c",
"string/wcslcat.c", "libc/string/wcslcat.c",
"string/wcslcpy.c", "libc/string/wcslcpy.c",
"string/wcslen.c", "libc/string/wcslen.c",
"string/wcsncasecmp.c", "libc/string/wcsncasecmp.c",
"string/wcsncasecmp_l.c", "libc/string/wcsncasecmp_l.c",
"string/wcsncat.c", "libc/string/wcsncat.c",
"string/wcsncmp.c", "libc/string/wcsncmp.c",
"string/wcsncpy.c", "libc/string/wcsncpy.c",
"string/wcsnlen.c", "libc/string/wcsnlen.c",
"string/wcspbrk.c", "libc/string/wcspbrk.c",
"string/wcsrchr.c", "libc/string/wcsrchr.c",
"string/wcsspn.c", "libc/string/wcsspn.c",
"string/wcsstr.c", "libc/string/wcsstr.c",
"string/wcstok.c", "libc/string/wcstok.c",
"string/wcswidth.c", "libc/string/wcswidth.c",
"string/wcsxfrm.c", "libc/string/wcsxfrm.c",
"string/wcsxfrm_l.c", "libc/string/wcsxfrm_l.c",
"string/wcwidth.c", "libc/string/wcwidth.c",
"string/wmemchr.c", "libc/string/wmemchr.c",
"string/wmemcmp.c", "libc/string/wmemcmp.c",
"string/wmemcpy.c", "libc/string/wmemcpy.c",
"string/wmemmove.c", "libc/string/wmemmove.c",
"string/wmempcpy.c", "libc/string/wmempcpy.c",
"string/wmemset.c", "libc/string/wmemset.c",
"string/xpg_strerror_r.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",
} }
+2 -2
View File
@@ -10,7 +10,7 @@ package builder
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"io/ioutil" "os"
"strconv" "strconv"
) )
@@ -26,7 +26,7 @@ func convertELFFileToUF2File(infile, outfile string, uf2FamilyID string) error {
if err != nil { if err != nil {
return err return err
} }
return ioutil.WriteFile(outfile, output, 0644) return os.WriteFile(outfile, output, 0644)
} }
// convertBinToUF2 converts the binary bytes in input to UF2 formatted data. // convertBinToUF2 converts the binary bytes in input to UF2 formatted data.
+15 -15
View File
@@ -493,15 +493,15 @@ func (p *cgoPackage) makeUnionField(typ *elaboratedTypeInfo) *ast.StructType {
// createUnionAccessor creates a function that returns a typed pointer to a // createUnionAccessor creates a function that returns a typed pointer to a
// union field for each field in a union. For example: // union field for each field in a union. For example:
// //
// func (union *C.union_1) unionfield_d() *float64 { // func (union *C.union_1) unionfield_d() *float64 {
// return (*float64)(unsafe.Pointer(&union.$union)) // return (*float64)(unsafe.Pointer(&union.$union))
// } // }
// //
// Where C.union_1 is defined as: // Where C.union_1 is defined as:
// //
// type C.union_1 struct{ // type C.union_1 struct{
// $union uint64 // $union uint64
// } // }
// //
// The returned pointer can be used to get or set the field, or get the pointer // The returned pointer can be used to get or set the field, or get the pointer
// to a subfield. // to a subfield.
@@ -617,9 +617,9 @@ func (p *cgoPackage) createUnionAccessor(field *ast.Field, typeName string) {
// createBitfieldGetter creates a bitfield getter function like the following: // createBitfieldGetter creates a bitfield getter function like the following:
// //
// func (s *C.struct_foo) bitfield_b() byte { // func (s *C.struct_foo) bitfield_b() byte {
// return (s.__bitfield_1 >> 5) & 0x1 // return (s.__bitfield_1 >> 5) & 0x1
// } // }
func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string) { func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string) {
// The value to return from the getter. // The value to return from the getter.
// Not complete: this is just an expression to get the complete field. // Not complete: this is just an expression to get the complete field.
@@ -729,15 +729,15 @@ func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string
// createBitfieldSetter creates a bitfield setter function like the following: // createBitfieldSetter creates a bitfield setter function like the following:
// //
// func (s *C.struct_foo) set_bitfield_b(value byte) { // func (s *C.struct_foo) set_bitfield_b(value byte) {
// s.__bitfield_1 = s.__bitfield_1 ^ 0x60 | ((value & 1) << 5) // s.__bitfield_1 = s.__bitfield_1 ^ 0x60 | ((value & 1) << 5)
// } // }
// //
// Or the following: // Or the following:
// //
// func (s *C.struct_foo) set_bitfield_c(value byte) { // func (s *C.struct_foo) set_bitfield_c(value byte) {
// s.__bitfield_1 = s.__bitfield_1 & 0x3f | (value << 6) // s.__bitfield_1 = s.__bitfield_1 & 0x3f | (value << 6)
// } // }
func (p *cgoPackage) createBitfieldSetter(bitfield bitfieldInfo, typeName string) { func (p *cgoPackage) createBitfieldSetter(bitfield bitfieldInfo, typeName string) {
// The full field with all bitfields. // The full field with all bitfields.
var field ast.Expr = &ast.SelectorExpr{ var field ast.Expr = &ast.SelectorExpr{
+3 -18
View File
@@ -5,12 +5,11 @@ import (
"flag" "flag"
"fmt" "fmt"
"go/ast" "go/ast"
"go/build"
"go/format" "go/format"
"go/parser" "go/parser"
"go/token" "go/token"
"go/types" "go/types"
"io/ioutil" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
@@ -40,20 +39,6 @@ func TestCGo(t *testing.T) {
} { } {
name := name // avoid a race condition name := name // avoid a race condition
t.Run(name, func(t *testing.T) { 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. // Read the AST in memory.
path := filepath.Join("testdata", name+".go") path := filepath.Join("testdata", name+".go")
fset := token.NewFileSet() fset := token.NewFileSet()
@@ -107,7 +92,7 @@ func TestCGo(t *testing.T) {
// Read the file with the expected output, to compare against. // Read the file with the expected output, to compare against.
outfile := filepath.Join("testdata", name+".out.go") outfile := filepath.Join("testdata", name+".out.go")
expectedBytes, err := ioutil.ReadFile(outfile) expectedBytes, err := os.ReadFile(outfile)
if err != nil { if err != nil {
t.Fatalf("could not read expected output: %v", err) t.Fatalf("could not read expected output: %v", err)
} }
@@ -118,7 +103,7 @@ func TestCGo(t *testing.T) {
// It is not. Test failed. // It is not. Test failed.
if *flagUpdate { if *flagUpdate {
// Update the file with the expected data. // Update the file with the expected data.
err := ioutil.WriteFile(outfile, []byte(actual), 0666) err := os.WriteFile(outfile, []byte(actual), 0666)
if err != nil { if err != nil {
t.Error("could not write updated output file:", err) t.Error("could not write updated output file:", err)
} }
-16
View File
@@ -1,16 +0,0 @@
//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"
+2 -2
View File
@@ -1,5 +1,5 @@
//go:build !byollvm && !llvm13 //go:build !byollvm
// +build !byollvm,!llvm13 // +build !byollvm
package cgo package cgo
+3 -5
View File
@@ -73,9 +73,7 @@ func (c *Config) BuildTags() []string {
for i := 1; i <= c.GoMinorVersion; i++ { for i := 1; i <= c.GoMinorVersion; i++ {
tags = append(tags, fmt.Sprintf("go1.%d", i)) tags = append(tags, fmt.Sprintf("go1.%d", i))
} }
if extraTags := strings.Fields(c.Options.Tags); len(extraTags) != 0 { tags = append(tags, c.Options.Tags...)
tags = append(tags, extraTags...)
}
return tags return tags
} }
@@ -442,13 +440,13 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
if openocdInterface == "" { if openocdInterface == "" {
return nil, errors.New("OpenOCD programmer not set") 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) return nil, fmt.Errorf("OpenOCD programmer has an invalid name: %#v", openocdInterface)
} }
if c.Target.OpenOCDTarget == "" { if c.Target.OpenOCDTarget == "" {
return nil, errors.New("OpenOCD chip not set") 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) return nil, fmt.Errorf("OpenOCD target has an invalid name: %#v", c.Target.OpenOCDTarget)
} }
if c.Target.OpenOCDTransport != "" && c.Target.OpenOCDTransport != "swd" { if c.Target.OpenOCDTransport != "" && c.Target.OpenOCDTransport != "swd" {
+3 -1
View File
@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
"time"
) )
var ( var (
@@ -29,6 +30,7 @@ type Options struct {
Scheduler string Scheduler string
Serial string Serial string
Work bool // -work flag to print temporary build directory Work bool // -work flag to print temporary build directory
InterpTimeout time.Duration
PrintIR bool PrintIR bool
DumpSSA bool DumpSSA bool
VerifyIR bool VerifyIR bool
@@ -38,7 +40,7 @@ type Options struct {
PrintSizes string PrintSizes string
PrintAllocs *regexp.Regexp // regexp string PrintAllocs *regexp.Regexp // regexp string
PrintStacks bool PrintStacks bool
Tags string Tags []string
WasmAbi string WasmAbi string
GlobalValues map[string]map[string]string // map[pkgpath]map[varname]value GlobalValues map[string]map[string]string // map[pkgpath]map[varname]value
TestConfig TestConfig TestConfig TestConfig
+12 -4
View File
@@ -88,8 +88,17 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
if !src.IsNil() { if !src.IsNil() {
dst.Set(src) dst.Set(src)
} }
case reflect.Slice: // for slices, append the field case reflect.Slice: // for slices, append the field and check for duplicates
dst.Set(reflect.AppendSlice(dst, src)) 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 {
panic("duplicate value '" + v + "' in field : " + field.Name)
}
}
}
default: default:
panic("unknown field type : " + kind.String()) panic("unknown field type : " + kind.String())
} }
@@ -193,11 +202,10 @@ func LoadTarget(options *Options) (*TargetSpec, error) {
// triples for historical reasons) have the form: // triples for historical reasons) have the form:
// arch-vendor-os-environment // arch-vendor-os-environment
target := llvmarch + "-unknown-" + llvmos target := llvmarch + "-unknown-" + llvmos
if options.GOARCH == "arm" {
target += "-gnueabihf"
}
if options.GOOS == "windows" { if options.GOOS == "windows" {
target += "-gnu" target += "-gnu"
} else if options.GOARCH == "arm" {
target += "-gnueabihf"
} }
return defaultTarget(options.GOOS, options.GOARCH, target) return defaultTarget(options.GOOS, options.GOARCH, target)
} }
+3 -2
View File
@@ -1,7 +1,8 @@
package compileopts package compileopts
import ( import (
"os" "errors"
"io/fs"
"reflect" "reflect"
"testing" "testing"
) )
@@ -17,7 +18,7 @@ func TestLoadTarget(t *testing.T) {
t.Error("LoadTarget should have failed with non existing target") t.Error("LoadTarget should have failed with non existing target")
} }
if !os.IsNotExist(err) { if !errors.Is(err, fs.ErrNotExist) {
t.Error("LoadTarget failed for wrong reason:", err) t.Error("LoadTarget failed for wrong reason:", err)
} }
} }
+2 -43
View File
@@ -16,6 +16,8 @@ import "tinygo.org/x/go-llvm"
var stdlibAliases = map[string]string{ var stdlibAliases = map[string]string{
// crypto packages // 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/md5.block": "crypto/md5.blockGeneric",
"crypto/sha1.block": "crypto/sha1.blockGeneric", "crypto/sha1.block": "crypto/sha1.blockGeneric",
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric", "crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
@@ -23,53 +25,10 @@ var stdlibAliases = map[string]string{
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric", "crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
// math package // 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.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.archMax": "math.max",
"math.Min": "math.min",
"math.archMin": "math.min", "math.archMin": "math.min",
"math.Mod": "math.mod",
"math.Modf": "math.modf",
"math.archModf": "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 // createAlias implements the function (in the builder) as a call to the alias
+22 -23
View File
@@ -22,10 +22,6 @@ import (
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
) )
var typeParamUnderlyingType = func(t types.Type) types.Type {
return t
}
func init() { func init() {
llvm.InitializeAllTargets() llvm.InitializeAllTargets()
llvm.InitializeAllTargetMCs() llvm.InitializeAllTargetMCs()
@@ -345,7 +341,6 @@ func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
// makeLLVMType creates a LLVM type for a Go type. Don't call this, use // makeLLVMType creates a LLVM type for a Go type. Don't call this, use
// getLLVMType instead. // getLLVMType instead.
func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type { func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
goType = typeParamUnderlyingType(goType)
switch typ := goType.(type) { switch typ := goType.(type) {
case *types.Array: case *types.Array:
elemType := c.getLLVMType(typ.Elem()) elemType := c.getLLVMType(typ.Elem())
@@ -420,6 +415,8 @@ func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
members[i] = c.getLLVMType(typ.Field(i).Type()) members[i] = c.getLLVMType(typ.Field(i).Type())
} }
return c.ctx.StructType(members, false) return c.ctx.StructType(members, false)
case *types.TypeParam:
return c.getLLVMType(typ.Underlying())
case *types.Tuple: case *types.Tuple:
members := make([]llvm.Type, typ.Len()) members := make([]llvm.Type, typ.Len())
for i := 0; i < typ.Len(); i++ { for i := 0; i < typ.Len(); i++ {
@@ -455,7 +452,6 @@ func (c *compilerContext) getDIType(typ types.Type) llvm.Metadata {
// createDIType creates a new DWARF type. Don't call this function directly, // createDIType creates a new DWARF type. Don't call this function directly,
// call getDIType instead. // call getDIType instead.
func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata { func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
typ = typeParamUnderlyingType(typ)
llvmType := c.getLLVMType(typ) llvmType := c.getLLVMType(typ)
sizeInBytes := c.targetData.TypeAllocSize(llvmType) sizeInBytes := c.targetData.TypeAllocSize(llvmType)
switch typ := typ.(type) { switch typ := typ.(type) {
@@ -619,6 +615,8 @@ func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
}) })
temporaryMDNode.ReplaceAllUsesWith(md) temporaryMDNode.ReplaceAllUsesWith(md)
return md return md
case *types.TypeParam:
return c.getDIType(typ.Underlying())
default: default:
panic("unknown type while generating DWARF debug type: " + typ.String()) panic("unknown type while generating DWARF debug type: " + typ.String())
} }
@@ -688,7 +686,7 @@ func (b *builder) getLocalVariable(variable *types.Var) llvm.Metadata {
Name: param.Name(), Name: param.Name(),
File: b.getDIFile(pos.Filename), File: b.getDIFile(pos.Filename),
Line: pos.Line, Line: pos.Line,
Type: b.getDIType(variable.Type()), Type: b.getDIType(param.Type()),
AlwaysPreserve: true, AlwaysPreserve: true,
ArgNo: i + 1, ArgNo: i + 1,
}) })
@@ -792,6 +790,12 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
} }
// Create the function definition. // Create the function definition.
b := newBuilder(c, irbuilder, member) 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 { if member.Blocks == nil {
// Try to define this as an intrinsic function. // Try to define this as an intrinsic function.
b.defineIntrinsicFunction() b.defineIntrinsicFunction()
@@ -1026,7 +1030,7 @@ func (c *compilerContext) getEmbedFileString(file *loader.EmbedFile) llvm.Value
// parameters, create basic blocks, and set up debug information. // parameters, create basic blocks, and set up debug information.
// This is separated out from createFunction() so that it is also usable to // This is separated out from createFunction() so that it is also usable to
// define compiler intrinsics like the atomic operations in sync/atomic. // define compiler intrinsics like the atomic operations in sync/atomic.
func (b *builder) createFunctionStart() { func (b *builder) createFunctionStart(intrinsic bool) {
if b.DumpSSA { if b.DumpSSA {
fmt.Printf("\nfunc %s:\n", b.fn) fmt.Printf("\nfunc %s:\n", b.fn)
} }
@@ -1099,20 +1103,20 @@ func (b *builder) createFunctionStart() {
} }
// Pre-create all basic blocks in the function. // 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 var entryBlock llvm.BasicBlock
if len(b.fn.Blocks) != 0 { if intrinsic {
// 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 // This function isn't defined in Go SSA. It is probably a compiler
// intrinsic (like an atomic operation). Create the entry block // intrinsic (like an atomic operation). Create the entry block
// manually. // manually.
entryBlock = b.ctx.AddBasicBlock(b.llvmFn, "entry") 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) b.SetInsertPointAtEnd(entryBlock)
@@ -1194,7 +1198,7 @@ func (b *builder) createFunctionStart() {
// function must not yet be defined, otherwise this function will create a // function must not yet be defined, otherwise this function will create a
// diagnostic. // diagnostic.
func (b *builder) createFunction() { func (b *builder) createFunction() {
b.createFunctionStart() b.createFunctionStart(false)
// Fill blocks with instructions. // Fill blocks with instructions.
for _, block := range b.fn.DomPreorder() { for _, block := range b.fn.DomPreorder() {
@@ -1656,11 +1660,6 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
// applied) function call. If it is anonymous, it may be a closure. // applied) function call. If it is anonymous, it may be a closure.
name := fn.RelString(nil) name := fn.RelString(nil)
switch { 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": 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) 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": case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
-18
View File
@@ -1,18 +0,0 @@
//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 -28
View File
@@ -3,13 +3,12 @@ package compiler
import ( import (
"flag" "flag"
"go/types" "go/types"
"io/ioutil" "os"
"strconv" "strconv"
"strings" "strings"
"testing" "testing"
"github.com/tinygo-org/tinygo/compileopts" "github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
"github.com/tinygo-org/tinygo/loader" "github.com/tinygo-org/tinygo/loader"
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
) )
@@ -28,18 +27,6 @@ type testCase struct {
func TestCompiler(t *testing.T) { func TestCompiler(t *testing.T) {
t.Parallel() 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. // Determine which tests to run, depending on the Go and LLVM versions.
tests := []testCase{ tests := []testCase{
{"basic.go", "", ""}, {"basic.go", "", ""},
@@ -54,20 +41,8 @@ func TestCompiler(t *testing.T) {
{"goroutine.go", "wasm", "asyncify"}, {"goroutine.go", "wasm", "asyncify"},
{"goroutine.go", "cortex-m-qemu", "tasks"}, {"goroutine.go", "cortex-m-qemu", "tasks"},
{"channel.go", "", ""}, {"channel.go", "", ""},
{"intrinsics.go", "cortex-m-qemu", ""},
{"intrinsics.go", "wasm", ""},
{"gc.go", "", ""}, {"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 { for _, tc := range tests {
name := tc.file name := tc.file
@@ -162,14 +137,14 @@ func TestCompiler(t *testing.T) {
// Update test if needed. Do not check the result. // Update test if needed. Do not check the result.
if *flagUpdate { if *flagUpdate {
err := ioutil.WriteFile(outPath, []byte(mod.String()), 0666) err := os.WriteFile(outPath, []byte(mod.String()), 0666)
if err != nil { if err != nil {
t.Error("failed to write updated output file:", err) t.Error("failed to write updated output file:", err)
} }
return return
} }
expected, err := ioutil.ReadFile(outPath) expected, err := os.ReadFile(outPath)
if err != nil { if err != nil {
t.Fatal("failed to read golden file:", err) t.Fatal("failed to read golden file:", err)
} }
+7 -7
View File
@@ -120,16 +120,16 @@ func (b *builder) createGo(instr *ssa.Go) {
// createGoroutineStartWrapper creates a wrapper for the task-based // createGoroutineStartWrapper creates a wrapper for the task-based
// implementation of goroutines. For example, to call a function like this: // 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: // It creates a wrapper like this:
// //
// func add$gowrapper(ptr *unsafe.Pointer) { // func add$gowrapper(ptr *unsafe.Pointer) {
// args := (*struct{ // args := (*struct{
// x, y int // x, y int
// })(ptr) // })(ptr)
// add(args.x, args.y) // add(args.x, args.y)
// } // }
// //
// This is useful because the task-based goroutine start implementation only // This is useful because the task-based goroutine start implementation only
// allows a single (pointer) argument to the newly started goroutine. Also, it // allows a single (pointer) argument to the newly started goroutine. Also, it
+22 -22
View File
@@ -17,7 +17,7 @@ import (
// operands or return values. It is useful for trivial instructions, like wfi in // operands or return values. It is useful for trivial instructions, like wfi in
// ARM or sleep in AVR. // ARM or sleep in AVR.
// //
// func Asm(asm string) // func Asm(asm string)
// //
// The provided assembly must be a constant. // The provided assembly must be a constant.
func (b *builder) createInlineAsm(args []ssa.Value) (llvm.Value, error) { 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 // This is a compiler builtin, which allows assembly to be called in a flexible
// way. // 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 // The asm parameter must be a constant string. The regs parameter must be
// provided immediately. For example: // provided immediately. For example:
// //
// arm.AsmFull( // arm.AsmFull(
// "str {value}, {result}", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1 // "value": 1
// "result": &dest, // "result": &dest,
// }) // })
func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) { func (b *builder) createInlineAsmFull(instr *ssa.CallCommon) (llvm.Value, error) {
asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value) asmString := constant.StringVal(instr.Args[0].(*ssa.Const).Value)
registers := map[string]llvm.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 // This is a compiler builtin which emits an inline SVCall instruction. It can
// be one of: // be one of:
// //
// func SVCall0(num uintptr) uintptr // func SVCall0(num uintptr) uintptr
// func SVCall1(num uintptr, a1 interface{}) uintptr // func SVCall1(num uintptr, a1 interface{}) uintptr
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr // func SVCall2(num uintptr, a1, a2 interface{}) uintptr
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr // func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
// func SVCall4(num uintptr, a1, a2, a3, a4 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 // The num parameter must be a constant. All other parameters may be any scalar
// value supported by LLVM inline assembly. // 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 // This is a compiler builtin which emits an inline SVCall instruction. It can
// be one of: // be one of:
// //
// func SVCall0(num uintptr) uintptr // func SVCall0(num uintptr) uintptr
// func SVCall1(num uintptr, a1 interface{}) uintptr // func SVCall1(num uintptr, a1 interface{}) uintptr
// func SVCall2(num uintptr, a1, a2 interface{}) uintptr // func SVCall2(num uintptr, a1, a2 interface{}) uintptr
// func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr // func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
// func SVCall4(num uintptr, a1, a2, a3, a4 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 // The num parameter must be a constant. All other parameters may be any scalar
// value supported by LLVM inline assembly. // 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: // This is a compiler builtin which emits CSR instructions. It can be one of:
// //
// func (csr CSR) Get() uintptr // func (csr CSR) Get() uintptr
// func (csr CSR) Set(uintptr) // func (csr CSR) Set(uintptr)
// func (csr CSR) SetBits(uintptr) uintptr // func (csr CSR) SetBits(uintptr) uintptr
// func (csr CSR) ClearBits(uintptr) uintptr // func (csr CSR) ClearBits(uintptr) uintptr
// //
// The csr parameter (method receiver) must be a constant. Other parameter can // The csr parameter (method receiver) must be a constant. Other parameter can
// be any value. // be any value.
+4 -4
View File
@@ -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 // internally to match interfaces and to call the correct method on an
// interface. Examples: // interface. Examples:
// //
// String() string // String() string
// Read([]byte) (int, error) // Read([]byte) (int, error)
func methodSignature(method *types.Func) string { func methodSignature(method *types.Func) string {
return method.Name() + signature(method.Type().(*types.Signature)) 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. // Make a readable version of a function (pointer) signature.
// Examples: // Examples:
// //
// () string // () string
// (string, int) (int, error) // (string, int) (int, error)
func signature(sig *types.Signature) string { func signature(sig *types.Signature) string {
s := "" s := ""
if sig.Params().Len() == 0 { if sig.Params().Len() == 0 {
+30 -42
View File
@@ -7,7 +7,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
) )
@@ -29,7 +28,7 @@ func (b *builder) defineIntrinsicFunction() {
case strings.HasPrefix(name, "runtime/volatile.Store"): case strings.HasPrefix(name, "runtime/volatile.Store"):
b.createVolatileStore() b.createVolatileStore()
case strings.HasPrefix(name, "sync/atomic.") && token.IsExported(b.fn.Name()): case strings.HasPrefix(name, "sync/atomic.") && token.IsExported(b.fn.Name()):
b.createFunctionStart() b.createFunctionStart(true)
returnValue := b.createAtomicOp(b.fn.Name()) returnValue := b.createAtomicOp(b.fn.Name())
if !returnValue.IsNil() { if !returnValue.IsNil() {
b.CreateRet(returnValue) b.CreateRet(returnValue)
@@ -44,7 +43,7 @@ func (b *builder) defineIntrinsicFunction() {
// specially by optimization passes possibly resulting in better generated code, // specially by optimization passes possibly resulting in better generated code,
// and will otherwise be lowered to regular libc memcpy/memmove calls. // and will otherwise be lowered to regular libc memcpy/memmove calls.
func (b *builder) createMemoryCopyImpl() { func (b *builder) createMemoryCopyImpl() {
b.createFunctionStart() b.createFunctionStart(true)
fnName := "llvm." + b.fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth()) fnName := "llvm." + b.fn.Name() + ".p0i8.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
llvmFn := b.mod.NamedFunction(fnName) llvmFn := b.mod.NamedFunction(fnName)
if llvmFn.IsNil() { if llvmFn.IsNil() {
@@ -64,7 +63,7 @@ func (b *builder) createMemoryCopyImpl() {
// memory, declaring the function if needed. These calls will be lowered to // 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. // regular libc memset calls if they aren't optimized out in a different way.
func (b *builder) createMemoryZeroImpl() { func (b *builder) createMemoryZeroImpl() {
b.createFunctionStart() b.createFunctionStart(true)
fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth()) fnName := "llvm.memset.p0i8.i" + strconv.Itoa(b.uintptrType.IntTypeWidth())
llvmFn := b.mod.NamedFunction(fnName) llvmFn := b.mod.NamedFunction(fnName)
if llvmFn.IsNil() { if llvmFn.IsNil() {
@@ -82,55 +81,44 @@ func (b *builder) createMemoryZeroImpl() {
} }
var mathToLLVMMapping = map[string]string{ var mathToLLVMMapping = map[string]string{
"math.Sqrt": "llvm.sqrt.f64",
"math.Floor": "llvm.floor.f64",
"math.Ceil": "llvm.ceil.f64", "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.Trunc": "llvm.trunc.f64", "math.Trunc": "llvm.trunc.f64",
} }
// createMathOp tries to lower the given call as a LLVM math intrinsic, if // defineMathOp defines a math function body as a call to a LLVM intrinsic,
// possible. It returns the call result if possible, and a boolean whether it // instead of the regular Go implementation. This allows LLVM to reason about
// succeeded. If it doesn't succeed, the architecture doesn't support the given // the math operation and (depending on the architecture) allows it to lower the
// intrinsic. // operation to very fast floating point instructions. If this is not possible,
func (b *builder) createMathOp(call *ssa.CallCommon) (llvm.Value, bool) { // LLVM will emit a call to a libm function that implements the same operation.
// Check whether this intrinsic is supported on the given GOARCH. //
// If it is unsupported, this can have two reasons: // 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
// 1. LLVM can expand the intrinsic inline (using float instructions), but // beneficial on architectures where 64-bit floating point operations are (much)
// the result doesn't pass the tests of the math package. // more expensive than 32-bit ones.
// 2. LLVM cannot expand the intrinsic inline, will therefore lower it as a func (b *builder) defineMathOp() {
// libm function call, but the libm function call also fails the math b.createFunctionStart(true)
// package tests. llvmName := mathToLLVMMapping[b.fn.RelString(nil)]
// if llvmName == "" {
// Whatever the implementation, it must pass the tests in the math package panic("unreachable: unknown math operation") // sanity check
// 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() { if llvmFn.IsNil() {
// The intrinsic doesn't exist yet, so declare it. // The intrinsic doesn't exist yet, so declare it.
// At the moment, all supported intrinsics have the form "double // At the moment, all supported intrinsics have the form "double
// foo(double %x)" so we can hardcode the signature here. // foo(double %x)" so we can hardcode the signature here.
llvmType := llvm.FunctionType(b.ctx.DoubleType(), []llvm.Type{b.ctx.DoubleType()}, false) llvmType := llvm.FunctionType(b.ctx.DoubleType(), []llvm.Type{b.ctx.DoubleType()}, false)
llvmFn = llvm.AddFunction(b.mod, mathToLLVMMapping[name], llvmType) llvmFn = llvm.AddFunction(b.mod, llvmName, llvmType)
} }
// Create a call to the intrinsic. // Create a call to the intrinsic.
args := make([]llvm.Value, len(call.Args)) args := make([]llvm.Value, len(b.fn.Params))
for i, arg := range call.Args { for i, param := range b.fn.Params {
args[i] = b.getValue(arg) args[i] = b.getValue(param)
} }
return b.CreateCall(llvmFn, args, ""), true result := b.CreateCall(llvmFn, args, "")
b.CreateRet(result)
} }
+1 -1
View File
@@ -152,7 +152,7 @@ func (s *stdSizes) Sizeof(T types.Type) int64 {
return align(offsets[n-1]+s.Sizeof(fields[n-1].Type()), maxAlign) return align(offsets[n-1]+s.Sizeof(fields[n-1].Type()), maxAlign)
case *types.Interface: case *types.Interface:
return s.PtrSize * 2 return s.PtrSize * 2
case *types.Pointer: case *types.Pointer, *types.Chan, *types.Map:
return s.PtrSize return s.PtrSize
case *types.Signature: case *types.Signature:
// Func values in TinyGo are two words in size. // Func values in TinyGo are two words in size.
-41
View File
@@ -1,41 +0,0 @@
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)
}
-161
View File
@@ -1,161 +0,0 @@
; 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 }
-34
View File
@@ -1,34 +0,0 @@
; 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 }
-38
View File
@@ -1,38 +0,0 @@
; 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 }
-14
View File
@@ -1,14 +0,0 @@
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)
}
+10
View File
@@ -3,44 +3,53 @@ package main
import _ "unsafe" import _ "unsafe"
// Creates an external global with name extern_global. // Creates an external global with name extern_global.
//
//go:extern extern_global //go:extern extern_global
var externGlobal [0]byte var externGlobal [0]byte
// Creates a // Creates a
//
//go:align 32 //go:align 32
var alignedGlobal [4]uint32 var alignedGlobal [4]uint32
// Test conflicting pragmas (the last one counts). // Test conflicting pragmas (the last one counts).
//
//go:align 64 //go:align 64
//go:align 16 //go:align 16
var alignedGlobal16 [4]uint32 var alignedGlobal16 [4]uint32
// Test exported functions. // Test exported functions.
//
//export extern_func //export extern_func
func externFunc() { func externFunc() {
} }
// Define a function in a different package using go:linkname. // Define a function in a different package using go:linkname.
//
//go:linkname withLinkageName1 somepkg.someFunction1 //go:linkname withLinkageName1 somepkg.someFunction1
func withLinkageName1() { func withLinkageName1() {
} }
// Import a function from a different package using go:linkname. // Import a function from a different package using go:linkname.
//
//go:linkname withLinkageName2 somepkg.someFunction2 //go:linkname withLinkageName2 somepkg.someFunction2
func withLinkageName2() func withLinkageName2()
// Function has an 'inline hint', similar to the inline keyword in C. // Function has an 'inline hint', similar to the inline keyword in C.
//
//go:inline //go:inline
func inlineFunc() { func inlineFunc() {
} }
// Function should never be inlined, equivalent to GCC // Function should never be inlined, equivalent to GCC
// __attribute__((noinline)). // __attribute__((noinline)).
//
//go:noinline //go:noinline
func noinlineFunc() { func noinlineFunc() {
} }
// This function should have the specified section. // This function should have the specified section.
//
//go:section .special_function_section //go:section .special_function_section
func functionInSection() { func functionInSection() {
} }
@@ -51,6 +60,7 @@ func exportedFunctionInSection() {
} }
// This function should not: it's only a declaration and not a definition. // This function should not: it's only a declaration and not a definition.
//
//go:section .special_function_section //go:section .special_function_section
func undefinedFunctionNotInSection() func undefinedFunctionNotInSection()
+35
View File
@@ -1,5 +1,7 @@
package main package main
import "unsafe"
func sliceLen(ints []int) int { func sliceLen(ints []int) int {
return len(ints) return len(ints)
} }
@@ -41,3 +43,36 @@ func makeArraySlice(len int) [][3]byte {
func makeInt32Slice(len int) []int32 { func makeInt32Slice(len int) []int32 {
return make([]int32, len) 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)
}
+143
View File
@@ -183,6 +183,149 @@ slice.throw: ; preds = %entry
unreachable 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 #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" }
attributes #2 = { nounwind } attributes #2 = { nounwind }
+2 -2
View File
@@ -6,7 +6,7 @@ package compiler
// createVolatileLoad is the implementation of the intrinsic function // createVolatileLoad is the implementation of the intrinsic function
// runtime/volatile.LoadT(). // runtime/volatile.LoadT().
func (b *builder) createVolatileLoad() { func (b *builder) createVolatileLoad() {
b.createFunctionStart() b.createFunctionStart(true)
addr := b.getValue(b.fn.Params[0]) addr := b.getValue(b.fn.Params[0])
b.createNilCheck(b.fn.Params[0], addr, "deref") b.createNilCheck(b.fn.Params[0], addr, "deref")
val := b.CreateLoad(addr, "") val := b.CreateLoad(addr, "")
@@ -17,7 +17,7 @@ func (b *builder) createVolatileLoad() {
// createVolatileStore is the implementation of the intrinsic function // createVolatileStore is the implementation of the intrinsic function
// runtime/volatile.StoreT(). // runtime/volatile.StoreT().
func (b *builder) createVolatileStore() { func (b *builder) createVolatileStore() {
b.createFunctionStart() b.createFunctionStart(true)
addr := b.getValue(b.fn.Params[0]) addr := b.getValue(b.fn.Params[0])
val := b.getValue(b.fn.Params[1]) val := b.getValue(b.fn.Params[1])
b.createNilCheck(b.fn.Params[0], addr, "deref") b.createNilCheck(b.fn.Params[0], addr, "deref")
+5 -2
View File
@@ -8,6 +8,7 @@ import (
"sync" "sync"
"testing" "testing"
"golang.org/x/tools/go/buildutil"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
@@ -111,9 +112,11 @@ func TestCorpus(t *testing.T) {
opts := optionsFromTarget(target, sema) opts := optionsFromTarget(target, sema)
opts.Directory = dir opts.Directory = dir
opts.Tags = repo.Tags var tags buildutil.TagsFlag
tags.Set(repo.Tags)
opts.Tags = []string(tags)
passed, err := Test(path, out, out, &opts, false, testing.Verbose(), false, "", "", "", "") passed, err := Test(path, out, out, &opts, false, testing.Verbose(), false, "", "", "", false, "")
if err != nil { if err != nil {
t.Errorf("test error: %v", err) t.Errorf("test error: %v", err)
} }
+16 -4
View File
@@ -1,6 +1,6 @@
module github.com/tinygo-org/tinygo module github.com/tinygo-org/tinygo
go 1.16 go 1.18
require ( require (
github.com/aykevl/go-wasm v0.0.2-0.20220616010729-4a0a888aebdc github.com/aykevl/go-wasm v0.0.2-0.20220616010729-4a0a888aebdc
@@ -11,9 +11,21 @@ require (
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892 github.com/marcinbor85/gohex v0.0.0-20200531091804-343a4b548892
github.com/mattn/go-colorable v0.1.8 github.com/mattn/go-colorable v0.1.8
go.bug.st/serial v1.1.3 go.bug.st/serial v1.3.5
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
golang.org/x/tools v0.1.11 golang.org/x/tools v0.1.11
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887 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
) )
+6 -23
View File
@@ -40,44 +40,27 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 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 h1:YEBxJa9pKS9Wdg46B/jiaKbvvbUrjhZZZITfJHEJhaE=
go.bug.st/serial v1.1.3/go.mod h1:8TT7u/SwwNIpJ8QaG4s+HTjFt9ReXs2cdOU7ZEk50Dk= 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= go.bug.st/serial v1.3.5 h1:k50SqGZCnHZ2MiBQgzccXWG+kd/XpOs1jUljpDDKzaE=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= go.bug.st/serial v1.3.5/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= 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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
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-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-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-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-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-20211124211545-fe61309f8881/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 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= 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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887 h1:k+Y1DU/WoBDkTkRJGF149yk3S2K2VhNglN435DXDS5s= tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7 h1:nSLR52mUw7DPQQVA3ZJFH63zjU4ME84fKiin6mdnYWc=
tinygo.org/x/go-llvm v0.0.0-20220626113704-45f1e2dbf887/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0= tinygo.org/x/go-llvm v0.0.0-20220802112859-5bb0b77907a7/go.mod h1:GFbusT2VTA4I+l4j80b17KFK+6whv69Wtny5U+T8RR0=
+9 -4
View File
@@ -6,6 +6,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"io/fs"
"os" "os"
"os/exec" "os/exec"
"os/user" "os/user"
@@ -41,10 +42,14 @@ var TINYGOROOT string
func Get(name string) string { func Get(name string) string {
switch name { switch name {
case "GOOS": case "GOOS":
if dir := os.Getenv("GOOS"); dir != "" { goos := os.Getenv("GOOS")
return dir if goos == "" {
goos = runtime.GOOS
} }
return runtime.GOOS if goos == "android" {
goos = "linux"
}
return goos
case "GOARCH": case "GOARCH":
if dir := os.Getenv("GOARCH"); dir != "" { if dir := os.Getenv("GOARCH"); dir != "" {
return dir return dir
@@ -122,7 +127,7 @@ func findWasmOpt() string {
} }
_, err := os.Stat(path) _, err := os.Stat(path)
if err != nil && os.IsNotExist(err) { if err != nil && errors.Is(err, fs.ErrNotExist) {
continue continue
} }
+4 -4
View File
@@ -4,7 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
@@ -12,7 +12,7 @@ import (
// Version of TinyGo. // Version of TinyGo.
// Update this value before release of new version of software. // Update this value before release of new version of software.
const Version = "0.25.0" const Version = "0.26.0-dev"
var ( var (
// This variable is set at build time using -ldflags parameters. // 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 // 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). // can have some variations (for beta releases, for example).
func GorootVersionString(goroot string) (string, error) { func GorootVersionString(goroot string) (string, error) {
if data, err := ioutil.ReadFile(filepath.Join(goroot, "VERSION")); err == nil { if data, err := os.ReadFile(filepath.Join(goroot, "VERSION")); err == nil {
return string(data), nil return string(data), nil
} else if data, err := ioutil.ReadFile(filepath.Join( } else if data, err := os.ReadFile(filepath.Join(
goroot, "src", "internal", "buildcfg", "zbootstrap.go")); err == nil { goroot, "src", "internal", "buildcfg", "zbootstrap.go")); err == nil {
r := regexp.MustCompile("const version = `(.*)`") r := regexp.MustCompile("const version = `(.*)`")
+7 -5
View File
@@ -30,10 +30,11 @@ type runner struct {
objects []object // slice of objects in memory objects []object // slice of objects in memory
globals map[llvm.Value]int // map from global to index in objects slice globals map[llvm.Value]int // map from global to index in objects slice
start time.Time start time.Time
timeout time.Duration
callsExecuted uint64 callsExecuted uint64
} }
func newRunner(mod llvm.Module, debug bool) *runner { func newRunner(mod llvm.Module, timeout time.Duration, debug bool) *runner {
r := runner{ r := runner{
mod: mod, mod: mod,
targetData: llvm.NewTargetData(mod.DataLayout()), targetData: llvm.NewTargetData(mod.DataLayout()),
@@ -42,6 +43,7 @@ func newRunner(mod llvm.Module, debug bool) *runner {
objects: []object{{}}, objects: []object{{}},
globals: make(map[llvm.Value]int), globals: make(map[llvm.Value]int),
start: time.Now(), start: time.Now(),
timeout: timeout,
} }
r.pointerSize = uint32(r.targetData.PointerSize()) r.pointerSize = uint32(r.targetData.PointerSize())
r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0) r.i8ptrType = llvm.PointerType(mod.Context().Int8Type(), 0)
@@ -58,8 +60,8 @@ func (r *runner) dispose() {
// Run evaluates runtime.initAll function as much as possible at compile time. // Run evaluates runtime.initAll function as much as possible at compile time.
// Set debug to true if it should print output while running. // Set debug to true if it should print output while running.
func Run(mod llvm.Module, debug bool) error { func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
r := newRunner(mod, debug) r := newRunner(mod, timeout, debug)
defer r.dispose() defer r.dispose()
initAll := mod.NamedFunction("runtime.initAll") initAll := mod.NamedFunction("runtime.initAll")
@@ -199,10 +201,10 @@ func Run(mod llvm.Module, debug bool) error {
// RunFunc evaluates a single package initializer at compile time. // RunFunc evaluates a single package initializer at compile time.
// Set debug to true if it should print output while running. // Set debug to true if it should print output while running.
func RunFunc(fn llvm.Value, debug bool) error { func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error {
// Create and initialize *runner object. // Create and initialize *runner object.
mod := fn.GlobalParent() mod := fn.GlobalParent()
r := newRunner(mod, debug) r := newRunner(mod, timeout, debug)
defer r.dispose() defer r.dispose()
initName := fn.Name() initName := fn.Name()
if !strings.HasSuffix(initName, ".init") { if !strings.HasSuffix(initName, ".init") {
+3 -3
View File
@@ -1,11 +1,11 @@
package interp package interp
import ( import (
"io/ioutil"
"os" "os"
"strconv" "strconv"
"strings" "strings"
"testing" "testing"
"time"
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
) )
@@ -53,7 +53,7 @@ func runTest(t *testing.T, pathPrefix string) {
defer mod.Dispose() defer mod.Dispose()
// Perform the transform. // Perform the transform.
err = Run(mod, false) err = Run(mod, 10*time.Minute, false)
if err != nil { if err != nil {
if err, match := err.(*Error); match { if err, match := err.(*Error); match {
println(err.Error()) println(err.Error())
@@ -87,7 +87,7 @@ func runTest(t *testing.T, pathPrefix string) {
pm.Run(mod) pm.Run(mod)
// Read the expected output IR. // Read the expected output IR.
out, err := ioutil.ReadFile(pathPrefix + ".out.ll") out, err := os.ReadFile(pathPrefix + ".out.ll")
if err != nil { if err != nil {
t.Fatalf("could not read output file %s: %v", pathPrefix+".out.ll", err) t.Fatalf("could not read output file %s: %v", pathPrefix+".out.ll", err)
} }
+3 -6
View File
@@ -17,8 +17,6 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
locals := make([]value, len(fn.locals)) locals := make([]value, len(fn.locals))
r.callsExecuted++ r.callsExecuted++
t0 := time.Since(r.start)
// Parameters are considered a kind of local values. // Parameters are considered a kind of local values.
for i, param := range params { for i, param := range params {
locals[i] = param locals[i] = param
@@ -143,11 +141,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
} }
switch inst.opcode { switch inst.opcode {
case llvm.Ret: case llvm.Ret:
const maxInterpSeconds = 180 if time.Since(r.start) > r.timeout {
if t0 > maxInterpSeconds*time.Second { // Running for more than the allowed timeout; This shouldn't happen, but it does.
// Running for more than maxInterpSeconds seconds. This should never happen, but does.
// See github.com/tinygo-org/tinygo/issues/2124 // 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 %d seconds, timing out (executed calls: %d)", maxInterpSeconds, r.callsExecuted)) 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))
} }
if len(operands) != 0 { if len(operands) != 0 {
+13 -6
View File
@@ -17,6 +17,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"io" "io"
"io/fs"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
@@ -45,7 +46,7 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
} }
// Find the overrides needed for the goroot. // Find the overrides needed for the goroot.
overrides := pathsToOverride(needsSyscallPackage(config.BuildTags())) overrides := pathsToOverride(config.GoMinorVersion, needsSyscallPackage(config.BuildTags()))
// Resolve the merge links within the goroot. // Resolve the merge links within the goroot.
merge, err := listGorootMergeLinks(goroot, tinygoroot, overrides) merge, err := listGorootMergeLinks(goroot, tinygoroot, overrides)
@@ -83,7 +84,7 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
} }
// Create a temporary directory to construct the goroot within. // Create a temporary directory to construct the goroot within.
tmpgoroot, err := ioutil.TempDir(goenv.Get("GOCACHE"), cachedGorootName+".tmp") tmpgoroot, err := os.MkdirTemp(goenv.Get("GOCACHE"), cachedGorootName+".tmp")
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -122,13 +123,13 @@ func GetCachedGoroot(config *compileopts.Config) (string, error) {
// Rename the new merged gorooot into place. // Rename the new merged gorooot into place.
err = os.Rename(tmpgoroot, cachedgoroot) err = os.Rename(tmpgoroot, cachedgoroot)
if err != nil { if err != nil {
if os.IsExist(err) { if errors.Is(err, fs.ErrExist) {
// Another invocation of TinyGo also seems to have created a GOROOT. // Another invocation of TinyGo also seems to have created a GOROOT.
// Use that one instead. Our new GOROOT will be automatically // Use that one instead. Our new GOROOT will be automatically
// deleted by the defer above. // deleted by the defer above.
return cachedgoroot, nil return cachedgoroot, nil
} }
if runtime.GOOS == "windows" && os.IsPermission(err) { if runtime.GOOS == "windows" && errors.Is(err, fs.ErrPermission) {
// On Windows, a rename with a destination directory that already // On Windows, a rename with a destination directory that already
// exists does not result in an IsExist error, but rather in an // exists does not result in an IsExist error, but rather in an
// access denied error. To be sure, check for this case by checking // access denied error. To be sure, check for this case by checking
@@ -222,7 +223,7 @@ func needsSyscallPackage(buildTags []string) bool {
// The boolean indicates whether to merge the subdirs. True means merge, false // The boolean indicates whether to merge the subdirs. True means merge, false
// means use the TinyGo version. // means use the TinyGo version.
func pathsToOverride(needsSyscallPackage bool) map[string]bool { func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool {
paths := map[string]bool{ paths := map[string]bool{
"": true, "": true,
"crypto/": true, "crypto/": true,
@@ -234,7 +235,6 @@ func pathsToOverride(needsSyscallPackage bool) map[string]bool {
"internal/bytealg/": false, "internal/bytealg/": false,
"internal/reflectlite/": false, "internal/reflectlite/": false,
"internal/task/": false, "internal/task/": false,
"internal/itoa/": false, // TODO: Remove when we drop support for go 1.16
"machine/": false, "machine/": false,
"net/": true, "net/": true,
"os/": true, "os/": true,
@@ -243,6 +243,13 @@ func pathsToOverride(needsSyscallPackage bool) map[string]bool {
"sync/": true, "sync/": true,
"testing/": true, "testing/": true,
} }
if goMinor >= 19 {
paths["crypto/internal/"] = true
paths["crypto/internal/boring/"] = true
paths["crypto/internal/boring/sig/"] = false
}
if needsSyscallPackage { if needsSyscallPackage {
paths["syscall/"] = true // include syscall/js paths["syscall/"] = true // include syscall/js
} }
+3 -8
View File
@@ -13,7 +13,6 @@ import (
"go/token" "go/token"
"go/types" "go/types"
"io" "io"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path" "path"
@@ -28,8 +27,6 @@ import (
"github.com/tinygo-org/tinygo/goenv" "github.com/tinygo-org/tinygo/goenv"
) )
var addInstances func(*types.Info)
// Program holds all packages and some metadata about the program as a whole. // Program holds all packages and some metadata about the program as a whole.
type Program struct { type Program struct {
config *compileopts.Config config *compileopts.Config
@@ -159,6 +156,7 @@ func Load(config *compileopts.Config, inputPkg string, clangHeaders string, type
EmbedGlobals: make(map[string][]*EmbedFile), EmbedGlobals: make(map[string][]*EmbedFile),
info: types.Info{ info: types.Info{
Types: make(map[ast.Expr]types.TypeAndValue), Types: make(map[ast.Expr]types.TypeAndValue),
Instances: make(map[*ast.Ident]types.Instance),
Defs: make(map[*ast.Ident]types.Object), Defs: make(map[*ast.Ident]types.Object),
Uses: make(map[*ast.Ident]types.Object), Uses: make(map[*ast.Ident]types.Object),
Implicits: make(map[ast.Node]types.Object), Implicits: make(map[ast.Node]types.Object),
@@ -166,9 +164,6 @@ func Load(config *compileopts.Config, inputPkg string, clangHeaders string, type
Selections: make(map[*ast.SelectorExpr]*types.Selection), Selections: make(map[*ast.SelectorExpr]*types.Selection),
}, },
} }
if addInstances != nil {
addInstances(&pkg.info)
}
err := decoder.Decode(&pkg.PackageJSON) err := decoder.Decode(&pkg.PackageJSON)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
@@ -269,7 +264,7 @@ func (p *Program) getOriginalPath(path string) string {
originalPath = realgorootPath originalPath = realgorootPath
} }
maybeInTinyGoRoot := false maybeInTinyGoRoot := false
for prefix := range pathsToOverride(needsSyscallPackage(p.config.BuildTags())) { for prefix := range pathsToOverride(p.config.GoMinorVersion, needsSyscallPackage(p.config.BuildTags())) {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
prefix = strings.ReplaceAll(prefix, "/", "\\") prefix = strings.ReplaceAll(prefix, "/", "\\")
} }
@@ -335,7 +330,7 @@ func (p *Package) OriginalDir() string {
// parseFile is a wrapper around parser.ParseFile. // parseFile is a wrapper around parser.ParseFile.
func (p *Package) parseFile(path string, mode parser.Mode) (*ast.File, error) { func (p *Package) parseFile(path string, mode parser.Mode) (*ast.File, error) {
originalPath := p.program.getOriginalPath(path) originalPath := p.program.getOriginalPath(path)
data, err := ioutil.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
-18
View File
@@ -1,18 +0,0 @@
//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)
}
}
+16 -15
View File
@@ -32,6 +32,7 @@ import (
"github.com/tinygo-org/tinygo/goenv" "github.com/tinygo-org/tinygo/goenv"
"github.com/tinygo-org/tinygo/interp" "github.com/tinygo-org/tinygo/interp"
"github.com/tinygo-org/tinygo/loader" "github.com/tinygo-org/tinygo/loader"
"golang.org/x/tools/go/buildutil"
"tinygo.org/x/go-llvm" "tinygo.org/x/go-llvm"
"go.bug.st/serial" "go.bug.st/serial"
@@ -194,7 +195,7 @@ func Build(pkgName, outpath string, options *compileopts.Options) error {
// Test runs the tests in the given package. Returns whether the test passed and // Test runs the tests in the given package. Returns whether the test passed and
// possibly an error if the test failed to run. // 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, 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, testBenchMem bool, outpath string) (bool, error) {
options.TestConfig.CompileTestBinary = true options.TestConfig.CompileTestBinary = true
config, err := builder.NewConfig(options) config, err := builder.NewConfig(options)
if err != nil { if err != nil {
@@ -218,6 +219,9 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
if testBenchTime != "" { if testBenchTime != "" {
flags = append(flags, "-test.benchtime="+testBenchTime) flags = append(flags, "-test.benchtime="+testBenchTime)
} }
if testBenchMem {
flags = append(flags, "-test.benchmem")
}
passed := false passed := false
err = buildAndRun(pkgName, config, os.Stdout, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error { err = buildAndRun(pkgName, config, os.Stdout, flags, nil, 0, func(cmd *exec.Cmd, result builder.BuildResult) error {
@@ -250,7 +254,7 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
} }
// create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR // create a new temp directory just for this run, announce it to os.TempDir() via TMPDIR
tmpdir, err := ioutil.TempDir("", "tinygotmp") tmpdir, err := os.MkdirTemp("", "tinygotmp")
if err != nil { if err != nil {
return fmt.Errorf("failed to create temporary directory: %w", err) return fmt.Errorf("failed to create temporary directory: %w", err)
} }
@@ -974,8 +978,7 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
preferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)}) preferredPortIDs = append(preferredPortIDs, [2]uint16{uint16(vid), uint16(pid)})
} }
var primaryPorts []string // ports picked from preferred USB VID/PID var primaryPorts []string // ports picked from preferred USB VID/PID
var secondaryPorts []string // other ports (as a fallback)
for _, p := range portsList { for _, p := range portsList {
if !p.IsUSB { if !p.IsUSB {
continue continue
@@ -997,8 +1000,6 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
continue continue
} }
} }
secondaryPorts = append(secondaryPorts, p.Name)
} }
if len(primaryPorts) == 1 { if len(primaryPorts) == 1 {
// There is exactly one match in the set of preferred ports. Use // There is exactly one match in the set of preferred ports. Use
@@ -1010,10 +1011,6 @@ func getDefaultPort(portFlag string, usbInterfaces []string) (port string, err e
// one device of the same type are connected (e.g. two Arduino // one device of the same type are connected (e.g. two Arduino
// Unos). // Unos).
ports = primaryPorts ports = primaryPorts
} else {
// No preferred ports found. Fall back to other serial ports
// available in the system.
ports = secondaryPorts
} }
if len(ports) == 0 { if len(ports) == 0 {
@@ -1294,10 +1291,12 @@ func main() {
scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)") scheduler := flag.String("scheduler", "", "which scheduler to use (none, tasks, asyncify)")
serial := flag.String("serial", "", "which serial output to use (none, uart, usb)") serial := flag.String("serial", "", "which serial output to use (none, uart, usb)")
work := flag.Bool("work", false, "print the name of the temporary build directory and do not delete this directory on exit") 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") printIR := flag.Bool("printir", false, "print LLVM IR")
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA") dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR") verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
tags := flag.String("tags", "", "a space-separated list of extra build tags") var tags buildutil.TagsFlag
flag.Var(&tags, "tags", "a space-separated list of extra build tags")
target := flag.String("target", "", "chip/board name or JSON target specification file") target := flag.String("target", "", "chip/board name or JSON target specification file")
printSize := flag.String("size", "", "print sizes (none, short, full)") printSize := flag.String("size", "", "print sizes (none, short, full)")
printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines") printStacks := flag.Bool("print-stacks", false, "print stack sizes of goroutines")
@@ -1330,6 +1329,7 @@ func main() {
var testBenchRegexp *string var testBenchRegexp *string
var testBenchTime *string var testBenchTime *string
var testRunRegexp *string var testRunRegexp *string
var testBenchMem *bool
if command == "help" || command == "test" { if command == "help" || command == "test" {
testCompileOnlyFlag = flag.Bool("c", false, "compile the test binary but do not run it") testCompileOnlyFlag = flag.Bool("c", false, "compile the test binary but do not run it")
testVerboseFlag = flag.Bool("v", false, "verbose: print additional output") testVerboseFlag = flag.Bool("v", false, "verbose: print additional output")
@@ -1337,6 +1337,7 @@ func main() {
testRunRegexp = flag.String("run", "", "run: regexp of tests to run") testRunRegexp = flag.String("run", "", "run: regexp of tests to run")
testBenchRegexp = flag.String("bench", "", "run: regexp of benchmarks to run") testBenchRegexp = flag.String("bench", "", "run: regexp of benchmarks to run")
testBenchTime = flag.String("benchtime", "", "run each benchmark for duration `d`") 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 // Early command processing, before commands are interpreted by the Go flag
@@ -1383,6 +1384,7 @@ func main() {
Scheduler: *scheduler, Scheduler: *scheduler,
Serial: *serial, Serial: *serial,
Work: *work, Work: *work,
InterpTimeout: *interpTimeout,
PrintIR: *printIR, PrintIR: *printIR,
DumpSSA: *dumpSSA, DumpSSA: *dumpSSA,
VerifyIR: *verifyIR, VerifyIR: *verifyIR,
@@ -1391,7 +1393,7 @@ func main() {
PrintSizes: *printSize, PrintSizes: *printSize,
PrintStacks: *printStacks, PrintStacks: *printStacks,
PrintAllocs: printAllocs, PrintAllocs: printAllocs,
Tags: *tags, Tags: []string(tags),
GlobalValues: globalVarValues, GlobalValues: globalVarValues,
WasmAbi: *wasmAbi, WasmAbi: *wasmAbi,
Programmer: *programmer, Programmer: *programmer,
@@ -1465,7 +1467,7 @@ func main() {
fmt.Fprintf(os.Stderr, "Unknown library: %s\n", name) fmt.Fprintf(os.Stderr, "Unknown library: %s\n", name)
os.Exit(1) os.Exit(1)
} }
tmpdir, err := ioutil.TempDir("", "tinygo*") tmpdir, err := os.MkdirTemp("", "tinygo*")
if err != nil { if err != nil {
handleCompilerError(err) handleCompilerError(err)
} }
@@ -1566,7 +1568,7 @@ func main() {
defer close(buf.done) defer close(buf.done)
stdout := (*testStdout)(buf) stdout := (*testStdout)(buf)
stderr := (*testStderr)(buf) stderr := (*testStderr)(buf)
passed, err := Test(pkgName, stdout, stderr, options, *testCompileOnlyFlag, *testVerboseFlag, *testShortFlag, *testRunRegexp, *testBenchRegexp, *testBenchTime, outpath) passed, err := Test(pkgName, stdout, stderr, options, *testCompileOnlyFlag, *testVerboseFlag, *testShortFlag, *testRunRegexp, *testBenchRegexp, *testBenchTime, *testBenchMem, outpath)
if err != nil { if err != nil {
printCompilerError(func(args ...interface{}) { printCompilerError(func(args ...interface{}) {
fmt.Fprintln(stderr, args...) fmt.Fprintln(stderr, args...)
@@ -1666,7 +1668,6 @@ func main() {
fmt.Printf("LLVM triple: %s\n", config.Triple()) fmt.Printf("LLVM triple: %s\n", config.Triple())
fmt.Printf("GOOS: %s\n", config.GOOS()) fmt.Printf("GOOS: %s\n", config.GOOS())
fmt.Printf("GOARCH: %s\n", config.GOARCH()) 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("build tags: %s\n", strings.Join(config.BuildTags(), " "))
fmt.Printf("garbage collector: %s\n", config.GC()) fmt.Printf("garbage collector: %s\n", config.GC())
fmt.Printf("scheduler: %s\n", config.Scheduler()) fmt.Printf("scheduler: %s\n", config.Scheduler())
+41 -36
View File
@@ -10,7 +10,6 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"reflect" "reflect"
@@ -52,6 +51,7 @@ func TestBuild(t *testing.T) {
"embed/", "embed/",
"float.go", "float.go",
"gc.go", "gc.go",
"generics.go",
"goroutines.go", "goroutines.go",
"init.go", "init.go",
"init_multi.go", "init_multi.go",
@@ -66,21 +66,10 @@ func TestBuild(t *testing.T) {
"stdlib.go", "stdlib.go",
"string.go", "string.go",
"structs.go", "structs.go",
"testing.go",
"timers.go",
"zeroalloc.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 != "" { if *testTarget != "" {
// This makes it possible to run one specific test (instead of all), // This makes it possible to run one specific test (instead of all),
@@ -181,6 +170,14 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
} }
for _, name := range tests { 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" { if options.Target == "simavr" {
// Not all tests are currently supported on AVR. // Not all tests are currently supported on AVR.
// Skip the ones that aren't. // Skip the ones that aren't.
@@ -193,7 +190,7 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
// Does not pass due to high mark false positive rate. // Does not pass due to high mark false positive rate.
continue continue
case "json.go", "stdlib.go", "testing.go", "testing_go118.go": case "json.go", "stdlib.go", "testing.go":
// Breaks interp. // Breaks interp.
continue continue
@@ -209,6 +206,11 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
// CGo does not work on AVR. // CGo does not work on AVR.
continue continue
case "timers.go":
// Doesn't compile:
// panic: compiler: could not store type code number inside interface type code
continue
default: default:
} }
} }
@@ -260,10 +262,11 @@ func emuCheck(t *testing.T, options compileopts.Options) {
t.Fatal("failed to load target spec:", err) t.Fatal("failed to load target spec:", err)
} }
if spec.Emulator != "" { if spec.Emulator != "" {
_, err := exec.LookPath(strings.SplitN(spec.Emulator, " ", 2)[0]) emulatorCommand := strings.SplitN(spec.Emulator, " ", 2)[0]
_, err := exec.LookPath(emulatorCommand)
if err != nil { if err != nil {
if errors.Is(err, exec.ErrNotFound) { if errors.Is(err, exec.ErrNotFound) {
t.Skipf("emulator not installed: %q", spec.Emulator[0]) t.Skipf("emulator not installed: %q", emulatorCommand)
} }
t.Errorf("searching for emulator: %v", err) t.Errorf("searching for emulator: %v", err)
@@ -275,14 +278,15 @@ func emuCheck(t *testing.T, options compileopts.Options) {
func optionsFromTarget(target string, sema chan struct{}) compileopts.Options { func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
return compileopts.Options{ return compileopts.Options{
// GOOS/GOARCH are only used if target == "" // GOOS/GOARCH are only used if target == ""
GOOS: goenv.Get("GOOS"), GOOS: goenv.Get("GOOS"),
GOARCH: goenv.Get("GOARCH"), GOARCH: goenv.Get("GOARCH"),
GOARM: goenv.Get("GOARM"), GOARM: goenv.Get("GOARM"),
Target: target, Target: target,
Semaphore: sema, Semaphore: sema,
Debug: true, InterpTimeout: 180 * time.Second,
VerifyIR: true, Debug: true,
Opt: "z", VerifyIR: true,
Opt: "z",
} }
} }
@@ -292,12 +296,13 @@ func optionsFromTarget(target string, sema chan struct{}) compileopts.Options {
func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options { func optionsFromOSARCH(osarch string, sema chan struct{}) compileopts.Options {
parts := strings.Split(osarch, "/") parts := strings.Split(osarch, "/")
options := compileopts.Options{ options := compileopts.Options{
GOOS: parts[0], GOOS: parts[0],
GOARCH: parts[1], GOARCH: parts[1],
Semaphore: sema, Semaphore: sema,
Debug: true, InterpTimeout: 180 * time.Second,
VerifyIR: true, Debug: true,
Opt: "z", VerifyIR: true,
Opt: "z",
} }
if options.GOARCH == "arm" { if options.GOARCH == "arm" {
options.GOARM = parts[2] options.GOARM = parts[2]
@@ -319,7 +324,7 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
if path[len(path)-1] == '/' { if path[len(path)-1] == '/' {
txtpath = path + "out.txt" txtpath = path + "out.txt"
} }
expected, err := ioutil.ReadFile(txtpath) expected, err := os.ReadFile(txtpath)
if err != nil { if err != nil {
t.Fatal("could not read expected output file:", err) t.Fatal("could not read expected output file:", err)
} }
@@ -430,7 +435,7 @@ func TestTest(t *testing.T) {
defer out.Close() defer out.Close()
opts := targ.opts opts := targ.opts
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/pass", out, out, &opts, false, false, false, "", "", "", "") passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/pass", out, out, &opts, false, false, false, "", "", "", false, "")
if err != nil { if err != nil {
t.Errorf("test error: %v", err) t.Errorf("test error: %v", err)
} }
@@ -451,7 +456,7 @@ func TestTest(t *testing.T) {
defer out.Close() defer out.Close()
opts := targ.opts opts := targ.opts
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/fail", out, out, &opts, false, false, false, "", "", "", "") passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/fail", out, out, &opts, false, false, false, "", "", "", false, "")
if err != nil { if err != nil {
t.Errorf("test error: %v", err) t.Errorf("test error: %v", err)
} }
@@ -478,7 +483,7 @@ func TestTest(t *testing.T) {
var output bytes.Buffer var output bytes.Buffer
opts := targ.opts opts := targ.opts
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/nothing", io.MultiWriter(&output, out), out, &opts, false, false, false, "", "", "", "") passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/nothing", io.MultiWriter(&output, out), out, &opts, false, false, false, "", "", "", false, "")
if err != nil { if err != nil {
t.Errorf("test error: %v", err) t.Errorf("test error: %v", err)
} }
@@ -502,7 +507,7 @@ func TestTest(t *testing.T) {
defer out.Close() defer out.Close()
opts := targ.opts opts := targ.opts
passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/builderr", out, out, &opts, false, false, false, "", "", "", "") passed, err := Test("github.com/tinygo-org/tinygo/tests/testing/builderr", out, out, &opts, false, false, false, "", "", "", false, "")
if err == nil { if err == nil {
t.Error("test did not error") t.Error("test did not error")
} }
@@ -0,0 +1,17 @@
// 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() {
}
+1
View File
@@ -27,5 +27,6 @@ func (r *reader) Read(b []byte) (n int, err error) {
} }
// void arc4random_buf(void *buf, size_t buflen); // void arc4random_buf(void *buf, size_t buflen);
//
//export arc4random_buf //export arc4random_buf
func libc_arc4random_buf(buf unsafe.Pointer, buflen uint) func libc_arc4random_buf(buf unsafe.Pointer, buflen uint)
+1
View File
@@ -38,5 +38,6 @@ func (r *reader) Read(b []byte) (n int, err error) {
// Cryptographically secure random number generator. // Cryptographically secure random number generator.
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rand-s?view=msvc-170 // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rand-s?view=msvc-170
// errno_t rand_s(unsigned int* randomValue); // errno_t rand_s(unsigned int* randomValue);
//
//export rand_s //export rand_s
func libc_rand_s(randomValue *uint32) int32 func libc_rand_s(randomValue *uint32) int32
+29 -29
View File
@@ -2,31 +2,31 @@
// //
// Original copyright: // Original copyright:
// //
// Copyright (c) 2009 - 2015 ARM LIMITED // Copyright (c) 2009 - 2015 ARM LIMITED
// //
// All rights reserved. // All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: // modification, are permitted provided that the following conditions are met:
// - Redistributions of source code must retain the above copyright // - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer. // notice, this list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright // - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the // notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution. // documentation and/or other materials provided with the distribution.
// - Neither the name of ARM nor the names of its contributors may be used // - Neither the name of ARM nor the names of its contributors may be used
// to endorse or promote products derived from this software without // to endorse or promote products derived from this software without
// specific prior written permission. // specific prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE // ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // 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 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
package arm package arm
import ( import (
@@ -46,12 +46,12 @@ func Asm(asm string)
// effects, as it would otherwise be optimized away. The inline assembly string // effects, as it would otherwise be optimized away. The inline assembly string
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// arm.AsmFull( // arm.AsmFull(
// "str {value}, {result}", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1 // "value": 1
// "result": &dest, // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
// return value. // return value.
+1
View File
@@ -60,5 +60,6 @@ const (
// Call a semihosting function. // Call a semihosting function.
// TODO: implement it here using inline assembly. // TODO: implement it here using inline assembly.
//
//go:linkname SemihostingCall SemihostingCall //go:linkname SemihostingCall SemihostingCall
func SemihostingCall(num int, arg uintptr) int func SemihostingCall(num int, arg uintptr) int
+6 -6
View File
@@ -9,12 +9,12 @@ func Asm(asm string)
// effects, as it would otherwise be optimized away. The inline assembly string // effects, as it would otherwise be optimized away. The inline assembly string
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// arm.AsmFull( // arm.AsmFull(
// "str {value}, {result}", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1 // "value": 1
// "result": &dest, // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
// return value. // return value.
+6 -6
View File
@@ -9,12 +9,12 @@ func Asm(asm string)
// effects, as it would otherwise be optimized away. The inline assembly string // effects, as it would otherwise be optimized away. The inline assembly string
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// arm.AsmFull( // arm.AsmFull(
// "str {value}, {result}", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1 // "value": 1
// "result": &dest, // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
// return value. // return value.
+6 -6
View File
@@ -9,12 +9,12 @@ func Asm(asm string)
// effects, as it would otherwise be optimized away. The inline assembly string // effects, as it would otherwise be optimized away. The inline assembly string
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// avr.AsmFull( // avr.AsmFull(
// "str {value}, {result}", // "str {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1 // "value": 1
// "result": &dest, // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
// return value. // return value.
+6 -6
View File
@@ -9,12 +9,12 @@ func Asm(asm string)
// effects, as it would otherwise be optimized away. The inline assembly string // effects, as it would otherwise be optimized away. The inline assembly string
// recognizes template values in the form {name}, like so: // recognizes template values in the form {name}, like so:
// //
// arm.AsmFull( // arm.AsmFull(
// "st {value}, {result}", // "st {value}, {result}",
// map[string]interface{}{ // map[string]interface{}{
// "value": 1 // "value": 1
// "result": &dest, // "result": &dest,
// }) // })
// //
// You can use {} in the asm string (which expands to a register) to set the // You can use {} in the asm string (which expands to a register) to set the
// return value. // return value.
-1
View File
@@ -1,6 +1,5 @@
// Example using the i2s hardware interface on the Adafruit Circuit Playground Express // Example using the i2s hardware interface on the Adafruit Circuit Playground Express
// to read data from the onboard MEMS microphone. // to read data from the onboard MEMS microphone.
//
package main package main
import ( import (
+1 -1
View File
@@ -24,7 +24,7 @@ main: clean wasm_exec
cp ./main/index.html ./html/ cp ./main/index.html ./html/
wasm_exec: wasm_exec:
cp ../../../targets/wasm_exec.js ./html/ cp `tinygo env TINYGOROOT`/targets/wasm_exec.js ./html/
clean: clean:
rm -rf ./html rm -rf ./html
-2
View File
@@ -1,2 +0,0 @@
internal/itoa is new to go as of 1.17.
This directory should be removed when tinygo drops support for go 1.16.
-33
View File
@@ -1,33 +0,0 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// 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:])
}
-40
View File
@@ -1,40 +0,0 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package 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)
}
}
}
+1
View File
@@ -89,6 +89,7 @@ func swapTask(oldStack uintptr, newStack *uintptr)
// startTask is a small wrapper function that sets up the first (and only) // 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 // argument to the new goroutine and makes sure it is exited when the goroutine
// finishes. // finishes.
//
//go:extern tinygo_startTask //go:extern tinygo_startTask
var startTask [0]uint8 var startTask [0]uint8
+1
View File
@@ -29,6 +29,7 @@ type calleeSavedRegs struct {
// archInit runs architecture-specific setup for the goroutine startup. // archInit runs architecture-specific setup for the goroutine startup.
// Note: adding //go:noinline to work around an AVR backend bug. // Note: adding //go:noinline to work around an AVR backend bug.
//
//go:noinline //go:noinline
func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) { func (s *state) archInit(r *calleeSavedRegs, fn uintptr, args unsafe.Pointer) {
// Store the initial sp for the startTask function (implemented in assembly). // Store the initial sp for the startTask function (implemented in assembly).
-1
View File
@@ -4,7 +4,6 @@
// This contains the pin mappings for the Arduino MKR1000 board. // This contains the pin mappings for the Arduino MKR1000 board.
// //
// For more information, see: https://store.arduino.cc/usa/arduino-mkr1000-with-headers-mounted // For more information, see: https://store.arduino.cc/usa/arduino-mkr1000-with-headers-mounted
//
package machine package machine
// used to reset into bootloader // used to reset into bootloader
-1
View File
@@ -4,7 +4,6 @@
// This contains the pin mappings for the Arduino MKR WiFi 1010 board. // This contains the pin mappings for the Arduino MKR WiFi 1010 board.
// //
// For more information, see: https://store.arduino.cc/usa/mkr-wifi-1010 // For more information, see: https://store.arduino.cc/usa/mkr-wifi-1010
//
package machine package machine
// used to reset into bootloader // used to reset into bootloader
-1
View File
@@ -4,7 +4,6 @@
// This contains the pin mappings for the Arduino Nano33 IoT board. // This contains the pin mappings for the Arduino Nano33 IoT board.
// //
// For more information, see: https://store.arduino.cc/nano-33-iot // For more information, see: https://store.arduino.cc/nano-33-iot
//
package machine package machine
// used to reset into bootloader // used to reset into bootloader
+3 -3
View File
@@ -6,7 +6,6 @@
// For more information, see: https://shop.pimoroni.com/products/badger-2040 // For more information, see: https://shop.pimoroni.com/products/badger-2040
// Also // Also
// - Badger 2040 schematic: https://cdn.shopify.com/s/files/1/0174/1800/files/badger_2040_schematic.pdf?v=1645702148 // - Badger 2040 schematic: https://cdn.shopify.com/s/files/1/0174/1800/files/badger_2040_schematic.pdf?v=1645702148
//
package machine package machine
import ( import (
@@ -58,14 +57,15 @@ const (
// QSPI pins¿? // QSPI pins¿?
const ( const (
/* TODO /*
TODO
SPI0_SD0_PIN Pin = QSPI_SD0 SPI0_SD0_PIN Pin = QSPI_SD0
SPI0_SD1_PIN Pin = QSPI_SD1 SPI0_SD1_PIN Pin = QSPI_SD1
SPI0_SD2_PIN Pin = QSPI_SD2 SPI0_SD2_PIN Pin = QSPI_SD2
SPI0_SD3_PIN Pin = QSPI_SD3 SPI0_SD3_PIN Pin = QSPI_SD3
SPI0_SCK_PIN Pin = QSPI_SCLKGPIO6 SPI0_SCK_PIN Pin = QSPI_SCLKGPIO6
SPI0_CS_PIN Pin = QSPI_CS SPI0_CS_PIN Pin = QSPI_CS
*/ */
) )
+5 -6
View File
@@ -10,11 +10,11 @@
// //
// Special version of bossac is required. // Special version of bossac is required.
// This executable can be obtained two ways: // This executable can be obtained two ways:
// 1) In Arduino IDE, install support for the board ("Arduino Mbed OS Nano Boards") // 1. In Arduino IDE, install support for the board ("Arduino Mbed OS Nano Boards")
// Search for "tools/bossac/1.9.1-arduino2/bossac" in Arduino IDEs directory // Search for "tools/bossac/1.9.1-arduino2/bossac" in Arduino IDEs directory
// 2) Download https://downloads.arduino.cc/packages/package_index.json // 2. Download https://downloads.arduino.cc/packages/package_index.json
// Search for "bossac-1.9.1-arduino2" in that file // Search for "bossac-1.9.1-arduino2" in that file
// Download tarball for your OS and unpack it // Download tarball for your OS and unpack it
// //
// Once you have the executable, make it accessible in your PATH as "bossac_arduino2". // Once you have the executable, make it accessible in your PATH as "bossac_arduino2".
// //
@@ -29,7 +29,6 @@
// //
// SoftDevice overwrites original bootloader and flashing method described above is not avalable anymore. // SoftDevice overwrites original bootloader and flashing method described above is not avalable anymore.
// Instead, please use debug probe and flash your code with "nano-33-ble-s140v7" target. // Instead, please use debug probe and flash your code with "nano-33-ble-s140v7" target.
//
package machine package machine
const HasLowFrequencyCrystal = true const HasLowFrequencyCrystal = true
-1
View File
@@ -10,7 +10,6 @@
// Also // Also
// - Datasheets: https://docs.arduino.cc/hardware/nano-rp2040-connect // - Datasheets: https://docs.arduino.cc/hardware/nano-rp2040-connect
// - Nano RP2040 Connect technical reference: https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-01-technical-reference // - Nano RP2040 Connect technical reference: https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-01-technical-reference
//
package machine package machine
import ( import (
-1
View File
@@ -4,7 +4,6 @@
// This contains the pin mappings for the ProductivityOpen P1AM-100 board. // This contains the pin mappings for the ProductivityOpen P1AM-100 board.
// //
// For more information, see: https://facts-engineering.github.io/ // For more information, see: https://facts-engineering.github.io/
//
package machine package machine
// used to reset into bootloader // used to reset into bootloader
+120
View File
@@ -0,0 +1,120 @@
//go:build qtpy_rp2040
// +build qtpy_rp2040
package machine
import (
"device/rp"
"runtime/interrupt"
)
// Onboard crystal oscillator frequency, in MHz.
const xoscFreq = 12 // MHz
// GPIO Pins
const (
SDA = GPIO24
SCL = GPIO25
TX = GPIO20
MO = GPIO3
MOSI = GPIO3
MI = GPIO4
MISO = GPIO4
SCK = GPIO6
RX = GPIO5
QT_SCL1 = GPIO23
QT_SDA1 = GPIO22
)
// Analog pins
const (
A0 = GPIO29
A1 = GPIO28
A2 = GPIO27
A3 = GPIO26
)
const (
NEOPIXELS = GPIO12
WS2812 = GPIO12
NEOPIXELS_POWER = GPIO11
LED = GPIO20
)
// I2C Pins.
const (
I2C0_SDA_PIN = GPIO24
I2C0_SCL_PIN = GPIO25
I2C1_SDA_PIN = GPIO26
I2C1_SCL_PIN = GPIO27
I2C1_QT_SDA_PIN = GPIO22
I2C1_QT_SCL_PIN = GPIO23
SDA_PIN = GPIO24
SCL_PIN = GPIO25
)
// SPI default pins
const (
// Default Serial Clock Bus 0 for SPI communications
SPI0_SCK_PIN = GPIO6
// Default Serial Out Bus 0 for SPI communications
SPI0_SDO_PIN = GPIO3 // Tx
// Default Serial In Bus 0 for SPI communications
SPI0_SDI_PIN = GPIO4 // Rx
SPI0_CS = GPIO5
// Default Serial Clock Bus 1 for SPI communications
SPI1_SCK_PIN = GPIO26
// Default Serial Out Bus 1 for SPI communications
SPI1_SDO_PIN = GPIO27 // Tx
// Default Serial In Bus 1 for SPI communications
SPI1_SDI_PIN = GPIO24 // Rx
SPI1_CS = GPIO25
)
// UART pins
const (
UART0_TX_PIN = GPIO28
UART0_RX_PIN = GPIO29
UART1_TX_PIN = GPIO20
UART1_RX_PIN = GPIO5
UART_TX_PIN = UART0_TX_PIN
UART_RX_PIN = UART0_RX_PIN
)
// UART on the RP2040
var (
UART0 = &_UART0
_UART0 = UART{
Buffer: NewRingBuffer(),
Bus: rp.UART0,
}
UART1 = &_UART1
_UART1 = UART{
Buffer: NewRingBuffer(),
Bus: rp.UART1,
}
)
var DefaultUART = UART0
func init() {
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
UART1.Interrupt = interrupt.New(rp.IRQ_UART1_IRQ, _UART1.handleInterrupt)
}
// USB identifiers
const (
usb_STRING_PRODUCT = "QT Py RP2040"
usb_STRING_MANUFACTURER = "Adafruit"
)
var (
usb_VID uint16 = 0x239A
usb_PID uint16 = 0x80F1
)
+63
View File
@@ -0,0 +1,63 @@
//go:build trinkey_qt2040
// +build trinkey_qt2040
// This file contains the pin mappings for the Adafruit Trinkey QT2040 board.
//
// The Trinkey QT2040 is a small development board based on the RP2040 which
// plugs into a USB A port. The board has a minimal pinout: an integrated
// NeoPixel LED and a STEMMA QT I2C port.
//
// - Product: https://www.adafruit.com/product/5056
// - Overview: https://learn.adafruit.com/adafruit-trinkey-qt2040
// - Pinouts: https://learn.adafruit.com/adafruit-trinkey-qt2040/pinouts
// - Datasheets: https://learn.adafruit.com/adafruit-trinkey-qt2040/downloads
package machine
// Onboard crystal oscillator frequency, in MHz
const xoscFreq = 12 // MHz
// Onboard LEDs
const (
NEOPIXEL = GPIO27
WS2812 = NEOPIXEL
)
// I2C pins
const (
I2C0_SDA_PIN = GPIO16
I2C0_SCL_PIN = GPIO17
I2C1_SDA_PIN = NoPin
I2C1_SCL_PIN = NoPin
)
// SPI pins
const (
SPI0_SCK_PIN = NoPin
SPI0_SDO_PIN = NoPin
SPI0_SDI_PIN = NoPin
SPI1_SCK_PIN = NoPin
SPI1_SDO_PIN = NoPin
SPI1_SDI_PIN = NoPin
)
// UART pins
const (
UART0_TX_PIN = NoPin
UART0_RX_PIN = NoPin
UART_TX_PIN = UART0_TX_PIN
UART_RX_PIN = UART0_RX_PIN
)
// USB identifiers
const (
usb_STRING_PRODUCT = "Trinkey QT2040"
usb_STRING_MANUFACTURER = "Adafruit"
)
var (
usb_VID uint16 = 0x239a
usb_PID uint16 = 0x8109
)
+105
View File
@@ -0,0 +1,105 @@
//go:build tufty2040
// +build tufty2040
// This contains the pin mappings for the Badger 2040 Connect board.
//
// For more information, see: https://shop.pimoroni.com/products/tufty-2040
// Also
// - Tufty 2040 schematic: https://cdn.shopify.com/s/files/1/0174/1800/files/tufty_schematic.pdf?v=1655385675
//
package machine
import (
"device/rp"
"runtime/interrupt"
)
const (
LED Pin = GPIO25
BUTTON_A Pin = GPIO7
BUTTON_B Pin = GPIO8
BUTTON_C Pin = GPIO9
BUTTON_UP Pin = GPIO22
BUTTON_DOWN Pin = GPIO6
BUTTON_USER Pin = GPIO23
LCD_BACKLIGHT Pin = GPIO2
LCD_CS Pin = GPIO10
LCD_DC Pin = GPIO11
LCD_WR Pin = GPIO12
LCD_RD Pin = GPIO13
LCD_DB0 Pin = GPIO14
LCD_DB1 Pin = GPIO15
LCD_DB2 Pin = GPIO16
LCD_DB3 Pin = GPIO17
LCD_DB4 Pin = GPIO18
LCD_DB5 Pin = GPIO19
LCD_DB6 Pin = GPIO20
LCD_DB7 Pin = GPIO21
VBUS_DETECT Pin = GPIO24
BATTERY Pin = GPIO29
USER_LED Pin = GPIO25
LIGHT_SENSE Pin = GPIO26
SENSOR_POWER Pin = GPIO27
)
// I2C pins
const (
I2C0_SDA_PIN Pin = GPIO4
I2C0_SCL_PIN Pin = GPIO5
I2C1_SDA_PIN Pin = NoPin
I2C1_SCL_PIN Pin = NoPin
)
// SPI pins.
const (
SPI0_SCK_PIN Pin = NoPin
SPI0_SDO_PIN Pin = NoPin
SPI0_SDI_PIN Pin = NoPin
SPI1_SCK_PIN Pin = NoPin
SPI1_SDO_PIN Pin = NoPin
SPI1_SDI_PIN Pin = NoPin
)
// Onboard crystal oscillator frequency, in MHz.
const (
xoscFreq = 12 // MHz
)
// USB CDC identifiers
const (
usb_STRING_PRODUCT = "Tufty 2040"
usb_STRING_MANUFACTURER = "Pimoroni"
)
var (
usb_VID uint16 = 0x2e8a
usb_PID uint16 = 0x1002
)
// UART pins
const (
UART0_TX_PIN = GPIO0
UART0_RX_PIN = GPIO1
UART_TX_PIN = UART0_TX_PIN
UART_RX_PIN = UART0_RX_PIN
)
// UART on the RP2040
var (
UART0 = &_UART0
_UART0 = UART{
Buffer: NewRingBuffer(),
Bus: rp.UART0,
}
)
var DefaultUART = UART0
func init() {
UART0.Interrupt = interrupt.New(rp.IRQ_UART0_IRQ, _UART0.handleInterrupt)
}
+4 -1
View File
@@ -349,8 +349,11 @@ var (
UART1 = &sercomUSART2 UART1 = &sercomUSART2
// RTL8720D // RTL8720D (tx: PC22, rx: PC23)
UART2 = &sercomUSART1 UART2 = &sercomUSART1
// RTL8720D (tx: PB24, rx: PC24)
UART3 = &sercomUSART0
) )
// I2C pins // I2C pins
-1
View File
@@ -17,7 +17,6 @@
// //
// - https://wiki.seeedstudio.com/XIAO_BLE/ // - https://wiki.seeedstudio.com/XIAO_BLE/
// - https://github.com/Seeed-Studio/ArduinoCore-mbed/tree/master/variants/SEEED_XIAO_NRF52840_SENSE // - https://github.com/Seeed-Studio/ArduinoCore-mbed/tree/master/variants/SEEED_XIAO_NRF52840_SENSE
//
package machine package machine
const HasLowFrequencyCrystal = true const HasLowFrequencyCrystal = true
+54
View File
@@ -0,0 +1,54 @@
//go:build xiao_esp32c3
// +build xiao_esp32c3
// This file contains the pin mappings for the Seeed XIAO ESP32C3 boards.
//
// Seeed Studio XIAO ESP32C3 is an IoT mini development board based on
// the Espressif ESP32-C3 WiFi/Bluetooth dual-mode chip.
//
// - https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html
// - https://wiki.seeedstudio.com/XIAO_ESP32C3_Getting_Started/
package machine
// Digital Pins
const (
D0 = GPIO2
D1 = GPIO3
D2 = GPIO4
D3 = GPIO5
D4 = GPIO6
D5 = GPIO7
D6 = GPIO21
D7 = GPIO20
D8 = GPIO8
D9 = GPIO9
D10 = GPIO10
)
// Analog pins
const (
A0 = GPIO2
A1 = GPIO3
A2 = GPIO4
A3 = GPIO5
)
// UART pins
const (
UART_RX_PIN = GPIO20
UART_TX_PIN = GPIO21
)
// I2C pins
const (
SDA_PIN = GPIO6
SCL_PIN = GPIO7
)
// SPI pins
const (
SPI_SCK_PIN = GPIO8
SPI_SDI_PIN = GPIO9
SPI_SDO_PIN = GPIO10
)
-1
View File
@@ -6,7 +6,6 @@
// XIAO RP2040 is a microcontroller using the Raspberry Pi RP2040 chip. // XIAO RP2040 is a microcontroller using the Raspberry Pi RP2040 chip.
// //
// - https://wiki.seeedstudio.com/XIAO-RP2040/ // - https://wiki.seeedstudio.com/XIAO-RP2040/
//
package machine package machine
import ( import (
+2 -2
View File
@@ -264,7 +264,7 @@ func (pwm PWM) Configure(config PWMConfig) error {
// SetPeriod updates the period of this PWM peripheral. // SetPeriod updates the period of this PWM peripheral.
// To set a particular frequency, use the following formula: // To set a particular frequency, use the following formula:
// //
// period = 1e9 / frequency // period = 1e9 / frequency
// //
// If you use a period of 0, a period that works well for LEDs will be picked. // If you use a period of 0, a period that works well for LEDs will be picked.
// //
@@ -694,7 +694,7 @@ func (pwm PWM) SetInverting(channel uint8, inverting bool) {
// cycle, in other words the fraction of time the channel output is high (or low // cycle, in other words the fraction of time the channel output is high (or low
// when inverted). For example, to set it to a 25% duty cycle, use: // when inverted). For example, to set it to a 25% duty cycle, use:
// //
// pwm.Set(channel, pwm.Top() / 4) // pwm.Set(channel, pwm.Top() / 4)
// //
// pwm.Set(channel, 0) will set the output to low and pwm.Set(channel, // pwm.Set(channel, 0) will set the output to low and pwm.Set(channel,
// pwm.Top()) will set the output to high, assuming the output isn't inverted. // pwm.Top()) will set the output to high, assuming the output isn't inverted.
+2 -2
View File
@@ -134,7 +134,7 @@ func (pwm PWM) Configure(config PWMConfig) error {
// SetPeriod updates the period of this PWM peripheral. // SetPeriod updates the period of this PWM peripheral.
// To set a particular frequency, use the following formula: // To set a particular frequency, use the following formula:
// //
// period = 1e9 / frequency // period = 1e9 / frequency
// //
// If you use a period of 0, a period that works well for LEDs will be picked. // If you use a period of 0, a period that works well for LEDs will be picked.
// //
@@ -375,7 +375,7 @@ func (pwm PWM) SetInverting(channel uint8, inverting bool) {
// cycle, in other words the fraction of time the channel output is high (or low // cycle, in other words the fraction of time the channel output is high (or low
// when inverted). For example, to set it to a 25% duty cycle, use: // when inverted). For example, to set it to a 25% duty cycle, use:
// //
// pwm.Set(channel, pwm.Top() / 4) // pwm.Set(channel, pwm.Top() / 4)
// //
// pwm.Set(channel, 0) will set the output to low and pwm.Set(channel, // pwm.Set(channel, 0) will set the output to low and pwm.Set(channel,
// pwm.Top()) will set the output to high, assuming the output isn't inverted. // pwm.Top()) will set the output to high, assuming the output isn't inverted.
+9 -10
View File
@@ -5,7 +5,6 @@
// //
// Datasheet: // Datasheet:
// http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf // http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf
//
package machine package machine
import ( import (
@@ -88,10 +87,11 @@ const (
// SERCOM and SERCOM-ALT. // SERCOM and SERCOM-ALT.
// //
// Observations: // Observations:
// * There are six SERCOMs. Those SERCOM numbers can be encoded in 3 bits. // - There are six SERCOMs. Those SERCOM numbers can be encoded in 3 bits.
// * Even pad numbers are always on even pins, and odd pad numbers are always on // - Even pad numbers are always on even pins, and odd pad numbers are always on
// odd pins. // odd pins.
// * Pin pads come in pairs. If PA00 has pad 0, then PA01 has pad 1. // - Pin pads come in pairs. If PA00 has pad 0, then PA01 has pad 1.
//
// With this information, we can encode SERCOM pin/pad numbers much more // With this information, we can encode SERCOM pin/pad numbers much more
// efficiently. First of all, due to pads coming in pairs, we can ignore half // efficiently. First of all, due to pads coming in pairs, we can ignore half
// the pins: the information for an odd pin can be calculated easily from the // the pins: the information for an odd pin can be calculated easily from the
@@ -1285,17 +1285,16 @@ var (
// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer. // This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.
// Note that the tx and rx buffers must be the same size: // Note that the tx and rx buffers must be the same size:
// //
// spi.Tx(tx, rx) // spi.Tx(tx, rx)
// //
// This form sends the tx buffer, ignoring the result. Useful for sending "commands" that return zeros // This form sends the tx buffer, ignoring the result. Useful for sending "commands" that return zeros
// until all the bytes in the command packet have been received: // until all the bytes in the command packet have been received:
// //
// spi.Tx(tx, nil) // spi.Tx(tx, nil)
// //
// This form sends zeros, putting the result into the rx buffer. Good for reading a "result packet": // This form sends zeros, putting the result into the rx buffer. Good for reading a "result packet":
// //
// spi.Tx(nil, rx) // spi.Tx(nil, rx)
//
func (spi SPI) Tx(w, r []byte) error { func (spi SPI) Tx(w, r []byte) error {
switch { switch {
case w == nil: case w == nil:
@@ -1441,7 +1440,7 @@ func (tcc *TCC) Configure(config PWMConfig) error {
// SetPeriod updates the period of this TCC peripheral. // SetPeriod updates the period of this TCC peripheral.
// To set a particular frequency, use the following formula: // To set a particular frequency, use the following formula:
// //
// period = 1e9 / frequency // period = 1e9 / frequency
// //
// If you use a period of 0, a period that works well for LEDs will be picked. // If you use a period of 0, a period that works well for LEDs will be picked.
// //
@@ -1709,7 +1708,7 @@ func (tcc *TCC) SetInverting(channel uint8, inverting bool) {
// cycle, in other words the fraction of time the channel output is high (or low // cycle, in other words the fraction of time the channel output is high (or low
// when inverted). For example, to set it to a 25% duty cycle, use: // when inverted). For example, to set it to a 25% duty cycle, use:
// //
// tcc.Set(channel, tcc.Top() / 4) // tcc.Set(channel, tcc.Top() / 4)
// //
// tcc.Set(channel, 0) will set the output to low and tcc.Set(channel, // tcc.Set(channel, 0) will set the output to low and tcc.Set(channel,
// tcc.Top()) will set the output to high, assuming the output isn't inverted. // tcc.Top()) will set the output to high, assuming the output isn't inverted.
-1
View File
@@ -5,7 +5,6 @@
// //
// Datasheet: // Datasheet:
// http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf // http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf
//
package machine package machine
import ( import (
-1
View File
@@ -5,7 +5,6 @@
// //
// Datasheet: // Datasheet:
// http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf // http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf
//
package machine package machine
import ( import (
+9 -10
View File
@@ -5,7 +5,6 @@
// //
// Datasheet: // Datasheet:
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf // http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
//
package machine package machine
import ( import (
@@ -250,12 +249,13 @@ const (
// SERCOM and SERCOM-ALT. // SERCOM and SERCOM-ALT.
// //
// Observations: // Observations:
// * There are eight SERCOMs. Those SERCOM numbers can be encoded in 4 bits. // - There are eight SERCOMs. Those SERCOM numbers can be encoded in 4 bits.
// * Even pad numbers are usually on even pins, and odd pad numbers are usually // - Even pad numbers are usually on even pins, and odd pad numbers are usually
// on odd pins. The exception is SERCOM-ALT, which sometimes swaps pad 0 and 1. // on odd pins. The exception is SERCOM-ALT, which sometimes swaps pad 0 and 1.
// With that, there is still an invariant that the pad number for an odd pin is // With that, there is still an invariant that the pad number for an odd pin is
// the pad number for the corresponding even pin with the low bit toggled. // the pad number for the corresponding even pin with the low bit toggled.
// * Pin pads come in pairs. If PA00 has pad 0, then PA01 has pad 1. // - Pin pads come in pairs. If PA00 has pad 0, then PA01 has pad 1.
//
// With this information, we can encode SERCOM pin/pad numbers much more // With this information, we can encode SERCOM pin/pad numbers much more
// efficiently. Due to pads coming in pairs, we can ignore half the pins: the // efficiently. Due to pads coming in pairs, we can ignore half the pins: the
// information for an odd pin can be calculated easily from the preceding even // information for an odd pin can be calculated easily from the preceding even
@@ -1538,17 +1538,16 @@ var (
// This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer. // This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.
// Note that the tx and rx buffers must be the same size: // Note that the tx and rx buffers must be the same size:
// //
// spi.Tx(tx, rx) // spi.Tx(tx, rx)
// //
// This form sends the tx buffer, ignoring the result. Useful for sending "commands" that return zeros // This form sends the tx buffer, ignoring the result. Useful for sending "commands" that return zeros
// until all the bytes in the command packet have been received: // until all the bytes in the command packet have been received:
// //
// spi.Tx(tx, nil) // spi.Tx(tx, nil)
// //
// This form sends zeros, putting the result into the rx buffer. Good for reading a "result packet": // This form sends zeros, putting the result into the rx buffer. Good for reading a "result packet":
// //
// spi.Tx(nil, rx) // spi.Tx(nil, rx)
//
func (spi SPI) Tx(w, r []byte) error { func (spi SPI) Tx(w, r []byte) error {
switch { switch {
case w == nil: case w == nil:
@@ -1672,7 +1671,7 @@ func (tcc *TCC) Configure(config PWMConfig) error {
// SetPeriod updates the period of this TCC peripheral. // SetPeriod updates the period of this TCC peripheral.
// To set a particular frequency, use the following formula: // To set a particular frequency, use the following formula:
// //
// period = 1e9 / frequency // period = 1e9 / frequency
// //
// If you use a period of 0, a period that works well for LEDs will be picked. // If you use a period of 0, a period that works well for LEDs will be picked.
// //
@@ -1962,7 +1961,7 @@ func (tcc *TCC) SetInverting(channel uint8, inverting bool) {
// cycle, in other words the fraction of time the channel output is high (or low // cycle, in other words the fraction of time the channel output is high (or low
// when inverted). For example, to set it to a 25% duty cycle, use: // when inverted). For example, to set it to a 25% duty cycle, use:
// //
// tcc.Set(channel, tcc.Top() / 4) // tcc.Set(channel, tcc.Top() / 4)
// //
// tcc.Set(channel, 0) will set the output to low and tcc.Set(channel, // tcc.Set(channel, 0) will set the output to low and tcc.Set(channel,
// tcc.Top()) will set the output to high, assuming the output isn't inverted. // tcc.Top()) will set the output to high, assuming the output isn't inverted.
-1
View File
@@ -5,7 +5,6 @@
// //
// Datasheet: // Datasheet:
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf // http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
//
package machine package machine
import "device/sam" import "device/sam"
-1
View File
@@ -5,7 +5,6 @@
// //
// Datasheet: // Datasheet:
// http://ww1.microchip.com/downloads/en/DeviceDoc/SAM_D5xE5x_Family_Data_Sheet_DS60001507F.pdf // http://ww1.microchip.com/downloads/en/DeviceDoc/SAM_D5xE5x_Family_Data_Sheet_DS60001507F.pdf
//
package machine package machine
import "device/sam" import "device/sam"
-1
View File
@@ -5,7 +5,6 @@
// //
// Datasheet: // Datasheet:
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf // http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
//
package machine package machine
import "device/sam" import "device/sam"

Some files were not shown because too many files have changed in this diff Show More