Compare commits

...

2253 Commits

Author SHA1 Message Date
deadprogram b9ce6c3374 build: allow building llvm image via workflow dispatch
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-03-11 13:08:20 +01:00
Ayke van Laethem cab3834bc9 riscv-qemu: add VirtIO RNG device
This implements machine.GetRNG() using VirtIO. This gets the tests to
pass for crypto/md5 and crypto/sha1 that use crypto/rand in their tests.
2025-03-11 04:22:16 -07:00
Elias Naur 7f970a45c2 machine: don't block the rp2xxx UART interrupt handler
Don't block forever if there's nothing to receive. On the other hand,
process the entire FIFO, not just a single byte.

This fixes an issue where the rp2350 would hang after programming through
openocd, where the UART0 interrupt would be spuriously pending.
2025-03-11 02:01:18 -07:00
Ayke van Laethem ebf70ab18e ci: add more tests for wasm and baremetal
Run a range of tests in CI, to make sure browser wasm and baremetal
don't regress too badly.

I have intentionally filtered out tests, so that newly added tests to
TEST_PACKAGES_FAST will be added here as well (and can be excluded if
needed).
2025-03-10 03:26:30 -07:00
Elias Naur 226744a538 machine: correct register address for Pin.SetInterrupt for rp2350 (#4782)
Fixes #4689
2025-03-09 10:26:38 -03:00
Ayke van Laethem dc876c6ed4 ci: add single test for wasm
It looks like we didn't have any tests for wasm. Having one tests is not
much, but it proves that the infrastructure works and it actually
verifies a fix to https://github.com/tinygo-org/tinygo/issues/4777.

We should add more packages to this list in the future.
2025-03-07 09:09:13 -08:00
Ayke van Laethem 5a09084c73 os: add stub Symlink for wasm
This doesn't do anything, but it makes tests work.
2025-03-07 09:09:13 -08:00
Ayke van Laethem 6c9074772c compiler: crypto/internal/sysrand is allowed to use unsafe signatures
Apparently this package imports `runtime.getRandomData` from the gojs
module. This is not yet implemented, but simply allowing this package to
do such imports gets crypto/sha256 to compile.
2025-03-07 09:09:13 -08:00
Ayke van Laethem e49663809b machine: fix RP2040 Pico board on the playground
Right now it doesn't compile, with errors like the following:

    # machine
    /app/tinygo/src/machine/board_pico.go:7:13: undefined: GPIO0
    /app/tinygo/src/machine/board_pico.go:8:13: undefined: GPIO1
    /app/tinygo/src/machine/board_pico.go:9:13: undefined: GPIO2
    /app/tinygo/src/machine/board_pico.go:10:13: undefined: GPIO3
    [...etc...]

This patch should fix that.
2025-03-07 07:20:40 -08:00
Elias Naur 7d6d93f7aa machine: bump rp2040 to 200MHz (#4768)
* machine: add support for core voltage adjustments to rp2040

In preparation for bumping the core frequency of the rp2040, this
change implements the required core voltage adjustment logic.

* machine: bump rp2040 to 200MHz
2025-03-04 08:57:59 -03:00
deadprogram 8c54e3dd88 release: update version to 0.36.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-03-03 13:02:59 -08:00
deadprogram 47c0debe4b docs: update CHANGELOG for 0.36.0 release
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-03-03 13:02:59 -08:00
Randy Reddig 9a1cde40a8 src/reflect: implement Value.Equal
Implementation copied from Go.
2025-03-03 12:14:30 -08:00
Elias Naur 20fc814635 machine: replace hard-coded cpu frequencies on rp2xxx (#4767)
Missed from the earlier change that bumped the rp2350 frequency.
2025-03-02 08:38:29 -03:00
Egawa Takashi 64d8a04308 convert offset as signed int into unsigned int in syscall/js.stringVal in wasm_exec.js 2025-03-01 09:14:57 -08:00
Elias Naur b95effbdd7 machine: bump rp2350 CPUFrequency to 150 MHz (#4766)
Leave rp2040 speed bump to 200 MHz for a future change, because it
requires bumping the core voltage as well[0].

[0] https://github.com/raspberrypi/pico-sdk/releases/tag/2.1.1
2025-03-01 10:09:53 -03:00
Elias Naur 92c130c7be machine: compute rp2 clock dividers from crystal and target frequency (#4747)
Follow-up to #4728 which implemented the algorithm for finding the
dividers.

The calculation is computed at compile time by interp, as verified by
building example/blinky1 for -target pico.
2025-02-28 19:05:27 -03:00
deadprogram 31c4bc1151 license: update for 2025
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 20:56:22 +01:00
deadprogram 42f5e55ed5 docs: small corrections for README regarding wasm
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 20:56:22 +01:00
deadprogram 81da7bb4c1 targets: add target for pico2-w board
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 20:02:35 +01:00
deadprogram 209754493b make: use GOOS and GOARCH for building wasm simulated boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 18:02:21 +01:00
deadprogram b0aef96340 fix: only infer target for wasm when GOOS and GOARCH are set correctly, not just based on file extension
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-28 18:02:21 +01:00
Ayke van Laethem 056394e24b make: add test-corpus-wasip2
I wanted to run the test corpus with WASIp2 so I added these lines.
2025-02-28 16:16:12 +01:00
Ayke van Laethem 1545659817 internal/syscall/unix: use our own version of this package
The upstream one assumes it's running on a Unix system (which makes
sense), but this package is also used on baremetal. So replace it on
systems that need a replaced syscall package.
2025-02-27 15:45:23 +01:00
Ayke van Laethem 38e3d55e64 all: add Go 1.24 support 2025-02-25 14:41:42 +01:00
Ayke van Laethem 66da29e89f wasip2: add stubs to get internal/syscall/unix to work
This fixes lots of broken tests in stdlib packages in Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem c180d6fe2f testing: add Chdir
This method was added in Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem cdea833b5c os: add File.Chdir support
We should really be using syscall.Fchdir here, but this is a fix to get
Go 1.24 working.
2025-02-25 14:41:42 +01:00
Ayke van Laethem c2eaa495df os: implement stub Chdir for non-OS systems 2025-02-25 14:41:42 +01:00
Ayke van Laethem 3476100dd0 syscall: add wasip1 RandomGet
This function is needed starting with Go 1.24.
2025-02-25 14:41:42 +01:00
Ayke van Laethem 07c7eff3c3 runtime: add FIPS helper functions
Not entirely sure what they're for, but the Go runtime also stores this
information per goroutine so let's go with that.
2025-02-25 14:41:42 +01:00
Ayke van Laethem a1be8cd9fe machine/usb/descriptor: avoid bytes package
We can't use the bytes package in Go 1.24 since it would result in an
import cycle. Therefore, use bytealg.Index instead.

(I'm not sure this code is correct - just searching for a range of bytes
seems brittle. But at least this commit shouldn't change the code).
2025-02-25 14:41:42 +01:00
Ayke van Laethem 52b9fcd57f machine: remove bytes package dependency in flash code
This also moves flash padding code to a single place, since it was
copied 5 times.

This change is necessary in Go 1.24 to avoid an import cycle.
2025-02-25 14:41:42 +01:00
Ayke van Laethem ea53ace270 cgo: mangle identifier names
This mangles CGo identifier names to something like "_Cgo_foo" instead
of using literal identifiers like "C.foo". This works around
https://github.com/golang/go/issues/71777.

I don't like this solution, but I hope we'll find a better solution in
the future. In that case we can revert this commit.
2025-02-25 14:41:42 +01:00
Ayke van Laethem a6cd072fa1 Revert "fix: implement testing {Skip,Fail}Now"
This reverts commit c5879c682c.

It doesn't look like this is working (see
https://github.com/tinygo-org/tinygo/pull/4736#issuecomment-2679670226),
and it doesn't have any tests anyway to prove that it does work. So I
think it's best to revert it for now and add a working implementation
with tests in the future.
2025-02-25 12:38:52 +01:00
Ayke van Laethem 4372dbdd41 ci: use older image for cross-compiling builds
This ensures that the resulting binaries are compatible with a wide
range of Linux systems, not just the most recent ones.
2025-02-24 19:22:27 +01:00
deadprogram 17bb1fec44 feature: add buildmode=wasi-legacy to support existing base of users who expected the
older behavior for wasi modules to not return an exit code as if they were reactors.

See #4726 for some details on what this is intended to address.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-21 13:06:14 +01:00
Ayke van Laethem f4fd79f7be runtime: manually initialize xorshift state
This ensures:

 1. The xorshift state is initialized during interp.
 2. The xorshift state gets initialized to a real random number on
    hardware that supports it at runtime.

This fixes a big binary size regression from the previous commit. It's
still not perfect: most programs increase binary size by a few bytes.
But it's not nearly as bad as before.
2025-02-21 11:36:17 +01:00
Ayke van Laethem 811b13a9d3 interp: correctly mark functions as modifying memory
Previously, if a function couldn't be interpreted in the interp pass, it
would just be run at runtime and the parameters would be marked as
potentially being modified. However, this is incorrect: the function
itself can also modify memory. So the function itself also needs to be
marked (recursively).

This fixes a number of regressions while upgrading to Go 1.24.

This results in a significant size regression that is mostly worked
around in the next commit.
2025-02-21 11:36:17 +01:00
Ron Evans 6e97079367 target: add Pimoroni Pico Plus2 (#4735)
* machine: separate definitions for ADC pins on rp2350/rp2350b

Signed-off-by: deadprogram <ron@hybridgroup.com>

* targets: add support for Pimoroni Pico Plus2

Signed-off-by: deadprogram <ron@hybridgroup.com>

---------

Signed-off-by: deadprogram <ron@hybridgroup.com>
Co-authored-by: Patricio Whittingslow <graded.sp@gmail.com>
2025-02-21 09:56:52 +01:00
soypat 9c7bbce029 rp2350: add pll generalized solution; fix ADC handles; pwm period fix 2025-02-21 09:56:52 +01:00
soypat 0ec1cb1e19 machine/rp2350: extending support to include the rp2350b 2025-02-21 09:56:52 +01:00
Scott Feldman e7118e5bda add comboat_fw tag for elecrow W5 boards with Combo-AT Wifi firmware 2025-02-21 07:22:17 +01:00
Ron Evans 150d9d1c6b fix: correctly handle id lookup for finalizeRef call
Modify the ID used for looking up the reference, based on suggestion made by @prochac

Also use console.error in the caase that the reference is not found, since it is now actually
known to be an error.
2025-02-20 22:17:38 +01:00
Laurent Demailly 8fe039156b fix: Avoid total failure on wasm finalizer call 2025-02-20 22:17:38 +01:00
leongross 2d17dec7bf os/file: add file.Chmod
Signed-off-by: leongross <leon.gross@9elements.com>
2025-02-19 22:12:51 +01:00
JP Hastings-Spital c1b267a208 Ensure build output directory is created
`tinygo build -o /path/to/out .` expected `/path/to/out` to already exist, which is different behaviour to `go build`. This change ensures tinygo creates any directories needed to be able to build to the specified output dir.
2025-02-19 19:55:48 +01:00
deadprogram f02c56c9e0 net: update to latest submodule with httptest subpackage and
ResolveIPAddress implementation.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-17 13:16:56 +01:00
leongross c5879c682c fix: implement testing {Skip,Fail}Now
PR https://github.com/tinygo-org/tinygo/pull/4623 implements
runtime.GoExit() with which we can improve the testing package
and align it more to upstream testing behavour https://cs.opensource.google/go/go/+/refs/tags/go1.24.0:src/testing/testing.go;l=1150

Signed-off-by: leongross <leon.gross@9elements.com>
2025-02-15 21:30:22 +01:00
deadprogram 190c20825f targets: turn on GC for TKey1 device, since it does in fact work
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-14 12:49:20 +01:00
deadprogram d04eea7185 fix: add NoSandbox flag to chrome headless that is run during WASM tests, since
this is now required for Ubuntu 23+ and we are using Ubuntu 24+ when running
Github Actions.

See https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md

Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-12 17:13:56 +01:00
deadprogram f24cd31895 build: update Linux builds to run on ubuntu-latest since 20.04 is being retired
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-02-12 17:13:56 +01:00
m00874241 2044f6fbcc Added VersionTLS constants and VersionName(version uint16) method that turns it into a string, copied from big go 2025-01-30 07:30:57 +01:00
HattoriHanzo031 d55a89f96a board: support for NRF51 HW-651 (#4712)
NRF51: Support for NRF51 HW-651 board
* smoketest
* removed redundant flash-method
* smoketest fix
* description and links
* link fix
2025-01-30 05:46:52 +01:00
Elias Naur 080a6648e9 targets: match Pico2 stack size to Pico
Took me a while to debug weird crashes after switching from Pico to
Pico2.
2025-01-26 17:04:04 +08:00
deadprogram ec0a142190 build: update wasmtime used for CI to 29.0.1 to fix issue with install during CI tests
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-01-23 17:56:02 +08:00
Yurii Soldak b7fcf6ad68 nrf: fix adc read near zero 2025-01-23 13:03:25 +08:00
milkpirate 7417c14c2d nrf: make ADC resolution changeable (#4701)
Signed-off-by: Paul Schroeder <milkpirate@users.noreply.github.com>
2025-01-20 21:51:05 +01:00
vaaski 4f39be9c3b targets: esp32c3-supermini (#4518) 2025-01-20 21:44:58 +01:00
Scott Feldman 7305a44f0c targets: add support for Elecrow Pico rp2350 W5 boards (#4706)
https://www.elecrow.com/pico-w5-microcontroller-development-boards-rp2350-microcontroller-board.html

Just the basics to get several test to work (blinky1, flash).

This board has an rtl8720d Wifi/bluetooth chip wired to UART1, but the
rtl8720d firmware installed is the AT cmd set, not the RPC interface
used by the rtl8720dn driver, so no wifi support at the moment.

---------

Co-authored-by: Yurii Soldak <ysoldak@gmail.com>
2025-01-20 15:36:03 +01:00
Scott Feldman 74effd2fa9 targets: add support for Elecrow Pico rp2040 W5 boards (#4705)
https://www.elecrow.com/pico-w5-microcontroller-development-boards-rp2040-microcontroller-board-support-wifi-2-4ghz-5ghz-bluetooth5.html

Just the basics to get several test to work (blinky1, flash).

This board has an rtl8720d Wifi/bluetooth chip wired to UART1, but the
rtl8720d firmware installed is the AT cmd set, not the RPC interface
used by the rtl8720dn driver, so no wifi support at the moment.
2025-01-20 13:48:51 +01:00
Ayke van Laethem 9e9768b51d all: add support for LLVM 19 2025-01-20 06:15:33 +01:00
Roman Grudzinski 127557d27e Fix ADC channel selecting and ADC value reading 2025-01-17 09:18:30 +01:00
Roman Grudzinski fd89e9b83a Fix stm32f103 ADC (#4702)
fix: Fix stm32f103 ADC
2025-01-16 10:06:22 +01:00
Ayke van Laethem 5a1b885024 sync: move Mutex to internal/task
The mutex implementation needs a different implementation once support
for threading lands. This implementation just moves code to the
internal/task package to centralize these algorithms.
2025-01-14 11:11:15 +01:00
Volodymyr Pobochii b15adf23f8 machine: add support for waveshare-rp2040-tiny (#4683) 2025-01-14 01:53:40 +01:00
Yurii Soldak 29d2719bad example: naive debouncing for pininterrupt example (#2233) 2025-01-13 13:21:23 -03:00
deadprogram 194438cdd6 fix: correctly handle calls for GetRNG() when being made from nrf devices with SoftDevice enabled.
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-01-12 16:44:35 +01:00
Scott Feldman 217f677bbe crypto/tls: add Dialer.DialContext() to fix websocket client
The latest golang.org/x/net websocket package v0.33.0 needs
Dialer.DailContext in crypto/tls.  This PR adds it.

Apps using golang.org/x/net are encouraged to use v0.33.0 to address:

CVE-2024-45338: Non-linear parsing of case-insensitive content in golang.org/x/net/html
CVE-2023-45288: net/http, x/net/http2: close connections when receiving too many headers

Tested with examples/net/websocket/dial.
2025-01-06 12:24:28 +01:00
Elliott Sales de Andrade 16b0f4cc9a builder: Fix parsing of external ld.lld error messages
If `ld.lld` is a version-specific binary (e.g., `ld.lld-18`), then its
error messages include the version. The parsing previously incorrectly
assumed it would be unversioned.
2025-01-05 13:44:56 +01:00
Elliott Sales de Andrade ff15b474fd Remove unnecessary executable permissions
These files are plain text and have no shebang.
2025-01-04 10:08:49 +01:00
sago35 3efc6340ad main: update to use Get-CimInstance as wmic is being deprecated 2025-01-04 08:27:58 +01:00
sago35 0426a5f902 goenv: update to new v0.36.0 development version 2024-12-26 12:25:20 +01:00
soypat b898916d52 rp2350 cleanup: unexport internal USB and clock package variable, consts and types 2024-12-26 10:49:48 +01:00
Ayke van Laethem 52983794d7 all: version 0.35.0 2024-12-20 12:09:22 +01:00
Ayke van Laethem 9d2f52805b builder: show files in size report table
Show which files cause a binary size increase. This makes it easier to
see where the size is going: for example, this makes it easy to see how
much the GC contributes to code size compared to other runtime parts.
2024-12-19 15:08:37 +01:00
Ayke van Laethem b18213805a builder: write HTML size report
This is not a big change over the existing size report with -size=full,
but it is a bit more readable.

More information will be added in subsequent commits.
2024-12-19 15:08:37 +01:00
Thomas Legris eeba90fd5b properly handle unix read on directory 2024-12-19 13:44:11 +01:00
deadprogram 6507765883 feature: make RNG implementation shared for rp2040/rp2350
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-19 12:54:25 +01:00
Ayke van Laethem a98e35ebab reflect: fix incorrect comment on elemType
PR that introduced this: https://github.com/tinygo-org/tinygo/pull/4543
2024-12-19 11:17:26 +01:00
deadprogram c4cfc01ba3 targets: add support for Pimoroni Tiny2350 board
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-19 10:12:57 +01:00
deadprogram f64e70e659 feature: make SPI implementation shared for rp2040/rp2350
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-19 08:01:36 +01:00
deadprogram 64fa7853a7 feature: make i2c implementation shared for rp2040/rp2350
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-18 21:16:07 +01:00
Patricio Whittingslow 37f35f8c91 Add RP2350 support (#4459)
machine/rp2350: add support

* add linker scripts for rp2350
* add bootloader
* begin melding rp2040 and rp2350 APIs
* add UART
* add rp2350 boot patching
* Fix RP2350 memory layout (#4626)
* Remove rp2040-style second stage bootloader.
* Add 'minimum viable' IMAGE_DEF embedded block
* Create a pico2 specific target
* Implement rp2350 init, clock, and uart support
* Merge rp2 reset code back together
* Separate chip-specific clock definitions
* Clear pad isolation bit on rp2350
* Init UART in rp2350 runtime
* Correct usb/serial initialization order
* Implement jump-to-bootloader
* test: add pico2 to smoketests

---------

Signed-off-by: deadprogram <ron@hybridgroup.com>
Co-authored-by: Matthew Mets <matt.mets@cibomahto.com>
Co-authored-by: Matt Mets <matt@blinkinlabs.com>
Co-authored-by: deadprogram <ron@hybridgroup.com>
2024-12-18 19:36:30 +01:00
deadprogram 0d13e61d0c fix: add build tags to ensure that tkey target has stubs for runtime/interrupt package
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-18 17:48:55 +01:00
deadprogram 5701bf81f3 feature: modify i2s interface/implementation to better match specification
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-18 15:23:00 +01:00
Ayke van Laethem 6110f0bc1b runtime: make channels parallelism-safe 2024-12-16 17:58:00 +01:00
Ron Evans 17302ca762 targets: add implementation for Tillitis TKey device (#4631)
* initial implementation for Tillitis TKey device
* add UART implementation for TKey
* add Pin interface implementation for TKey touch sensor
* add RNG interface implementation for TKey
* add helpful machine package functions to return identifiers such as name and version for TKey
* use built-in timer for sleep timing on TKey
* modify UART implementation for TKey to implement Serialer interface
* implement BLAKE2s ROM function call for TKey device
* handle abort by triggering TKey device fault using illegal instruction to halt CPU
* simplify TKey implementation by inheriting from existing riscv32 target
* return error for trying to configure invalid baudrates on UART
* add tkey to builder test
* be very specific for features passed to LLVM for specific config in use for TKey
* handle feedback items from TKey device code review

Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-14 14:26:03 +01:00
Ayke van Laethem f246599253 compiler: report error instead of crashing on missing function body
This can happen with generic functions, see:
https://github.com/tinygo-org/tinygo/issues/4486
2024-12-14 13:34:58 +01:00
deadprogram ec3f387f21 fix: specify ubuntu-22.04 during GH actions transition period to ubuntu-24.04
See https://github.com/actions/runner-images/issues/10636

Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-09 20:26:06 +01:00
Ayke van Laethem 31f7214156 test: make tests deterministic with -scheduler=threads 2024-12-06 11:55:34 +01:00
Ayke van Laethem 6faf36fc64 sync: make Cond MT-safe
This actually simplifies the code and avoids a heap allocation in the
call to Wait. Instead, it uses the Data field of the task to store
information on whether a task was signalled early.
2024-12-06 11:04:14 +01:00
deadprogram edb2f2a417 make: modify smoketest for nintendoswitch target to build something that includes the 'os' package
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-04 15:53:49 +01:00
deadprogram 3eee686932 fix: allow nintendoswitch target to compile
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-12-04 15:53:49 +01:00
Ayke van Laethem 4aac3cd7b1 sync: implement WaitGroup using a futex
This prepares sync.WaitGroup for multithreading.
Code size for the cooperative scheduler is nearly unchanged.
2024-12-04 11:13:35 +01:00
Ayke van Laethem 2588bf7fa0 internal/task: add cooperative implementation of Futex
See the code comments for details. But in short, this implements a futex
for the cooperative scheduler (that is single threaded and
non-reentrant). Similar implementations can be made for basically every
other operating system, and even WebAssembly with the threading
(actually: atomics) proposal.
Using this basic futex implementation means we can use the same
implementation for synchronisation primitives on cooperative and
multicore systems.

For more information on futex across operating systems:
https://outerproduct.net/futex-dictionary.html
2024-12-04 10:12:55 +01:00
Ayke van Laethem 72f564555e internal/task: add non-atomic atomic operations
This adds some non-atomic types that have the same interface as the ones
in sync/atomic.

We currently don't need these to be atomic (because the scheduler is
entirely cooperative), but once we add support for a scheduler with
multiple threads and/or preemptive scheduling we can trivially add some
type aliases under a different build tag in the future when real
atomicity is needed for threading.
2024-12-04 10:12:52 +01:00
Ayke van Laethem b5a8931fb5 runtime: remove Cond
I don't think this is used anywhere right now, and it would need to be
updated to work with multithreading. So instead of fixing it, I think we
can remove it.

My original intention was to have something like this that could be used
in the machine package, but since this is in the runtime package (and
the runtime package imports the machine package on baremetal) it can't
actually be used that way.

I checked the TinyGo repo and the drivers repo, and `runtime.Cond` isn't
used anywhere except in that one test.
2024-12-04 09:43:10 +01:00
Ayke van Laethem d3810ecd48 ci: cache the Go cache across builds
This should hopefully make the build slightly faster.
2024-12-04 06:58:04 +01:00
Ayke van Laethem 3b8062170c mips: fix a bug when scanning the stack
Previously the assembler was reordering this code:

    jal tinygo_scanstack
    move $a0, $sp

Into this:

    jal tinygo_scanstack
    nop
    move $a0, $sp

So it was "helpfully" inserting a branch delay slot, even though this
was already being taken care of.
Somehow this didn't break, but it does break in the WIP threading branch
(https://github.com/tinygo-org/tinygo/pull/4559) where this bug leads to
a crash.
2024-12-01 11:23:27 +01:00
Ayke van Laethem 26c36d0a2e runtime: lock output in print/println
This ensures that calls to print/println happening in different threads
are not interleaved. It's a task.PMutex, so this should only change
things when threading is used.

This matches the Go compiler, which does the same thing:
https://godbolt.org/z/na5KzE7en

The locks are not recursive, which means that we need to be careful to
not call `print` or `println` inside a runtime.print* implementation,
inside putchar (recursively), and inside signal handlers. Making them
recursive might be useful to do in the future, but it's not really
necessary.
2024-12-01 11:12:00 +01:00
Ayke van Laethem 09a22ac4b4 runtime: make signals parallelism-safe 2024-12-01 07:40:22 +01:00
Ayke van Laethem aed555d858 runtime: implement Goexit
This is needed for full support for the testing package
2024-11-30 11:55:22 +01:00
deadprogram 65b085a5d5 examples: use default UART settings in echo example
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-11-29 11:33:45 +01:00
Ayke van Laethem 392a709b77 runtime: use uint32 for the channel state and select index
This uses uint32 instead of uint64. The reason for this is that uint64
atomic operations aren't universally available (especially on 32-bit
architectures). We could also use uintptr, but that seems needlessly
complicated: it's unlikely real-world programs will use more than a
billion select states (2^30).
2024-11-27 12:16:10 +01:00
Ayke van Laethem ee6fcd76f4 builder: add testing for -size=full
This helps to make sure this feature continues to work and we won't
accidentally introduce regressions.
2024-11-26 12:41:12 +01:00
Ayke van Laethem ca80c52df1 builder: fix wasi-libc path names on Windows with -size=full
Without this fix, wasi-libc is listed as follows:

     65       0       0       0 |      65       0 | C:\Users\Ayke\src\tinygo\tinygo\lib\wasi-libc\libc-bottom-half\sources
     14       0       0       0 |      14       0 | C:\Users\Ayke\src\tinygo\tinygo\lib\wasi-libc\libc-top-half\musl\src\exit
   1398       0       0       0 |    1398       0 | C:\Users\Ayke\src\tinygo\tinygo\lib\wasi-libc\libc-top-half\musl\src\string
   1525       0       0       0 |    1525       0 | C:\Users\Ayke\src\tinygo\tinygo\lib\wasi-libc\libc-top-half\sources

With this fix, it's identified as the wasi-libc C library:

   3002       0       0       0 |    3002       0 | C wasi-libc
2024-11-26 12:41:12 +01:00
Ayke van Laethem b76ea29520 builder: work around bug in DWARF paths in Clang
See bug: https://github.com/llvm/llvm-project/issues/117317
2024-11-26 12:41:12 +01:00
Ayke van Laethem 9172cc15d2 builder: fix cache paths in -size=full output
This fixes long paths from the TinyGo cached GOROOT, as can be seen
here:

   code  rodata    data     bss |   flash     ram | package
------------------------------- | --------------- | -------
      0       5       0       5 |       5       5 | (padding)
    148       0       0       5 |     148       5 | (unknown)
     76       0       0       0 |      76       0 | /home/ayke/.cache/tinygo/goroot-ce8827882be9dc201bed279a631881177ae124ea064510684a3cf4bb66436e1a/src/device/arm
      4       0       0       0 |       4       0 | /home/ayke/.cache/tinygo/goroot-ce8827882be9dc201bed279a631881177ae124ea064510684a3cf4bb66436e1a/src/internal/task

They're now attributed to the correct package instead (device/arm and
internal/task).
2024-11-26 12:41:12 +01:00
Ayke van Laethem 1b83d43cfa cgo: fix build warnings on Windows ARM
Fix the warning, and also remove tinygo_clang_enum_visitor which was
unused.

See: https://github.com/golang/go/issues/49721
2024-11-26 09:30:13 +01:00
Matt Mets 7847f4ea8e Fix invalid assembler syntax from gen-device-svd
This addresses #4608
2024-11-22 14:44:27 +01:00
Matt Mets 19736e5be2 Update cmsis-svd library
This updates the version of the cmsis-svd library, to include a version
that supports rp2350. This is in support of #4452
2024-11-22 14:44:27 +01:00
Ayke van Laethem 51504bfd2e sync: make Pool thread-safe
Make sure the object is locked when trying to modify it.
Binary size seems unaffected when not using threading.
2024-11-22 11:55:52 +01:00
Ayke van Laethem 79164dae71 sync: only use a lock in the Map implementation when needed 2024-11-22 09:42:39 +01:00
Ayke van Laethem 8d04821639 runtime: prepare the leaking GC for concurrent operations
This uses the task.PMutex parallel-only-mutex type to make the leaking
GC parallelism safe. The task.PMutex type is currently a no-op but will
become a real mutex once we add true parallelism.
2024-11-22 08:17:35 +01:00
Ayke van Laethem f75187392d internal/task: implement PMutex
PMutex is a mutex when threading is possible, and a dummy mutex-like
object (that doesn't do anything) otherwise.
2024-11-22 08:17:35 +01:00
Ayke van Laethem ecc6d16f22 interp: align created globals
Use the alignment from the align attribute of the runtime.alloc call.
This is going to be a more accurate alignment, and is typically smaller
than the default.
2024-11-21 10:19:19 +01:00
Ayke van Laethem 5f252b3e16 runtime: fix regression introduced by merging conflicting PRs 2024-11-21 09:37:13 +01:00
Ayke van Laethem dd1ebbd31b runtime: implement race-free signals using futexes
This requires an API introduced in MacOS 11. I think that's fine, since
the version before that (MacOS 10.15) is EOL since 2022. Though if
needed, we could certainly work around it by using an older and slightly
less nice API.
2024-11-20 18:50:34 +01:00
Ayke van Laethem 95671469c7 runtime: use SA_RESTART when registering a signal
This really is the only sane way to register a signal. If this flag is
not set, many syscalls will return EINTR (and not complete their
operation) which will be a massive source of hard-to-debug bugs.
2024-11-20 18:50:34 +01:00
deadprogram 6601c1b1a6 fix: add updated test output to match recent changes
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-11-20 17:55:04 +01:00
Ayke van Laethem 5ebda89d78 runtime: rewrite channel implementation
This rewrite simplifies the channel implementation considerably, with
34% less LOC. Perhaps the most important change is the removal of the
channel state, which made sense when we had only send and receive
operations but only makes things more compliated when multiple select
operations can be pending on a single channel.

I did this rewrite originally to make it possible to make channels
parallelism-safe. The current implementation is not parallelism-safe,
but it will be easy to make it so (the main additions will be a channel
lock, a global select lock, and an atomic compare-and-swap in
chanQueue.pop).
2024-11-20 14:57:30 +01:00
Ayke van Laethem b7a3fd8d2f cgo: add support for #cgo noescape lines
Here is the proposal:
https://github.com/golang/go/issues/56378

They are documented here:
https://pkg.go.dev/cmd/cgo@master#hdr-Optimizing_calls_of_C_code

This would have been very useful to fix
https://github.com/tinygo-org/bluetooth/issues/176 in a nice way. That
bug is now fixed in a different way using a wrapper function, but once
this new noescape pragma gets included in TinyGo we could remove the
workaround and use `#cgo noescape` instead.
2024-11-20 14:07:55 +01:00
Ayke van Laethem fd625f7265 compiler: add //go:noescape pragma
This only works on declarations, not definitions. This is intentional:
it follows the upstream Go implemetation.

However, we might want to loosen this requirement at some point: TinyGo
sometimes stores pointers in memory mapped I/O knowing they won't
actually escape, but the compiler doesn't know about this.
2024-11-20 14:07:55 +01:00
Ayke van Laethem d1fe02df23 runtime: move scheduler code around
This moves all scheduler code into a separate file that is only compiled
when there's a scheduler in use (the tasks or asyncify scheduler, which
are both cooperative). The main goal of this change is to make it easier
to add a new "scheduler" based on OS threads.

It also fixes a few subtle issues with `-gc=none`:

  - Gosched() panicked. This is now fixed to just return immediately
    (the only logical thing to do when there's only one goroutine).
  - Timers aren't supported without a scheduler, but the relevant code
    was still present and would happily add a timer to the queue. It
    just never ran. So now it exits with a runtime error, similar to any
    blocking operation.
2024-11-20 12:45:09 +01:00
Ayke van Laethem 6593cf22fa cgo: support errno value as second return parameter
Making this work on all targets was interesting but there's now a test
in place to make sure this works on all targets that have the CGo test
enabled (which is almost all targets).
2024-11-20 07:53:59 +01:00
Damian Gryski 548fba82e6 compiler: Fix wasmimport -> wasmexport in error message
Fixes #4615
2024-11-20 07:53:02 +01:00
Ayke van Laethem 2d26b6cc8d windows: don't return, exit via exit(0) instead
This fixes a bug where output would not actually be written to stdout
before exiting the process, leading to a flaky Windows CI. Exiting using
`exit(0)` appears to fix this.

For some background, see: https://github.com/tinygo-org/tinygo/pull/4589
2024-11-19 11:58:07 +01:00
Ayke van Laethem 0087d4c6bf syscall: use wasi-libc tables for wasm/js target
Instead of using fake tables for errno and others, use the ones that
correspond to wasi-libc.
2024-11-19 07:51:58 +01:00
Ayke van Laethem 289fceb3ea syscall: refactor environment handling
* Move environment functions to their own files.
  * Rewrite the WASIp2 version of environment variables to be much
    simpler (don't go through C functions).
2024-11-19 07:51:58 +01:00
Ayke van Laethem e12da15f7d cgo: support function-like macros
This is needed for code like this:

    #define __WASI_ERRNO_INVAL (UINT16_C(28))
    #define EINVAL __WASI_ERRNO_INVAL
2024-11-18 18:35:20 +01:00
Ayke van Laethem c4867c8743 cgo: define idents referenced only from macros 2024-11-18 18:35:20 +01:00
Ayke van Laethem 8068419854 runtime: heapptr only needs to be initialized once
There is no need to initialize it twice.
2024-11-18 17:14:55 +01:00
Ayke van Laethem 9b3eb3fe59 ci: run at least some tests on older Go/LLVM versions
These should make sure basic functionality is still working.
Using the `-short` flag to avoid taking too long to run all tests (and
to install all the necessary emulators), and because some targets might
not work in older Go/LLVM versions (such as WASI).

This does _not_ run tests and checks against expected IR, because LLVM
IR changes a lot across versions.
2024-11-18 16:42:14 +01:00
leongross 1dcccf87b5 linux: add runtime.fcntl function
This is needed for the internal/syscall/unix package.

Signed-off-by: leongross <leon.gross@9elements.com>
2024-11-18 14:44:06 +01:00
Ayke van Laethem d51ef253a9 builder: whitelist temporary directory env var for Clang invocation
It looks like this breaks on Windows:
https://github.com/tinygo-org/tinygo/issues/4557
I haven't confirmed this is indeed the problem, but it would make sense.
And passing through the temporary directory seems like a good idea
regardless, there's not much that could break due to that.
2024-11-15 18:27:48 +01:00
Ayke van Laethem 6d4dfcf72f compiler, runtime: move constants into shared package
Use a single package for certain constants that must be the same between
the compiler and the runtime.

While just using the same values in both places works, this is much more
obvious and harder to mess up. It also avoids the need for comments
pointing to the other location the constant is defined. And having it in
code makes it possible for IDEs to analyze the source.

In the future, more such constants and maybe algorithms can be added.
2024-11-15 10:11:57 +01:00
sivchari ac9f72be61 support to parse devl version
Signed-off-by: sivchari <shibuuuu5@gmail.com>
2024-11-15 09:21:47 +01:00
Ayke van Laethem 258dac2324 wasm: tidy up wasm_exec.js a bit 2024-11-14 11:02:54 -08:00
Ayke van Laethem b7d91e2f33 ci: use TinyGo version in artifact files
This avoids needing to rename them ourselves (which is kinda annoying)
and also avoids mistakes in the process.
2024-11-14 10:38:56 +01:00
Ayke van Laethem 860697257b runtime: optimize findHead
This is similar to https://github.com/tinygo-org/tinygo/pull/3899, but
smaller and hopefully just as efficient.

Thanks to @HattoriHanzo031 for starting this work, benchmarking, and for
improving the performance of the code even further.
2024-11-14 09:28:25 +01:00
Damian Gryski 91563cff1f targets/wasm_exec: call process.exit() when go.run() returns 2024-11-14 09:16:25 +01:00
Ben Krieger 4f96a50fd0 reflect: fix Copy of non-pointer array with size > 64bits 2024-11-13 10:28:33 -07:00
Ben Krieger e98fea0bba reflect: add Value.Clear; support anytype->interface{}, Slice->(*)Array in Value.Convert 2024-11-13 10:28:33 -07:00
Ayke van Laethem c728e031df goenv: read git hash embedded in the binary
The git hash that's part of `tinygo version` is now read from the binary
itself instead of embedding it with a `-ldflags` flag. This means it is
also present when building TinyGo using `go build` or `go install`.
2024-11-10 08:59:22 +01:00
Ayke van Laethem ceb7891986 wasm: correctly return from run() in wasm_exec.js
Instead of hanging forever, it should return the exit code from os.Exit.
2024-11-08 11:55:38 +01:00
Ayke van Laethem 04a7baec3e wasm: support //go:wasmexport functions after a call to time.Sleep
This fixes a bug where `//go:wasmexport` functions would not be allowed
anymore after a call to `time.Sleep` (when using `-buildmode=default`).
2024-11-08 11:55:38 +01:00
Ayke van Laethem 8ff97bdedd runtime: remove unnecessary check for negative sleepTicks duration
This is now fixed for every target in the previous commit.

Also see: https://github.com/tinygo-org/tinygo/pull/4239
2024-11-07 15:37:18 +01:00
Ayke van Laethem a6c4287b4d runtime: don't call sleepTicks with a negative duration
There are rare cases where this can happen, see for example
https://github.com/tinygo-org/tinygo/issues/4568
2024-11-07 15:37:18 +01:00
leongross f9f439ad49 os: implement StartProcess
Signed-off-by: leongross <leon.gross@9elements.com>
2024-11-07 09:45:47 +01:00
Randy Reddig c02a8141c7 internal/wasm-tools, syscall: update to wasm-tools-go@v0.3.1 (#4577)
* internal/wasm-tools, internal/cm: update wasm-tools-go to v0.3.1 and regenerate bindings

* syscall: use new (cm.Result).Result() method instead of OK() and Err()
2024-11-04 14:32:17 -08:00
sago35 5862b481a4 goenv: update to new v0.35.0 development version 2024-11-01 09:14:09 +01:00
Joonas Bergius 1648fe8ef2 runtime/trace: stub all public methods
Signed-off-by: Joonas Bergius <joonas@cosmonic.com>
2024-11-01 09:12:59 +01:00
Ayke van Laethem 449eefdb19 compiler: allow deferred panic
This is rare, but apparently some programs do this:

    defer panic("...")

This is emitted in the IR as a builtin function.
2024-11-01 09:11:38 +01:00
Ayke van Laethem 058f62ac08 main: parse extldflags early so we can report the error message
This avoids some weird behavior when the -extldflags flag cannot be
parsed by TinyGo.
2024-11-01 09:10:49 +01:00
Ayke van Laethem 4e49ba597d interrupt: fix bug in interrupt lowering
The alignment wasn't set, so defaulted to 4 (for a 32-bit int). LLVM saw
this, and therefore assumed that a ptrtoint of the pointer would have
had the lowest bits unset. That's an entirely valid optimization, except
that we are using these globals for arbitrary values (and aren't
actually using these globals).

Fixed by setting alignment to 1. It works, though long-term we should
maybe find a different solution for this.
2024-11-01 09:10:25 +01:00
Ayke van Laethem 4b706ae25c test: show output even when a test binary didn't exit cleanly
This was a problem on wasm, where node would exit with a non-zero exit
code when there was a panic.
2024-11-01 08:49:00 +01:00
Ayke van Laethem 1ac26d3d2f test: run TestWasmExportJS tests in parallel 2024-11-01 08:48:19 +01:00
Randy Reddig 0edeaf657f tinygo: revise and simplify wasmtime argument handling (#4555) 2024-10-28 17:57:24 +01:00
Ayke van Laethem 76d5b3d786 sync: don't use volatile in Mutex
Volatile loads/stors are only useful for communication with interrupts
or for memory-mapped I/O. They do not provide any sort of safety for
sync.Mutex, while making it *appear* as if it is more safe.

  * `sync.Mutex` cannot be used safely inside interrupts, because any
    blocking calls (including `Lock`) will cause a runtime panic.
  * For multithreading, `volatile` is also the wrong choice. Atomic
    operations should be used instead, and the current code would not
    work for multithreaded programs anyway.
2024-10-28 16:43:28 +01:00
Ayke van Laethem 915132645e ci: remove 'shell: bash' lines from MacOS build
Unlike Windows, we can just use the default shell here.
2024-10-28 10:22:05 +01:00
Ayke van Laethem 2a76ceb7dd all: version v0.34.0 2024-10-25 18:22:40 +01:00
Ayke van Laethem 69263e7319 GNUmakefile: do not use the -v flag in go test
This makes it easier to find what actually went wrong in CI.
This flag was added in #4431, I think it was unintentional.
2024-10-25 17:01:35 +02:00
Damian Gryski 9a6397b325 runtime: bump markStackSize
Every time we overflow the stack, we have to do a full rescan of the heap.  Making this larger
means fewer overflows and thus fewer secondary+ heap scans.
2024-10-25 16:24:01 +02:00
sago35 b8420e78bb machine/usb/adc/midi: fix PitchBend 2024-10-25 06:25:49 +01:00
sago35 f0d523f778 machine/usb/adc/midi: clarify operator precedence 2024-10-25 06:25:49 +01:00
Damian Gryski 6e6507bf77 runtime: add gc layout info for some basic types 2024-10-24 13:07:17 +02:00
Ayke van Laethem b8fe75a9dd runtime: add support for os/signal
This adds support for enabling and listening to signals on Linux and
MacOS.
2024-10-23 12:25:27 +01:00
Ayke van Laethem 0f95b4102d wasm: use precise GC for WebAssembly (including WASI)
With a few small modifications, all the problems with `-gc=precise` in
WebAssembly seem to have been fixed.

I didn't do any performance measurements, but this is supposed to
improve GC performance.
2024-10-23 09:13:30 +01:00
Randy Reddig 24c11d4ba5 compiler: conform to latest iteration of wasm types proposal (#4501)
compiler: align with current wasm types proposal

https://github.com/golang/go/issues/66984

- Remove int and uint as allowed types in params, results, pointers, or struct fields
- Only allow small integers in pointers, arrays, or struct fields
- enforce structs.HostLayout usage per wasm types proposal
https://github.com/golang/go/issues/66984
- require go1.23 for structs.HostLayout
- use an interface to check if GoVersion() exists
This permits TinyGo to compile with Go 1.21.
- use goenv.Compare instead of WantGoVersion
- testdata/wasmexport: use int32 instead of int
- compiler/testdata: add structs.HostLayout
- compiler/testdata: improve tests for structs.HostLayout
2024-10-22 18:05:04 +02:00
Daniel Esteban 3dcac3b539 Add sponsor button to key repositories 2024-10-22 12:32:15 +01:00
Ayke van Laethem e615c25319 targets: add WaveShare ESP-C3-32S-Kit
I've had this board for a while now, but never added proper TinyGo
support. So here is a PR to do just that.
2024-10-22 11:21:48 +01:00
Ayke van Laethem b2fbbeb771 esp32c3: add smoke tests for a few boards
These boards probably haven't been working since the addition of I2C,
because they were missing some constants in the machine package.
2024-10-22 09:23:31 +01:00
Ayke van Laethem bcfe751f62 fe310: support GPIO PinInput
This is needed to support switching between input and output.
2024-10-21 18:30:31 +01:00
Randy Reddig a191326ea8 goenv: parse patch version, add func Compare to compare two Go version strings (#4536)
goenv: parse patch version, add func Compare to compare two Go version strings
* Parse tests
* add Compare function to compare two Go version strings
* goenv, builder: parse patch version in Go version string
2024-10-21 16:01:59 +02:00
Damian Gryski 23d3a31107 runtime: use unsafe.Slice for leveldb code 2024-10-19 15:16:30 -07:00
Damian Gryski 0dfa57ea04 runtime: use unsafe.Slice in tsip code 2024-10-19 15:16:30 -07:00
Ayke van Laethem 2f9e39e21c runtime: remove minSched hack for wasm
I am not entirely sure what it's doing (it seems related to js.FuncOf),
but tests still seem to pass when this code is removed. So let's remove
it.
2024-10-19 16:00:45 +01:00
Ayke van Laethem cd2bb8333d wasm: add test for js.FuncOf
While there are some browser tests, Node.js is just a lot better for
testing this kind of stuff because it's much faster and we don't need a
browser for this.
2024-10-19 16:00:45 +01:00
Ayke van Laethem 5e3c816373 ci: use macos-13 instead of macos-12 for amd64 builds
The macos-12 runner is being deprecated, so we have to switch to a new
runner: https://github.com/actions/runner-images/issues/10721

The next one is macos-13, which is still amd64.
2024-10-19 13:36:55 +01:00
Damian Gryski 951e50c06f compiler: mark stringFromRunes as nocapture/readonly 2024-10-19 11:02:54 +01:00
Damian Gryski 40c9c66c1d compiler: mark stringFromBytes as nocapture/readonly to help escape analysis
Fixes #4525
2024-10-19 11:02:54 +01:00
leongross 01dac8ba8e os/file_unix: add runtime function net.NewFile stub
Signed-off-by: leongross <leon.gross@9elements.com>
2024-10-18 18:37:49 +01:00
Ayke van Laethem ac5f84e3d7 builder: check for Go toolchain version used to compile TinyGo
This shows a much better error message for issues like this one:
https://github.com/NixOS/nixpkgs/pull/341170#issuecomment-2359237471

The new error message would be:

    cannot compile with Go toolchain version go1.23 (TinyGo was built using toolchain version go1.21.4)
2024-10-18 17:43:17 +02:00
Ayke van Laethem 9583439be4 loader: make sure we always return an error even without type errors
This issue was originally reported here:
https://github.com/NixOS/nixpkgs/pull/341170#issuecomment-2359237471

The fix here isn't a great fix, it turns the error message from this:

    # runtime/interrupt

into this:

    # runtime/interrupt
    package requires newer Go version go1.23

...so not great, because it doesn't show the real error message (which
is that TinyGo wasn't compiled with the right Go version). But at least
it gives a hint in the right direction.

It's difficult to test for this specific case, so I've left out testing
in this case (boo!)
2024-10-18 17:43:17 +02:00
Ayke van Laethem 2690b243ea main: make sure typecheck errors are correctly reported 2024-10-18 17:43:17 +02:00
Ayke van Laethem df724f5827 loader: don't panic when main package is not named 'main'
This can in fact happen in practice, so return an actual error message
instead.
2024-10-18 17:43:17 +02:00
Elias Naur 539cc5c47b transform: optimize range over []byte(string)
Fixes #2700
2024-10-18 17:42:20 +02:00
Ayke van Laethem 45cc5b58cd runtime: disallow defer in interrupts
This often doesn't work because there might not be a current task to
push the defer frame to. It will instead show an unhelpful nil pointer
dereference panic.

We could make this work with a separate defer stack for interrupts (as
if they were newly started goroutines) but that is difficult with
multiple interrupts happening at the same time (we shouldn't jump to a
previous interrupt in `panic()`!). So instead, disable defer altogether
in interrupts and adjust panic/recover accordingly.
2024-10-18 14:50:56 +01:00
Ayke van Laethem c6acaa981d builder: remove environment variables when invoking Clang
This is a problem on Guix, which sets C_INCLUDE_PATH that is not
affected by `-nostdlibinc`. And therefore it affects the build in
unintended ways.

Removing all environmental variables fixes this issue, and perhaps also
other issues caused by Clang being affected by environment variables.
2024-10-18 13:42:02 +01:00
Ayke van Laethem 4ef5109a07 wasm: add //go:wasmexport support to js/wasm
This adds support for //go:wasmexport with `-target=wasm` (in the
browser). This follows the //go:wasmexport proposal, meaning that
blocking functions are not allowed.

Both `-buildmode=default` and `-buildmode=c-shared` are supported. The
latter allows calling exported functions after `go.run()` has returned.
2024-10-18 10:07:21 +01:00
Ayke van Laethem 6016d0c739 main_test: refactor output comparison into separate function
This shouldn't affect anything, just make the code a bit better
(especially for the next commit).
2024-10-18 10:07:21 +01:00
Elias Naur 07d23c9d83 runtime: implement newcoro, coroswitch to support package iter 2024-10-18 10:44:20 +02:00
Randy Reddig d5f195387d internal/{cm,wasi}: regenerate WASI 0.2 bindings with wasm-tools-go v0.3.0 2024-10-17 17:30:33 +01:00
Randy Reddig a0d4ecb607 internal/wasm-tools: update wasm-tools-go to v0.3.0 2024-10-17 17:30:33 +01:00
Ayke van Laethem 505e68057d nix: use LLVM 18 instead of LLVM 17
This should fix some CI issues we're currently having.

Thanks to @sylv-io for discovering that we need to remove LLVM to avoid
an Xtensa backend linker error.
2024-10-17 14:21:58 +01:00
Damian Gryski 87c6e19921 runtime: add HeapAlloc to gc_leaking 2024-10-09 07:01:09 -07:00
deadprogram 62c1555aa8 targets: add bulk memory flags to wasm-unknown target since basically every runtime has it now
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-10-09 08:18:58 +01:00
Elias Naur e62fc43b05 crypto/x509/internal/macos: add package stub to build crypto/x509 on macOS 2024-10-08 08:54:35 +01:00
Damian Gryski 158be02ef7 builder: fix sizes 2024-10-07 19:23:49 -07:00
Damian Gryski fbb125131d runtime: track Memstats.HeapAlloc for gc_blocks 2024-10-07 19:23:49 -07:00
BCG c77ed8e50e Added mstats fields 2024-10-07 19:23:49 -07:00
Ayke d1b7238a36 Truly ignore //export when //go:wasmexport is used (#4500) 2024-10-05 18:53:38 +02:00
Randy Reddig 453a1d35c3 compiler, runtime: enable go:wasmexport for wasip2 (#4499)
* compiler: prefer go:wasmexport over go:export

* runtime, targets/wasip2: enable -buildmode=c-shared for wasip2

* runtime: rename import from wasi_run to wasiclirun (PR feedback)
2024-10-04 17:36:47 -07:00
Ayke 9da8b5c786 wasm: add //go:wasmexport support (#4451)
This adds support for the `//go:wasmexport` pragma as proposed here:
https://github.com/golang/go/issues/65199

It is currently implemented only for wasip1 and wasm-unknown, but it is
certainly possible to extend it to other targets like GOOS=js and
wasip2.
2024-10-04 15:33:47 -07:00
Damian Gryski 407889864f GNUmakefile: more stdlib packages 2024-10-04 08:09:10 +01:00
Damian Gryski e17daf165d GNUmakefile: add some more passing stdlib tests (#4492) 2024-10-03 16:03:08 -07:00
Ayke van Laethem 666d2bd501 builder: keep wasm temporary files
Don't rename them when -work is set, instead update result.Binary each
time and leave result.Executable be the linker output (as intended:
result.Executable should be the unmodified linker output).
2024-10-03 19:17:12 +01:00
Damian Gryski 9d14489547 TestWebAssembly: use wasm-unknown for panic=trap test 2024-10-02 12:40:07 +02:00
Damian Gryski f3dfe1d49e runtime: seed fastrand() with hardware randomness 2024-10-02 12:40:07 +02:00
Damian Gryski b3e1974c30 runtime: add maps.clone
Fixes #4382
2024-10-02 12:40:07 +02:00
Damian Gryski fa12450552 runtime: fix building with -tags=runtime_memhash_tsip 2024-10-02 12:40:07 +02:00
Damian Gryski b3c040e9f7 runtime: make map iteration less defined
Fixes #3726
2024-10-02 12:40:07 +02:00
leongross 52788e5826 main: rework usage (#4467)
main: rework usage

* remove unused switch case statement and improve/add command specific usage.
* limit help to 80 col width
* remove inconsistent ':'
* remove trailing spaces
* rmove spaces woth tabs
* reworkd build command

Signed-off-by: leongross <leon.gross@9elements.com>
2024-09-28 21:33:18 +02:00
leongross bcd4c6b658 builder: nits
remove unused job state enum, nits/reformatting

Signed-off-by: leongross <leon.gross@9elements.com>
2024-09-24 17:42:30 +01:00
Ayke van Laethem 37460ad60a compiler: support pragmas on generic functions 2024-09-23 09:41:44 +01:00
Ayke van Laethem dcca47f1f6 main: add -ldflags='-extldflags=...' support
This matches upstream Go. Example:

    $ go test -ldflags='-extldflags=-foobar' os
    # os.test
    /usr/local/go1.23.1/pkg/tool/linux_arm64/link: running gcc failed: exit status 1
    /usr/bin/gcc -s -o $WORK/b001/os.test -rdynamic /tmp/go-link-914594215/go.o /tmp/go-link-914594215/000000.o /tmp/go-link-914594215/000001.o /tmp/go-link-914594215/000002.o /tmp/go-link-914594215/000003.o /tmp/go-link-914594215/000004.o /tmp/go-link-914594215/000005.o /tmp/go-link-914594215/000006.o /tmp/go-link-914594215/000007.o /tmp/go-link-914594215/000008.o /tmp/go-link-914594215/000009.o /tmp/go-link-914594215/000010.o /tmp/go-link-914594215/000011.o /tmp/go-link-914594215/000012.o /tmp/go-link-914594215/000013.o /tmp/go-link-914594215/000014.o /tmp/go-link-914594215/000015.o /tmp/go-link-914594215/000016.o /tmp/go-link-914594215/000017.o /tmp/go-link-914594215/000018.o /tmp/go-link-914594215/000019.o /tmp/go-link-914594215/000020.o /tmp/go-link-914594215/000021.o -O2 -g -O2 -g -lresolv -O2 -g -lpthread -foobar
    gcc: error: unrecognized command-line option ‘-foobar’

    FAIL    os [build failed]
    FAIL

And TinyGo, with this patch:

    $ tinygo test -ldflags='-extldflags=-foobar' os
    FAIL    os      0.000s
    ld.lld: error: unknown argument '-foobar'

Also note that Go doesn't support the `-extldflags` directly (which was
previously the case with TinyGo):

    $ go test -extldflags='-foobar' os
    flag provided but not defined: -extldflags
    [...]
2024-09-18 12:43:05 +02:00
Damian Gryski 892efaec97 support -extldflags
Fixes #4320
2024-09-18 08:05:25 +02:00
leongross 84048f299f os/File: add stubs for os.File Deadlines (#4465)
os/File: add stubs for os.File Deadlines
* add os.SetDeadline, os.SetReadDeadline, os.SetWriteDeadline stubs for
posix files.
* deadline: add tests

Signed-off-by: leongross <leon.gross@9elements.com>
2024-09-17 17:26:22 +02:00
leongross a9bf981d92 Cgo add cbytes implementation (rebased version of #3318) (#4470)
cgo: added CBytes implementation
2024-09-17 16:12:57 +02:00
Randy Reddig d4729f92bd targets/wasip2: add wasmtime -S args to support network interfaces 2024-09-17 11:24:13 +02:00
Randy Reddig 5a014dd6a3 tinygo: add relative and absolute --dir options to wasmtime args (#4431)
main: add relative and absolute --dir options to wasmtime args
2024-09-17 09:24:23 +02:00
Ron Evans d948941d82 governance: add initial documentation for project governance (#4457)
governance: add initial attempt to document project governance

Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-09-13 11:24:10 +02:00
archie2x 5abf1e998d Fix #4421: Add -C DIR flag (#4422)
feature: Fix #4421: Add `-C DIR` flag

Signed-off-by: Roger Standridge <9526806+archie2x@users.noreply.github.com>
2024-09-13 07:05:44 +02:00
deadprogram b5626e70cb submodules: remove separate renesas-svd repo in favor of more recent changes.
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-09-08 15:09:17 +02:00
deadprogram c201faab92 gitignore: ignore device files generated for Renesas
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-09-08 15:09:17 +02:00
deadprogram 2e47a9c5cd gen-device: switch generator for Renesas code to use main cmsis-svd repo 2024-09-08 15:09:17 +02:00
Randy Reddig e13d4ba3d0 GNUmakefile, internal/wasm-tools: s/ydnar/bytecodealliance/g 2024-09-06 11:31:42 +02:00
Randy Reddig 9dcb63ca98 internal/wasi: regenerated with wit-bindgen-go@v0.20 2024-09-06 11:31:42 +02:00
Randy Reddig 78ddc51471 internal/wasm-tools: update wasm-tools-go to new repo and version 2024-09-06 11:31:42 +02:00
Ayke van Laethem c931bc7394 wasip2: do not export the _start function
It seems to have been replaced with the Component Model `run` function.
2024-09-06 08:54:20 +02:00
Warren Guy 1f3e0004a9 add board: RAKwireless RAK4631 (#4454)
targets: add rak4631
2024-09-05 11:49:36 +02:00
Ayke van Laethem d4cb92f27c compiler: fix passing weirdly-padded structs to new goroutines
The values were stored in the passed object as the values itself (not
expanded like is common in the calling convention), and read back after
assuming they were expanded. This often works for simple parameters
(int, pointer, etc), but not for more complex parameters. Especially
when there's padding.

Found this while working on `//go:wasmexport`.
2024-09-05 10:53:33 +02:00
Ayke van Laethem ee5bc65c97 compiler: move some code around to make the next bugfix easier
This just makes the next fix easier to read.
2024-09-05 10:53:33 +02:00
Ayke van Laethem 4f1b69827d reflect: support big-endian systems
The reflect package needs to know the endianness of the system in a few
places. Before this patch, it assumed little-endian systems. But with
GOARCH=mips we now have a big-endian system which also needs to be
supported. So this patch fixes the reflect package to work on big-endian
systems.

Also, I've updated the tests for MIPS: instead of running the
little-endian tests, I've changed it to run the big-endian tests
instead. The two are very similar except for endianness so this should
be fine. To be sure we won't accidentally break little-endian support,
I've kept a single MIPS little-endian test (the CGo test, which doesn't
yet work on big-endian systems anyway).
2024-09-05 10:06:30 +02:00
Ayke van Laethem 73f519b589 interp: support big-endian targets
The interp package was assuming that all targets were little-endian. But
that's not true: we now have a big-endian target (GOARCH=mips).

This fixes the interp package to use the appropriate byte order for a
given target.
2024-09-05 10:06:30 +02:00
Ayke van Laethem 25abfff632 mips: use MIPS32 (instead of MIPS32R2) as the instruction set
This should widen compatibility a bit, so that older CPUs can also
execute programs built by TinyGo. The performance may be lower, if
that's an issue we can look into implementing the proposal here:
https://github.com/golang/go/issues/60072

This still wouldn't make programs usable on MIPS II CPUs, I suppose we
can lower compatiblity down to that CPU if needed.

I tried setting the -cpu flag in the QEMU command line to be able to
test this, but it looks like there are no QEMU CPU models that are
mips32r1 and have a FPU. So it's difficult to test this.
2024-09-05 08:00:03 +02:00
Roger Standridge e39358d0ee stub runtime_{Before,After}Exec for linkage 2024-09-04 23:18:11 +02:00
Ayke van Laethem 105fe9b25d darwin: replace custom syscall package with Go native syscall package
This required a few compiler and runtime tricks to work, but I ran a
bunch of tests and it seems fine. (CI will of course do more exhaustive
testing).

The main benefit here is that we don't need to maintain the darwin
version of the syscall package, and reduce extra risks for bugs (because
we reuse the well-tested syscall package). For example, Go 1.23 needed a
bunch of new constants in the syscall package. That would have been
avoided if we had used the native syscall package on MacOS.
2024-09-04 20:04:25 +02:00
sago35 753f4b38b4 version: update to 0.34.0-dev 2024-09-04 18:04:49 +02:00
deadprogram d144b11611 fix: add missing Truncate() function stub to os/file for bare-metal systems
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-08-26 15:24:51 +02:00
Ayke van Laethem 1ef1aa7862 mips: fix big-endian (GOARCH=mips) support
I made an awkward mistake, mixing up GOOS and GOARCH. So here is a fix,
with an associated test.
2024-08-22 16:36:40 +02:00
Ayke van Laethem 83c98a23ce mips: fix crash with GOMIPS=softfloat
`defer` and `GOMIPS=softfloat` together would result in a crash. This
patch fixes this issue.
2024-08-22 07:59:37 +02:00
Randy Reddig 336b9b33ab tinygo: detect GOOS=wasip1 for relative WASI paths via config instead of target name (#4423) 2024-08-20 17:03:02 -07:00
Ayke van Laethem ef4f46f1d1 all: version 0.33.0 2024-08-20 09:21:48 +02:00
Ayke van Laethem 16cd500000 ci: update apt repo for sizediff toolchain
This was still at jammy (22.04), while the CI container was noble
(24.04). Somehow this didn't break, but it certainly isn't ideal to
install packages across Ubuntu versions!
2024-08-20 08:33:49 +02:00
deadprogram 16950780d3 targets: remove import-memory flag from wasm-unknown target to fix #4319
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-08-17 18:16:39 +02:00
Ayke van Laethem 7e284a37fc ci: use Go 1.23 2024-08-17 11:49:14 +02:00
Ayke van Laethem b6c53a6f0e darwin: work around a linker error for the mime/quotedprintable tests
This is needed for Go 1.23 support.

These functions should ideally get implemented. Until that's done, just
panic here. Apparently panicking in internal/abi.FuncPCABI0 is enough to
fix all linker errors for mime/quotedprintable.
2024-08-17 11:49:14 +02:00
Ayke van Laethem 8b626e6ea7 compiler: add support for Go 1.23 range-over-func 2024-08-17 11:49:14 +02:00
Ayke van Laethem 1d1f4fc401 syscall: add all MacOS errno values
ELOOP is used starting with Go 1.23. But I figured I could just add the
whole set.
2024-08-17 11:49:14 +02:00
Ayke van Laethem 250426c1e5 sync: add Map.Clear()
This was added in Go 1.23 and is needed for the net/mail package.
2024-08-17 11:49:14 +02:00
Ayke van Laethem e300e90a63 reflect: implement Type.Overflow* functions
They're already implemented for the Value equivalents. But since Go
1.23, such methods also exist for reflect.Type.
2024-08-17 11:49:14 +02:00
Ayke van Laethem e865db232b runtime: implement timers for Go 1.23
There were a number of changes in time.Timer/time.Ticker that need a
separate implementation for Go 1.22 and Go 1.23.
2024-08-17 11:49:14 +02:00
Ayke van Laethem db2a06a9bb internal/abi: implement initial version of this package
This package can never be a full version as seen in upstream Go, because
TinyGo is very different. But it is necessary to define so that no code
can accidentally use this package (now or in the future).

It currently defines:

  - NoEscape which is needed by strings.Builder since Go 1.23.
  - FuncPCABI* which is needed by internal/syscall/unix on MacOS.
2024-08-17 11:49:14 +02:00
Ayke van Laethem 560fd0a558 unique: implement custom version of unique package
This version probably isn't as fast as the upstream version, but it is
good enough for now. It also doesn't free unreferenced handles like the
upstream version.
2024-08-17 11:49:14 +02:00
Ayke van Laethem b8048112df internal/bytealg: add CompareString
This function was added to Go many years ago, but is starting to be used
in packages in Go 1.23.
2024-08-17 11:49:14 +02:00
Ayke van Laethem b51cda9721 sync/atomic: add And* and Or* compiler intrinsics needed for Go 1.23 2024-08-17 11:49:14 +02:00
Damian Gryski 4d60d679d3 compiler: fixup Sprintf uses 2024-08-15 13:57:02 +02:00
Damian Gryski 9932f2e126 builder: os.SEEK_CUR -> io.SeekCurrent 2024-08-15 13:57:02 +02:00
Ayke van Laethem bf8d6460da os/user: use stdlib version of this package
I tried implementing enough CGo support to get the native os/user
package to work. But I hit a few bugs, probably in CGo itself. Then I
realized I could just as well set the osusergo build tag to disable CGo
for this specific case.

This actually gets the os/user package to work correctly on Linux (I
confirmed it returns my name/uid/homedir etc). On other systems, it
probably just returns an error if it can't determine these kinds of
things. But that's no worse than the current behavior which just doesn't
do anything at all.
2024-08-15 12:15:45 +02:00
Dan Kegel d3e67cf18c make spellfix: fix top level files, too.
Do manual fix in GNUmakefile, since spellchecking that is just too meta.
2024-08-15 10:34:35 +02:00
Dan Kegel 5d82a7eee6 misspell.csv: add another misspelling. Fix by hand, since spellfix is too timid to fix in non-whitespace context? 2024-08-15 10:34:35 +02:00
Dan Kegel c82ff057f5 Fix 'numer of', since 'NUMER' by itself is valid abbrev for numerator.
Oddly, misspell was not able to detect this one, even though in
theory it allows detecting multiword typos, so the fix was done by
hand.
2024-08-15 10:34:35 +02:00
Dan Kegel 5368dd22c5 misspell.csv: add new misspellings; also check in result of 'make spellfix'. 2024-08-15 10:34:35 +02:00
Ayke van Laethem 194396d715 unix: print a message when a fatal signal happens
Print a message for SIGBUS, SIGSEGV, and SIGILL when they happen.
These signals are always fatal, but it's very useful to know which of
them happened.

Also, it prints the location in the binary which can then be parsed by
`tinygo run` (see https://github.com/tinygo-org/tinygo/pull/4383).

While this does add some extra binary size, it's for Linux and MacOS
(systems that typically have plenty of RAM/storage) and could be very
useful when debugging some low-level crash such as a runtime bug.
2024-08-15 02:00:28 +02:00
Unrud 815784bd96 machine/usb/descriptor: Reset joystick physical 2024-08-14 18:43:27 +02:00
Unrud 7fc64a27b4 machine/usb/descriptor: Drop second joystick hat 2024-08-14 18:43:27 +02:00
Unrud c38bf27091 machine/usb/hid/joystick: Allow more hat switches 2024-08-14 18:43:27 +02:00
Unrud 9a2fab8874 machine/usb/descriptor: Add more HID... functions 2024-08-14 18:43:27 +02:00
Unrud f1516ad3ee machine/usb/descriptor: Fix encoding of values
The limit for positive values is incorrect and leads to an overflow (e.g. 0xFF and 0xFFFF become -1)
2024-08-14 18:43:27 +02:00
Ayke van Laethem 4dc07d6cc3 arm: support softfloat in GOARM environment variable
This adds softfloat support to GOARM, as proposed here:
https://github.com/golang/go/issues/61588

This is similar to https://github.com/tinygo-org/tinygo/pull/4189 but
with a few differences:

  * It is based on the work to support MIPS softfloat.
  * It fixes the issue that the default changed to softfloat everywhere.
    This PR defaults to softfloat on ARMv5 and hardfloat on ARMv6 and
    ARMv7.
  * It also compiles the C libraries (compiler-rt, musl) using the same
    soft/hard floating point support. This is important because
    otherwise a GOARM=7,softfloat binary could still contain hardware
    floating point instructions.
2024-08-14 16:25:42 +02:00
Ayke van Laethem a35b983a5d linux: use -musleabi* instead of -gnueabi* (or nothing)
This more accurately describes the libc we are using.
This also adds the environment to _all_ Linux systems, not just ARM. And
selects the correct ABI (soft/hardfloat) that's in use.

I don't know whether it has any practical implications, but LLVM appears
to be using this information so it seems wise to use the correct values.
2024-08-14 16:25:42 +02:00
Dan Kegel a47ff02c82 make spell: add a few missing misspellings, fix format of .csv file, also fix *.md 2024-08-14 12:00:55 +02:00
Dan Kegel e27b2c4ad6 circleci: our version of misspell is no longer supported with go < 1.21, so disable lint in go 1.19 ci job
I jumped through quite a few hoops to get test-llvm15-go119 to work, but this last hoop seems not worth jumping through:

  cd internal/tools && go generate -tags tools ./
  /go/pkg/mod/github.com/golangci/misspell@v0.6.0/mime.go:10:2: package slices is not in GOROOT (/usr/local/go/src/slices)
  tools.go:12: running "go": exit status 1
  make: *** [GNUmakefile:952: tools] Error 1

I mean, we could patch misspell to not use slices, or to use the prerelease slices, but...
2024-08-13 10:46:29 +02:00
dkegel-fastly 8135be4e90 GNUmakefile: add spellfix target, use it. (#4387)
TODO: Remove the go.mod/go.sum in internal/tools once doing so doesn't break CI (e.g. once we drop support for go 1.19)

* builder/cc1as.h: fix typo found by 'make spell'
* GNUmakefile: remove exception for inbetween, fix instance now found by 'make spell'
* GNUmakefile: remove exception for programmmer, fix instance now found by 'make spell'
* go.mod: use updated misspell. GNUmakefile: add spellfix target, use it.
* ignore directories properly when invoking spellchecker.
* make spell: give internal/tools its own go.mod, as misspell requires newer go
* make lint: depend on tools and run the installed revive
(which was perhaps implied by the change that added revive to internal/tools,
but not required in GNUmakefile until we gave internal/tools its own temporary go.mod)
* .github: now that 'make spell' works well, run it from CI
* GNUmakefile: make spell now aborts if it finds misspelt words, so what it finds doesn't get lost in CI logs
* GNUmakefile: tools: avoid -C option on go generate to make test-llvm15-go119 circleci job happy, see
https://cs.opensource.google/go/go/+/2af48cbb7d85e5fdc635e75b99f949010c607786
* internal/tools/go.mod: fix format of go version to leave out patchlevel, else go complains.
2024-08-12 14:24:38 -07:00
dkegel-fastly 835e73237e GNUmakefile: add "help" target (#4390)
Example output:

$ make help
clean                           Remove build directory
fmt                             Reformat source
fmt-check                       Warn if any source needs reformatting
gen-device                      Generate microcontroller-specific sources
llvm-source                     Get LLVM sources
llvm-build                      Build LLVM
lint                            Lint source tree
spell                           Spellcheck source tree

Might even work on windows, since git for windows comes with awk.
2024-08-12 10:19:16 -07:00
Ayke van Laethem eab1a5d7ec reflect, runtime: remove *UnsafePointer wrappers for functions
This was needed in the past because LLVM used typed pointers and there
was a mismatch between pointer types. But we've dropped support for
typed pointers a while ago so now we can remove these wrappers.

This is just a cleanup, it shouldn't have any practical effect.
2024-08-12 15:26:18 +02:00
Ayke van Laethem f188eaf5f9 mips: add GOMIPS=softfloat support
Previously, the compiler would default to hardfloat. This is not
supported by some MIPS CPUs.

This took me much longer than it should have because of a quirk in the
LLVM Mips backend: if the target-features string is not set (like during
LTO), the Mips backend picks the first function in the module and uses
that. Unfortunately, in the case of TinyGo this first function is
`llvm.dbg.value`, which is an LLVM intrinsic and doesn't have the
target-features string. I fixed it by adding a `-mllvm -mattr=` flag to
the linker.
2024-08-12 13:23:32 +02:00
Ayke van Laethem 6efc6d2bb6 compileopts: refactor defaultTarget function
Move triple calculation into defaultTarget. It was separate for historic
reasons that no longer apply. Merging the code makes future changes
easier (in particular, softfloat support).

The new code is actually shorter than the old code even though it has
more comments.
2024-08-12 13:23:32 +02:00
Roger Standridge d6e73b4c68 add os.Truncate(name, size) (see #4209)
See https://pkg.go.dev/os#Truncate
2024-08-11 02:42:30 -07:00
Ayke van Laethem 2e76cd3687 builder: interpret linker error messages
This shows nicely formatted error messages for missing symbol names and
for out-of-flash, out-of-RAM conditions (on microcontrollers with
limited flash/RAM).

Unfortunately the missing symbol name errors aren't available on Windows
and WebAssembly because the linker doesn't report source locations yet.
This is something that I could perhaps improve in LLD.
2024-08-11 01:48:11 -07:00
Ayke van Laethem 2eb39785fe cgo: add support for printf
The C printf function is sometimes needed for C files included using
CGo. This commit makes sure they're available on all systems where CGo
is fully supported (that is, everywhere except on AVR).

For baremetal systems using picolibc, I've picked the integer-only
version of printf to save on flash size. We might want to consider
providing a way to pick the floating point version instead, if needed.
2024-08-10 23:46:58 -07:00
Ayke van Laethem 3021e16bbf wasm: call __stdio_exit on exit
This flushes stdio, so that functions like puts and printf write out all
buffered data even if the output isn't connected to a terminal.

For discussion, see:
https://github.com/bytecodealliance/wasmtime/issues/7833
2024-08-10 23:46:58 -07:00
Ayke van Laethem 55f7d21ff5 builtins: add GENERIC_TF_SOURCES
This addes GENERIC_TF_SOURCES, which contains long double floating point
builtins (80 bit, 128 bit, etc).

This is needed for full printf support.
2024-08-10 23:46:58 -07:00
Kobayashi Shunta 841abb0903 feat: add node: specifier 2024-08-09 20:30:58 +02:00
Ayke van Laethem fb3d98ce6e compileopts: add CanonicalArchName to centralize arch detection
It's possible to detect the architecture from the target triple, but
there are a number of exceptions that make it unpleasant to use for this
purpose. There are just too many weird exceptions (like mips vs mipsel,
and armv6m vs thumv6m vs arm64 vs aarch64) so it's better to centralize
these to canonical architecture names.

I picked the architecture names that happen to match the musl
architecture names, because those seem the most natural to me.
2024-08-07 14:41:21 +02:00
Ayke van Laethem 020664591a main: show runtime panic addresses for tinygo run
This adds the same panic locations that are already present for
`tinygo flash -monitor`, but for `tinygo run` and `tinygo test`.

For example, this is the output that I get while working on some GC
code. It now shows the source location instead of just an address:

    $ tinygo test -v archive/zip
    === RUN   TestReader
    === RUN   TestReader/test.zip
    panic: runtime error at 0x000000000024d9b4: goroutine stack overflow
    [tinygo: panic at /home/ayke/src/tinygo/tinygo/src/internal/task/task_stack.go:58:15]
    FAIL    archive/zip     0.139s

(This particular location isn't all that useful, but it shows that the
feature works).
2024-08-06 13:28:07 +02:00
Ayke van Laethem 2d6d9eb76d ci: don't include prebuilt libraries in the release
These libraries will be automatically built when needed and cached.

The main reason these were needed is for play.tinygo.org, but I've now
prebuilt them there directly (so they don't need to be built for every
tarball).
2024-08-06 13:27:23 +02:00
leongross a8a532f9d6 os: add file.Truncate 2024-08-02 17:22:46 +02:00
L. Pereira 417a26d20c runtime: Simplify slice growing/appending code (#4287)
* reflect: rawFieldByNameFunc: copy index slice to avoid later overwrites

* runtime: Simplify slice growing/appending code

Refactor the slice appending function to rely on the slice growing
function, and remove branches/loops to use a branchfree variant.

Signed-off-by: L. Pereira <l.pereira@fastly.com>

* runtime: Remove one branch in sliceAppend()

Both branches were equivalent, so guard the overall logic in
sliceAppend() with the more general condition.

Signed-off-by: L. Pereira <l.pereira@fastly.com>

* runtime: Simplify slice growing calculation

Use `bits.Len()` rather than `32 - bits.LeadingZeros32()`.  They're
equivalent, but the Len version is a bit easier to read.

Signed-off-by: L. Pereira <l.pereira@fastly.com>

* reflect: Always call sliceGrow() in extendSlice()

sliceGrow() will return the old slice if its capacity is large enough.

Signed-off-by: L. Pereira <l.pereira@fastly.com>

---------

Signed-off-by: L. Pereira <l.pereira@fastly.com>
Co-authored-by: Damian Gryski <damian@gryski.com>
2024-07-31 13:20:12 -07:00
Ayke van Laethem 88f9fc3ce2 reflect: return correct name for unsafe.Pointer type
For some reason, the type kind name is "unsafe.Pointer" while the
.Name() method just returns "Pointer".

Not sure why this difference exists, but to be able to test .Name() in
testdata/reflect.go it needs to match.
2024-07-31 21:08:23 +02:00
Ayke van Laethem 84c376160f transform: use thinlto-pre-link passes
This improves compilation performance by about 5% in my quick test,
while increasing binary size on average by  0.13% when comparing the
smoke tests in the drivers repo (and about two thirds of that 0.13% is
actually caused by a single smoke test).

I think this is a good idea because it aligns the TinyGo optimization
sequence with what ThinLTO expects.
2024-07-31 21:07:20 +02:00
Ayke van Laethem 6184a6cd35 Revert "Getting DeepEqual to work with maps whose key is an interface (#4360)"
This reverts commit 1fd75ffbda.

The change is not correct and allows code to continue while it should
panic. For details, see:
https://github.com/tinygo-org/tinygo/pull/4360#issuecomment-2252943012
2024-07-29 14:10:02 +02:00
Laurent Demailly 1fd75ffbda Getting DeepEqual to work with maps whose key is an interface (#4360)
reflect: Getting DeepEqual to work with maps whose key is an interface
2024-07-24 00:30:02 +02:00
Laurent Demailly 61d36fb3f8 Add missing T.Deadline 2024-07-23 22:23:35 +02:00
leongross b318a941a4 add Fork and Exec libc hooks
Signed-off-by: leongross <leon.gross@9elements.com>
2024-07-23 16:24:41 +02:00
Ayke van Laethem 725518f007 all: add linux/mipsle support
This adds linux/mipsle (little endian Mips) support to TinyGo.

It also adds experimental linux/mips (big-endian) support. It doesn't
quite work yet, some parts of the standard library (like the reflect
package) currently seem to assume a little-endian system.
2024-07-22 16:21:26 +02:00
Ayke van Laethem 04d1261f8a build: add package ID to compiler and optimization error messages
This improves error reporting slightly.
2024-07-21 18:23:49 +02:00
leongross 3e2230eadb os/Chown (#4213)
src/os, src/syscall: add os.Chown
2024-07-21 10:56:55 +02:00
deadprogram 4f908f4877 net: update to latest net package
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-07-21 09:14:08 +02:00
Laurent Demailly 319683b863 Add enough tls.ConnectionState and tls.CipherSuiteName() to compile fortio/log (#4345)
src/crypt: add enough tls.ConnectionState and tls.CipherSuiteName() to compile fortio/log
2024-07-20 20:19:03 +02:00
Matthew Hiles 4af3f618f8 rewrite Reply() to fix sending long replies in I2C Target Mode 2024-07-20 18:36:59 +02:00
Laurent Demailly 89340f82dc Allows compilation of code using debug.BuildInfo and show correct tinygo version (#4343)
debug: Allows compilation of code using debug.BuildInfo and show correct tinygo version
2024-07-20 15:26:08 +02:00
Ayke van Laethem 824bf24445 diagnostics: sort package diagnostics by position
Previously, the error messages could be shown out of order.
With this patch, the errors are sorted before being shown to the user.
This makes it easier to read the error messages, and matches what the
`go` toolchain does.
2024-07-20 14:30:34 +02:00
Ayke van Laethem 80269b98ba diagnostics: move diagnostic printing to a new package
This is a refactor, which should (in theory) not change the behavior of
the compiler. But since this is a pretty large change, there is a chance
there will be some regressions. For that reason, the previous commits
added a bunch of tests to make sure most error messages will not be
changed due to this refactor.
2024-07-20 14:30:34 +02:00
Ayke van Laethem 3788b31ba5 main: add test for error coming from the optimizer
This is just one optimizer pass that's easy to test for. There are
others, but I'm ignoring them for now.

The one other that would be reasonable to test is when starting a
goroutine with -gc=none, but I'm leaving that one for another time.
2024-07-20 14:30:34 +02:00
Ayke van Laethem f4ce11ef37 main: add error tests for the compiler
The compiler can in fact return errors, but these weren't tested yet.
2024-07-20 14:30:34 +02:00
Ayke van Laethem a5f78a3900 main: add interp tests
This one needed more advanced checking of the error messages, because we
don't want to hardcode things like `!dbg !10` in the output.
2024-07-20 14:30:34 +02:00
Ayke van Laethem e409950492 main: refactor error messages to use FileCheck-like patterns
Match the error messages in testdata/errors/*.go like LLVM FileCheck,
which includes regular expressions.

I believe this is much more flexible, and LLVM uses it in nearly all of
their tests so it must work quite well for compilers.
2024-07-20 14:30:34 +02:00
deadprogram 208eb1a817 fix: set ubuntu version to 24.04 to try to address #4347
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-07-20 12:47:20 +02:00
Ayke van Laethem 2920492e0a syscall: remove some dead code
Not sure why it's here but it's not referenced anywhere.
2024-07-18 08:57:02 +02:00
Randy Reddig 87a8aafc4f all: simplify wasm-tools-go dependency
- add internal/wasm-tools/go.mod file to depend on wasm-tools-go
- copy package cm into src/internal/cm
- remove wasm-tools-go "vendor" submodule

internal/tools: fix typo

go.{mod,sum}, internal/tools: add wit-bindgen-go to tools

GNUmakefile: use go run for wit-bindgen-go

GNUmakefile: add tools target to go:generate tools binaries in internal/tools

GNUmakefile: add .PHONY for lint and spell

GNUmakefile, internal/cm: vendor package cm into internal/cm

go.{mod,sum}: update wasm-tools-go to v0.1.4

internal/wasi: use internal/cm package

remove submodule src/vendor/github.com/ydnar/wasm-tools-go

GNUmakefile: add comment documenting what wasi-cm target does

go.{mod,sum}: remove toolchain; go mod tidy

go.mod: revert to Go 1.19

go.mod: go 1.19

go.{mod,sum}, internal/{tools,wasm-tools}: revert root go.mod file to go1.19

Create a wasm-tools specific module that can require go1.22 for wasm-tools-go.
2024-07-17 20:17:03 +02:00
Tai Groot f026422b04 add chromeos 9p support 2024-07-15 10:13:43 +02:00
Anatol Pomozov fb91c7097f Do not stop compilation on compiler warnings
Compilers like GCC keep adding new checks that produce new warnings.
Sometimes it can be false positives.

Do not treat such warnings in binaryen library as errors. tinygo won't
be able to provide zero warnings in its dependencies.

Closes #4332
2024-07-14 14:31:14 +02:00
Ayke van Laethem d7773d3e86 loader: handle go list errors inside TinyGo
Instead of exiting with an error, handle these errors internally.
This will enable a few improvements in the future.
2024-07-13 13:26:26 +02:00
Ayke van Laethem b04b690842 libclang: do not make error locations relative
This is done at a later time anyway, so doesn't need to be done in the
cgo package. In fact, _not_ doing it there makes it easier to print
correct relative packages.
2024-07-13 13:26:26 +02:00
Ayke van Laethem 8a357af3d8 all: add testing for compiler error messages
This is needed for some improvements I'm going to make next.

This commit also refactors error handling slightly to make it more
easily testable, this should hopefully not result in any actual changes
in behavior.
2024-07-13 13:26:26 +02:00
Ayke van Laethem 7ac1ca0ae2 builder: remove workaround for generics race condition
This commit reverts commit 13a8eae0d.

It appars that the race has been fixed by
https://github.com/golang/tools/commit/db513b091504, which we now use
because it fixes another race condition as well.
See: https://github.com/tinygo-org/tinygo/issues/4206
2024-07-13 13:05:28 +02:00
Ayke van Laethem 2f3d821b13 cgo: support preprocessor macros passed on the command line
Go code might sometimes want to use preprocessor macros that were passed
on the command line. This wasn't working before and resulted in the
following error:

    internal error: could not find file where macro is defined

This is now supported, though location information isn't available
(which makes sense: the command line is not a file).

I had to use the `clang_tokenize` API for this and reconstruct the
original source location. Apparently this is the only way to do it:
https://stackoverflow.com/a/19074846/559350
In the future we could consider replacing our own tokenization with the
tokenizer that's built into Clang directly. This should reduce the
possibility of bugs a bit.
2024-07-13 13:03:50 +02:00
Dmitry Shemin 6f462fba4c fix: remove message after test binary built 2024-07-09 18:57:05 +02:00
L. Pereira ac396708da main_test: Diff expected and actual results when tests fail (#4288)
Uses a vendored "internal/diff" from Big Go to show the differences
between the expected and actual outputs when tests fail.

Signed-off-by: L. Pereira <l.pereira@fastly.com>
2024-07-08 16:35:06 -07:00
L. Pereira d150badf33 gc_leaking: Don't zero out new allocations in some targets (#4302)
Wasm linear memory is always initialized to zero by definition,
so there's no need to waste time zeroing out this allocation. This
is the case for freshly-obtained memory from mmap().

Signed-off-by: L. Pereira <l.pereira@fastly.com>
2024-07-08 16:34:40 -07:00
Randy Reddig 2d85fc6a64 internal/wasi: update to wasm-tools-go@v0.1.2 (#4326)
* internal/wasi: update to wasm-tools-go@v0.1.1

See https://github.com/ydnar/wasm-tools-go/releases/tag/v0.1.1 for additional information.

* internal/wasi: update to wasm-tools-go@v0.1.2

* internal/wasi: regenerate with wasm-tools-go@v0.1.3
2024-07-08 13:09:47 -07:00
Elias Naur 5ca3e4a2da runtime: implement dummy getAuxv to satisfy golang.org/x/sys/cpu (#4325)
Fixes the program

  package main

  import _ "golang.org/x/sys/cpu"

  func main() {
  }
2024-07-08 13:09:30 -07:00
Ayke van Laethem e6caa3fe9e transform: fix incorrect alignment of heap-to-stack transform
It assumed the maximum alignment was equal to sizeof(void*), which is
definitely not the case. So this only worked more or less by accident
previously.

It now uses the alignment as specified by the frontend, or else
`unsafe.Alignof(complex128)` which is typically the maximum alignment of
a given platform (though this shouldn't really happen in practice: the
optimizer should keep the 'align' attribute in place).
2024-07-03 07:31:37 +02:00
Ayke van Laethem 571447c7c1 compiler: add 'align' attribute to runtime.alloc calls
This adds something like 'align 4' to the runtime.alloc calls, so that
the compiler knows the alignment of the allocation and can optimize
accordingly.

The optimization is very small, only 0.01% in my small test. However, my
plan is to read the value in the heap-to-stack transform pass to make it
more correct and let it produce slightly more optimal code.
2024-07-03 07:31:37 +02:00
Damian Gryski 9cb263479c wasi preview 2 support (#4027)
* all: wasip2 support

Co-authored-by: Randy Reddig <randy.reddig@fastly.com>
2024-07-02 07:02:03 -07:00
Ayke van Laethem f18c6e342f test: support GOOS/GOARCH pairs in the -target flag
This means it's possible to test just a particular OS/arch with a
command like this:

    go test -run=Build -target=linux/arm

I found it useful while working on MIPS support.
2024-06-28 12:31:38 +02:00
leongross 2d5a8d407b add support for unix.{RawSyscall,RawSyscallNoError} 2024-06-27 21:14:22 +02:00
leongross 36958b2875 add support for unix.Syscall* invocations
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-27 21:14:22 +02:00
Ayke van Laethem fae0402fde wasm-unknown: make sure the os package can be imported
See: https://github.com/tinygo-org/tinygo/issues/4314

The os package isn't particularly useful on wasm-unknown, but just like
on baremetal systems it's imported by a lot of packages so it should at
least be possible to import this package.
2024-06-27 21:11:11 +02:00
deadprogram 4517a0c17b version: update to 0.33.0-dev
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-06-25 22:18:20 +02:00
Ayke van Laethem 6abaee4640 compiler: remove old atomics workaround for AVR
The bug should have been fixed in any LLVM version that we currently
support.
2024-06-25 09:27:31 +02:00
Ayke van Laethem 1270a50104 machine: use new internal/binary package
The encoding/binary package in Go 1.23 imports the slices package, which
results in circular import when imported from the machine package.
Therefore, encoding/binary cannot be used in the machine package.

This commit fixes that by introducing a new internal/binary package that
is just plain Go code without dependencies. It can be safely used
anywhere (including the runtime if needed).
2024-06-24 21:21:52 +02:00
Ayke van Laethem 868262f4a7 all: use latest version of x/tools
We previously picked a work-in-progress patch, but this is the proper
fix for this race condition. I think we should use that instead of
relying on the previous work-in-progress patch.
2024-06-23 19:11:06 +02:00
leongross d33ace7b59 remove unused registers for x86_64 linux syscalls
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-23 07:47:34 +02:00
Ayke van Laethem dd6fa89aa6 Release 0.32.0 2024-06-16 18:24:36 +02:00
leongross d513cae5d2 add SetReadDeadline stub 2024-06-15 11:34:06 +02:00
Ayke van Laethem e612f7cf3f Add smoke tests for machine package
The machine package wasn't tested for every board. Therefore, add a new
serial-like test that also tries to import the machine package. This
should highlight potential issues in the future.
2024-06-14 17:28:31 +02:00
Ayke van Laethem 385a7920e6 compiler: fix race condition by applying a proposed patch
This commit switches to v0.22.0 of golang.org/x/tools and then applies
https://go-review.googlesource.com/c/tools/+/590815 to fix the race
condition.

In my testing, it seems to fix these issues.
2024-06-12 14:46:47 +02:00
Ayke van Laethem 077b35e9ad all: drop support for Go 1.18
Go 1.18 has been unsupported for quite a while now (the oldest supported
version is Go 1.21). But more importantly, the golang.org/x/tools module
now requires Go 1.19 or later. So we'll drop this older version.
2024-06-12 14:46:47 +02:00
deadprogram 880e940417 targets: add cyw43439 tag to badger2040-w and also add new pico-w target for wireless support
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-06-11 07:57:58 +02:00
L. Pereira ad6c89bf64 transform/rtcalls: Bail fast if can't convert pointer
There's no need to keep looping if one of the uses makes it impossible
to convert a call to `runtime.stringToBytes()` with a raw pointer.

Signed-off-by: L. Pereira <l.pereira@fastly.com>
2024-06-10 12:39:55 +02:00
Ayke van Laethem ae6220262a cgo: implement shift operations in preprocessor macros 2024-06-07 20:40:27 +02:00
leongross e731a31eb9 update fpm ci, fixup import
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-06 16:24:33 +02:00
leongross 3023ba584b Add process.Release for unix
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-06 16:24:33 +02:00
leongross 3a8ef33c72 add FindProcess for posix
Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-06 16:24:33 +02:00
leongross 20b58a0128 Add signal stubs (#4270)
os: init signal ignore stub and add other stubs

Signed-off-by: leongross <leon.gross@9elements.com>
2024-06-02 09:52:31 +02:00
Damian Gryski bfccf3592a builder: make sure wasm-opt command line is printed if asked 2024-05-31 11:20:04 -07:00
Damian Gryski 272fea13e7 builder: keep un-wasm-opt'd .wasm if -work was passed 2024-05-31 11:20:04 -07:00
Damian Gryski b6fd0c818e src/reflect: uncomment more tests that pass 2024-05-29 13:56:04 -07:00
Ayke van Laethem c383a407e3 cgo: do a basic test that math functions work
They should, but we weren't testing this.
I discovered this while working on
https://github.com/tinygo-org/macos-minimal-sdk/pull/4 which will likely
make math.h not work anymore. So I wanted to make sure we have a test in
place before we update that dependency.
2024-05-29 21:51:39 +02:00
diamondburned 7b7601d77c os/user: add stubs for Lookup{,Group} and Group 2024-05-28 23:56:51 +02:00
frenkel26 f7c0466f78 compiler,reflect: fix NumMethods for Interface type 2024-05-28 14:09:59 +02:00
Ayke van Laethem 81ce7fb738 LLVM 18 support 2024-05-24 19:12:26 +02:00
Ayke van Laethem c2776dcf78 main: add -serial=rtt flag as possible option
I added this a while ago but forgot to change the help documentation.
2024-05-24 17:37:49 +02:00
leongross ad0340d437 fix fpm ci installion
Signed-off-by: leongross <leon.gross@9elements.com>
2024-05-18 12:00:28 +02:00
leongross 30c4df16f2 add aes generic aliases 2024-05-14 20:44:48 +02:00
Randy Reddig fe27b674cd reflect: use int in StringHeader and SliceHeader on non-AVR platforms (#4156) 2024-05-14 14:04:54 +02:00
Mateusz Nowak c78dbcd3f2 Support UF2 drives with space in their name on Linux
Some devices, such as Seeed Studio XIAO with Adafruit bootloader, use complex names for UF2 device. With this fix applied, /proc/mounts should be parsed correctly
2024-05-14 13:58:44 +02:00
Johann Freymuth 8890b57ba0 Add I2C support for esp32 (#4259)
machine/esp32: add i2c support
2024-05-13 21:58:06 +02:00
deadprogram ee3a05f1de targets: add support for Badger2040 W
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-05-13 20:10:36 +02:00
Elias Naur 9307204111 Revert "flake.nix: explicitly add libcxx as dependency"
This reverts commit 7b8ae2d6b6.
2024-05-13 19:04:01 +02:00
Marco Manino 71878c2c0c Adding a comment 2024-05-13 16:49:18 +02:00
Marco Manino cef2a82c97 Checking for methodset existance 2024-05-13 16:49:18 +02:00
Johann Freymuth 1d9f26cee1 targets: add support for m5paper 2024-05-12 16:09:27 +02:00
sago35 6e58c44390 machine: add TxFifoFreeLevel() for CAN 2024-05-10 18:45:06 +02:00
deadprogram 7d6b667bba machine/stm32: add i2c Frequency and SetBaudRate() function for boards that were missing implementation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-05-08 10:57:46 +02:00
Christian Stewart 72f30ca6ec Makefile: add lld to list of build targets for wasm-ld
The current list of targets does not build wasm-ld.

wasm-ld is a symlink created in ./llvm-build/bin pointing to ./lld.

Add the "lld" build target to get wasm-ld into ./llvm-build/bin.

Fixes a build failure where wasm-ld is not found.

Signed-off-by: Christian Stewart <christian@aperture.us>
2024-05-05 11:31:46 +02:00
deadprogram 293b620faf build: update llvm cache to use tagged LLVM source version
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-04-30 19:02:45 +02:00
Dan Kegel ad0af607ef Add 'make spell' target, fix what it finds. In .go files, only checks comments. 2024-04-30 07:47:11 +02:00
deadprogram da23cdeae4 make: use release esp-17.0.1_20240419 tag for source from espressif LLVM fork for reproducible builds
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-04-29 20:50:23 +02:00
Ayke van Laethem d419cc11bf simulator: add support for GetRNG
This is needed to be able to simulate the Gopher Badge code:
https://github.com/conejoninja/gopherbadge
2024-04-28 23:59:23 +02:00
Ayke van Laethem 441dfc98d7 simulator: fix I2C support
- Add ReadRegister and WriteRegister (because they're still used by
    some packages).
  - Fix out-of-bounds panic in I2C.Tx when either w or r has a length of
    zero (or is nil).
2024-04-28 23:05:49 +02:00
Elias Naur 2b3b870bfe mksnanov3: limit programming speed to 1800 kHz
Both of my development boards exhibit stability problems when
programming at the default 4000 kHz speed of the target/stmf32d4x
OpenOCD configuration.

Note that the speed limit must be set by an event handler, because it
is hard-coded by a similar event handler in stmf32f4x.cfg:

  $_TARGETNAME configure -event reset-init {
  	# Configure PLL to boost clock to HSI x 4 (64 MHz)
    ...

  	# Boost JTAG frequency
  	adapter speed 8000     <-- resolves to 4000 kHz by the SWD interface
  }

While here, replace the reference to the deprecated "stlink-v2"
configuration.
2024-04-27 13:02:20 +02:00
Ayke van Laethem 7748c4922e compileopts: fix race condition
Appending to a slice can lead to a race condition if the capacity of the
slice is larger than the length (and therefore the returned slice will
overwrite some fields in the underlying array).

This fixes that race condition. I don't know how severe this particular
one is. It shouldn't be that severe, but it is a bug and it makes it
easier to hunt for possibly more serious race conditions.
2024-04-27 11:12:19 +02:00
Elias Naur 50f700ddb5 runtime: skip negative sleep durations in sleepTicks
sleepTicks calls machineLightSleep with the duration cast to an unsigned
integer. This underflow for negative durations.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-04-27 09:52:44 +02:00
Ayke van Laethem f986ea84ac rp2040: fix timeUnit type
It should be int64 like for all other systems, not uint64.
2024-04-26 14:12:10 +02:00
sago35 797a5a2031 machine/thingplus_rp2040, machine/waveshare-rp2040-zero:add WS2812 definition 2024-04-24 08:50:53 +02:00
dkegel-fastly 3d433fe9f1 Lint: lint and fix src/{os,reflect} (#4228)
* lint: expand to src/{os,reflect}, fix or suppress what it found

* internal/tools/tools.go: the tools idiom requires a build tag guard to avoid go test complaints
2024-04-22 11:10:13 -07:00
hongkuang 1154212c15 chore: fix function names in comment
Signed-off-by: hongkuang <liurenhong@outlook.com>
2024-04-20 14:58:06 +02:00
Patrick Ting 22bf045c9a add stm32 nucleol476rg support 2024-04-19 20:50:00 +02:00
dkegel-fastly 39029cc376 Run Nick G's spellchecker github.com/client9/misspell, carefuly fix what it found (#4235) 2024-04-19 06:57:01 -07:00
Elias Naur 7122755725 compileopts: apply OpenOCD commands after target configuration
The openocd-commands option cannot refer to commands defined by the
target configuration. Lift this restriction by moving the commands to
after target loading.
2024-04-17 21:54:38 +02:00
leongross dcee228c4e add os.Link
Signed-off-by: leongross <leon.gross@9elements.com>
2024-04-14 16:56:53 +02:00
Dan Kegel 9d6e30701b lint: add "make lint" target, run it from ci
See https://github.com/tinygo-org/tinygo/issues/4225

Runs in both circleci and github, circleci is run on branch push, github is run on PR

Revive builds so fast, don't bother installing it; saves us wondering which one we get

Uses tools.go idiom to give control over linter versions to go.mod.

Also pacifies linter re AppendToGlobal as a token first fix.

TODO: gradually expand the number of directories that are linted,
uncomment more entries in revive.toml, and fix or suppress the
warnings lint finds.

TODO: add linters "go vet" and staticcheck

NOT TODO: don't add metalinters like golangci-lint that pull in
lots of new of dependencies; we'd rather not clutter go.mod that
much, let alone open ourselves up to the additional attack surface.
2024-04-13 18:57:31 +02:00
Ayke van Laethem 85b59e66da machine: add __tinygo_spi_tx function to simulator
This is much, _much_ faster than __tinygo_spi_transfer which can only
transfer a single byte at a time. This is especially important for
simulated displays.

I've already implemented the browser side of this on the playground and
have used this patch for local testing where it massively speeds up
display operations.
2024-04-13 11:38:18 +02:00
Ayke van Laethem 90b0bf646c rp2040: make all RP2040 boards available for simulation
This makes all rp2040 boards available for simulation using
-tags=<board_name>. Importantly, this includes the Gopher Badge which
I'm working on to add to the TinyGo Playground.
2024-04-04 19:34:01 +02:00
Ayke van Laethem c55ac9f28e rp2040: move UART0 and UART1 to common file
This is makes it easier to use these in simulation, plus it avoids
duplication. The only downside I see is that more UARTs get defined than
a board supports, but no existing code should break (no UARTs get
renamed for example).
2024-04-04 19:34:01 +02:00
leongross 2733e376bd fix square alias for ed25519
Signed-off-by: leongross <leon.gross@9elements.com>
2024-04-03 12:35:20 +02:00
Ayke van Laethem 331cfb65b7 nix: fix wasi-libc include headers
Apparently Nix really doesn't like --sysroot, so we have to use
`-nostdlibinc` and `-isystem` instead.
2024-03-28 15:46:00 +01:00
Randy Reddig 055950421a all: change references of 'wasi' to 'wasip1'; test hygiene 2024-03-27 16:01:40 +01:00
Randy Reddig cfcc894855 targets: add wasi.json that inherits wasip1.json
PR feedback
2024-03-27 16:01:40 +01:00
Randy Reddig 8bd0155c51 os, testing: just check runtime.GOOS == "wasip1" 2024-03-27 16:01:40 +01:00
Randy Reddig 32a056c32a syscall: use libc_getpagesize instead of hard-coded constant
TODO: should Getpagesize on wasip1 just return wasmPageSize?
2024-03-27 16:01:40 +01:00
Randy Reddig 8e8ad9004f all: replace target=wasi with target=wasip1
This eliminates the 'wasi' build tag in favor of 'GOOS=wasip1', introduced in Go 1.21.

For backwards compatablity, -target=wasi is a synonym for -target=wasip1.
2024-03-27 16:01:40 +01:00
Patrick Lindsay 62d8cdb218 Map the rest of the pinout 2024-03-27 11:55:25 +01:00
Patrick Lindsay b6fdbee14e Begin implementing support for Adafruit ESP32 Feather V2 2024-03-27 11:55:25 +01:00
deadprogram a5ceb793be builder: add check for error on creating needed directory as suggested by @b0ch3nski
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-03-26 12:20:50 +01:00
Ayke van Laethem 7c546525ea wasm-unknown: add math and memory builtins that LLVM needs
This new library is needed for wasm targets that aren't WASI and don't
need/want a libc, but still need some intrinsics that are generated by
LLVM.
2024-03-26 12:20:50 +01:00
Ayke van Laethem d628e3e2cb ci: don't add --recursive when updating submodules
It's not generally needed. It was added in
https://github.com/tinygo-org/tinygo/pull/3958 to fix an issue with
binaryen that has since been fixed in a different way, so we don't need
the googletest dependency anymore.
2024-03-24 13:04:47 +01:00
Jonathan Böcker d97e4dbccf Add smoke test for pca10059-s140v7 2024-03-23 10:23:07 +01:00
Jonathan Böcker a7ddb33bea Add pca10059-s140v7 as a target 2024-03-23 10:23:07 +01:00
Ayke van Laethem 8a93196f1f Makefile: allow overriding the packages to test in make test
This way you can for example run `make test GOTESTPKGS=./builder` to
only test the builder package.
I've often done this by manually modifying the Makefile, so having a
make parameter available would make this much easier.
2024-03-22 23:18:10 +01:00
Anders Savill 6714974aba feather-nrf52840-sense doesn't use LFXO 2024-03-21 20:29:02 +01:00
deadprogram d67ec3b266 goenv: put back @sago35 update to new v0.32.0 development version
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-03-21 06:41:10 +01:00
Ayke van Laethem 78775007fa wasm: fix symbol table index for archives
The symbol table was generated incorrectly. The correct way is to use
the custom linking WebAssembly section, which I implemented in go-wasm
for this purpose.

This fixes https://github.com/tinygo-org/tinygo/issues/4114 and is a
prerequisite for https://github.com/tinygo-org/tinygo/pull/4176.
2024-03-19 07:12:22 +01:00
Ayke van Laethem ad4d722f54 all: move -panic=trap support to the compiler/runtime
Support for `-panic=trap` was previously a pass in the optimization
pipeline. This change moves it to the compiler and runtime, which in my
opinion is a much better place.

As a side effect, it also fixes
https://github.com/tinygo-org/tinygo/issues/4161 by trapping inside
runtime.runtimePanicAt and not just runtime.runtimePanic.

This change also adds a test for the list of imported functions. This is
a more generic test where it's easy to add more tests for WebAssembly
file properties, such as exported functions.
2024-03-19 07:10:51 +01:00
deadprogram 6384ecace0 docs: update CHANGELOG for 0.31.2 patch release
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-03-10 15:13:23 +01:00
deadprogram 38881a2850 goenv: update to v0.31.2 for patch release
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-03-10 15:13:23 +01:00
deadprogram 0f1cf14743 net: update to net package with Buffers implementation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-03-09 10:56:14 -05:00
sago35 7c34f7704e goenv: update to new v0.32.0 development version 2024-03-04 19:29:26 +01:00
Randy Reddig 377415a6c3 runtime: add Frame.Entry field
This enables compatibility with golang.org/x/tools/internal/pkgbits.

https://github.com/golang/tools/blob/master/internal/pkgbits/frames_go17.go
2024-03-02 21:17:34 +01:00
deadprogram 1e13c6d18f syscall: add wasm_unknown to some additional files so it can compile more code
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-03-02 20:49:56 +01:00
deadprogram 14121f4b0e all: update for 0.31.1
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-28 13:22:23 +01:00
deadprogram 7768195835 net: update to latest main
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-28 13:22:23 +01:00
deadprogram c095b7e9c4 build: only use GHA cache for docker dev builds, ignore the previous saved build-context
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-28 08:57:35 +01:00
Ayke van Laethem 1f6d34d995 interp: make getelementptr offsets signed
getelementptr offsets are signed, not unsigned. Yet they were used as
unsigned integers in interp.
Somehow this worked most of the time, until finally there was some code
that did a getelementptr with a negative index.
2024-02-27 15:16:38 +01:00
Ayke van Laethem 9951eb9990 interp: return a proper error message when indexing out of range
This helps debug issues inside interp.
2024-02-27 15:16:38 +01:00
deadprogram c8f77d26a8 docker: update final build stage to go1.22
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-27 11:57:37 +01:00
Ayke van Laethem 8eaa9bd8d0 ci: fix binaryen build
Disable the googletest dependency so that we can avoid that submodule
dependency.
2024-02-26 15:30:41 +01:00
Ayke van Laethem 6061f3db92 all: version 0.31.0 2024-02-26 09:37:39 +01:00
Akshay Pai 410aa0e0d8 Stub CallSlice for Value 2024-02-25 14:45:50 +01:00
deadprogram c66836cf3a targets: add support for Thumby
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-23 14:00:57 +01:00
Ayke van Laethem ca9211b582 main: make ports subcommand more verbose
By listing column headers and printing a message when no ports are
found, it should be a bit easier to use.
2024-02-23 08:37:26 +01:00
Ayke van Laethem cb7d470ba4 main: change monitor -info to ports
I believe this provides a better UX.
2024-02-23 08:37:26 +01:00
Ayke van Laethem 5baee9a8ee ci: switch to Go 1.22 2024-02-20 21:58:09 +01:00
Ayke van Laethem c47f52b546 Dockerfile: reduce size of resulting image
This reduces the size of the Docker image from 13GB to 1.71GB, and
should therefore make CI of the drivers package much faster. It should
hopefully also avoid the out-of-space problem we currently have when
building the smoke tests for the drivers repo.

 This size reduction is done by using multistage builds and only copying
 the necessary files in the final stage.
2024-02-20 21:00:22 +01:00
Ayke van Laethem a2588d8db3 compileopts: remove workaround for LLVM 16
This workaround is no longer needed now that we've switched to LLVM 17
where this bug has been fixed upstream:
https://github.com/espressif/llvm-project/pull/84
2024-02-19 23:29:44 +01:00
Ayke van Laethem f529b6071d interp: do not register runtime timers during interp
The runtime hasn't been initialized yet so this leads to problems.

This fixes https://github.com/tinygo-org/tinygo/issues/4123.
2024-02-19 22:17:19 +01:00
Ayke van Laethem 5557e97888 device: update SVD files
This updates lib/cmsis-svd, pulling in the updates to the Espressif SVD
files here:
https://github.com/cmsis-svd/cmsis-svd-data/pull/3

This is needed for wifi/BLE support on the ESP32-C3 (the older SVD files
were missing some necessary interrupts).
2024-02-19 19:10:21 +01:00
Ayke van Laethem d04b07fa8b compileopts: always enable CGo
CGo is needed for the rp2040 and for macOS (GOOS=darwin), without it
these targets just won't work. And there really isn't a benefit from
disabling CGo: we don't need any external linkers for example.

This avoids a somewhat common issue of people having CGO_ENABLED=0
somewhere in their environment and not understanding why things don't
work. See for example: https://github.com/tinygo-org/tinygo/issues/3450
2024-02-19 17:53:36 +01:00
Ayke van Laethem 7486277012 all: make TinyGo code usable with "big Go" CGo
I managed to get CGo sort-of working in VSCode (meaning that it will
typecheck code in the IDE itself) using a few crude hacks, but it
requires a few minor changes to the TinyGo standard library.

I intend to eventually add this support in the TinyGo extension for
VSCode directly, but for now I've manually updated .vscode/settings.json
to get IDE support. In any case, it would be nice to have this for when
I hopefully add this to the TinyGo extension eventually.
2024-02-19 15:49:36 +01:00
deadprogram 36d60b8349 targets/wasm_unknown: remove _start to _initialize to match WASI
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-17 10:18:00 +01:00
deadprogram c55191283b builder: add 'wasm-unknown' to list of targets for clang features verification
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-17 10:18:00 +01:00
deadprogram ad30085b93 targets/wasm_unknown: use proper defaults for GC
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-17 10:18:00 +01:00
deadprogram e9ca41735a make: add smoketest for wasm-unknown target
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-15 17:54:18 +01:00
deadprogram df1f83f4e1 examples: add example for use with wasm-unknown target
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-15 17:54:18 +01:00
deadprogram 5879d785a9 target/wasm_unknown: remove bulk memory and use imported memory for extreme tinyness
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-15 17:54:18 +01:00
deadprogram 186018abeb runtime, targets: some WIP on wasm unknown in part from PR #3072
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-15 17:54:18 +01:00
BCG 828b9614c2 nrf52840: generic board support (#4121)
machine/nrf52840: generic board support
2024-02-12 10:37:19 +01:00
Xudong Zheng f5e933cd4d machine/rp2040: set XOSC startup delay multiplier
XOSC requires additional time to stablize on certain RP2040 boards.

Signed-off-by: Xudong Zheng <7pkvm5aw@slicealias.com>
2024-02-11 11:59:54 +01:00
Ayke van Laethem 0952b1b984 compileopts: set 'purego' build tag by default
This is needed for various crypto libraries.
2024-02-11 10:43:28 +01:00
Ayke van Laethem ed55f56d85 ci: update from Node.js 16 to Node.js 18
Node.js 16 is no longer supported, so we can drop support for it as
well.

This also means updating a whole lot of GitHub Actions versions, because
they were updated to work on Node.js 20 instead. For most actions this
should be a relatively small change, but the upload-aftifact action has
had some major changes (which should generally improve things a lot).
2024-02-11 09:43:22 +01:00
Ayke van Laethem edb8766aab esp32: switch over to the official SVD file 2024-02-09 16:12:21 +01:00
deadprogram 413bb55e2c build: remove more files from host on Docker build to avoid running out of disk space
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-02-07 07:31:54 +01:00
Ayke van Laethem 0db1a4bec1 gi: add macOS ARM64 builder
This means we can finally release native arm64 builds of TinyGo on
macOS!

Also update from macOS 11 to macOS 12, because macOS 11 is not supported
anymore.
2024-02-05 20:43:43 +01:00
Damian Gryski 2867da164d Allow larger systems to have a larger max stack alloc
Fixes #3331
2024-01-31 17:51:55 +01:00
Elias Naur 7b8ae2d6b6 flake.nix: explicitly add libcxx as dependency
Without this change, my tinygo builds crash with

SIGSEGV: segmentation violation
PC=0x10884f87c m=16 sigcode=2
signal arrived during cgo execution

goroutine 378 [syscall]:
runtime.cgocall(0x100631e44, 0x1401755be88)
	/nix/store/4hf287252ilsdf2w36mfm8fa0rvbf33w-go-1.21.4/share/go/src/runtime/cgocall.go:157 +0x44 fp=0x1401755be50 sp=0x1401755be10 pc=0x1002a5084
tinygo.org/x/go-llvm._Cfunc_LLVMGoWriteThinLTOBitcodeToMemoryBuffer(0x123614160)
	_cgo_gotypes.go:6078 +0x34 fp=0x1401755be80 sp=0x1401755be50 pc=0x1004b66b4
...

and reports using LLVM 16:

$ tinygo version
tinygo version 0.31.0-dev darwin/arm64 (using go version go1.21.4 and LLVM version 16.0.6)

I don't know why libcxx-16 is being included, but explicitly specifying
llvmPackages_17.libcxx fixes the crash and version skew.
2024-01-31 14:56:16 +01:00
Damian Gryski 5b8127fd4e reflect: move indirect values into interface when setting interfaces
Fixes #4040
2024-01-31 13:48:02 +01:00
= cc3e785692 Remove unused value 2024-01-29 16:23:35 +01:00
BCG 0ea5cfc8fe rp2040: add definition for machine.PinToggle 2024-01-29 12:38:06 +01:00
Ayke van Laethem 70f1a5429a esp32c3: update linker script to support binary blobs
To be able to link with the binary blobs that provide wifi and BLE, the
linker script needs a few tweaks.
2024-01-27 14:11:09 +01:00
Ayke van Laethem 2fb2113168 esp32c3: add more ROM functions
These functions are used by the binary blobs that implement wifi/BLE on
the ESP32-C3. While this is a lot of lines of linker script, I think
it's a good idea to add them here (instead of in a separate library)
because they're part of the ESP32-C3 hardware.
2024-01-27 14:11:09 +01:00
soypat cb39611389 sync: implement trylock 2024-01-26 14:30:06 +01:00
Elias Naur 45764325b4 targets: add motor control pin definitions for MKS Nano V3x boards
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-01-23 21:04:22 +01:00
Elias Naur bb66232164 targets: add support for the MKS Robin Nano V3.x
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2024-01-23 21:04:22 +01:00
Daniel Esteban 9679e7f1cc fix typo 2024-01-23 16:52:37 +01:00
Ayke van Laethem 6cdfc298cf all: switch to LLVM 17 by default 2024-01-20 10:50:42 +01:00
Ayke van Laethem 9a4bfd0e96 ci: fix sizediff error when changing the LLVM version 2024-01-20 10:50:42 +01:00
Ayke van Laethem ee3106be98 reflect: update to Go 1.22 semantics
The IsZero function was changed slightly in Go 1.22, so we'll need to
update it.

While this could in theory break existing programs that rely on the old
behavior, they'd also break with the imminent Go 1.22 release so I don't
think this is a real problem.
2024-01-20 08:53:49 +01:00
Ayke van Laethem 57f49af726 loader: make sure Go version is plumbed through
This fixes the new loop variable behavior in Go 1.22.

Specifically:
  * The compiler (actually, the x/tools/go/ssa package) now correctly
    picks up the Go version.
  * If a module doesn't specify the Go version, the current Go version
    (from the `go` tool and standard library) is used. This fixes
    `go run`.
  * The tests in testdata/ that use a separate directory are now
    actually run in that directory. This makes it possible to use a
    go.mod file there.
  * There is a test to make sure old Go modules still work with the old
    Go behavior, even on a newer Go version.
2024-01-19 21:23:58 +01:00
Ayke van Laethem 38a80b45d3 all: support Go 1.22
This adds initial support for Go 1.22. Not all new features are
supported yet.
2024-01-19 13:51:40 +01:00
Ayke van Laethem e9003e2deb runtime: add runtime.rand function
This function is needed for Go 1.22, and is used from various packages
like math/rand.

When there is no random number generator available, it falls back to a
static sequence of numbers. I think this is fine, because as far as I
can see it is only used for non-cryptographic needs.
2024-01-19 13:46:27 +01:00
Ayke van Laethem 204659bdcd reflect: add TypeFor[T]
This function was added in Go 1.22. See:
https://github.com/golang/go/commit/42d2dfb4305aecb3a6e5494db6b8f6e48a09b420
2024-01-19 13:46:27 +01:00
Ayke van Laethem 08ca1d13d0 loader: enforce Go language version in the type checker
This means for example that ranging over integers will only work when
setting the Go version to go1.22 or later in the go.mod file.
2024-01-19 13:46:27 +01:00
Ayke van Laethem 53db436a7d cgo: add file AST for fake C file locations
This is needed for the type checker, otherwise it doesn't know which Go
version it should use for type checking.
2024-01-18 20:19:15 +01:00
Ayke van Laethem 0ad15551c8 compiler: update golang.org/x/tools/go/ssa package
This update includes support for the new range loops over integers.
2024-01-18 19:51:52 +01:00
Ayke van Laethem afd65e224a bytealg: update to Go 1.22
A few non-generic functions like HashStrBytes have been kept for
backwards compatibility, so this package should continue to work with
older Go versions (as long as they support generics).
2024-01-17 13:39:57 +01:00
deadprogram 5f50c3b60b machine/samd51: add UART hardware flow control support
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-17 12:41:15 +01:00
deadprogram 8858d49989 targets: add ninafw tag to Arduino mkrwifi1010 and Adafruit Matrix Portal M4 for drivers netlink support
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-15 19:34:05 -05:00
deadprogram cf39d8b2c8 targets: add ninafw pins and settings to Adafruit PyBadge board with AirLift Featherwing
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-15 19:34:05 -05:00
deadprogram d92a31b440 targets: add ninafw pins and settings to Adafruit Metro M4 Airlift board
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-15 19:34:05 -05:00
deadprogram 9c77a38358 build: use llvm-17 base image correctly for faster docker dev builds
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-12 19:23:33 +01:00
Ayke van Laethem d0445d6f83 cgo: fix calling CGo callback inside generic function
The package of the generic function might not be set, so we have to call
Origin() for it.

Found while porting mcufont to TinyGo.
2024-01-12 14:54:42 +01:00
BCG a40b11f535 Adding additional build tag for boards with ninafw 2024-01-07 16:06:16 +01:00
deadprogram 8c90f4facf machine/pyportal: add needed values to board file for ninafw BLE support
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-06 22:46:47 +01:00
deadprogram c7c9a76af5 build: add step to build LLVM 17 base image
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-05 21:13:30 +01:00
Ayke van Laethem 6984af43a0 all: statically link to LLVM 17 instead of LLVM 16
We can now finally do it, now that Espressif has updated their fork.
2024-01-05 21:13:30 +01:00
deadprogram 81c56c3ab8 machine, targets: ninafw support for arduino-nano33 and nano-rp2040 boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-05 19:04:12 +01:00
deadprogram 3d9a1ca22a machine/samd21: add hardware flow control for UART
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-05 17:56:45 +01:00
deadprogram c2083014b3 targets: add ninafw tag to nano-rp2040 for ninafw BLE support
Signed-off-by: deadprogram <ron@hybridgroup.com>
2024-01-03 23:28:28 -05:00
Scott Feldman 603a81f194 expose UART4 on wioterminal board
The right-hand grove port on the wioterminal can be used as UART, using
D0/D1 pins.  The pins D0/D1 are tied to SERCOM4, so this patch exposes a
UART4 for sercom4 access.

  RX = A0/D0 = PB08/SERCOM4.0 (port 4 pad 0)
  TX = A1/D1 = PB09/SERCOM4.1 (port 4 pad 1)

Tested with Lora E5 UART.

  uart : = machine.UART4
  tx := machine.D0
  rx := machine.D1

Note: must also cross Tx/Rx wires in grove cable.  See
https://www.lucadentella.it/en/2022/01/29/wio-terminal-porta-grove-di-destra-e-moduli-uart/
2023-12-31 10:54:11 +01:00
Elias Naur cfc32794a7 os/user: add bare-bones implementation of the os/user package
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2023-12-30 10:56:23 +01:00
Elias Naur 1d9c53d00e nix: upgrade to NixOS 23.11
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2023-12-24 16:32:16 +01:00
Ayke van Laethem 8d2a07b927 main: add -serial=rtt support 2023-12-23 08:14:35 -05:00
deadprogram ffe6dfd21b machine/nano-rp2040: add UART1 and correct mappings for NINA via UART.
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-20 16:51:21 -05:00
deadprogram cf21380264 machine/serial, rp2040: add support for hardware flow control
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-20 16:48:12 -05:00
deadprogram 534b3b0c0b net: update to latest main branch with accept fix
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-19 08:16:40 +01:00
deadprogram ceeb233ff6 build: another try to handle python unlink/link due to homebrew
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-18 20:23:19 +01:00
deadprogram de3f0af829 build: fix for macos homebrew as discussed in https://github.com/Homebrew/brew/issues/15621
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-17 21:26:23 +01:00
Scott Feldman a511f18c64 stub out more types/funcs to compile against golang.org/x/net/internal/socket (#4037)
* stub out more types/funcs to compile against golang.org/x/net/internal/socket

These are changes need to compile github.com/domainr/dnsr/ with TinyGo.
See issue https://github.com/tinygo-org/net/issues/14.

These change are mostly to fix missing symbols in src/crypto/tls and
src/net.  Missing types and functions are cut-and-pasted from go1.21.4.
Functions are stubbed out returning errors.New("not implemented").

DNRS is compiled by running tinygo test:

   sfeldma@nuc:~/work/dnsr$ tinygo test -target=wasi

With this patch, and a corresponding patch for tinygo-org/net to fixup
src/net, you should get a clean compile.
2023-12-17 15:32:53 +01:00
deadprogram 731bd5cd1b net: update to latest main branch with TCPListener
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-09 12:11:04 +01:00
deadprogram 4acf59546e modules: update net submodule to latest commit with http Client Transport interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-09 09:48:29 +01:00
deadprogram 2ee4d9aaa1 builder/picolib: add needed file for compiling math functions with error support.
Thanks to @aykevl for actually finding and providing this fix, I really just
reported the problem and tested the fix.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-09 07:47:27 +01:00
deadprogram b58b7c59ae runtime: stub out Breakpoint() function
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-08 21:10:26 +01:00
deadprogram e14b6a7009 lib/cmsis-svd: change to new repo location for the SVD files
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-07 14:38:36 +01:00
deadprogram a1a2d1ab81 modules: switch to main branch of net submodule
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-06 13:11:44 +01:00
Scott Feldman 07591178cd move syscall constants for networking into net space to avoid windows build issue 2023-12-06 13:11:44 +01:00
Scott Feldman 43bdc888dd move IPPROTO_TLS to netdev to avoid src/syscall dependency 2023-12-06 13:11:44 +01:00
Scott Feldman 4229e670ce Add network device driver model, netdev
This PR adds a network device driver model called netdev. There will be a companion PR for TinyGo drivers to update the netdev drivers and network examples. This PR covers the core "net" package.

An RFC for the work is here: #tinygo-org/drivers#487. Some things have changed from the RFC, but nothing major.

The "net" package is a partial port of Go's "net" package, version 1.19.3. The src/net/README file has details on what is modified from Go's "net" package.

Most "net" features are working as they would in normal Go. TCP/UDP/TLS protocol support is there. As well as HTTP client and server support. Standard Go network packages such as golang.org/x/net/websockets and Paho MQTT client work as-is. Other packages are likely to work as-is.

Testing results are here (https://docs.google.com/spreadsheets/d/e/2PACX-1vT0cCjBvwXf9HJf6aJV2Sw198F2ief02gmbMV0sQocKT4y4RpfKv3dh6Jyew8lQW64FouZ8GwA2yjxI/pubhtml?gid=1013173032&single=true).
2023-12-06 13:11:44 +01:00
deadprogram 76a7ad2a3e modules: add tinygo net package as submodule
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-06 13:11:44 +01:00
deadprogram e4f551ac7f src/net: remove existing files to replace with submodule
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-06 13:11:44 +01:00
Yurii Soldak 338590cc75 machine/atmega: uart double speed mode
Less errors and higher throughput.
Example: default / slow mode is problematic for 115200 on 16Mhz CPU.
2023-12-05 16:29:51 +01:00
deadprogram 22d70604d8 sizediff: cleanup before checkout of branche to allow for new/removed files to be able to still run thru size tests
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-04 18:26:00 +01:00
deadprogram c6add1e769 machine/esp32c3: implement RNG
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-04 09:34:20 +01:00
deadprogram c6609a02fa machine/esp32c3: move i2c implementation into separate file to skip m5stamp-c3 since it does not appear to expose those pins
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-03 22:05:08 +01:00
deadprogram a449c4813a build: can only build boards with board files for pin mapping
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-03 22:05:08 +01:00
deadprogram 19fb1bfafc machine/esp32c3: corrected implementation for error handling and when to expect NACK
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-03 22:05:08 +01:00
deadprogram f91b6ad0df machine/esp32c3: handle defaults for I2C configuration
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-12-03 22:05:08 +01:00
Dmitriy 94459cefe5 machine/esp32c3: implement i2c for esp32-c3 2023-12-03 22:05:08 +01:00
Yurii Soldak 803ba4f54d tools/sizediff: cleanup and calculate ram 2023-12-03 20:08:48 +01:00
Yurii Soldak 2919fa8b14 machine/atmega: bufferSize = 32
to save memory on 2k ram targets
also updates sizediff tool to show ram differences
2023-12-03 12:55:22 +01:00
Yurii Soldak 6420e90124 machine/atmega328pb: refactor to enable extra uart 2023-12-02 13:26:59 +01:00
deadprogram 2d289addb7 builds: update all GH action workflows to use latest versions
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-11-29 08:58:27 +01:00
sago35 4df145dcb4 m5stamp-c3: change settings to explicitly use UART 2023-11-29 08:11:46 +01:00
deadprogram e065da20cb targets: add Adafruit qtpy-esp32c3 board support
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-11-28 23:57:30 +01:00
deadprogram d7c77b6761 machine/esp32c3: implement USB_SERIAL for USBCDC communication
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-11-28 23:05:07 +01:00
deadprogram f51029484a builds: free space before doing docker build job
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-11-28 20:56:08 +01:00
deadprogram 03cfcbc17c docker: makefile was renamed but did not show error util cache was busted
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-11-28 19:52:43 +01:00
deadprogram 649f49e000 docker: remove lists after update to reduce image size
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-11-28 19:52:43 +01:00
deadprogram 3bcd4dc3e0 lib/cmsis-svd: switch to new location and latest version of shared SVD repository
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-11-25 15:34:20 +01:00
deadprogram 772c71ec27 make/gen-device-esp: change order of generating ESP32 device wrappers to avoid community ESP32 being overwritten by the official one
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-11-25 15:34:20 +01:00
Rado M 9b896dc981 refactor: reuse OptLevel() to get the opt level 2023-11-24 16:19:18 +01:00
Scott Feldman d4189feca6 Bump default stack size for target pico to 8kb from 2kb 2023-11-12 19:22:50 +01:00
Damian Gryski 777048cfa9 compiler: fix crash on type assert on interfaces with no methods 2023-11-08 19:41:25 +01:00
sago35 2b215955ca machine/usb: add support for ISERIAL descriptor 2023-11-07 00:11:40 +01:00
Elliott Sales de Andrade ce25f00769 Bump wasi-libc to SDK 20
The version 17 SDK adds `getpagesize`, so use it instead of hardcoding a
number (even if their implementation is _also_ a hardcoded number.)
2023-11-04 23:32:42 +01:00
Elliott Sales de Andrade 1a59aecb63 Point wasi-libc submodule to new location. 2023-11-04 23:32:42 +01:00
Shane O'Donovan cca32e67a9 reflect: stub FuncOf() 2023-11-04 22:44:56 +01:00
Randy Reddig 174d492355 compileopts, targets, main: support Wasmtime v14 (#3972)
compileopts, targets, main: support Wasmtime v14
2023-11-02 19:49:52 +01:00
Christian Ege 5355473dce doc: fix a typo in the rtcinterrupt example (#3981)
docs: fix a typo in the rtcinterrupt example, also provide a link to the interrupt online doc
2023-11-02 18:13:22 +01:00
sago35 a531ed614a main, compileopts: move GetTargetSpecs() to compileopts package 2023-11-02 15:37:43 +01:00
sago35 24ae6fdf29 main: add -info option to tinygo monitor 2023-11-02 15:37:43 +01:00
deadprogram 938ce22307 machine/stm32: implement DeviceID() with unique ID per processor
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-27 17:44:53 +02:00
Kenneth Bell 9fb5a5b9a4 nrf,sam,rp2040: add machine.HardwareID function 2023-10-27 13:25:32 +02:00
deadprogram 9fd9d9c05a compileopts: add cflag '-isystem' for resource directory search since needed for Xtensa
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-25 08:57:39 +02:00
deadprogram fd50227a3d build: pin wasmtime version used for testing to v13.0.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-24 13:10:09 +02:00
Kenneth Bell a90295430c ci: work-around for broken links in github runners 2023-10-23 21:25:41 +02:00
deadprogram fa4ca63ff2 machine/spi: use interface to ensure uniformity for all machine implementations
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-17 13:41:32 +02:00
Flavio Castelli 7019c4e8fc Binaryen116 (#3958)
dependencies: update binaryen submodule to version 116

Signed-off-by: Flavio Castelli <fcastelli@suse.com>
Co-authored-by: DarkByteBen <ben@darkbytelabs.com>
2023-10-16 18:34:20 +02:00
deadprogram b79e0e8528 docs: add Nix badge for builds to README
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-15 21:02:25 +02:00
Ayke van Laethem 51bed3afae nix: fix md5sum on MacOS
The default on MacOS is `md5`, while Nix only has `md5sum` available.
Therefore, make it possible to override the variable via the environment
so that flake.nix can set the correct binary name.
2023-10-15 17:51:13 +02:00
Ayke van Laethem 4d4ccddad8 nix: support make wasi-libc on MacOS 2023-10-15 17:51:13 +02:00
Ayke van Laethem f55f5315cc builder: generalize build ID fallback to darwin
This is to support NixOS, who have added -no_uuid to the linker.
Upstream bug report: https://github.com/NixOS/nixpkgs/issues/178366
2023-10-15 17:51:13 +02:00
Ayke van Laethem 7468a00ef4 all: fix a small incompatibility with Nix
Hopefully this won't break anybody: while all tests still pass, there
could in theory be systems where not supplying those libraries leads to
linker errors.
2023-10-15 17:51:13 +02:00
ginglis13 8d77278c6b refactor: rm io/ioutil funcs
io/ioutil has been deprecated since Go 1.16
https://pkg.go.dev/io/ioutil

Signed-off-by: ginglis13 <ginglis05@gmail.com>
2023-10-15 12:12:07 +02:00
Ayke van Laethem dde9b5ad3a goenv: re-add support for Clang headers on darwin
When TinyGo is installed using `go install` or `go build`, it uses the
Clang resource directory from the host. This works for Linux, but
doesn't work anymore on macOS with a recent change I made.

This re-adds support for Darwin in that case (with much, much simpler
code than there used to be).
2023-10-15 10:51:06 +02:00
Ayke van Laethem 2d4307647e nix: improve docs and add support for wasi-libc
I forgot a few things in the flake file, but now everything should be
included.
2023-10-14 17:32:56 +02:00
Ron Evans 935a293106 machine/i2c: add interface check and implementation where missing for SetBaudRate() (#3406)
* machine/i2c: add interface check and placeholder implementation where missing for SetBaudRate()
2023-10-14 13:17:24 +02:00
Ayke van Laethem 72b715fa99 all: add Nix flake file
This adds a flake.nix file that makes it possible to quickly create a
development environment.

You can download Nix here, for use on your Linux or macOS system:
https://nixos.org/download.html

After you have installed Nix, you can enter the development environment
as follows:

    nix develop

This drops you into a bash shell, where you can install TinyGo simply
using the following command:

    go install

That's all! Assuming you've set up your $PATH correctly, you can now use
the tinygo command as usual:

    tinygo version

You can also do many other things from this environment. Building and
flashing should work as you're used to: it's not a VM or container so
there are no access restrictions.
2023-10-14 11:35:26 +02:00
Ayke van Laethem d801d0cd53 builder: refactor clang include headers
Set -resource-dir in a central place instead of passing the header path
around everywhere and adding it using the `-I` flag. I believe this is
closer to how Clang is intended to be used.

This change was inspired by my attempt to add a Nix flake file to
TinyGo.
2023-10-14 11:35:26 +02:00
Anuraag Agrawal c2f1965e03 Fix bitstring order in precise GC docs (#3947)
docs: Fix bitstring order in precise GC docs
2023-10-13 08:57:30 +02:00
sago35 75bba42b60 goenv: update to new v0.31.0 development version 2023-10-11 02:24:58 +02:00
Ayke van Laethem 18b50db0dc all: add initial LLVM 17 support
This allows us to test and use LLVM 17, now that it is available in
Homebrew.

Full support for LLVM 17 (including using it by default) will have to
wait until Espressif rebases their Xtensa fork of LLVM.
2023-10-06 09:05:07 +02:00
Ayke van Laethem 499fce9cee avr: don't compile large parts of picolibc (math, stdio)
These parts aren't critical and lead to crashes on small chips without
long jumps (like the attiny85) with LLVM 17. (Older LLVM versions would
emit long jumps regardless, even if the chip didn't support those).

For more information, see: https://github.com/llvm/llvm-project/issues/67042
2023-10-06 09:05:07 +02:00
deadprogram 88b29589d6 targets: increase default stack size to 64k for wasi/wasm targets
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-10-04 22:43:14 +02:00
Ayke van Laethem 8cbfbcae5a build: avoid sharing GlobalValues between build instances
This happens with `tinygo test` for example when testing multiple
packages at the same time. I found this because the compiler crashed in
`make tinygo-test-fast`:

    fatal error: concurrent map writes
    fatal error: concurrent map read and map write

    goroutine 15 [running]:
    github.com/tinygo-org/tinygo/builder.Build({0x40002d0be0, 0xa}, {0x0, 0x0}, {0x4000398048, 0x14}, 0x40003b0000)
            /home/ayke/src/tinygo/tinygo/builder/build.go:131 +0x388
    main.buildAndRun({0x40002d0be0, 0xa}, 0x40003b0000, {0x8bc178, 0x40003a4090}, {0x0, 0x0, 0x0}, {0x0, 0x0, ...}, ...)
            /home/ayke/src/tinygo/tinygo/main.go:856 +0x45c
    main.Test({0x40002d0be0, 0xa}, {0x8bc118, 0x40000b3a08}, {0x0?, 0x0?}, 0x40001e6000, {0x0, 0x0})
            /home/ayke/src/tinygo/tinygo/main.go:270 +0x758
    main.main.func3()
            /home/ayke/src/tinygo/tinygo/main.go:1718 +0xe4
    created by main.main in goroutine 1
            /home/ayke/src/tinygo/tinygo/main.go:1712 +0x34ec

My solution is essentially to copy the map over instead of modifying it
directly.

I've also moved the code up a little, because I think that's a more
sensible place (out of the way of the whole package compile logic).
2023-10-04 16:20:32 +02:00
Ayke van Laethem 5cd8ba2421 all: refactor goenv.Version to add the git sha1 if needed
Previously all (except one!) usage of goenv.Version manually added the
git sha1 hash, leading to duplicate code. I've moved this to do it all
in one place, to avoid this duplication.
2023-10-04 16:20:32 +02:00
Ayke van Laethem 2320b18953 ci: use matrix instead of duplicating the Linux cross job
This reduces a lot of copy-pasted code (that was in fact different in a
small way!)
2023-10-04 14:21:43 +02:00
Ayke van Laethem 3b1913ac57 all: use the new LLVM pass manager
The old LLVM pass manager is deprecated and should not be used anymore.
Moreover, the pass manager builder (which we used to set up a pass
pipeline) is actually removed from LLVM entirely in LLVM 17:
https://reviews.llvm.org/D145387
https://reviews.llvm.org/D145835

The new pass manager does change the binary size in many cases: both
growing and shrinking it. However, on average the binary size remains
more or less the same.

This is needed as a preparation for LLVM 17.
2023-10-04 13:05:58 +02:00
Ayke van Laethem 1da1abe314 all: remove LLVM 14 support
This is a big change: apart from removing LLVM 14 it also removes typed
pointer support (which was only fully supported in LLVM up to version
14). This removes about 200 lines of code, but more importantly removes
a ton of special cases for LLVM 14.
2023-10-01 18:32:15 +02:00
ayan george c9721197d5 bulid: Rename Makefile to GNUmakefile
Prior to this commit, the build instructions were encoded in Makefiles
that contained GNU extensions that are unique to GNU Make and
incompatible with older implementations.

Thie commit renames all Makefiles to GNUmakefile which clearly denotes
that the file contains GNU extensions.

GNU Make actually first looks for a GNUmakefile, then makefile, THEN
Makefile so in addition to simply being more correct and portable, it
saves a few unnecessary failed attempts to open the correct build
file.
2023-10-01 14:55:34 +02:00
ayan george 738747bd05 build: use $(MAKE) to represent make executable
Prior to this commit, our Makefiles assumed the name of the make program
was simply "make".

Since we use GNU make extensions, this isn't always the case --
operating systems like FreeBSD come with their own implementation named
make which can be incompatible with the extensions used in by tinygo.

To run a compatible make on some of these systems, we have explicitly
call GNU make by running gmake.

This commit changes references to the command "make" to "$(MAKE)" which
is a variable that contains the name of the executable invoked to
process the Makefile.

This allow the Makefiles to be uniformly processed by the same make
program.
2023-10-01 14:55:34 +02:00
ayan george 0bb4a8abeb docs: Update BUILDING.md
Indicate that GNU Make is the version of make required to build.
2023-09-29 17:45:59 +02:00
Ayke van Laethem 6ef8fcd537 cgo: add C._Bool type
This fixes https://github.com/tinygo-org/tinygo/issues/3926.

While working on this I've found another bug: if C.bool is referenced
from within Go, it isn't available anymore on the C side. This is an
existing bug that also applies to float and double, but may be less
likely to be triggered there.
This bug is something to be fixed at a later time (it has something to
do with preprocessor defines).
2023-09-24 07:41:26 -07:00
Ayke van Laethem a896f7f218 transform: fix bug in StringToBytes optimization pass
Previously, this pass would convert any read-only use of a
runtime.stringToBytes call to use the original string buffer instead.
This is incorrect: if there are any writes to the resulting buffer, none
of the slice buffer pointers can be converted to use the original
read-only string buffer.

This commit fixes that bug and adds a test to prove the new (correct)
behavior.
2023-09-23 07:48:43 -07:00
Ayke van Laethem 081d2e58c6 interp: print LLVM instruction in traceback
The old traceback would look like this:

    # internal/godebug
    /usr/local/go/src/internal/godebug/godebug.go:101:11: interp: test
    call <2> 0 <3> 0

    traceback:
    /usr/local/go/src/internal/godebug/godebug.go:101:11:
    call <2> 0 <3> 0
    /usr/local/go/src/internal/godebug:
    call <1> 0

With this patch, it looks like this:

    # io/fs
    /usr/local/go/src/io/fs/fs.go:144:45: interp: test
      %0 = load %runtime._interface, ptr @"internal/oserror.ErrInvalid", align 8, !dbg !316

    traceback:
    /usr/local/go/src/io/fs/fs.go:144:45:
      %0 = load %runtime._interface, ptr @"internal/oserror.ErrInvalid", align 8, !dbg !316
    /usr/local/go/src/io/fs/fs.go:137:28:
      %0 = call %runtime._interface @"io/fs.errInvalid"(ptr undef), !dbg !317

For developers (like me) who are familiar with LLVM, this is probably
easier to read. For users, I'm not sure: the instructions have quite a
lot of distracting fluff in them. But at least it contains the function
names that are called (which are not currently present in the old
traceback).
...that said, having the LLVM instructions in a bug report is probably
going to be easier for people who are familar with LLVM.
2023-09-22 15:28:52 +02:00
Ayke van Laethem ed2a98c7d0 ci: redo LLVM build on Windows
MinGW got updated, so it looks like we need to do a new LLVM build.
2023-09-21 21:33:34 +02:00
Ayke van Laethem 731532cd2b all: release 0.30.0
This is a small release just in time for GopherCon US.

Some of the big changes of this release are:

  - switch to LLVM 16
  - fixes for two separate hard-to-reproduce compiler crashes
  - added support for the Adafruit Gemma M0
2023-09-21 08:03:16 +02:00
Kenneth Bell adadbadec3 interp: improve unknown opcode handling 2023-09-21 01:18:05 +02:00
Kenneth Bell 58fafaeb5c build: #3893 do not return LLVM structs from Build 2023-09-21 01:18:05 +02:00
Dan Kegel 13a8eae0d4 build: build Go SSA serially [issue 3895]
From
https://github.com/tinygo-org/tinygo/pull/3915#issuecomment-1724405109

According to Ayke, it slows down the build but seems to reliably fix https://github.com/tinygo-org/tinygo/issues/3895
2023-09-20 23:22:18 +02:00
Ayke van Laethem 42da7654ec compiler: don't use types in the global context
This usually works by chance, but leads to crashes. So we should never
ever do this.

I'm pretty sure this is the crash behind this issue: https://github.com/tinygo-org/tinygo/issues/3894

It may also have caused this crash: https://github.com/tinygo-org/tinygo/issues/3874

I have a suspicion this is also behind the rather crash-prone CircleCI
jobs, that we haven't been able to find the source of. But we'll find
out soon enough once this fix is merged.

To avoid hitting this issue again in the future, I've created a PR to
remove these dangerous functions altogether from the go-llvm API:
https://github.com/tinygo-org/go-llvm/pull/54
2023-09-19 09:21:51 +02:00
Ayke van Laethem 8698a7e496 all: default to LLVM 16
So that `go install` works on MacOS with Homebrew (and on Linux with an
up-to-date distro).
2023-09-18 21:58:02 +02:00
Ayke van Laethem 1d7543e2bf all: switch to LLVM 16
This commit adds support for LLVM 16 and switches to it by default. That
means three LLVM versions are supported at the same time: LLVM 14, 15,
and 16.

This commit includes work by QuLogic:

  * Part of this work was based on a PR by QuLogic:
    https://github.com/tinygo-org/tinygo/pull/3649
    But I also had parts of this already implemented in an old branch I
    already made for LLVM 16.
  * QuLogic also provided a CGo fix here, which is also incorporated in
    this commit:
    https://github.com/tinygo-org/tinygo/pull/3869

The difference with the original PR by QuLogic is that this commit is
more complete:
  * It switches to LLVM 16 by default.
  * It updates some things to also make it work with a self-built LLVM.
  * It fixes the CGo bug in a slightly different way, and also fixes
    another one not included in the original PR.
  * It does not keep compiler tests passing on older LLVM versions. I
    have found this to be quite burdensome and therefore don't generally
    do this - the smoke tests should hopefully catch most regressions.
2023-09-18 21:58:02 +02:00
deadprogram ff32fbbb4f targets: increase default stack size to 32k for wasi/wasm targets
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-09-17 14:24:21 +02:00
sago35 3ad2530ee7 atsamd21, atsamd51: add support for USB INTERRUPT OUT 2023-09-16 09:30:05 +02:00
deadprogram c4de195f04 machine/rp2040: always use the USB device enum fix, even in chips that supposedly have the HW fix.
Additionally, correct the amount of time spent waiting after USB reset, based on advice from @sago35

Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-09-12 08:41:58 +02:00
Timothy Rule 75aca0f5ee Board support for Adafruit Gemma M0 (#3903)
machine, targets: Board support for Adafruit Gemma M0
2023-09-11 11:11:26 +02:00
Elliott Sales de Andrade bb9a9beed5 Update golang.org/x/tools to v0.12.0 2023-09-10 23:14:58 +02:00
Elliott Sales de Andrade 4042c1d618 Update tools to 0.9.0
This requires updating test data, due to the change noted in the
previous commit.
2023-09-10 23:14:58 +02:00
Elliott Sales de Andrade bf73516259 compiler: Handle nil array and struct constants
This is necessary for tools 0.9.0, which started lifting those since
https://github.com/golang/tools/commit/71ea8f168c160da91116b4ddbd577a8fc95aa334
2023-09-10 23:14:58 +02:00
deadprogram 43d282174f targets: add GoBadge target as alias for PyBadge :)
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-09-10 15:52:55 +02:00
Damian Gryski 0042bf62a5 compiler,reflect: add support for [...]T -> []T in reflect 2023-09-10 13:05:18 +02:00
Ayke van Laethem f11731ff35 interp: don't copy unknown values in runtime.sliceCopy
This was bug https://github.com/tinygo-org/tinygo/issues/3890.
See the diff for details. Essentially, it means that `copy` in the
interpreter was copying data that wasn't known yet, or copying data into
a slice that could be read externally after the interp pass.
2023-09-10 11:30:09 +02:00
sago35 e9d8a9bc0b goenv: update to new v0.30.0 development version 2023-09-08 17:41:31 +02:00
deadprogram 9d6eb1ff06 machine/usb/adc/midi: improve implementation to include several new messages
such as program changes and pitch bend. Also add error handling for invalid
parameter values such as MIDI channel. This however makes a somewhat breaking
change to the current implementation, in that we now use the typical MIDI user
system of counting MIDI channels from 1-16 instead of from 0-15 as the lower
level USB-MIDI API itself expects.

Also add constant values for continuous controller messages, rename SendCC
function, and add SysEx function.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-09-07 08:41:57 +02:00
Ayke van Laethem 4643401a1d runtime: refactor markGlobals to findGlobals
Instead of markGlobals calling markRoots unconditionally (which doesn't
make sense for -gc=none and -gc=leaking), provide markRoots as a
callback function.

This is in preparation for -gc=boehm, where the previous design is even
more awkward and a callback makes far more sense.

I've tested the size impact using `make smoketest XTENSA=0`. There is
none, except for two cases:

  * One with `-opt=0` so const-propagation for the callback didn't take
    place.
  * One other on AVR, I don't know why but as it's only 16 bytes in a
    very specific case I'm going to assume it's just a random change in
    compiler output that caused a size difference.
2023-09-05 00:42:01 +02:00
deadprogram dc449882ad docs: update CHANGELOG for release 0.29
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-25 15:57:40 +02:00
deadprogram a158d3194f all: update version for 0.29 release
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-25 15:57:40 +02:00
Pertti Erkkilä 806498f099 nRF52: set SPI TX/RX lengths even data is empty. Fixes #3868 (#3877)
machine/hrf: Set SPI TX/RX lengths even data is empty. Fixes #3868
2023-08-24 13:15:18 +02:00
deadprogram e3bc6da9e4 make: add task to check NodeJS version before running tests
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-19 20:04:10 +02:00
Pierre Constantineau 3e2471d934 adding new uf2 target for PCA10056 (#3765)
targets: adding new uf2 target for PCA10056
2023-08-19 11:06:17 +02:00
Ayke van Laethem a545f17d2e wasm: add support for GOOS=wasip1
This adds true GOOS=wasip1 support in addition to our existing
-target=wasi support. The old support for WASI isn't removed, but should
be treated as deprecated and will likely be removed eventually to reduce
the test burden.
2023-08-17 18:16:54 +02:00
Kenneth Bell f4375d0452 samd51,rp2040,nrf528xx,stm32: implement watchdog 2023-08-15 11:50:07 +02:00
deadprogram 756cdf44ed loader: merge go.env file which is now required starting in Go 1.21 to correctly get required packages
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-13 17:11:11 +02:00
Ayke van Laethem 9037bf8bf0 main: add target JSON file in tinygo info output
It looks like this on my system, for example:

    {
      "target": {
        "llvm-target": "aarch64-unknown-linux",
        "cpu": "generic",
        "features": "+neon",
        "goos": "linux",
        "goarch": "arm64",
        "build-tags": [
          "linux",
          "arm64"
        ],
        "gc": "precise",
        "scheduler": "tasks",
        "linker": "ld.lld",
        "rtlib": "compiler-rt",
        "libc": "musl",
        "default-stack-size": 65536,
        "ldflags": [
          "--gc-sections"
        ],
        "extra-files": [
          "src/runtime/asm_arm64.S",
          "src/internal/task/task_stack_arm64.S"
        ],
        "gdb": [
          "gdb"
        ],
        "flash-1200-bps-reset": "false"
      },
      "goroot": "/home/ayke/.cache/tinygo/goroot-23c311bcaa05f188affa3c42310aba343acc82562d5e5f04dea9d5b79ac35f7e",
      "goos": "linux",
      "goarch": "arm64",
      "goarm": "6",
      ...
    }

This can be very useful while working on the automatically generated
target object for example (in my case, GOOS=wasip1).
2023-08-13 15:27:21 +02:00
deadprogram bfe9ee378f rp2040: move flash related functions into separate file from C imports for correct LSP. Fixes #3852
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-13 14:08:57 +02:00
deadprogram 37a4fa205c modules: update to go-serial package v1.6.0
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-11 18:21:05 +02:00
deadprogram 59cc7d4c42 docker: use Go 1.21 for Docker dev container build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-11 17:35:43 +02:00
deadprogram ab64e215dd build: switch GH actions builds to use Go 1.21 final release
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-10 12:45:52 +02:00
deadprogram 253dbe335a builder: update message for max supported Go version
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-08-09 19:27:15 +02:00
Unrud 0ef86e1534 Add support for HID Keyboard LEDs 2023-08-07 14:00:32 +02:00
Kenneth Bell 72270f9052 all: use https for renesas submodule #3856 2023-08-07 10:29:31 +02:00
sago35 67ec722a74 board: add AKIZUKI DENSHI AE-RP2040 2023-08-04 17:53:01 +02:00
Ayke van Laethem 62294feb56 compiler: improve panic message when a runtime call is unavailable
This should not happen under normal circumstances. It can still happen
when there is a mismatch between TinyGo version and the associated
runtime, or while developing the compiler package.
2023-08-04 11:59:11 +02:00
Ayke van Laethem f1e25a18d2 compiler: implement clear builtin for maps 2023-08-04 11:59:11 +02:00
Ayke van Laethem a2f886a67a compiler: implement clear builtin for slices 2023-08-04 11:59:11 +02:00
Ayke van Laethem f791c821ff compiler: add min and max builtin support 2023-08-04 11:59:11 +02:00
Ayke van Laethem a93f0ed12a all: Go 1.21 support 2023-08-04 11:59:11 +02:00
Ayke van Laethem c25dd0a972 testing: add Testing function
This is new in Go 1.21.
2023-08-04 11:59:11 +02:00
sago35 215dd3f0be machine/usb/hid: rename Handler() to TxHandler() 2023-08-04 09:43:53 +02:00
sago35 c51f5cea0b machine/usb/hid: add RxHandler interface 2023-08-04 09:43:53 +02:00
sago35 395ee2d338 machine/usb: refactor endpoint configuration 2023-08-02 09:16:29 +02:00
sago35 069e4f0d98 machine/usb: allow USB Endpoint settings to be changed externally 2023-08-02 09:16:29 +02:00
sago35 d1eb642d45 machine/usb: remove usbDescriptorConfig 2023-08-01 15:24:42 +02:00
Charlie Haley 5f2e72f371 compiler: add compiler-rt to wasm.json 2023-08-01 09:56:58 +02:00
Charlie Haley 5b581d83b3 compiler: add compiler-rt and wasm symbols to table 2023-07-31 14:52:26 +02:00
Ayke van Laethem d845f1e1b2 wasm: fix functions exported through //export
When a function is exported using //export, but also had a
//go:wasm-module pragma, the //export name was ignored. The
//go:wasm-module doesn't actually do anything besides breaking the
export (exported functions don't have a module name).

I've refactored and cleaned up the code, and in the process removed this
weird edge case.
2023-07-28 13:57:24 +02:00
Yurii Soldak 00d46bd25d avr: pin change interrupt 2023-07-27 18:15:22 +02:00
deadprogram 01d2ef327d sync: add implementation from upstream Go for OnceFunc, OnceValue, and OnceValues
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-07-20 08:09:03 +02:00
soypat 4da1f6bcbe rp2040:add NoPin support 2023-07-16 16:25:30 +02:00
Ayke van Laethem 14ddba8519 nrf: add I2C timeout
This commit adds I2C timeouts for nrf51 and nrf52 (but not yet for
others like nrf52840).

Tested on the PineTime, where I now got a timeout instead of hanging and
resetting due to a watchdog reset.
2023-07-16 10:27:33 +02:00
Patricio Whittingslow a7b205c26c machine.UART refactor (#3832)
* add gosched calls to UART

* add UART.flush() stubs for all supported architectures

* add comment un uart.go on flush functionality

* uart.writeByte as base of UART usage

* fix NXP having duplicate WriteByte

* fix writeByte not returning error on some platforms

* add flush method for fe310 device

* check for error in WriteByte call to writeByte
2023-07-15 11:24:53 -03:00
deadprogram c83f712c17 machine/rp2040: wait for 1000 us after flash reset to avoid issues with busy USB bus
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-07-07 22:13:26 +02:00
Ayke van Laethem fffad84a63 reflect: add SetZero
This was added in Go 1.20 and is required by encoding/json starting with
Go 1.21.
2023-07-07 18:12:57 +02:00
Ayke van Laethem e075e0591d main: use go env instead of doing all detection manually
This replaces our own manual detection of various variables (GOROOT,
GOPATH, Go version) with a simple call to `go env`.

If the `go` command is not found:

    error: could not find 'go' command: executable file not found in $PATH

If the Go version is too old:

    error: requires go version 1.18 through 1.20, got go1.17

If the Go tool itself outputs an error (using GOROOT=foobar here):

    go: cannot find GOROOT directory: foobar

This does break the case where `go` wasn't available in $PATH but we
would detect it anyway (via some hardcoded OS-dependent paths). I'm not
sure we want to fix that: I think it's better to tell users "make sure
`go version` prints the right value" than to do some automagic detection
of Go binary locations.
2023-07-07 16:55:59 +02:00
Achille Roussel 46d2696363 wasi: allow zero inodes when reading directories
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-07-07 09:56:38 +02:00
Ayke van Laethem e98dfd6c46 reflect: implement Value.Grow
This was added in Go 1.20 and becomes necessary for encoding/json in Go
1.21.
2023-07-07 08:10:47 +02:00
sago35 9126b95737 machine/samd51: fix i2cTimeout was decreasing due to cache activation 2023-07-06 21:35:54 +02:00
deadprogram 3871b831af make: add make task to generate Renesas device wrappers
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-07-05 13:30:21 +02:00
deadprogram 7755f2385c tools/gen-device-svd: small changes needed for Renesas MCUs
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-07-05 13:30:21 +02:00
deadprogram 04601a29e8 modules: add submodule for Renesas SVD file mirror repo
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-07-05 13:30:21 +02:00
Ayke van Laethem 9aadea930f main: improve detection of filesystems
This is a rewrite of how filesystems are detected. Specifically, it
fixes an issue on Linux where the location of the FAT filesystem can
vary between distributions (for example, we supported most distros by
checking two different paths, but NixOS uses a different path): it now
uses the data in /proc/mounts instead which should be universal.
2023-07-03 13:37:38 +02:00
sago35 6efa94035e machine/macropad_rp2040: add machine.BUTTON 2023-07-03 11:44:44 +02:00
Mansour Behabadi db8d80755f rp2040: add missing suffix to CMD_READ_STATUS 2023-07-03 10:52:33 +02:00
Yurii Soldak dc91c96305 example: adjust time offset 2023-07-02 18:25:20 +02:00
Damian Gryski 08b3a4576d compiler: update .ll test output 2023-07-02 15:35:42 +02:00
Damian Gryski acba0748f1 compiler,reflect: NumMethods reports exported methods only
Fixes #3796
2023-07-02 15:35:42 +02:00
Damian Gryski ef72c5bb4e reflect: fix iterating over maps with interface{} keys
Fixes #3794
2023-07-02 11:47:08 +02:00
Rado M 93cc03b15a docker: update clang to version 15 2023-07-02 10:54:23 +02:00
Tyler Rockwood fdc4bbbfad reflect: Add FieldByNameFunc
This adds FieldByNameFunc, which some libraries like reflect2 need.

For my usecase I could also just stub FieldByNameFunc to panic, but
figured that it would work OK to just make it work. I'm not sure if
the overhead to FieldByName using a closure is acceptable.

Signed-off-by: Tyler Rockwood <rockwood@redpanda.com>
2023-07-02 09:14:36 +02:00
soypat dd4e9e86e7 reflect: remove unecessary heap allocations 2023-07-01 21:03:10 +02:00
sago35 ad32d26511 machine/usb/hid,joystick: fix hidreport (3) (#3802)
* machine/usb/hid,joystick: fix hidreport (3) and handling of logical, usage, and physical minimum/maximum values
2023-07-01 11:58:23 +02:00
Ayke van Laethem 4619896c19 nrf: wait for stop condition after reading from the I2C bus
Found while working on the PineTime. For some reason it still kind of
works in most cases, but I was hitting this issue when interacting with
two different I2C devices (the touch sensor and the BMA421).
2023-06-22 10:41:05 +02:00
Yurii Soldak cec237917f example: simplify pininterrupt 2023-06-18 10:59:23 +02:00
Ayke van Laethem 4d2a6d2bbe wasm: remove i64 workaround, use BigInt instead
Browsers previously didn't support the WebAssembly i64 type, so we had
to work around that limitation by converting the LLVM i64 type to
something else. Some people used a pair of i32 values, but we used a
pointer to a stack allocated i64.

Now however, all major browsers and Node.js do support WebAssembly
BigInt integration so that i64 values can be passed back and forth
between WebAssembly and JavaScript easily. Therefore, I think the time
has come to drop support for this workaround.

For more information: https://v8.dev/features/wasm-bigint (note that
TinyGo has used a slightly different way of passing i64 values between
JS and Wasm).

For information on browser support: https://webassembly.org/roadmap/
2023-06-17 18:08:09 +02:00
Ayke van Laethem 6d5f4c4be2 ci: update Node.js from version 14 to version 16
Node.js 14 is not maintained anymore, so we can drop support for it.
2023-06-17 18:08:09 +02:00
Ayke van Laethem 0cb5d336f4 reflect: use .key() instead of a type assert
This should be ever so slightly more efficient.
2023-06-17 15:58:03 +02:00
Stepan Rakitin 91ee4d0030 os: define ErrNoDeadline 2023-06-17 10:38:48 +02:00
Ayke van Laethem 785eb93b62 ci: rename release-double-zipped to something more useful
The Linux artifacts have clear names (linux-amd64-double-zipped etc),
but the MacOS and Windows ones didn't. This patch renames these artifact
names to be more readable, especially when downloading the artifacts.
2023-06-16 21:32:22 +02:00
sago35 e041a8ed88 goenv: update to new v0.29.0 development version 2023-06-16 11:36:41 +02:00
soypat d01d85930d rp2040: add spi busy waits on read and read/write transactions 2023-06-11 22:24:26 +02:00
Ayke van Laethem ac821d8295 goenv: fix version number to 0.28.1 (without -dev) 2023-06-11 18:56:38 +02:00
Ayke van Laethem 5c2753e54e all: release 0.28.0
These are some major or breaking changes:

 - Reflect support got improved a lot.
 - Interrupts became more strict: heap allocations an blocking
   operations, which have always been undefined behavior, now result in
   a panic.
 - `//go:wasmimport` was added
 - various new flags were added to `tinygo test`
 - the source location for panics is printed in the `-monitor` output
2023-06-10 17:11:37 +02:00
Damian Gryski 0212f0c008 compiler: limit level of pointer-to-pointer-to-... types 2023-06-09 17:30:02 +02:00
Damian Gryski f5f4751088 compiler,transform: fix for pointer-to-pointer type switches from @aykevl 2023-06-09 17:30:02 +02:00
Damian Gryski 62fb386d57 compiler,reflect: add tagged pointers for **T etc 2023-06-09 17:30:02 +02:00
ivoszz a59f92daf8 Add smoke test for target m5stick-c 2023-06-08 09:27:41 +02:00
ivoszz b7508818ee Support for the M5STACK M5StickC ESP32-PICO device 2023-06-08 09:27:41 +02:00
Damian Gryski 284e1acd87 compiler: update testdata 2023-06-08 07:55:37 +02:00
Damian Gryski 37849c4897 compiler,reflect: use two bits of the meta byte for comparable/isBinary
Fixes #3683
2023-06-08 07:55:37 +02:00
deadprogram 213e73ad84 build: only make comment on sizediff job when run from the main repo, take 2
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-06-07 12:54:15 +02:00
Ayke van Laethem 4a240827cb main: add -internal-nodwarf flag
This can be useful during development to avoid generating debug
information in IR.
2023-06-06 11:46:16 +02:00
Ayke van Laethem 92d9f856ab main: rename some flags to make them explicitly internal
These flags shouldn't be used by users, but they are occasionally
helpful for developers.
2023-06-06 11:46:16 +02:00
Damian Gryski ee5890f36f tools: use geomean for sizediff 2023-06-06 09:30:35 +02:00
soypat 744574193b machine/rp2040: fix i2c crash when getting abort while waiting for stop condition 2023-06-04 20:17:33 +02:00
soypat bbe755fb69 fix bug in rp2040 SetPeriod implementation 2023-06-03 13:16:32 +02:00
Pierre Constantineau 635d322703 Add bluemicro840 board 2023-06-01 21:04:36 +02:00
deadprogram ee90bdebff build: only make comment on sizediff job when run from the main repo
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-31 21:24:50 +02:00
soypat bcdb3fc681 fix go:noinlines in volatile package 2023-05-29 22:16:35 +02:00
Ayke van Laethem b7b23ace3f samd21: fix issue with WS2812 driver
The regular port access is around 4 cycles, instead of the usual 2
cycles for a store instruction on Cortex-M0+. The IOBUS however is
faster, I didn't measure exactly but I guess it's 2 cycles as expected.

This fixes a bug in the WS2812 driver that only happens on samd21 chips:
https://github.com/tinygo-org/drivers/issues/540
2023-05-29 20:45:31 +02:00
deadprogram f366cd53b7 build: explicitly pass the github token to GH action
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-23 11:06:02 +02:00
Ayke van Laethem da81784ee9 attiny1616: implement Pin.Get()
I didn't add this method in the initial PR.

Also, I found that a few of my assumptions were incorrect. I've changed
the code that configures the pin to make input (floating and pullup)
actually work. These chips really are quite different from all the older
AVRs.
2023-05-21 10:44:02 +02:00
Ayke van Laethem 481f60c5ea interp: add support for reading a pointer tag
This is necessary to get https://github.com/tinygo-org/tinygo/pull/3691
working.
2023-05-20 23:57:20 +02:00
Ayke van Laethem cf39db36fe interp: fix subtle bug in pointer xor
If a pointer value was xor'ed with a value other than 0, it would not
have been run at runtime but instead would fall through to the generic
integer operations. This would likely result in a "cannot convert
pointer to integer" panic.

This commit fixes this subtle case.
2023-05-20 23:57:20 +02:00
Ayke van Laethem 54c07b7de8 interp: move some often-repeated code into a function 2023-05-20 23:57:20 +02:00
Ayke van Laethem 2fb866ca86 avr: add attiny1616 support
This is just support for the chip, no boards are currently supported.
However, you can use this target on a custom board.

Notes:

  - This required a new runtime and machine implementation, because the
    hardware is actually very different (and much nicer than older
    AVRs!).
  - I had to update gen-device-avr to support this chip. This also
    affects the generated output of other AVRs, but I checked all chips
    we support and there shouldn't be any backwards incompatible
    changes.
  - I did not implement peripherals like UART, I2C, SPI, etc because I
    don't need them. That is left to do in the future.

You can flash these chips with only a UART and a 1kOhm resistor, which
is really nice (no special hardware needed). Here is the program I've
used for this purpose: https://pypi.org/project/pymcuprog/
2023-05-20 21:18:02 +02:00
Ayke van Laethem 4d11d552db avr: update gen-device-avr tool to support newer AVRs
This refactors gen-device-avr to output two different formats: one for
all the existing AVR chips (that don't really have the concept of a
peripheral, just a bunch of registers), and one for all the new chips
like the ATtiny1616 (tinyAVR 1-series and 2-series) that have
peripherals like the Cortex-M chips with type structs and instances.

I checked the generated code for all the AVR chips we have support for
(atmega1280, atmega1284p, atmega2560, atmega328p, atmega32u4, attiny85)
and while the generated Go code did change, it looks safe to me.
2023-05-20 21:18:02 +02:00
Ayke van Laethem b43bd9e62a avr: fix interrupt names for newer attiny chips
This only affects chips that aren't supported by TinyGo yet, so this
should be a safe change. Importantly, it fixes interrupts on the
ATtiny1616.
2023-05-20 21:18:02 +02:00
Rajat Jindal 572c22f66a add Settings to debug.BuildInfo
Signed-off-by: Rajat Jindal <rajatjindal83@gmail.com>
2023-05-20 14:49:31 +02:00
deadprogram 1b66da4dff build: add issues write permission to sizediff job
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-20 14:02:14 +02:00
Ayke van Laethem b08ff17f6b compiler: disallow most types in //go:wasmimport
This is for compatibility with upstream Go.
See https://github.com/golang/go/issues/59149 for more context.
2023-05-20 11:24:20 +02:00
Ayke van Laethem 41e787d504 compiler: add tests for error messages
The test is currently empty, but will be used in the next commit.
2023-05-20 11:24:20 +02:00
Ayke van Laethem 6dba16f28e compiler: only calculate functionInfo once
This is a small change that's not really important in itself, but it
avoids duplicate errors in a future commit that adds error messages to
//go:wasmimport.
2023-05-20 11:24:20 +02:00
deadprogram b336a1561f build: update GH actions-comment-pull-request to v2.3.1
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-17 17:54:47 +02:00
Ayke van Laethem 4c682680ca compileopts: don't filter build tags, use specific build tags instead
This basically reverts https://github.com/tinygo-org/tinygo/pull/3357
and replaces it with a different mechanism to get to the same goal.

I do not think filtering tags like this is a good idea: it's the wrong
part of the compiler to be concerned with such tags (that part sets
tags, but doesn't modify existing tags). Instead, I've written the
//go:build lines in such a way that it has the same effect: WASI
defaults to leveldb, everything else defaults to fnv, and it's possible
to override the default using build tags.
2023-05-17 11:21:15 +02:00
Ayke van Laethem af76c807e2 windows: re-enable parallelism
This reverts https://github.com/tinygo-org/tinygo/pull/3525, because
that change didn't seem to stop the CI failures we have been seeing.
Instead, I've added thread support in
https://github.com/tinygo-org/tinygo/pull/3130 which IIRC fixed most of
the CI crashes.

Re-enabling parallelism should improve the performance of TinyGo a bit
on Windows.
2023-05-16 21:47:24 +02:00
sago35 cdbd850f80 machine: add DefaultUART to xiao 2023-05-16 20:10:44 +02:00
Damian Gryski d256804af7 src/reflect: remove overflow checks from uvarint32 2023-05-16 19:02:08 +02:00
Damian Gryski e3c96803c3 runtime: fix structField.data comment 2023-05-16 19:02:08 +02:00
Damian Gryski f55bb8e030 builder: bump sizes_test 2023-05-16 19:02:08 +02:00
Damian Gryski 07fb3a0cad compiler,reflect: make field offsets varints
Fixes #3686
2023-05-16 19:02:08 +02:00
deadprogram 02913563df build: add write permission to sizediff GH actions job to always be able to add comments
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-16 18:41:45 +02:00
Ayke van Laethem 535e64adbc reflect: optimize Zero() a little bit
It could be expensive to call Size() three times, and it is unnecessary.
Instead, do it only once.

This results in a very small reduction of binary size if Zero() is used.
2023-05-14 18:23:23 +02:00
Ayke van Laethem af936f3261 ci: add comment with binary size difference
This makes reviewing PRs a lot easier because I don't have to run this
myself :)

This only uses the drivers repo so far, which is a good starting point
but doesn't include binary size changes for WebAssembly for example. A
future change could add some real-world programs to get a better idea of
the real-world impact.

To be clear: the intention is not to just look at the number at the
bottom. It is important to look at the actual size difference to see the
overall pattern (like, the difference may be due to a few outlier).
2023-05-14 15:38:57 +02:00
sago35 d1a45f2efc machine/usb/hid: fix hidreport (2) 2023-05-14 12:17:01 +02:00
deadprogram b56a263d0d machine/flash: remove FlashBuffer, modify flash example to use BlockDevice interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-14 10:41:03 +02:00
Ayke van Laethem 6435f62dcc builder: implement Nordic DFU file writer in Go
This avoids a dependency on nrfutil. I have verified that it creates
equivalent zip files to a wasp-os DFU zip file I downloaded here:
https://github.com/wasp-os/wasp-os/releases/
I have also tested that it produces valid DFU files that can be uploaded
using the dfu.py program here to my PineTime:
https://github.com/wasp-os/ota-dfu-python/tree/3d6fd30d33c2b20bc86ff6b9269fddf4a1d4c7c6

There are some minor differences in the generated file that should not
matter in practice (JSON whitespace, firmware file name, zip
compression).
2023-05-13 09:52:42 +02:00
Ayke van Laethem f4c8c37b7b nrf: add ADC oversampling support
This is a lot easier to support than on other chips, and results in
noticeably better output when set to a higher value.
2023-05-09 19:51:05 +02:00
Ayke van Laethem 868812717f nrf: add sample time to ADC
This is important for inputs with a high input resistance. In those
cases, the sample time needs to be longer.
2023-05-09 19:51:05 +02:00
Ayke van Laethem e82f595f37 nrf: add ability to set the reference voltage
The reference voltage can't be 3.3V, so we pick 3.0V as this was the
previous default.
2023-05-09 19:51:05 +02:00
Ayke van Laethem e5af121553 nrf: refactor ADC code a little bit
* Initialize the ADC in Configure() (instead of in Get()).
  * Do not set all channels to "not connected" - that's already the
    reset value.
  * Don't disable the ADC after use. It's not necessary to disable
    (current consumption appears to remain the same whether enabled or
    disabled).
2023-05-09 19:51:05 +02:00
Ayke van Laethem 20fdbc1f9d pinetime: update the target file
* Rename pinetime-devkit0 to pinetime because the production device is
    almost the same hardware (the only noticeable difference is a
    different accelerometer, which isn't part of the board file).
  * Remove the UART and set serial to none. The UART uses a lot of
    current by default, so it seems better to disable it.

This is a breaking change, but honestly I think I'm the only one who has
ever actually used TinyGo for the PineTime and I'm fine with this
change :)
2023-05-09 19:44:00 +02:00
sago35 14fed59827 machine/usb/hid: fix hidreport 2023-05-07 10:25:40 +02:00
deadprogram d331aca296 machine/rp2040: correct write block size for flash
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-07 00:49:10 +02:00
deadprogram 7e8a2e8934 machine/rp2040: correct param for number of bytes to be erased by flash
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-07 00:49:10 +02:00
deadprogram e7363966a5 machine/atsam*, nrf, rp2040, stm32: correct error flashBlockDevice pad() function
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-06 23:24:01 +02:00
Daz Wilkin 373ab34492 Add dummy package for runtime/metrics to that modules that depend upon it (e.g. [Prometheus Go client library](https://github.com/prometheus/client_golang/blob/main/prometheus/internal/go_runtime_metrics.go)) will compile.
Avoids:
```console
package runtime/metrics is not in GOROOT
```

Fixes #3705
2023-05-06 14:55:17 +02:00
Achille 602f35a5ca os: implement os.(*File).WriteAt (#3697)
os: implement os.(*File).WriteAt

Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-05-05 09:40:15 +02:00
deadprogram 1d5c5ca2ef machine/usb/descriptor: further refactor HID report creation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-05 07:44:03 +02:00
deadprogram 90935703e6 machine/usb/descriptor: rename and export Append() to make it easier to create new descriptors in user code
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-05 07:44:03 +02:00
deadprogram d8ee520bdc machine/usb/descriptor: refactor HID report creation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-05-05 07:44:03 +02:00
Ayke van Laethem e4da35486b tools: add sizediff tool
This tool can be very useful to compare binary sizes as output by
`-size=short`.

This is a tool I wrote a while ago. It's not perfect (we should probably
use a geomean) but it works well enough to get a good idea on the binary
size impact of a change.
2023-05-04 21:46:53 +02:00
Edoardo Vacchi 4e41e9084a cgo: allow LDFLAGS: --export=...
Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
2023-05-04 20:45:02 +02:00
Achille Roussel ee3af40cab os: implement os.(*File).ReadDir for -target=wasi
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-05-03 21:24:11 +02:00
Achille Roussel 666312f63f implement Sync on stdioFileHandle
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-05-03 19:37:53 +02:00
Achille Roussel ccfe92a58c os: add os.(*File).Sync
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-05-03 19:37:53 +02:00
Achille Roussel 4fa6a132e2 syscall: add fsync using libc
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-05-03 19:37:53 +02:00
deadprogram 1a67795fd3 examples/usb-midi: remove serial communication from MIDI example
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-29 10:06:52 +02:00
deadprogram c70daa2497 machine/usb: move MIDI under usb/adc (Audio Device Class) package
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-29 10:06:52 +02:00
sago35 d28b58e4dd machine/usb/hid/mouse: add support for mouse back and forward 2023-04-28 17:41:00 +02:00
deadprogram 25b03414dc machine/usb/hid/joystick: handle case where we cannot find the correct HID descriptor
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-28 15:15:54 +02:00
deadprogram 2ab7ee6a8a machine/usb: refactoring descriptors into subpackage for modularity
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-28 15:15:54 +02:00
Damian Gryski 6a2dd35fe6 builder: bump sizes test values 2023-04-27 11:15:41 +02:00
Damian Gryski 4c0fbbfc7f add struct size and field offsets to reflect data 2023-04-27 11:15:41 +02:00
deadprogram 36bd66a858 docs: update README for brevity and to add further info about webassembly
also, add links to guides about OS-specific development on website
      for macOS and Windows.

Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-27 09:08:37 +02:00
deadprogram 9d7dd3dd4b docs: update LICENSE year
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-27 09:08:37 +02:00
Ayke van Laethem 9bf5d6a4aa builder: add link to compatibility matrix
For context, see: https://github.com/tinygo-org/tinygo-site/pull/327

It only needs to be updated every half year, so it's not too bad, and it
could be very useful to some people.
2023-04-27 02:44:58 +02:00
Ayke van Laethem 839edec64c cortexm: fix stack size offset
The old code was broken and led to a HardFault in a rather convoluted
way:

 1. The CFA offset was incorrect, in fact it was not aligned (the stack
    is supposed to always be aligned to 4 bytes at least).
 2. This unaligned size was then used for stack size calculations.
 3. A stack that wasn't a multiple of 4 was allocated.
 4. The calleeSavedRegs struct (in `(internal/task.state).archInit`) was
    not correctly aligned.
 5. Writing to this struct resulted in a HardFault.
2023-04-27 00:11:53 +02:00
Ayke van Laethem 7e05c92420 cortexm: add "gdb" as a debugger
At least on Arch Linux ARM, there is no gdb-multiarch or something, just
"gdb" and it works for 32-bit ARM as well.
2023-04-26 23:07:52 +02:00
Ayke van Laethem 0b2aec1164 runtime: improve panic message when heap allocating in an interrupt
The old message may have been confusing. With the new message, it should
be more clear that we mean a _heap_ allocation.
2023-04-26 20:04:06 +02:00
Ayke van Laethem ae381e74a5 main: print source location when a panic happens in -monitor
The previous commit started printing the instruction address for runtime
panics. This commit starts using this address to print the source
location.

Here is an example where this feature is very useful. There is a heap
allocation in the Bluetooth package, but we don't know where exactly.
Printing the instruction address of the panic is already useful, but
what is even more useful is looking up this address in the DWARF debug
information that's part of the binary:

    $ tinygo flash -target=circuitplay-bluefruit -monitor ./examples/heartrate
    Connected to /dev/ttyACM0. Press Ctrl-C to exit.
    tick 00:00.810
    tick 00:01.587
    tick 00:02.387
    tick 00:03.244
    panic: runtime error at 0x00027c4d: alloc in interrupt
    [tinygo: panic at /home/ayke/src/tinygo/bluetooth/adapter_sd.go:74:4]

To be clear, this path isn't stored on the microcontroller. It's stored
as part of the build, and `-monitor` just looks up the path from the
panic message.

Possible enhancements:

  - Print such an address for regular panics as well. I'm not sure
    that's so useful, as it's usually a lot easier to look up panics
    just by their message.
  - Use runtimePanicAt (instead of runtimePanic) in other locations, if
    that proves to be beneficial.
  - Print the TinyGo-generated output in some other color, to
    distinguish it from the regular console output.
  - Print more details when panicking (registers, stack values), and
    print an actual backtrace.
2023-04-26 18:40:35 +02:00
Ayke van Laethem 3392827c3e runtime: print the address where a panic happened
This is not very useful in itself, but makes it possible to detect this
address in the output. See the next commit.

This adds around 50 bytes to each binary (except for AVR and wasm). This
is unfortunate, but I think this feature is quite useful still.
A future enhancement might be to create a build tag for extended panic
information that's not set by default.
2023-04-26 18:40:35 +02:00
Scott Feldman 59838338ba Add machine.CPUReset() (#3595)
machine: Add machine.CPUReset() for cortexm
2023-04-25 19:10:47 +02:00
Ron Evans 76303f9db4 Revert "all: better errors when multiple mcus share VID/PID"
This reverts commit af9f19615b.
2023-04-25 18:18:23 +02:00
Ron Evans 4bf8b618e5 Revert "all: honour port for -monitor flash flag"
This reverts commit 7aac1a1391.
2023-04-25 18:18:23 +02:00
deadprogram c89a684ad2 machine/gba: rename display and make pointer receivers
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-25 16:43:29 +02:00
Kenneth Bell 7aac1a1391 all: honour port for -monitor flash flag 2023-04-25 11:21:16 +02:00
Kenneth Bell af9f19615b all: better errors when multiple mcus share VID/PID 2023-04-25 11:21:16 +02:00
deadprogram 79b63dd041 device/gba: additional IO mapping for sound, DMA, SIO, and sprites
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-24 18:11:29 +02:00
Damian Gryski 06e34caa5f builder: print the status of the job that just completed 2023-04-22 10:01:02 +02:00
cui fliter 4e9f9e2773 fix some comments
Signed-off-by: cui fliter <imcusg@gmail.com>
2023-04-18 22:51:49 +02:00
Ayke van Laethem 64957c5254 samd51: fix ADC multisampling
Multisampling/averaging (using the Samples configuration property) was
returning incorrect values. When I investigated this, I found that the
samd51 gives erratic values when using multisampling together with fewer
than 16 bits resolution.

I fixed this by forcing 16 bit resolution when multisampling, and
adjusting the output to account for multisampling.

Found while reading the battery value on a pybadge, which gave
non-sensible values with Samples set to a value larger than 1.
2023-04-18 19:00:11 +02:00
Kenneth Bell 1bba5f5d7b targets: make msd-volume-name an array 2023-04-17 18:56:32 +02:00
deadprogram 48ef68dd86 examples: replace fmt with encoding/hex in usb-midi example
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-17 08:54:06 +02:00
Damian Gryski 8b9bee4cad main: don't print ok for a successful compile-only 2023-04-16 03:38:33 +02:00
Elliott Sales de Andrade b4c9b579b8 Switch interp tests to opaque pointers 2023-04-16 03:34:46 +02:00
Damian Gryski 2b1dc4fee5 testing: add -test.shuffle to order randomize test and benchmark order 2023-04-12 20:43:41 +02:00
Damian Gryski 0244bed033 testdata: add test for else/defer bug 2023-04-11 18:54:05 -07:00
Damian Gryski 60b23a7035 compiler: update test outputs 2023-04-11 18:54:05 -07:00
Damian Gryski 4326c8f10e compiler: ensure all defers have been seen before creating rundefers
Fixes #3643
2023-04-11 18:54:05 -07:00
Damian Gryski 1672610749 testing: move runtime.GC() call to runN to match upstream 2023-04-11 12:16:25 +02:00
Damian Gryski e00a2395d9 testing: fix benchmark logging output 2023-04-11 12:16:25 +02:00
sago35 42175496eb machine/atsamd51: remove extra BK0RDY clear 2023-04-10 09:16:52 +02:00
Ayke van Laethem 3b4e543f4e rp2040: use DMA for send-only SPI transfers
This improves slightly. It also is some groundwork for better DMA
support in TinyGo in the future.

I'm not entirely sure why it improves performance (in theory the old
code should already saturate the SPI bus) but it does, so 🤷
2023-04-04 12:22:52 +02:00
Kenneth Bell ad3e9e1a77 i2c: implement target mode for rp2040 and nrf 2023-04-04 09:36:42 +02:00
Kenneth Bell e0385e48d0 nrf: new peripheral type for nrf528xx chips 2023-04-04 09:36:42 +02:00
Kenneth Bell feadb9c85c nrf: move nrf52 family code to correct file name 2023-04-04 09:36:42 +02:00
Kenneth Bell 4bf7308d26 machine: make gosched available to machine package 2023-04-04 09:36:42 +02:00
Ayke van Laethem 19e4db45db samd51: use correct SPI frequency
The SPI frequency was rounded up, not rounded down. This meant that if
you wanted to configure 15MHz for example, it would pick the next
available frequency (24MHz). That's unsafe, the safe option is to round
down and the SPI support for most other chips also rounds down for this
reason.

In addition, I've improved SPI clock selection so that it will pick the
best clock of the two, widening the available frequencies. See the
comments in the patch for details.
2023-04-03 19:40:20 +02:00
sago35 71b44e79b3 machine/usb/hid/joystick: allow joystick settings override 2023-04-03 00:50:30 +02:00
deadprogram 9e97566b5f machine/usb/hid/joystick: move joystick under HID as it belongs and also remove duplicate code
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-04-03 00:50:30 +02:00
Ayke van Laethem 7d83e76833 rp2040: use 4MHz as default frequency for SPI
This matches other SPI implementations. I think the original value of
115200 was from a confusion with UART.
2023-04-02 01:04:37 +02:00
Damian Gryski 9e7882b1b7 reflect: uncomment a another test the fails and doc some that don't 2023-04-01 22:46:46 +02:00
Damian Gryski 0c4f9d1f19 reflect; uncomment SetZero (but comment out the parts that fail) 2023-04-01 22:46:46 +02:00
Damian Gryski a85cb22193 reflect: uncomment TestAppend and fix a bug it found 2023-04-01 22:46:46 +02:00
Damian Gryski 60bb832c89 reflect: handle Convert'ing between identical underlying types
Needed for go-jose/v3
2023-04-01 22:46:46 +02:00
Ayke van Laethem 6eda52a289 rp2040: remove SPI deadline
Removing it improves SPI performance by about 20% for me (updating the
display of a Gopher Badge).
2023-04-01 11:18:51 +02:00
Damian Gryski 8badf79af9 testing: remove unused variable left over from count prototyping 2023-03-31 19:17:02 -07:00
Damian Gryski 66d3c4edb8 main: fix typos in flag usage messages 2023-03-31 19:17:02 -07:00
Damian Gryski 63aaa43072 testing: add test.skip
Fixes #3056
2023-03-31 19:17:02 -07:00
Damian Gryski ee81c31884 testing: import new version of match.go 2023-03-31 19:17:02 -07:00
Damian Gryski 50d681359d main: set WASMTIME_BACKTRACE_DETAILS when running in wasmtime.
I find myself consistently running tests, seeing them panic, and then
immediately running them again with this environment variable set.  It's
easier to just have tinygo do this for me.
2023-03-31 13:06:23 -07:00
Damian Gryski d50c54fce0 Makefile: compress/lzw seems to work on wasi now. 2023-03-31 20:41:51 +02:00
Damian Gryski 4a81cac53b main: make sure all testing output goes to the same place 2023-03-31 09:07:13 +02:00
Damian Gryski 84a3273131 main: fix tests with default TestConfig.Count=0 doesn't skip all tests 2023-03-31 09:07:13 +02:00
Damian Gryski 9182664845 testing: make test output unbuffered when verbose
Fixes #3579
2023-03-31 09:07:13 +02:00
Damian Gryski a2f95d6b87 main: stuff test runner options into their own struct
Fixes #2406
2023-03-31 09:07:13 +02:00
Damian Gryski 698b1f19c6 testing: support -test.count
This makes running benchmarks repeatedly easier.
2023-03-31 09:07:13 +02:00
Damian Gryski e6ccdd9d1a reflect: another obscure RO bug 2023-03-31 01:08:04 +02:00
Damian Gryski b39a982067 reflect: uncomment another test and fix RO logic issues it uncovered 2023-03-31 01:08:04 +02:00
Ayke van Laethem e0bf376068 rp2040: unify all linker scripts using LDFLAGS
The only thing that's different between all these chips is the flash
size, which can easily be passed as a linker flag instead. This removes
a bunch of duplicate code in an uncommon language (linker script).

I've also fixed a few boards with incorrect flash sizes:

  * nano-rp2040 has 16MB instead of 2MB
  * macropad-rp2040 has 8MB instead of 2MB
  * gopher-badge has 8MB instead of 1MB
2023-03-30 23:49:02 +02:00
Damian Gryski b044d4ff3d reflect: add more RO checks 2023-03-30 21:10:54 +02:00
Damian Gryski 0cd93a3a9e reflect: add valueFlagRO 2023-03-30 21:10:54 +02:00
Damian Gryski 5faff2e13a reflect: add sipmlified strconv.Quote() implementation for struct tags 2023-03-30 21:10:54 +02:00
Damian Gryski 195de23d3b reflect: Fix Kind(-1).String() and enable test 2023-03-30 21:10:54 +02:00
Damian Gryski d4bdd836bc reflect: implement and test Value.Comparable 2023-03-30 21:10:54 +02:00
Damian Gryski a11f2436e3 reflect: TestAliasNames passes 2023-03-30 21:10:54 +02:00
Damian Gryski 017ab4c352 reflect: fix TestCanSetField 2023-03-30 21:10:54 +02:00
Damian Gryski 181d2ad2b4 reflect: add CanInt() and friends and uncomments tests that pass 2023-03-30 21:10:54 +02:00
Damian Gryski 53b95cad08 reflect: uncomment Type.String() tests that pass 2023-03-30 21:10:54 +02:00
Damian Gryski e7bd22edf2 reflect: print struct tags in Type.String() (with a caveat) 2023-03-30 21:10:54 +02:00
Damian Gryski 1a60a1f526 reflect: stub channel select routines/types 2023-03-30 21:10:54 +02:00
Damian Gryski 3fbd3c4d93 compiler,reflect: support channel directions 2023-03-30 21:10:54 +02:00
deadprogram 1213a45197 build: add GH workflow to build LLVM image when needed
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-30 12:40:02 +02:00
Damian Gryski 4e4e4eee04 runtime: use unsafe.Add() in hashmap code 2023-03-30 00:08:07 +02:00
Damian Gryski bf20c652e2 runtime: take max hash size into account when preallocating with size hint 2023-03-30 00:08:07 +02:00
Damian Gryski a3afd4e8ac runtime: factor duplicate hashmap snippts to functions 2023-03-30 00:08:07 +02:00
Damian Gryski cb9c6f0074 runtime: zero map key/value on deletion to so GC doesn't see them 2023-03-30 00:08:07 +02:00
Damian Gryski 5fee3428bc runtime: preallocate maps to size hint actually works 2023-03-30 00:08:07 +02:00
Ayke van Laethem 464ebc4fe1 compiler: implement most math/bits functions
These functions can be implemented more efficiently using LLVM
intrinsics. That makes them the Go equivalent of functions like
__builtin_clz which are also implemented using these LLVM intrinsics.

I believe the Go compiler does something very similar: IIRC it converts
calls to these functions into optimal instructions for the given
architecture.

I tested these by running `tinygo test math/bits` after uncommenting the
tests that would always fail (the *PanicZero and *PanicOverflow tests).
2023-03-29 20:55:09 +02:00
Ayke van Laethem 568c2a4363 rp2040: remove SPI DataBits property
As discussed on Slack, I believe this property does more harm than good:

  * I don't think it's used anywhere. None of the drivers use it.
  * It is not fully implemented. While values <= 8 might work fine,
    values larger than 8 result in extra zero bits (instead of anything
    sensible).
  * Worse, it doesn't return an error when it's out of range. This is
    not an optional property: if the SPI peripheral doesn't support a
    particular number of bits, it should return an error instead of
    silently limiting the number of bits. This will be confusing to
    users.

Therefore, I propose we drop it. Maybe there are good uses for it
(perhaps for displays that use big endian 16-bit values?), but without a
good use case like a driver in tinygo.org/x/drivers, I think it's more
trouble than it's worth.
2023-03-29 09:30:16 +02:00
Kenneth Bell c611c72526 build: test net on linux & mac only (random CI fails on windows) 2023-03-29 07:57:55 +02:00
deadprogram dfb8c996a1 machine/lorae5: correct mapping for I2C bus, add pin mapping to enable power
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-28 15:28:14 +02:00
Achille Roussel 85da9a0aac fix resource leak in os.(*File).Close
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-03-28 13:12:21 +02:00
Ayke van Laethem 17bc0d6663 compiler: only support //go:wasmimport on declared functions
Don't support this pragma on defined functions. It is only meant for
importing, not for exporting.
2023-03-28 09:31:09 +02:00
Ayke van Laethem 31043628d8 reflect: use direct calls to runtime string functions
The runtime.stringFromBytesTyped and runtime.stringToBytesTyped
functions aren't really necessary, because they have the same LLVM IR
signature. Therefore, remove them and link directly to the functions
that the compiler uses internally.
2023-03-27 22:24:20 +02:00
Damian Gryski 2c0f61cad1 reflect: fix bug found by Convert() tests on wasi 2023-03-27 18:53:37 +02:00
Damian Gryski 97ece754f6 reflect: add missing Uintptr type and some numerical tests 2023-03-27 18:53:37 +02:00
Damian Gryski 39f76f43fc reflect: fix indirect issues with makeInt/makeUint/makeFloat 2023-03-27 18:53:37 +02:00
Damian Gryski f239e8e2d9 reflect: typo in uint test 2023-03-27 18:53:37 +02:00
Damian Gryski 6b73b5e486 reflect: document which Convert() cases are still unimplemented 2023-03-27 18:53:37 +02:00
Damian Gryski 855e12df51 reflect: Convert(): add Float() conversions 2023-03-27 18:53:37 +02:00
Damian Gryski 0b6bb12e9e reflect: add Convert() for string -> []byte and []byte -> string 2023-03-27 18:53:37 +02:00
Damian Gryski 72c7adf94a reflect: Convert() for integer and float types 2023-03-27 18:53:37 +02:00
waj334 13fb5aa7e7 Update task_stack_cortexm.c
Added build tag.
2023-03-27 12:35:39 +02:00
Justin A. Wilson a3fdbec13d Refactor SystemStack function for arm targets.
Removing usage of AsmFull in favor of writing inline assembly in C.
2023-03-27 12:35:39 +02:00
Damian Gryski 360f6904f5 reflect: add test for map[interface{}]T 2023-03-25 22:32:29 +01:00
Damian Gryski 7201b13085 reflect: fix key type logic for maps 2023-03-25 22:32:29 +01:00
Damian Gryski 9c0bf8bd2c reflect: Value.Set: fix direction of assignment check 2023-03-25 22:32:29 +01:00
Damian Gryski 63c7a41337 reflect: convert non-interface to interface in Set() 2023-03-25 22:32:29 +01:00
Damian Gryski c0f8f129c0 reflect: convert map elements to an interface, if needed 2023-03-25 22:32:29 +01:00
Damian Gryski adaa7ca27a reflect: SetMapIndex: use AssignableTo() instead of type equality 2023-03-25 22:32:29 +01:00
Damian Gryski a5ddc68845 reflect: unpack interfaces in MapKeys() if needed 2023-03-25 22:32:29 +01:00
Damian Gryski f7880e73d8 reflect: tweak v.typecode.Key().(*rawType) -> v.typecode.key() 2023-03-25 22:32:29 +01:00
Damian Gryski 3aa8c8e0d1 reflect: fix typo in unit test 2023-03-25 22:32:29 +01:00
Damian Gryski 6cb7f29d9b reflect: add tests for map interface lookup fixes 2023-03-25 22:32:29 +01:00
Damian Gryski 21527353f7 compiler: for interface maps, use the original named type if available 2023-03-25 22:32:29 +01:00
Damian Gryski bedd27b20e reflect: handle map-keys-as-interfaces for MapIter() 2023-03-25 22:32:29 +01:00
Damian Gryski 3612b7749e reflect: uncomment all(?) the tests that pass 2023-03-25 13:57:00 +01:00
Damian Gryski 45c916f5c0 reflect: rename tests in value_test to avoid conflicts upstream tests 2023-03-25 13:57:00 +01:00
Damian Gryski 688a5dbf8d reflct: reenable DeepEqual tests 2023-03-25 13:57:00 +01:00
Damian Gryski 35dcf135c0 reflect: comment out all tests but keep imports 2023-03-25 13:57:00 +01:00
Damian Gryski c482d65397 reflect: replace all_test with copy from upstream 2023-03-25 13:57:00 +01:00
shivay d73e12db63 feat: fix typos 2023-03-24 09:22:38 -07:00
Daniel Esteban 4b0e56cbec Added Gopher Badge support 2023-03-22 16:17:12 +01:00
Ayke van Laethem 62e1c3ebb7 wasm: implement the //go:wasmimport directive
It is implemented upstream and looks pretty stable.
2023-03-22 11:29:26 +01:00
deadprogram a4a1001dd3 examples: use hid-keyboard example to show how to to override default USB VID, PID, manufacturer name, and product name
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-22 08:35:42 +01:00
deadprogram e8f6df928c machine/usb: add ability to override default VID, PID, manufacturer name, and product name
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-22 08:35:42 +01:00
Ayke van Laethem f180339d6b compiler: add alloc attributes to runtime.alloc
This gives a small improvement now, and is needed to be able to use the
Heap2Stack transform that's available in the Attributor pass. This
Heap2Stack transform could replace our custom OptimizeAllocs pass.

Most of the changes are just IR that changed, the actual change is
relatively small.

To give an example of why this is useful, here is the code size before
this change:

    $ tinygo build -o test -size=short ./testdata/stdlib.go
       code    data     bss |   flash     ram
      95620    1812     968 |   97432    2780

    $ tinygo build -o test -size=short ./testdata/stdlib.go
       code    data     bss |   flash     ram
      95380    1812     968 |   97192    2780

That's a 0.25% reduction. Not a whole lot, but nice for such a small
patch.
2023-03-22 00:34:43 +01:00
Ayke van Laethem 5ed0cecf0d nrf: fix memory issue in ADC read
There was a very subtle bug in the ADC read code: it stores a pointer to
a variable in a register, waits for the hardware to complete the read,
and then reads the value again from the local variable. Unfortunately,
the compiler doesn't know there is some form of synchronization
happening in between.

This can be fixed in roughly two ways:
  * Introduce some sort of synchronization.
  * Do a volatile read from the variable.

I chose the second one as it is probably the least intrusive. We
certainly don't need atomic instructions (the chip is single threaded),
we just need to tell the compiler the value could have changed by making
the read volatile.
2023-03-22 00:34:43 +01:00
Ayke van Laethem 523c6c0e3b compiler: correctly generate code for local named types
It is possible to create function-local named types:

    func foo() any {
        type named int
        return named(0)
    }

This patch makes sure they don't alias with named types declared at the
package scope.

Bug originally found by Damian Gryski while working on reflect support.
2023-03-21 22:22:03 +01:00
Damian Gryski 17f5fb1071 reflect; SetLen() requires an addressable value 2023-03-21 20:53:37 +01:00
Damian Gryski 4d43df75d5 reflect: fix some vet issues 2023-03-21 20:53:37 +01:00
Damian Gryski 57b0c21492 reflect: tweak Type.String() for interfaces to make encoding/xml happy 2023-03-19 13:50:38 -07:00
Damian Gryski 8fb5877d9e reflect: fix isBinary() for float types 2023-03-19 13:49:55 -07:00
Damian Gryski 6fbe6fa2ae reflect: tweak Type.String() to match what encoding/json expects for empty structs 2023-03-19 20:37:57 +01:00
Damian Gryski 24b4dc31a4 reflect: stub MapOf() 2023-03-19 19:12:34 +01:00
Damian Gryski 4f8127d0bf builder: bump sizes tests 2023-03-19 17:45:43 +01:00
Damian Gryski e0329b25de transform: fix OptimizeReflectImplements pass for new named elem offset 2023-03-19 17:45:43 +01:00
Damian Gryski 229f479a7d reflect: make sure pointerTo() works for named types 2023-03-19 17:45:43 +01:00
Damian Gryski 876f08979f compiler,reflect: sort out pkg path vs pkg name for named types 2023-03-19 17:45:43 +01:00
Damian Gryski f2cc98caa5 compiler,reflect: adjust struct layout for type info 2023-03-19 17:45:43 +01:00
Damian Gryski 0d65b4dd26 compiler: only define the package path once
Adding https://github.com/tinygo-org/tinygo/pull/3534 by hand to avoid conflicts when I rebase.
2023-03-19 17:45:43 +01:00
Damian Gryski 6a685b2a8d reflect: add test for Type.NumMethod() 2023-03-19 17:45:43 +01:00
Damian Gryski 569817a514 refect: Type.String() should use a shortened package name 2023-03-19 17:45:43 +01:00
Damian Gryski 7a96f0f609 compiler,reflect: add reflect.Type.NumMethods() 2023-03-19 17:45:43 +01:00
deadprogram 821227a03b docker: correct path for GHCR dev container build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-19 16:16:42 +01:00
Ayke van Laethem 5b42871baa compiler: support all kinds of recursive types
Previously we only supported recursive types in structs. But there can
be other kinds of recursive types, like slices:

    type RecursiveSlice []RecursiveSlice

This doesn't involve structs, so it led to infinite recursion in the
compiler. This fix avoids recursion at the proper level: at the place
where the named type is defined.
2023-03-18 17:53:47 +01:00
deadprogram c5598630c9 machine/stm32: correct Flash implementation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-18 11:18:17 +01:00
Ayke van Laethem 6c40ee93fe transform: update wasm-abi to use opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem 4acb1a5845 transform: update stringtobytes test to opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem e0f3333cc3 transform: update stringequal test to opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem af247e27ff transform: update stacksize test to opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem ec3a4da4df transform: update panic test to opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem 905269bf11 transform: update maps test to opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem e4f29ae2f9 transform: update interrupt test to opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem 7fb23824e2 transform: update interface test to opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem f8a6e662d8 transform: update gc-stackslots test to opaque pointers 2023-03-16 13:46:03 -07:00
Ayke van Laethem 0ddd65658e transform: update allocs test to opaque pointers
Also, rename most of the SSA values while we're at it.
2023-03-16 13:46:03 -07:00
Ayke van Laethem db08b5aaa5 transform: update reflect-implements test to opaque pointers 2023-03-16 13:46:03 -07:00
deadprogram 383e7ae14a machine, runtime/interrupt: switch to use register definitions from device/gba
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-16 15:27:15 +01:00
deadprogram 4f7864b757 device/gba: add mostly complete hand-written register definitions
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-16 15:27:15 +01:00
Damian Gryski 833c91fceb builder: fix binary size rodata value 2023-03-15 21:53:57 +01:00
Damian Gryski 344e493ac8 compiler,reflect: fix pkgpath for struct fields 2023-03-15 21:53:57 +01:00
Damian Gryski 1626b50457 reflect: set PkgPath in StructField 2023-03-15 21:53:57 +01:00
Damian Gryski 93fb897feb compiler, reflect: properly handle embedded structs 2023-03-15 21:53:57 +01:00
Damian Gryski 15109a2924 reflect: disable visiblefields test for FieldByIndexErr 2023-03-15 21:53:57 +01:00
Damian Gryski d9c6f7c11f reflect: import visiblefields code and tests from upstream 2023-03-15 21:53:57 +01:00
Damian Gryski fa4f361ca7 reflect: add FieldByName(), and FieldByIndex() 2023-03-15 21:53:57 +01:00
Damian Gryski 9f02340a26 reflect: fix Type.Name to return empty string for non-named types
// Name returns the type's name within its package for a defined type.
    // For other (non-defined) types it returns the empty string.
2023-03-15 13:14:21 -07:00
Damian Gryski c6728643e6 reflect: loosen unaddressable array rules for Copy() 2023-03-15 10:49:08 -07:00
Damian Gryski e849901ad6 Update src/reflect/value.go
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2023-03-15 10:06:19 -07:00
Damian Gryski 91d6ca057c reflect: add SetBytes() 2023-03-15 10:06:19 -07:00
Damian Gryski 0da97e2427 reflect: fix IsNil() for interfaces 2023-03-15 16:23:52 +01:00
Damian Gryski ac36f232bc reflect: MapIter.Next() needs to allocate new keys/values every time 2023-03-15 15:17:16 +01:00
Damian Gryski 94a54bc105 reflect: add UnsafePointer() for Func types 2023-03-15 15:08:26 +01:00
Damian Gryski b044d27dff reflect: move StructField.Anonymous field to match upstream location 2023-03-15 00:13:08 +01:00
Damian Gryski 6768af91e7 reflect: TypeOf(nil) should be nil 2023-03-14 23:58:27 +01:00
Damian Gryski a366c014c7 reflect: call decomposeInterface() directly in TypeOf() 2023-03-14 09:53:45 -07:00
Damian Gryski 584a2718d0 reflect: add type check to Value.Field() 2023-03-14 09:53:00 -07:00
Damian Gryski 069c397975 reflect: fix off-by-one in Zero sizing
Without this, pointers wouldn't be set to nil.  Add some tests.
2023-03-14 09:42:51 -07:00
Damian Gryski e0aee1f23c reflect: Type.AssignableTo(): you can assign anything to interface{} 2023-03-14 17:07:23 +01:00
Damian Gryski ad9f790dfc reflect: set Index field in Field() 2023-03-14 17:04:24 +01:00
Damian Gryski f42d8b3056 debug: stub SetGCPercent() 2023-03-14 16:54:44 +01:00
Damian Gryski 04412cba0e reflect: add stub for StructOf() 2023-03-14 16:54:44 +01:00
Damian Gryski 3b2763896f reflect: add stubs for Method(), CanConvert(), ArrayOf() 2023-03-14 16:54:44 +01:00
Damian Gryski fb394c7685 reflect: add UnsafeAddr() 2023-03-14 16:53:57 +01:00
Damian Gryski a52cad3825 reflect: fix Addr() indirect value/flags and add tests. 2023-03-14 16:49:05 +01:00
Ayke van Laethem 0e94553b26 builder: add test to check for changes in binary size
This test only applies when using the built-in LLVM version. This way,
we have a stable LLVM version to test against. Distribution versions of
LLVM (especially Debian) tend to be patched in a way that affect the
results.
2023-03-13 22:57:02 +01:00
deadprogram e6580bfff4 machine/rp2040: correct Flash implementation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-12 23:53:59 +01:00
deadprogram 5db83f11df machine/flash: refactor to keep use of pure offset relative to start
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-12 23:53:59 +01:00
deadprogram 60366adfa8 machine/rp2040: implement Flash interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-12 23:53:59 +01:00
Kenneth Bell faa449a9e1 arm: enable functions in RAM for go & cgo 2023-03-12 23:53:59 +01:00
sago35 08cf2b25c5 machine/rp2040: change uart to allow for a single pin 2023-03-12 13:41:29 +01:00
sago35 d6103222f7 wioterminal: fix pin definition of BCM13 2023-03-12 10:52:15 +01:00
Damian Gryski 69e5c5088d reflect: add support for remaining map types 2023-03-10 16:28:22 -08:00
Damian Gryski a6084767b3 syscall: remove misleading comment about Stat_t fields 2023-03-10 15:01:48 -08:00
Damian Gryski cf4a6d3253 syscall: add Timespec.Unix() for wasi.
This allows archive/tar to build (but not yet pass).
2023-03-10 15:01:48 -08:00
Damian Gryski 4716298044 os,syscall: Stat_t timespec fields are Atimespec on darwin
This allows archive/tar to build and pass.
2023-03-10 15:01:48 -08:00
Justin A. Wilson 7706c41bf6 Added missing TCPAddr and UDPAddr implementations to the net package 2023-03-10 10:11:32 -08:00
deadprogram 0bc19735f3 machine/samd51: disable/restore Flash cache on write/erase
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-09 06:42:41 +01:00
deadprogram 51c1579c3d machine/samd51: implement Flash interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-09 06:42:41 +01:00
Damian Gryski 6a45b73fcb compiler, reflect: replace package and name length with null-byte termination 2023-03-08 09:38:49 -08:00
Damian Gryski 2de64d3f4e compiler, reflect: add Type.PkgPath 2023-03-08 09:38:49 -08:00
Damian Gryski c192c7376e targets: bump cortex-m-qemu default stack size 2023-03-08 09:38:49 -08:00
Damian Gryski 2a821d2a66 reflect: improve Value.String() 2023-03-08 09:38:49 -08:00
Damian Gryski 90af41d089 reflect: add Type.String() 2023-03-08 09:38:49 -08:00
Damian Gryski 7654d86d2c compiler, reflect: add support for named types 2023-03-08 09:38:49 -08:00
sago35 45f119de34 machine/atsamd51: remove extra BK0RDY clear 2023-03-08 09:40:01 +01:00
Ayke van Laethem 71be24e4f9 transform: add debug information to internal/task.stackSize
This has two benefits:
 1. It attributes these bytes to the internal/task package (in
    -size=full), instead of (unknown).
 2. It makes it possible to print the stack sizes variable in GDB.

This is what it might look like in GDB:

    (gdb) p 'internal/task.stackSizes'
    $13 = {344, 120, 80, 2048, 360, 112, 80, 120, 2048, 2048}
2023-03-08 07:09:46 +01:00
Ayke van Laethem 3701e6eac1 compiler: account for alignment with -size=full 2023-03-08 07:09:46 +01:00
Ayke van Laethem 0463d34887 compiler: emit correct alignment in debug info for global variables
Previously we were using a really weird calculation to determine the
alignment in bits - written by me (no idea what I was thinking at the
time, it's obviously incorrect). Just replace it with the much more
obviously correct multiplication by 8 to get bits from bytes.

Found while working on properly dealing with alignment in `-size=full`.
2023-03-08 07:09:46 +01:00
Ayke van Laethem 0b47b99448 builder: improve reading of DWARF variables
The compiler now uses DW_OP_plus_uconst in the address attribute of
DWARF variables. To be able to understand these addresses, we need to be
able to parse this opcode.

This commit should also improve the reliability of address parsing a
bit.
2023-03-08 07:09:46 +01:00
Ayke van Laethem ea97c60959 builder: sizes: list interrupt vector as a pseudo-package for -size=full
This is another bit of memory that is now correctly accounted for in
`-size=full`.
2023-03-08 07:09:46 +01:00
Ayke van Laethem de281191e0 builder: detect compiler-rt size usage
Previously the code size of the compiler-rt library might be displayed
like this:

```
   1050       0       0       0 |    1050       0 | /home/ayke/src/tinygo/tinygo/llvm-project/compiler-rt/lib/builtins
    146       0       0       0 |     146       0 | /home/ayke/src/tinygo/tinygo/llvm-project/compiler-rt/lib/builtins/arm
```

With this change, it is displayed nicely like this:

```
   1196       0       0       0 |    1196       0 | C compiler-rt
```
2023-03-08 07:09:46 +01:00
Ron Evans fc28f513c7 machine/samd21: implement Flash interface (#3496)
machine/samd21: implement Flash interface
2023-03-08 06:06:49 +01:00
Ayke van Laethem 34ba0c1be1 ci: build LLVM with thread support on Windows
This should fix a number of concurrency/threading issues.

I had to force-disable concurrency in the linker using a hack. I'm not
entirely sure what the cause is, possibly the MinGW version (version 12
appears to work for me, while version 11 as used on the GitHub runner
image seems to be broken).
There are a few ways to fix this in a better way:
  * Fix the underlying cause (possibly by upgrading to MinGW-w64 12).
  * Add the `--threads` flag to the LLD MinGW linker, so we can use a
    regular parameter instead of this hack.
2023-03-07 22:38:14 +01:00
sago35 7ca45d61fc machine/rp2040: correct issue with spi pin validation 2023-03-07 21:11:57 +09:00
deadprogram 871cd66b98 build/linux: switch to ubuntu-20.04 for arm builds since ubuntu-18.04 is deprecated for GH actions runner
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-03-07 07:25:08 +01:00
Ayke van Laethem 192a55970f windows: disable parallelism on Windows
This is an attempt to figure out why the Windows CI keeps crashing. It
should be removed before the next release, by which point we should know
whether this has helped or not.
2023-03-06 18:48:55 +01:00
Ayke van Laethem 8babc47638 compiler: fix a race condition
There was a mostly benign race condition in the compiler. The issue was
that there is a check for type aliases (which can alias types in another
function), but this check was _after_ accessing a property of the
function that might not have been completed.

I don't think this can have any serious effects, as the function is
skipped anyway, but such bugs should certainly be fixed.
2023-03-06 09:30:11 +01:00
Ayke van Laethem 1cb702ac4c compiler: try harder to find source locations for constants
If there is no source location, at least use the file (but not line) for
debug information.

This attributes almost 1kB of string data for ./testdata/stdlib.go when
compiling for WASI.
2023-03-05 17:13:16 -08:00
Ayke van Laethem c6ac1cc969 compiler: add debug location to string values
This is helpful for WebAssembly: it makes it possible to attribute many
more data to locations in the source code, which makes `-size=full` more
useful.
2023-03-05 17:13:16 -08:00
Ayke van Laethem 0ce539ad42 compiler; add position information to createConstant
Non-functional change. The position information will be used later to
emit debug info locations to string constants.
2023-03-05 17:13:16 -08:00
Christian Stewart 930255ff46 os: add IsTimeout function
Fixes build error: undefined: os.IsTimeout

Signed-off-by: Christian Stewart <christian@paral.in>
2023-03-05 22:24:36 +01:00
Damian Gryski 57ecf1acdc testdata: add brandondube/pctl to corpus 2023-03-05 10:08:36 -08:00
Justin A. Wilson 313c9e31dd Refactor EnableInterrupts and DisableInterrupts
Removes usage of AsmFull which required an optimization pass to remove the map parameter passed into it. This caused issues when compiling with -opt=0 where memory for the map was being allocated as an unintended side-effect of using AsmFull with no optimizations enabled.
2023-03-05 17:34:48 +01:00
Ayke van Laethem d87e3ce330 compiler: add debug information to []embed.file slice global 2023-03-05 07:50:42 -08:00
Ayke van Laethem 11a6c84ea5 compiler: add debug information to //go:embed slice data 2023-03-05 07:50:42 -08:00
Ayke van Laethem 1d86b3f425 compiler: add debug info to []embed.files backing array 2023-03-05 07:50:42 -08:00
Damian Gryski f9b6f8339b reflect: ensure all ValueError panics have Kind fields 2023-03-03 10:18:32 -08:00
Damian Gryski 0ff243e5e2 reflect: add OverflowFloat(), OverflowInt(), OverflowUint() 2023-03-03 10:18:32 -08:00
Damian Gryski 79930a209c reflect: add Addr() 2023-03-03 10:18:32 -08:00
Damian Gryski bbc79ee40a reflect: add Zero() 2023-03-03 10:18:32 -08:00
Damian Gryski 960a0b79bf reflect: add SetLen() 2023-03-03 10:18:32 -08:00
Damian Gryski e4ef6f85ac reflect: allow nil rawType to call Kind() 2023-03-03 10:18:32 -08:00
Damian Gryski 3a3de8a778 reflect: add pointerTo() 2023-03-03 10:18:32 -08:00
Ayke van Laethem ca823f9a0d compiler: remove unsafe.Pointer(uintptr(v) + idx) optimization
I have checked this conversion is not needed anymore after the previous
commit, by running various smoke tests of which none triggered this
optimization. The only case where the optimization would have kicked in
is in syscall/syscall_windows.go:76 of the Go standard library.
Therefore, I prefer to remove it to reduce code complexity.
2023-03-03 16:55:13 +01:00
Ayke van Laethem 4ec1e58aa6 all: use unsafe.Add instead of unsafe.Pointer(uintptr(...) + ...)
We have an optimization for this specific pattern, but it's really just
a hack. With the addition of unsafe.Add in Go 1.17 we can directly
specify the intent instead and eventually remove this special case.

The code is also easier to read.
2023-03-03 16:55:13 +01:00
Damian Gryski d98c0afbab reflect: add Bytes() 2023-03-03 05:21:02 -08:00
Damian Gryski 12e3d1d81d reflect: add Copy() 2023-03-03 05:21:02 -08:00
Damian Gryski a7e3cf0826 reflect: add Slice3() 2023-03-03 05:21:02 -08:00
Damian Gryski 43a4b256bd reflect: add Slice() 2023-03-03 05:21:02 -08:00
Damian Gryski 5cc5f11b58 reflect: add MakeSlice() 2023-03-03 05:21:02 -08:00
Damian Gryski 836689fdd2 reflect: add Append() 2023-03-03 05:21:02 -08:00
Damian Gryski 9b86080c80 runtime: add sliceGrow function for reflect 2023-03-03 05:21:02 -08:00
Ayke van Laethem 517098c468 transform: fix non-determinism in the interface lowering pass
This non-determinism was introduced in
https://github.com/tinygo-org/tinygo/pull/2640. Non-determinism in the
compiler is a bug because it makes it harder to find whether a compiler
change actually affected the binary.

Fixes https://github.com/tinygo-org/tinygo/issues/3504
2023-03-02 18:47:09 +01:00
Damian Gryski 1cce1ea423 reflect: uncomment some DeepEqual tests that now pass 2023-02-28 13:10:40 -08:00
Damian Gryski a2bb1d3805 reflect: add MapKeys() 2023-02-28 13:10:40 -08:00
Damian Gryski c4dadbaaab reflect: add MakeMap() 2023-02-28 13:10:40 -08:00
Damian Gryski 828c3169ab reflect: add SetMapIndex() 2023-02-28 13:10:40 -08:00
Damian Gryski f6ee470eda reflect: add MapRange/MapIter 2023-02-28 13:10:40 -08:00
Damian Gryski d0f4702f8b reflect: add MapIndex() 2023-02-28 13:10:40 -08:00
Damian Gryski c0a50e9b47 runtime: add unsafe.pointer reflect wrappers for hashmap calls 2023-02-28 13:10:40 -08:00
Damian Gryski 9541525402 reflect: add Type.Elem() and Type.Key() for Maps 2023-02-28 13:10:40 -08:00
Damian Gryski 60a93e8e2d compiler, reflect: add map key and element type info 2023-02-28 13:10:40 -08:00
Federico G. Schwindt cdf785629a Fail earlier if Go is not available 2023-02-28 08:25:33 +01:00
Ayke van Laethem ea183e9197 compiler: add llvm.ident metadata
This metadata is emitted by Clang and I found it is important for source
level debugging on MacOS. This patch does not get source level debugging
to work yet (for that, it seems like packages need to be built
separately), but it is a step in the right direction.
2023-02-27 23:11:22 +01:00
deadprogram 74160c0e32 runtime/atsamd51: enable CMCC cache for greatly improved performance on SAMD51
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-27 20:40:41 +01:00
Ron Evans 6e1b8a54aa machine/stm32, nrf: flash API (#3472)
machine/stm32, nrf: implement machine.Flash

Implements the machine.Flash interface using the same definition as the tinyfs BlockDevice.

This implementation covers the stm32f4, stm32l4, stm32wlx, nrf51, nrf52, and nrf528xx processors.
2023-02-27 13:55:38 +01:00
Ayke van Laethem 8bf94b9231 internal/task: disallow blocking inside an interrupt
Blocking inside an interrupt is always unsafe and will lead to all kinds
of bad behavior (even if it might appear to work sometimes). So disallow
it, just like allocating heap memory inside an interrupt is not allowed.

I suspect this will usually be caused by channel sends, like this:

    ch <- someValue

The easy workaround is to make it a non-blocking send instead:

    select {
    case ch <- someValue:
    default:
    }

This does mean the application might become a bit more complex to be
able to deal with this case, but the alternative (undefined behavior) is
IMHO much worse.
2023-02-26 22:42:24 +01:00
Ayke van Laethem 488174767b builder: remove non-ThinLTO build mode
All targets now support ThinLTO so let's remove the old unused code.
2023-02-26 19:22:10 +01:00
Ayke van Laethem 201592d93b ci: add AVR timers test
Add the timers test because they now work correctly on AVR, probably as
a result of the reflect refactor: https://github.com/tinygo-org/tinygo/pull/2640

I've also updated a few of the other tests to indicate the new status
and why they don't work. It's no longer because of compiler errors, but
because of linker or runtime errors (which is at least some progress).
For example, I found that testdata/reflect.go works if you disable
`testAppendSlice` and increase the stack size.
2023-02-26 17:14:04 +01:00
Damian Gryski 476621736c compiler: zero struct padding during map operations
Fixes #3358
2023-02-25 22:40:08 +01:00
Damian Gryski 7b44fcd865 runtime: properly turn pointer into empty interface when hashing 2023-02-25 06:42:30 -08:00
Bjoern Poetzschke cfe971d723 Rearrange switch case for get pin cfg 2023-02-24 08:53:51 +01:00
John Clark bad7bfc4d5 Pins D4 & D5 are I2C1. Use pins D2 & D3 for I2C0.
Signed-off-by: John Clark <inindev@gmail.com>
2023-02-24 02:20:26 +01:00
deadprogram ad1da7d26f machine/rp2040: correct issue with spi pin validation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-24 01:05:58 +01:00
deadprogram 6df303ff19 machine/rp2040: correct issue with i2c pin validation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-24 01:05:58 +01:00
Patricio Whittingslow 96b70fd619 rp2040: provide better errors for invalid pins on i2c and spi (#3443)
machine/rp2040: provide better errors for invalid pins on i2c and spi
2023-02-23 13:26:14 +01:00
Yurii Soldak 4d0dfbd6fd rp2040: rtc delayed interrupt 2023-02-23 09:23:37 +01:00
deadprogram 1065f06e57 machine/lorae5: add needed definition for UART2
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-20 14:15:31 +01:00
Ayke van Laethem ec27d9fb48 ci: don't pass -v to go test
It can be difficult to find what went wrong in a test. Omitting -v
should make it easier to see the failing tests and the output for them
(note that output is still printed for tests that fail).
2023-02-20 00:23:52 +01:00
Ayke van Laethem cce9c6d5a1 arm64: fix register save/restore to include vector registers
Some vector registers must be preserved across calls, but this wasn't
happening on Linux and MacOS. When I added support for windows/arm64, I
saw that it required these vector registers to be preserved and assumed
this was Windows deviating from the standard calling convention. But
actually, Windows was just implementing the standard calling convention
and the bug was on Linux and MacOS.

This commit fixes the bug on Linux and MacOS and at the same time merges
the Go and assembly files as they no longer need to be separate.
2023-02-19 20:48:32 +01:00
Ayke van Laethem f41b6a3b96 runtime: check for heap allocations inside interrupts
This is unsafe and should never be done.
2023-02-19 11:33:24 +01:00
deadprogram e066e67baf machine/rp2040: change calling order for device enumeration fix to do first
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-19 08:32:39 +01:00
Ayke van Laethem cacb452aa6 main: support qemu-user debugging
Running binaries in QEMU (when debugging on Linux for example) did not
work correctly as qemu-user expects the `-g` flag to be first on the
command line before the program name. Putting it after will make it a
command line parameter for the emulated program, which is not what we
want.

I don't think this ever worked correctly.
2023-02-19 01:35:10 +01:00
Andy Shinn 9296332151 fix bad qt py pin assignment 2023-02-19 00:39:41 +01:00
deadprogram 1125d42149 build/docker: use build context from pre-saved LLVM container to avoid rebuilding
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-18 19:41:11 +01:00
deadprogram 7982d26db0 docker: ignore changes to CI itself to avoid breaking cache on images
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-18 19:41:11 +01:00
deadprogram f6758d22d8 build/linux: install wasmtime directly from github release
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-18 19:41:11 +01:00
deadprogram 87cfe6a538 build/docker: trigger all builds in tinygo ecosystem repos using GH actions
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-02-18 19:41:11 +01:00
Ayke van Laethem c02cc339c5 runtime: implement KeepAlive using inline assembly 2023-02-18 10:50:26 +01:00
Anton D. Kachalov 361ecf9ea4 Better handling of sub-clusters in SVD (#3335)
gen: Better handling of sub-clusters in SVD
2023-02-18 09:10:23 +01:00
sago35 e21ab04fad machine/usb/hid: add MediaKey support (#3436)
machine/usb/hid: add MediaKey support
2023-02-18 01:27:15 +01:00
Ayke van Laethem 4e8453167f all: refactor reflect package
This is a big commit that changes the way runtime type information is stored in
the binary. Instead of compressing it and storing it in a number of sidetables,
it is stored similar to how the Go compiler toolchain stores it (but still more
compactly).

This has a number of advantages:

  * It is much easier to add new features to reflect support. They can simply
    be added to these structs without requiring massive changes (especially in
    the reflect lowering pass).
  * It removes the reflect lowering pass, which was a large amount of hard to
    understand and debug code.
  * The reflect lowering pass also required merging all LLVM IR into one
    module, which is terrible for performance especially when compiling large
    amounts of code. See issue 2870 for details.
  * It is (probably!) easier to reason about for the compiler.

The downside is that it increases code size a bit, especially when reflect is
involved. I hope to fix some of that in later patches.
2023-02-17 22:54:34 +01:00
Ayke van Laethem ebb410afd9 reflect: make sure null bytes are supported in tags 2023-02-17 22:54:34 +01:00
Ron Evans 012bdfae80 build: always cache LLVM source/build even if the tests fail to avoid extra rebuilds (#3453)
builds/macos, linux, windows: update to explicit restore/save for LLVM source and LLVM builds
2023-02-17 17:52:15 +01:00
Anuraag Agrawal f6df276118 runtime: allow custom-gc SetFinalizer and clarify KeepAlive 2023-02-17 00:51:51 +01:00
Anuraag Agrawal e0a5fc2555 Filter target build-tags if user specified an overriding option (#3357)
compileopts: Filter target build-tags if user specified an overriding option
2023-02-14 23:21:28 +01:00
sago35 cecb80b8bf goenv: update to new v0.28.0 development version 2023-02-14 19:32:02 +01:00
Damian Gryski d899895e32 Makefile: more stdlib tests for CI 2023-02-14 05:17:46 -08:00
Ayke van Laethem 0d56dee00f ci: don't link with libzstd in release builds
libzstd was added in LLVM 15, but we don't currently use it. So let's
disable it in LLVM just like libzlib.

See: https://reviews.llvm.org/D128465
2023-02-11 09:14:15 +01:00
Ayke van Laethem 1f0bf9ba63 ci: switch to actions/checkout@v3
I saw the following warning on GitHub Actions:

    Node.js 12 actions are deprecated. Please update the following
    actions to use Node.js 16: actions/checkout@v2. For more information
    see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/.

Updating seems quite reasonable to me.
2023-02-07 22:00:21 +01:00
Ayke van Laethem 0b0ae19656 all: update x/tools/go/ssa to include slice-to-array bugfix
For the bugfix, see: https://github.com/golang/go/issues/57790
2023-02-07 10:21:35 +01:00
Ayke van Laethem 9027c50405 all: update to version 0.27.0 2023-02-03 07:38:40 -08:00
Ayke van Laethem 4ce54ede15 ci: switch to Go 1.20 2023-02-03 07:31:38 -08:00
Ayke van Laethem d8b1fac690 syscall: add more stubs as needed for Go 1.20 support 2023-02-03 07:31:38 -08:00
Ayke van Laethem 1996fad075 windows: add support for syscall.runtimeSetenv
I missed this in https://github.com/tinygo-org/tinygo/pull/3391 (because
I didn't test on Windows, my fault).
2023-02-03 07:31:38 -08:00
Ayke van Laethem 7fe996e7ba runtime: implement internal/godebug.setUpdate
This function was a stub, but it really needs to be implemented for full
Go 1.20 support. Without it, the archive/zip tests will fail.
2023-02-03 07:31:38 -08:00
Anuraag Agrawal 47ca1c037b Add custom-gc stub for ReadMemStats 2023-01-31 16:41:49 +01:00
Ayke van Laethem df0f5ae1da windows: add ARM64 support
This was actually surprising once I got TinyGo to build on Windows 11
ARM64. All the changes are exactly what you'd expect for a new
architecture, there was no special weirdness just for arm64.

Actually getting TinyGo to build was kind of involved though. The very
short summary is: install arm64 versions of some pieces of software
(like golang, cmake) instead of installing them though choco. In
particular, use the llvm-mingw[1] toolchain instead of using standard
mingw.

[1]: https://github.com/mstorsjo/llvm-mingw/releases
2023-01-30 21:42:47 +01:00
John Clark 45c8817ddd Support for the Espressif ESP32-C3-DevKit-RUST-1 development board
Signed-off-by: John Clark <inindev@gmail.com>
2023-01-29 22:50:12 +01:00
Anuraag Agrawal eebd2f648b Add -gc=custom option (#3302)
* Add -gc=custom option
2023-01-28 20:24:56 +01:00
Takeshi Yoneda 13698b17f7 runtime/debug: stubs PrintStack
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-27 10:24:54 +01:00
deadprogram dd9c2273e4 runtime/stm32wlx: change order for init so clock speeds are set before peripheral start
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-27 00:08:38 +01:00
John Clark 1adfdf8fa5 Support for Makerfabs ESP32C3SPI35 TFT Touchscreen board
Signed-off-by: John Clark <inindev@gmail.com>
2023-01-26 20:16:11 +01:00
Ayke van Laethem da362b8a24 wasm: support ThinLTO
Using ThinLTO manages to optimize binaries quite significantly. The
exact amount varies a lot by program but it's about 10-15% usually.

Don't remove non-ThinLTO support yet. It would not surprise me if this
triggered some unintended side effect. Eventually, non-ThinLTO support
should be removed though.
2023-01-25 18:43:00 +01:00
Olivier Fauchon 7fa13ed0a6 Target MCU was not properly defined for LGT92 target
Change openocd interface from stlink-v2 to stlink (interface/stlink-v2.cfg is deprecated)
2023-01-25 14:11:28 +01:00
Olivier Fauchon eec915170d stm32wl: Fix incomplete RNG initialisation 2023-01-24 16:16:56 +01:00
Adrian Cole 334a12818d Allows the emulator to expand {tmpDir}
This allows you to expand {tmpDir} in the json "emulator" field, and
uses it in wasmtime instead of custom TMPDIR mapping logic.

Before, we had custom logic for wasmtime to create a separate tmpDir
when running go tests. This overwrite the TMPDIR variable when running,
after making a mount point. A simpler way to accomplish the end goal of
writing temp files is to use wasmtime's map-dir instead. When code is
compiled to wasm with the wasi target, tempDir is always /tmp, so we
don't need to add variables (since we know what it is). Further, the
test code is the same between normal go and run through wasmtime. So, we
don't need to make a separate temp dir first, and avoiding that reduces
logic, as well makes it easier to swap out the emulator (for wazero
which has no depedencies). To map the correct directory, this introduces
a {tmpDir} token whose value is the host-specific value taken from
`os.TempDir()`.

The motivation I have for this isn't so much to clean up the wasmtime
code, but allow wazero to execute the same tests. After this change, the
only thing needed to pass tests is to change the emulator, due to
differences in how wazero deals with relative lookups (they aren't
restricted by default, so there's not a huge amount of custom logic
needed).

In other words, installing wazero from main, `make tinygo-test-wasi`
works with no other changes except this PR and patching
`targets/wasi.json`.
```json
	"emulator":      "wazero run -mount=.:/ -mount={tmpDir}:/tmp {}",
```

On that note, if there's a way to override the emulator via arg or env,
this would be even better, but in any case patching json is fine.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-19 20:06:18 +01:00
Damian Gryski 0504e4a201 compiler,runtime: make keySize and valueSize uintptr 2023-01-18 09:48:00 +01:00
Damian Gryski 530ca0838d compiler,runtime: allow map values >256 bytes 2023-01-18 09:48:00 +01:00
Ayke van Laethem c41a212712 wasm: avoid miscompile with ThinLTO
I found that when I enable ThinLTO, a miscompilation triggers that had
been hidden all the time previously. The bug appears to happen as
follows:

 1. TinyGo generates a function with a runtime.trackPointer call, but
    without an alloca (or the alloca gets optimized away).
 2. LLVM sees that no alloca needs to be kept alive across the
    runtime.trackPointer call, and therefore it adds the 'tail' flag.
    One of the effects of this flag is that it makes it undefined
    behavior to keep allocas alive across the call (which is still safe
    at that point).
 3. The GC lowering pass adds a stack slot alloca and converts
    runtime.trackPointer calls into alloca stores.

The last step triggers the bug: the compiler inserts an alloca where
there was none before but that's not valid as long as the 'tail' flag is
present.

This patch fixes the bug in a somewhat dirty way, by always creating a
dummy alloca so that LLVM won't do the optimization in step 2 (and
possibly other optimizations that rely on there being no alloca
instruction).
2023-01-18 08:24:42 +01:00
Ayke van Laethem 27824e3c80 compiler: move some llvmutil code into the compiler
This is purely a refactor, to make the next change simpler.
The wordpack functionality used to be necessary in transform passes, but
now it isn't anymore so let's not complicate this more than necessary.
2023-01-18 08:24:42 +01:00
Ayke van Laethem 159317a5fe all: remove remaining +build lines 2023-01-17 23:35:53 +01:00
Ayke van Laethem 655075e5e0 runtime: implement precise GC
This implements the block-based GC as a partially precise GC. This means
that for most heap allocations it is known which words contain a pointer
and which don't. This should in theory make the GC faster (because it
can skip non-pointer object) and have fewer false positives in a GC
cycle. It does however use a bit more RAM to store the layout of each
object.

Right now this GC seems to be slower than the conservative GC, but
should be less likely to run out of memory as a result of false
positives.
2023-01-17 19:32:18 +01:00
Ayke van Laethem f9d0ff3bec all: store data layout as little endian value
This makes it much easier to read the value at runtime, as pointer
indices are naturally little endian. It should not affect anything else
in the program.
2023-01-17 19:32:18 +01:00
Ayke van Laethem 17176a2cea runtime: zero freed memory
This helps to find bugs in the GC. It does have a performance impact so
it's only enabled when asserts are enabled.
2023-01-17 19:32:18 +01:00
Ayke van Laethem fb73074325 runtime: move GC code around to prepare for precise GC
Most of the code of the conservative GC can be reused for the precise
GC. So before adding precise GC support, this commit just moves code
around to make the next commit cleaner. It is a non-functional change.
2023-01-17 19:32:18 +01:00
Ayke van Laethem 187d9c6aca riscv: use 16-byte alignment everywhere
Source: https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf
2023-01-17 19:32:18 +01:00
Ayke van Laethem 35f427c8cc xtensa: use 8-byte alignment
This is probably not necessary on Espressif chips, but let's strictly
follow the ABI to be sure.
2023-01-17 19:32:18 +01:00
Ayke van Laethem 26b6d0b06d runtime: arm actually has 8-byte alignment
Specification:
https://developer.arm.com/documentation/dui0472/k/C-and-C---Implementation-Details/Basic-data-types-in-ARM-C-and-C--
There are multiple types that have an 8-byte alignment (long long,
double) so we need to use the same maximum alignment in TinyGo.

Fixing this is necessary for the precise GC.
2023-01-17 19:32:18 +01:00
Ayke van Laethem 38252e338f runtime: arm64 actually has 16-byte alignment like amd64
Proof: https://godbolt.org/z/as4EM3713
Essentially, this means that there are objects on arm64 that have a
16-byte alignment and so we have to respect that when we allocate things
on the heap.
2023-01-17 19:32:18 +01:00
Marcus Sorensen e7ba07dd5a Add PDM support for circuitplay-bluefruit (#3359)
machine/nrf52840: add PDM support

Signed-off-by: Marcus Sorensen <marcus@turboio.com>
2023-01-17 12:32:01 +01:00
Ayke van Laethem 0d646d8e95 builder: add support for Go 1.20
Not all features work yet, but allow it to compile with this Go version.
2023-01-17 08:38:54 +01:00
Ayke van Laethem 3177591b31 syscall: implement setenv/unsetenv in the runtime
This is expected starting with Go 1.20.

I've also applied the same modification to syscall_libc.go so that
setenv is only called in a single place.
2023-01-17 08:38:54 +01:00
Ayke van Laethem 19db0144ae runtime: implement internal/godebug.setUpdate as a stub
This function provides a mechanism to watch for changes to the GODEBUG
environment variable. For now, we'll not implement it. It might be
useful in the future, when it can always be added.
2023-01-17 08:38:54 +01:00
Ayke van Laethem d639e01650 runtime: implement math/rand.fastrand64 to fix linker error
This is needed for Go 1.20 support.
2023-01-17 08:38:54 +01:00
Ayke van Laethem c43958972c compiler: add support for new unsafe slice/string functions
This adds support for unsafe.SliceData, unsafe.String, and
unsafe.SringData that were introduced in Go 1.20.
2023-01-17 08:38:54 +01:00
Ayke van Laethem 33489d6344 testing: implement t.Setenv
This method has been added in Go 1.17 and is used in archive/zip
starting with Go 1.20. Therefore, this method is now needed in Go 1.20.

I've left out the parts that disable parallel execution of tests,
because we don't do that in TinyGo.

See:
* https://github.com/golang/go/issues/41260
* https://go-review.googlesource.com/c/go/+/260577
2023-01-15 11:48:05 +01:00
Ayke van Laethem 80077ef276 test: print package name when compilation failed
Before this patch, a compile error would prevent the 'ok' or 'FAIL' line
to be printed. That's unexpected. This patch changes the code in such a
way that it's obvious a test result line is printed in all cases.

To be able to also print the package name, I had to make sure the build
result is passed through everywhere even on all the failure paths. This
results in a bit of churn, but it's all relatively straightforward.

Found while working on Go 1.20.
2023-01-15 08:49:18 +01:00
Ayke van Laethem 911ce3a4bc compiler: update golang.org/x/tools/ssa
This package needs to be updated to support Go 1.20. There were a few
backwards incompatible changes that required updates to the compiler
package.
2023-01-14 22:08:38 +01:00
joey 776dabb2c8 add a stub for os.Chtimes 2023-01-12 15:58:08 +01:00
Ayke van Laethem e11df5c212 cgo: add support for bitwise operators 2023-01-12 08:51:03 +01:00
deadprogram 656805d91f docs: update README with missing boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
2023-01-11 21:51:03 +01:00
Thomas Richner 05ec4e6bd0 Support for Adafruit Feather M0 Express board 2023-01-11 10:07:11 +01:00
Achille Roussel ae65b37762 add comment about where src/os/file.go came from
Signed-off-by: Achille Roussel <achille.roussel@gmail.com>
2023-01-10 20:40:53 +01:00
John Clark aa12579864 Add SPI support for for the ESP32-C3 device.
Signed-off-by: John Clark <inindev@gmail.com>
2023-01-10 15:52:25 +01:00
Damian Gryski 715b269f78 src/runtime: add xorshift-based fastrand64 2023-01-08 10:35:31 +01:00
sago35 5f3534fe72 machine/usb: change to not send before endpoint initialization 2023-01-08 08:44:27 +01:00
irieda a7ff2731b9 Add USB HID joystick support (#3366)
machine/usb: add USB HID joystick support
2023-01-07 22:30:40 +01:00
Anuraag Agrawal 0566bbfeb4 Use renamed EXTRA_CFLAGS when building wasi-libc 2023-01-07 19:53:48 +01:00
sago35 70c4e1cf96 machine/usb: improve buffer size definition 2023-01-07 17:57:19 +01:00
Ayke van Laethem 9fd0567fb5 compiler: fix stack overflow when creating recursive pointer types
There were two types that could result in a compiler stack overflow.
This is difficult to fix in LLVM 14, so I won't even bother. However,
this is trivial to fix with opaque pointers in LLVM 15. Therefore, this
fix is for LLVM 15 only.

Fixes: https://github.com/tinygo-org/tinygo/issues/3341
2022-12-22 17:45:05 +01:00
BCG 481aba6536 board: Adafruit KB2040 (https://www.adafruit.com/product/5302) 2022-12-22 11:49:31 +01:00
Adrian Cole a700f58581 wasi: makes wasmtime "run" explicit
wasmtime by default will assume the subcommand is "run" vs one of its
others, but being explicit helps clarify the actual command invoked.

For example, we pass similar looking args to wasmtime and also wasi.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-22 09:22:17 +01:00
Jesús Espino e71e289e8b Add basic atmega32u support (#3337)
machine/atmega32u: add support for arduino leonardo
2022-12-20 16:57:55 +01:00
sago35 6cdc718bfb rp2040: drop deprecated build tags 2022-12-20 15:53:02 +01:00
sago35 70c94c6d01 rp2040: add version check for RP2040-E5 2022-12-20 15:53:02 +01:00
sago35 762a6f1256 rp2040: fix usb device enumeration (RP2040-E5) 2022-12-20 15:53:02 +01:00
Yurii Soldak 8d4d3c6201 build: drop deprecated build tags 2022-12-19 23:20:11 +01:00
Yurii Soldak 146e2cd376 build: generate files with go:build tags 2022-12-19 23:20:11 +01:00
Jesús Espino d304e6706b Adding support for waveshare rp2040-zero (#3321)
machine: adding support for waveshare rp2040-zero
2022-12-19 12:15:03 +01:00
deadprogram c5c6464175 compileopts: replace 'retries' with more correct 'timeout' param
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-12-19 08:44:39 +01:00
sago35 c90ff1e1cf rp2040: fix interrupt issue (2) 2022-12-19 08:43:56 +01:00
sago35 0f6dfedcfd rp2040: fix interrupt issue 2022-12-17 12:52:19 +01:00
Ron Evans 69a284bd36 Revert "Bump CMSIS to 5.9.0"
This reverts commit 92be61534e.
2022-12-16 21:26:49 +01:00
Anton D. Kachalov 92be61534e Bump CMSIS to 5.9.0 2022-12-16 15:42:35 +01:00
Damian Gryski 675b8e3f3c builder: always run wasm-opt for wasm32 binaries 2022-12-16 10:11:39 +01:00
Ayke van Laethem f3d0195d35 runtime: move KeepAlive/SetFinalizer to common code
We don't support these yet so let's just put them in a central location.
Once these functions are supported we can think about how to structure
the code again.
2022-12-15 19:25:27 +01:00
sago35 398c284480 usbhid: change usage-maximum to 0xFF 2022-12-15 18:24:54 +01:00
Damian Gryski 86f125cf72 reflect: track flags when size changes from fits-in-pointer to not
Fixes #3328
2022-12-07 23:11:40 +01:00
sago35 5293d3e5f0 atsame5x: reduce heap allocation 2022-12-01 22:27:12 +01:00
Ayke van Laethem 7aca814954 windows: update mingw-w64 version
This gets rid of the following messages:

    ld.lld: warning: duplicate /export option: hypot
    ld.lld: warning: duplicate /export option: nextafter

I've wanted to wait for the next release but that may take a long while,
so I've simply set the submodule to the commit that fixes this message.
2022-11-26 21:42:15 +01:00
deadprogram 1d52e6be29 machine/nrf51: add ADC implementation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-11-26 20:17:11 +01:00
sago35 acb2391439 atsame5x: fix extendedID handling 2022-11-25 17:57:16 +01:00
Ayke van Laethem 49007891c8 all: re-enable AVR tests
I have some confidence they'll work reliably now.
2022-11-25 10:56:42 +01:00
Ayke van Laethem 54aec042b7 avr: add channel test
It is working now, so add it as a test. Not sure why, maybe the ThinLTO
change fixed something here?
2022-11-25 10:56:42 +01:00
sago35 baca8a643e xiao-rp2040: add pin definitions 2022-11-23 09:01:48 +01:00
Anuraag Agrawal b731919f97 Fix panic when size 0 passed to malloc 2022-11-21 21:00:36 +01:00
Julia Ogris c759e6fc2d reflect: Add Value.IsZero() method
Add Value.IsZero() with tests, largely copied from the Go source code.

The tests were altered to remove the parts calling `Zero()` as that is
still unimplemented in tinygo, and to remove a test that tries to catch
a panic which is not supported on wasi.

A new case for `UnsafePointer` in `Value.IsNil()` was required for
unsafe.Pointer tests to pass.

Link: https://cs.opensource.google/go/go/+/refs/tags/go1.19.3:src/reflect/value.go;l=1568
Link: https://cs.opensource.google/go/go/+/refs/tags/go1.19.3:src/reflect/all_test.go;l=1322
Co-authored-by: Cam Hutchison <camh@xdna.net>
2022-11-21 14:51:22 +01:00
goropikari a329f56ec2 Fix xiao rp2040 pin variable assignment
According to official infomation(https://wiki.seeedstudio.com/XIAO-RP2040/), D9 and D10 are corresponding to GPIO4 and GPIO3, respectively.
2022-11-21 11:49:18 +01:00
deadprogram 6e503f5ab9 build: update docker GH action to use latest docker action versions 2022-11-21 10:59:59 +01:00
deadprogram 217449df07 machine/stm32f1, stm32f4: fix ADC by clearing the correct bit for rank after each read
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-11-21 08:53:21 +01:00
deadprogram a7fc65861d machine/stm32: always set ADC pins to pullups floating
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-11-21 08:53:21 +01:00
Damian Gryski f0a271bd21 transform: remove duplicate if in gc transform 2022-11-18 20:19:47 +01:00
Ayke van Laethem 4d14d3cd54 avr: support ThinLTO
ThinLTO results in a small code size reduction, which is nice
(especially on these very small chips). It also brings us one step
closer to using ThinLTO everywhere.
2022-11-18 18:40:38 +01:00
Ayke van Laethem 5c622cfc43 compiler: refactor some code for the next commit
This is a pure refactor, it doesn't change the behavior of anything.
It's separate from the next commit so that the actual changes are easier
to read.
2022-11-18 18:40:38 +01:00
Ayke van Laethem 783c6a813a wasm: fix scanning of the stack
LLVM wasn't aware that runtime.stackChainStart must be kept live and
can't be optimized away. With this hack, it is forced to consider
stackChainStart live at the time of the stack scan.

This fixes the corruption in https://github.com/tinygo-org/tinygo/issues/3277
2022-11-17 17:19:10 +01:00
Ayke van Laethem 67841207e8 Revert "Enable wasm pointer tracking for gc=none."
This reverts commit 0b3a7280fa and updates
the documentation a little bit to explain the purpose of -gc=none. (I'm
thinking about the attiny10 by the way where defaulting to -gc=none
makes sense).
2022-11-17 15:50:57 +01:00
tachyonicbytes d92e16e6dc Stubbed Setuid and friends. Stubbed Exec (#3290)
Co-authored-by: TachyonicBytes <TB>
2022-11-16 10:14:27 +01:00
Dan Kegel 4daf4fa0a0 corpus: add buger/jsonparser 2022-11-15 11:03:05 +01:00
Anuraag Agrawal 0b3a7280fa Enable wasm pointer tracking for gc=none. 2022-11-15 10:21:11 +01:00
Ayke van Laethem bb5050a50d avr: fix .data initialization for binaries over 64kB
I found that .data is not correctly initialized with firmware images
that use over 64kB of flash. The problem is that the data in .data
(which is stored in flash, and copied to RAM at reset) is beyond the
64kB limit and must therefore be loaded using the elpm instruction
instead of the lpm instruction.

I encountered this issue while getting testdata/math.go to work for AVR.
The following command mostly works with this patch, while it prints
garbage withtout it:

    tinygo run -target=simavr -size=short -scheduler=none ./testdata/math.go

(This also requires a patch to picolibc to work, see
https://github.com/picolibc/picolibc/pull/371)

It still doesn't work entirely with this patch: some of the math
operations have an incorrect result. But at least it's an improvement as
it won't print garbage anymore.
2022-11-14 22:22:26 +01:00
deadprogram 73b368270c compileopts: add 'retries' flag to allow setting the number of times to retry locating the MSD volume when flashing
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-11-13 20:47:11 +01:00
Ayke van Laethem 2001c44ed3 builder: print compiler commands while building a library
We should have been doing this all along and makes it easier to debug
things that go wrong while compiling a library.
2022-11-12 17:38:02 +01:00
Ayke van Laethem 666ead3996 main: fix -work flag
I broke this flag in f866d5cc38. This
commit fixes it.
2022-11-06 14:06:58 +01:00
Ayke van Laethem df888acd5e avr: drop GNU toolchain dependency
- Use compiler-rt and picolibc instead of avr-libc.
  - Use ld.lld instead of avr-ld (or avr-gcc).

This makes it much easier to get started with TinyGo on AVR because
installing these extra tools (gcc-avr, avr-libc) can be a hassle.
It also opens the door for future improvements such as ThinLTO.

There is a code size increase but I think it's worth it in the long run.
The code size increase can hopefully be reduced with improvements to the
LLVM AVR backend and to compiler-rt.
2022-11-06 09:05:05 +01:00
Ayke van Laethem b9bb605257 all: update picolibc to v1.7.9
This newer version has some support for AVR.
2022-11-06 09:05:05 +01:00
Ayke van Laethem e1281b0128 darwin: fix error with tinygo lldb
Before this patch, `tinygo lldb path/to/package` would result in an
error:

    (lldb) target create --arch=arm64-unknown-macosx10.12.0 "/var/folders/17/btmpymwj0wv6n50cmslwyr900000gn/T/tinygo2731663853/main"
    error: the specified architecture 'arm64-unknown-macosx10.12.0' is not compatible with 'arm64-apple-macosx10.12.0' in '/var/folders/17/btmpymwj0wv6n50cmslwyr900000gn/T/tinygo2731663853/main'

This patch fixes this error.

Unfortunately, it doesn't get debug information to work yet. I still
haven't figured out what's going wrong here. But it's progress, I guess.
2022-11-05 10:20:03 +01:00
Ayke van Laethem 81dbbea1c8 esp: use ThinLTO for Xtensa
This is now possible because we're using the LLVM linker. It results in
some very minor code size reductions. The main benefit however is
consistency: eventually, all targets will support ThinLTO at which point
we can remove support for GNU linkers and simplify the compiler.
2022-11-04 22:49:22 +01:00
Anuraag Agrawal a834359079 Update docs 2022-11-04 19:53:12 +01:00
Anuraag Agrawal 29f8d22a2d sync: implement simple pooling in sync.Pool 2022-11-04 19:53:12 +01:00
Ayke van Laethem 9e34ca9e5f esp: use LLVM Xtensa linker instead of Espressif toolchain
The Espressif fork of LLVM now has Xtensa support in the linker LLD.
(This support was written mosly by me). This means we don't have to use
the Espressif GNU toolchain anymore and makes installing TinyGo simpler.

In the future, this also paves the way for ThinLTO support. Right now it
is mostly just a way to simplify TinyGo installation and speed up CI
slightly.
2022-11-04 09:11:21 +01:00
Ayke van Laethem 268140ae40 wasm: remove -wasm-abi= flag
This flag controls whether to convert external i64 parameters for use in
a browser-like environment.

This flag was needed in the past because back then we only supported
wasm on browsers but no WASI. Now, I can't think of a reason why anybody
would want to change the default. For `-target=wasm` (used for
browser-like environments), the wasm_exec.js file expects this
i64-via-stack ABI. For WASI, there is no limitation on i64 values and
`-wasm-abi=generic` is the default.
2022-11-04 08:28:26 +01:00
deadprogram 8906584fb9 testdata: clearly correct values for timing test with a little more time to spare on CI machines
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-11-03 15:26:20 +01:00
Ayke van Laethem aaa860f154 cgo: support anonymous enums included in multiple Go files
Anonymous enums (often used in typedefs) triggered a problem that was
already solved for structs but wasn't yet solved for enums. So this
patch generalizes the code to work for both structs and enums, and adds
testing for both.
2022-11-02 21:21:40 +01:00
Anuraag Agrawal bce0516394 Allow custom wasm malloc implementation (#3245) 2022-11-02 08:52:48 +01:00
Austin Vazquez 726d74ad1b Upgrade GitHub actions packages from v2 to v3
Signed-off-by: Austin Vazquez <macedonv@amazon.com>
2022-11-01 23:30:39 +01:00
waj334 ad544b5133 Implements calloc. 2022-10-31 17:46:09 +01:00
Ayke van Laethem 580fd490a5 all: remove libffi warning on macos
Running `go install` on MacOS produces the following warning:

    # github.com/tinygo-org/tinygo
    ld: warning: directory not found for option '-L/opt/homebrew/opt/libffi/lib'

It doesn't look like libffi is used anywhere, so I simply removed it.
Not sure why it was included in the first place.

(I updated the Makefile for consistency, but we really should be
removing that Makefile especially because the Go bindings are removed in
upstream LLVM).
2022-10-31 12:19:24 +01:00
Ayke van Laethem c0d505d13a all: use DWARF version 4
This should hopefully fix the following issue:

    DW_FORM_rnglistx index pointing outside of .debug_rnglists offset array [in module /tmp/tinygo4013272868/main]
2022-10-31 09:59:32 +01:00
Matt Johnston 12a41dc791 Add basic GPIO support for rp2040 PIO 2022-10-27 11:47:47 +02:00
soypat dd3ad57efb avoid allocating clock on heap 2022-10-26 23:27:28 +02:00
Damian Gryski 89facf834f fix printing of benchmark output 2022-10-26 20:07:31 +02:00
Anuraag Agrawal 62594004c6 Stub out reflect.Type FieldByIndex 2022-10-26 12:06:08 +02:00
Ayke van Laethem 3dbc4d5210 main: fix outputting .ll files
This command didn't work anymore since the refactor in #3211.
The reason it doesn't work anymore is that before the refactor, the code
in the callback wasn't executed for .ll, .bc and .o files but after the
refactor it is, which causes a spurious error.

This commit fixes this oversight.

Example that didn't work anymore and is fixed with this change:

    tinygo build -o test.ll examples/serial
2022-10-22 11:55:34 +02:00
Anuraag Agrawal 42e4a75319 Look for LLVM 15 in makefile 2022-10-21 09:16:46 +02:00
Ayke van Laethem 2b7f562202 ci: add support for LLVM 15
This commit switches to LLVM 15 everywhere by default, while still
keeping LLVM 14 support.
2022-10-19 22:23:19 +02:00
Ayke van Laethem 08a51535d4 interp: add support for constant icmp instructions
These instructions sometimes pop up in LLVM 15, but they never occured
in LLVM 14. Implementing them is relatively straightforward: simply
generalize the code that already exists for llvm.ICmp interpreting.
2022-10-19 22:23:19 +02:00
Ayke van Laethem 0ddcf4af96 riscv: add "target-abi" metadata flag
This flag is necessary in LLVM 15 because it appears that LLVM 15 has
changed the default target ABI from lp64 to lp64d. This results in a
linker failure. Setting the "target-abi" forces the RISC-V backend to
use the intended target ABI.
2022-10-19 22:23:19 +02:00
Ayke van Laethem d435fc868b transform: fix memory corruption issues
There was a bug in the wasm ABI lowering pass (found using
AddressSanitizer on LLVM 15) that resulted in a rather subtle memory
corruption. This commit fixes this issues.
2022-10-19 22:23:19 +02:00
Ayke van Laethem 62df1d7490 all: remove pointer ElementType calls
This is needed for opaque pointers, which are enabled by default in
LLVM 15.
2022-10-19 22:23:19 +02:00
Ayke van Laethem 229746b71e interp: change object.llvmType to the initializer type
Previously it was a pointer type, which won't work with opaque pointers.
Instead, use the global initializer type instead.
2022-10-19 22:23:19 +02:00
Ayke van Laethem 09ec846c9f all: replace llvm.Const* calls with builder.Create* calls
A number of llvm.Const* functions (in particular extractvalue and
insertvalue) were removed in LLVM 15, so we have to use a builder
instead. This builder will create the same constant values, it simply
uses a different API.
2022-10-19 22:23:19 +02:00
Ayke van Laethem f57cffce2d all: add type parameter to *GEP calls
This is necessary for LLVM 15.
2022-10-19 22:23:19 +02:00
Ayke van Laethem 7b6a9fab42 all: add type parameter to CreateLoad
This is needed for LLVM 15.
2022-10-19 22:23:19 +02:00
Ayke van Laethem 6bc6de8f82 all: add type parameter to CreateCall
This uses LLVMBuildCall2 in the background, which is the replacement for
the deprecated LLVMBuildCall function.
2022-10-19 22:23:19 +02:00
Ayke van Laethem b79bf29c11 compiler: return a FunctionType (not a PointerType) in getRawFuncType
This is necessary for opaque pointer support (in LLVM 15).
2022-10-19 22:23:19 +02:00
Ayke van Laethem 65d65c1313 wasm: fix GC scanning of allocas
Scanning of allocas was entirely broken on WebAssembly. The code
intended to do this was never run. There were also no tests.

Looking into this further, I found that it is actually not really
necessary to do that: the C stack can be scanned conservatively and in
fact this was already done for goroutine stacks (because they live on
the heap and are always referenced). It wasn't done for the system stack
however.

With these fixes, I believe code should be both faster *and* more
correct.

I found this in my work to get opaque pointers supported in LLVM 15,
because the code that was never reached now finally got run and was
actually quite buggy.
2022-10-19 18:36:53 +02:00
Damian Gryski 6b46ae261a runtime: switch some panic() calls in the gc to runtimePanic() for consistency 2022-10-19 12:54:17 +02:00
Fred Goya b734b3c7a1 Print PASS on pass when running standalone test binaries (#3229)
* Add test.batch flag so standalone tests print PASS on pass
* Add comment; use single-dash flag style to match usage elsewhere
* Don't add test.batch for wasmtime
* Skip test.batch unless emulator name is blank
* Remove test.batch flag; buffer test output and show only on verbose or failure
* Remove FAIL when all tests fail to match go test output
2022-10-19 09:46:43 +02:00
Ayke van Laethem 5937f03a07 corpus: remove 'noasm' from some tests
Unfortunately I couldn't fully test these changes, but they don't seem
to be needed on linux/amd64.
2022-10-19 00:03:40 +02:00
Ayke van Laethem bf9282a3a0 corpus: remove golang.org/x/crypto/internal/subtle
This subdirectory appears to be gone now.
2022-10-18 20:44:40 +02:00
Hrishi Hiraskar cad5b79a2d net: implement Pipe 2022-10-18 07:50:31 +02:00
deadprogram d56c9f5533 machine/usb: add back New() with deprecation comment to use Port() instead
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-10-17 14:46:18 +02:00
deadprogram 3d7f24e26c machine/usb: rename 'New()' to 'Port()' to have the API better match the singleton that is actually being returned
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-10-17 14:46:18 +02:00
Ayke van Laethem c32490935b main: fix error message when a serial port can't be accessed
Old message:

    error: failed to reset port /tmp/tinygo1441085170/main.uf2: opening port: Permission denied

new message:

    error: failed to reset port /dev/ttyACM0: opening port: Permission denied
2022-10-16 22:17:27 +02:00
Ayke van Laethem 2b04006b1e main: fix USB vid/pid lookup
I introduced a bug in #3207: looking up a VID/PID pair would result in a
slice out of bounds panic. This is a trivial fix for that bug.
2022-10-16 22:17:27 +02:00
Ayke van Laethem 9de757205f linux: include musl 'getpagesize' function in release
I wonder why nobody else noticed this bug? In any case, this patch fixes it.
2022-10-16 12:03:03 +02:00
Ayke van Laethem f866d5cc38 builder: refactor Build function to not use a callback
The only reason a callback was used, was so that the temporary directory
gets removed once `Build` returns. But that is honestly a really bad
reason: the parent function can simply create a temporary function and
remove it when it returns. It wasn't worth the code complexity that this
callback created.

This change should not cause any observable differences in behavior (it
should be a non-functional change).

I have no reason to do this now, but this unclean code has been bugging
me and I just wanted to get it fixed.
2022-10-16 10:48:34 +02:00
Ayke van Laethem c153239682 targets: remove "acm:"` prefix for USB vid/pid pair
This prefix isn't actually used and only adds noise, so remove it.

It may have been useful on Linux that makes a distinction between
/dev/ttyACM* and /dev/ttyUSB* but it isn't now. Also, it's unlikely that
the same vid/pid pair will be shared between an acm and usb driver
anyway.
2022-10-16 10:02:48 +02:00
deadprogram 8e88f3e76a build/windows: use GH actions parallel execution to cut build time in half.
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-10-16 09:22:01 +02:00
Ayke van Laethem a62044d89b targets: do not set stack size per board
The needed stack size is hard to determine by the compiler. It will try,
but will fail in many common cases. Therefore, the runtime will pick a
fixed stack size.

There is a tradeoff between avoiding stack overflows and wasting RAM.
This tradeoff depends on the application: some don't need large stack
sizes but do need a lot of memory, while others need deep stacks but
aren't so memory constrained. That's why I've added a flag to do this on
the command line: https://github.com/tinygo-org/tinygo/pull/3159

It may be reasonable to use a different stack size per chip, for example
chips with lots of RAM could default to a larger stack size. But I don't
think it's a good idea to do this per board.
2022-10-14 13:36:42 +02:00
Ayke van Laethem 5548b5999b Makefile: add ASAN=1 flag to build with AddressSanitizer enabled
This sanitizer is useful to detect use-after-free, double free, buffer
overflows, and more such errors.

I've found it useful lately to detect some bugs in TinyGo, and having a
single flag to enable it makes it much easier to enable
AddressSanitizer.
2022-10-14 11:17:51 +02:00
Kenneth Bell 8f33721b88 usb: remove allocs in ISR 2022-10-13 23:37:34 +02:00
Ayke van Laethem 7e9d84777e darwin: fix syscall.Open on darwin/arm64
Unfortunately the calling convention for variadic functions is different from
the calling convention of regular functions on darwin/arm64, and open happens
to be such a variadic function. The syscall package treated it like a regular
function, which resulted in buggy behavior.

This fix introduces a wrapper function. This is the cleanest change I could
come up with.
2022-10-13 21:07:38 +02:00
Ayke van Laethem 2072d1bb5c main: print ldflags including ThinLTO flags with -x
The -x flag prints commands as they are executed. Unfortunately, for the link
command, they were printed too early: before the ThinLTO flags were added.
This is somewhat confusing while debugging.
2022-10-13 18:57:49 +02:00
Ayke van Laethem 636a151ffe cgo: add support for C.float and C.double
They are not necessary in TinyGo because they always map to float32 and
float64, but it's a good idea to add them regardless for compatibility
with existing software.

(Now I think about it, perhaps it would have been better to require
explicit casts here just in case we want to support some really weird C
system, but then again we even force 64-bit double on AVR even though
avr-gcc defaults to 32-bit double).
2022-10-13 17:13:12 +02:00
Ayke van Laethem e7d02cd51b all: update musl 2022-10-13 13:38:02 +02:00
Ayke van Laethem f136eb6adf goenv: update to new v0.27.0 development version 2022-10-13 12:06:48 +02:00
Kenneth Bell 2688d9d733 rp2040: remove mem allocation in GPIO ISR 2022-10-07 11:46:12 +01:00
Ayke van Laethem b5ad81c884 all: update to version 0.26.0 2022-09-29 15:05:15 +02:00
deadprogram c2fb1e776a testdata: increase timings used for timers test to try to avoid race condition errors on macOS CI
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-28 21:55:37 +02:00
Ayke van Laethem 895c542076 builder: do not ignore debug info on baremetal targets
Since https://github.com/tinygo-org/tinygo/pull/3200, `-no-debug` would
ignore debug info for some linkers. Example:

    $ tinygo build -o test.elf -target=arduino -no-debug examples/blinky1
    $ objdump -h test.elf

    test.elf:       file format elf32-avr

    Sections:
    Idx Name            Size     VMA      LMA      Type
      0                 00000000 00000000 00000000
      1 .text           000004e0 00000000 00000000 TEXT
      2 .trampolines    00000000 000004e0 000004e0 TEXT
      3 .stack          00000200 00800100 00800100 BSS
      4 .data           0000004c 00800300 000004e0 DATA
      5 .bss            000000a9 0080034c 0000052c BSS
      6 .debug_loc      00001bf0 00000000 00000000 DEBUG
      7 .debug_abbrev   000004ed 00000000 00000000 DEBUG
      8 .debug_info     00004176 00000000 00000000 DEBUG
      9 .debug_ranges   00000150 00000000 00000000 DEBUG
     10 .debug_str      0000206e 00000000 00000000 DEBUG
     11 .debug_pubnames 000024bf 00000000 00000000 DEBUG
     12 .debug_pubtypes 000004ca 00000000 00000000 DEBUG
     13 .debug_line     0000193c 00000000 00000000 DEBUG
     14 .debug_aranges  0000002c 00000000 00000000 DEBUG
     15 .debug_rnglists 00000015 00000000 00000000 DEBUG
     16 .debug_line_str 00000082 00000000 00000000 DEBUG
     17 .shstrtab       000000d9 00000000 00000000
     18 .symtab         000006d0 00000000 00000000
     19 .strtab         00000607 00000000 00000000

This shows that even though `-no-debug` is supplied, debug information
is emitted in the ELF file.

With this change, debug information is not stripped when TinyGo doesn't
know how to do it:

    $ tinygo build -o test.elf -target=arduino -no-debug examples/blinky1
    error: cannot remove debug information: unknown linker: avr-gcc

(This issue will eventually be fixed by moving to `ld.lld`).
2022-09-28 19:18:11 +02:00
Adrian Cole e91fae5756 compileopts: silently succeed when there's no debug info to strip
Before, on the baremetal target or MacOS, we errored if the user
provided configuration to strip debug info.

Ex.
```bash
$ $ tinygo build -o main.go  -scheduler=none --no-debug  main.go
error: cannot remove debug information: MacOS doesn't store debug info in the executable by default
```

This is a poor experience which results in having OS-specific CLI
behavior. Silently succeeding is good keeping with the Linux philosophy
and less distracting than logging the same without failing.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-27 08:16:35 +02:00
Ayke van Laethem f52ecf3054 machine: use NoPin constant where appropriate
In some cases, regular integers were used. But we have a constant to
explicitly say these pins are undefined: `NoPin`. So use this.

A better solution would be to not require these constants, like with the
proposal in https://github.com/tinygo-org/tinygo/issues/3152. This
change is just a slight improvement over the current state.
2022-09-26 20:44:47 +02:00
Crypt Keeper 725864d8dc cgo: fixes panic when FuncType.Results is nil (#3136)
* cgo: fixes panic when FuncType.Results is nil

FuncType.Results can be nil. This fixes the comparison and backfills
relevant tests.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2022-09-26 19:08:23 +02:00
Damian Gryski fca2de21b1 runtime: make gc and scheduler asserts settable with build tags 2022-09-25 16:47:07 +02:00
Ayke van Laethem 107b1c2906 machine: do not expose RESET_MAGIC_VALUE
This is a constant for internal use only, but was (unintentionally?)
exported. In addition, it doesn't follow the Go naming convention.
This change simply renames the constant so that it is unexported.
2022-09-25 12:38:12 +02:00
deadprogram 2409bbef69 build: set circleci resource class to large for CI build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-25 10:08:10 +02:00
Ayke van Laethem 8b078a9e8f machine: remove level triggered pin interrupts
This removes level-triggered interrupts.

While working on https://github.com/tinygo-org/tinygo/pull/3170, I found
these level triggered interrupt constants. Apart from them being
inconsistent with each other (PinLowLevel vs PinLevelLow) I don't think
they are actually used anywhere. In addition, I removed the
PinNoInterrupt constant on the esp32c3. This makes the esp32c3 pass the
tests in #3170.

I looked into level-triggered interrupts and I really couldn't find a
good justification for them:

  - They were added to the esp32c3 and the rp2040 together with other
    pin interrupt types, meaning they were probably just added because
    the chip supports the feature and not because they were actually
    needed.
  - Level interrupts aren't supported in TinyGo for any other chip, and
    I haven't seen anybody ask for this feature.
  - They aren't supported in the nrf series chips _at all_, and with a
    quick search I found only very little demand for them in general.
  - I tried to see whether there is any good use case for them, but I
    couldn't really find one (where an edge triggered interrupt wouldn't
    work just as well). If there is one where level triggered interrupts
    are a real advantage over edge triggered interrupts, please let me
    know.

Of course, we shouldn't remove a feature lightly. But in this case, I
can't think of an advantage of having this feature. I can think of
downsides: more maintenance and having to specify their behavior in the
machine package documentation.
In general, I would like to keep the machine package clean and only
support things that have a proven use case.
2022-09-24 22:58:22 +02:00
sago35 9e24441978 main: allow setting the baud rate for serial monitors (#3190)
* main: allow setting the baud rate for serial monitors with default baudrate of 115200 bps
2022-09-24 19:09:41 +02:00
Ayke van Laethem 1e6c14b3e4 ci: build TinyGo using Go 1.19
We've supported Go 1.19 for a while now, let's actually use it in CI.
2022-09-24 13:22:38 +02:00
Crypt Keeper 25f6be1488 build: makes CI choose latest Go 1.18.x (#3143)
* build: makes CI choose latest Go 1.18.x
2022-09-24 10:14:18 +02:00
Ayke van Laethem 9a9106a297 esp32c3: remove unused UARTStopBits constants 2022-09-21 18:16:29 +02:00
Ayke van Laethem a68f7e4ce3 nrf: add ReadTemperature method
Similar to the rp2040, the nrf has an on-board temperature sensor.

The main reason why I added this function was to show how this new API
is more general and can be used on multiple chips.
2022-09-21 08:26:56 +02:00
Ayke van Laethem 70b3ece6ec rp2040: add machine.ReadTemperature
Replace ADCChannel.ReadTemperature() with a simple ReadTemperature
function.

Not all chips will have a temperature sensor that is read by sampling an
ADC channel. The replacement ReadTemperature is simpler and more generic
to other chip families.

This breaks chips that were relying on the previous ReadTemperature
method. I hope it won't break a lot of existing code. If it does, a
fallback can be added.
2022-09-21 08:26:56 +02:00
Ayke van Laethem 86ea216e7d machine: move SPI Tx function into separate file
This makes the code a bit cleaner because ErrTxInvalidSliceSize isn't
redefined in every file that uses SPI and Mode0/Mode1/Mode2/Mode3 is
defined for every target that uses SPI.
2022-09-21 06:52:42 +02:00
Ayke van Laethem 5a92c35536 main: restore support for flashing Espressif chips
This reverts commit 303410d3fc and also
removes the unnecessary fallback.
2022-09-20 23:03:07 +02:00
Ayke van Laethem 7513fa2c96 machine: add KHz, MHz, GHz constants, deprecate TWI_FREQ_* constants
There are two main issues with these constants:

  * They don't follow the Go naming convention.
  * They call themselves "TWI", while it makes a lot more sense to refer
    to the actual name which is I2C (or I²C).

I have not removed them but just deprecated them. Perhaps we can remove
them when we move towards version 1.0.
2022-09-20 21:00:17 +02:00
Ayke van Laethem bc946f346d machine: rename PinInputPullUp/PinInputPullDown
Some targets used capital PullUp/PullDown, while the documented standard
is Pullup/Pulldown. This commit fixes this mismatch, while preserving
compatibility with aliases that are marked deprecated.
2022-09-20 05:45:53 +02:00
Ayke van Laethem 6e6666519c go mod tidy 2022-09-19 20:14:09 +02:00
Ayke van Laethem cecae8084c nrf52840: do not export DFU_MAGIC_* constants
These constants are for internal use only, so should not have been
exported. In addition, they didn't follow the Go naming convention
before this change.
2022-09-19 07:41:46 +02:00
Ayke van Laethem 9720ccacbb machine: improve UARTParity slightly
There are only 3 possible values, so a uint8 seems more appropriate.
Also, there is no reason to use specific numbers over a simple
enumeration.
2022-09-18 21:30:30 +02:00
Damian Gryski a5aa777c7b src/runtime: add a few more docs about the garbage collector 2022-09-18 15:19:11 +02:00
sago35 aca1ad187d targets: remove usbpid of bootloader
For more information, see
https://github.com/tinygo-org/tinygo/pull/3168
2022-09-17 11:00:31 +02:00
sago35 5a41ed6329 xiao-ble: fix usbpid 2022-09-17 07:25:41 +02:00
Ayke van Laethem 91e9c84d85 nrf: make GetRNG available to all chips
All nrf chips have a cryptographically secure RNG on board. Therefore,
I've made the code more portable so that it works on all nrf chips.

I did remove a number of exported functions. I am of the opinion that
these should only be made available once we have an agreed upon API for
multiple chips. People who want to have greater control over the RNG
should use the device/nrf package directly instead.

I have also changed the behavior to always enable digital error
correction. Enabling it seems like a more conservative (and secure)
default to me. Again, people who would like to have it disabled can use
the device/nrf package directly.
2022-09-17 06:08:54 +02:00
sago35 4af530f238 wioterminal: remove serial-port setting of bootloader 2022-09-16 20:12:47 +02:00
Ayke van Laethem d3863f337d rp2040: do not use GetRNG in crypto/rand
The crypto/rand package is used for sensitive cryptographic operations.
Do not use the rp2040 RNG for this purpose, because it's not strong
enough for cryptography.

I think it is _possible_ to make use of the RP2040 RNG to create
cryptographically secure pseudo-random numbers, but it needs some
entropy calculation and secure hashing (blake2s or so) to make them
truly unpredictable.
2022-09-16 14:48:41 +02:00
Ayke van Laethem 5551ec7a1e cgo: implement support for static functions 2022-09-16 14:05:17 +02:00
Ayke van Laethem 91104b2f27 runtime: ensure some headroom for the GC to run
The GC was originally designed for systems with a fixed amount of
memory, like baremetal systems. Therefore, it just used what it could
and ran a GC cycle when out of memory.

Other systems (like Linux or WebAssembly) are different. In those
systems, it is possible to grow the amount of memory on demand. But the
GC only actually grew the heap when it was really out of memory, not
when it was getting very close to being out of memory.

This patch fixes this by ensuring there is at least 33% headroom for the
GC. This means that programs can allocate around 50% more than what was
live in the last GC cycle. It should fix a performance cliff when a
program is almost, but not entirely, out of memory and the GC has to run
almost every heap allocation.
2022-09-16 11:11:50 +02:00
sago35 80f38e8449 main: add serial port monitoring functionality
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2022-09-16 09:28:03 +02:00
Adrian Cole 22893c5180 wasm: documents memory constants
This documents memory constants. Somewhere, we should document what the
default memory size is (seems 2 pages so 128KB), as that determines the
initial heap size (which is a portion of that).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-16 07:32:43 +02:00
Ayke van Laethem 9e4e182615 interp: fix reading from external global
This fixes https://github.com/tinygo-org/tinygo/issues/3020.
2022-09-15 19:07:04 +02:00
Ayke van Laethem 5f96d2b784 all: add flag for setting the goroutine stack size
This is helpful in some cases where the default stack size isn't big
enough.
2022-09-15 12:43:51 +02:00
Ayke van Laethem bd1d93b705 go mod tidy 2022-09-15 12:43:51 +02:00
Anuraag Agrawal 03d1c44265 wasm,wasi: make sure buffers returned by malloc are not freed until f… (#3148)
* wasm,wasi: make sure buffers returned by malloc are not freed until free is called
2022-09-15 09:14:39 +02:00
Adrian Cole dc0346d968 wasi: adds more details about why wasmtime flags are added
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-14 19:52:04 +02:00
Ayke van Laethem dadae95448 ci: use the Go Alpine image for building the release binary
This fixes https://github.com/tinygo-org/tinygo/issues/3146 by using a
prebuilt Docker image. I don't remember why I used `setup-go` but
probably to make it faster (setup-go usually uses cached binaries).
2022-09-14 15:43:14 +02:00
sago35 f5fc2fc072 main: add support for stlink-dap programmer 2022-09-14 14:58:31 +02:00
Matt Schultz 4ba76a5df9 machine/nrf52840: implement RNG peripheral operation 2022-09-12 09:54:51 +02:00
deadprogram ea1e08f53f machine/rp2040: implement semi-random RNG based on ROSC based on pico-sdk
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-10 10:47:48 +02:00
Adrian Cole bba0dc9575 build: uses setup-go@v3 to simplify cache config
This updates to setup-go@v3 which is the only updated version (v2 last
updated in feb), and employs its cache to simplify workflow
configuration.

Notably, we can't do this for Alpine until #3146

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-09 21:48:51 +02:00
Isaac Rodman 617c7586fe Remove unconnected simple LED pin from qtpy-rp2040 2022-09-09 11:05:12 +02:00
Isaac Rodman 7366d5e185 Set default-stack-size to 4096, and remove NEOPIXELS pluralization for qtpy-rp2040 2022-09-09 11:05:12 +02:00
Adrian Cole 96e3ecd949 build: updates to actions/cache@v3
v2 has bugs and hasn't had a release since last November.

See https://github.com/actions/cache/releases

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-08 16:27:40 +02:00
Ayke van Laethem 8bbfb1ee68 wasm: do not allow undefined symbols
--allow-undefined can be a problem: it allows compiling code that will
fail when loaded. This change makes sure that if some symbols are
undefined, they are reported as an error by the linker.

Previously, people could get away with importing a function that was not
defined, like this:

    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

This was always unintended but mostly worked. With this change, it isn't
possible anymore. Now every function needs to be marked with //export
explicitly:

    //export add
    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

As before, functions will be placed in the `env` module with the name
set from the `//export` tag. This can be overridden with
`//go:import-module`:

    //go:import-module math
    //export add
    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

For the syscall/js package, I needed to give a list of symbols that are
undefined. This list is based on the JavaScript functions defined in
targets/wasm_exec.js.
2022-09-08 08:25:27 +02:00
Adrian Cole 07cdcc61f7 examples: adds summary of wasm examples and fixes callback bug
This adds a summary of each wasm example, as before it was a bit unclear
how to do so. This also fixes the callback example which was broken.

Fixes #2568

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-07 13:31:21 +02:00
Ayke van Laethem 4ca9b34133 machine: add PWM peripheral comments to pins
These comments will be used in a change to the tinygo.org documentation.
2022-09-05 18:56:34 +02:00
Patricio Whittingslow d5e4b16911 add github.com/soypat/mu8 to corpus.yaml 2022-09-04 09:42:49 +02:00
sago35 fd05254683 Update compileopts/target.go
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2022-09-03 11:50:41 +02:00
sago35 c579e7e509 Update compileopts/target.go
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2022-09-03 11:50:41 +02:00
sago35 d463528a72 smoketest: add test to run tinygo targets 2022-09-03 11:50:41 +02:00
sago35 49b0086f8f main: improve error handling when loading target/*.json 2022-09-03 11:50:41 +02:00
Yurii Soldak d7814ff50b targets: fix build tag duplicates
and add missing targets to smoke test
2022-09-03 08:31:27 +02:00
Ayke van Laethem 02160aa8d8 windows: run more tests where supported
I found that some packages do in fact run on Windows, so I've added them
where possible. I've also updated the description of which packages fail
tests and why.
2022-09-02 20:04:28 +02:00
Ayke van Laethem c199dd03c7 windows: save and restore xmm registers when switching goroutines
This is required according to the Windows x64 calling convention:
https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#callercallee-saved-registers
We didn't do this, and this didn't appear to cause any problems. But we
should do it anyway for correctness.
2022-09-02 18:47:00 +02:00
Ayke van Laethem 472aecf07a targets: remove hifive1-qemu target
This target was added purely for running tests, and it is currently
unused. When I try to use it, it causes runtime exceptions.
The replacement riscv-qemu is much better behaved.

This doesn't drop support for any actual hardware, the HiFive 1 B will
remain supported.
2022-09-02 16:35:05 +02:00
Isaac Rodman 09350e5719 Add qtpy-rp2040 to TinyGo v0.25.0 2022-09-02 15:06:37 +02:00
Tim Schaub 623dd6a815 sync: implement map.LoadAndDelete 2022-09-02 11:48:01 +02:00
Joe Shaw e09bd5abb3 runtime/pprof, runtime/trace: stub some additional functions
These are necessary to import some parts of the net/http package.
2022-09-02 10:37:50 +02: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
Ayke van Laethem f0391eac25 all: update to version 0.25.0 2022-08-02 18:25:51 +02:00
Phil Kedy 05cdde162c Set internal linkage and keeping default visibility for anonymous functions 2022-08-01 10:53:48 +02:00
sago35 25c8d3ec3a wasm,wasi: stub runtime.buffered, runtime.getchar 2022-07-30 17:41:54 +02:00
Ayke van Laethem 7b1e5f6f99 compiler: implement unsafe.Alignof and unsafe.Sizeof for generic code
For some reason, these aren't lowered when a generic function is
instantiated by the SSA package.

I've left unsafe.Offsetof to be implemented later, it's a bit difficult
to do correctly the way the code is currently structured.
2022-07-28 15:43:51 +02:00
Ayke van Laethem 70c52ef1b4 compiler: fix type names for generic named structs
Without this change, the compiler would probably have worked just fine
but the generated types would look odd.

You can see in the test case that it now doesn't use `main.Point` but
rather the correct `main.Poin[float32]` etc.
2022-07-28 15:43:51 +02:00
Ayke van Laethem 5078ce382d compiler: do not try to build generic functions
There is no reason to: we should only build instantiated generic
functions.
2022-07-28 15:43:51 +02:00
Ayke van Laethem 408855da14 compiler: add generics test case
This test case shows a few bugs, that I will fix in subsequent patches.
2022-07-28 15:43:51 +02:00
Phil Kedy 58072a5167 compiler: fix issue with methods on generic structs 2022-07-28 13:46:07 +02:00
Kenneth Bell 5026047cde rp2040: make picoprobe default openocd interface 2022-07-28 06:48:46 +02:00
deadprogram 67aea275c5 machine/rp2040: turn off pullup/down when not input type not specified
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-27 21:45:45 +02:00
Ayke van Laethem 99bd4d2c7c esp32: optimize SPI transmit
For write-only operations (in SPI displays for example), the transmit
speed is doubled with this relatively small change.

In the future, we should try to use DMA instead for larger buffers. But
this is already a significant improvement and will always be an
improvement for small buffer sizes.
2022-07-27 17:22:34 +02:00
sago35 a4b22bd125 usb/midi: add definition of MIDI note number 2022-07-27 16:19:13 +02:00
deadprogram 2ed7523001 build/linux/arm: pin dotenv Ruby gem to version 2.7.6
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-27 14:25:23 +02:00
Ayke van Laethem 4aec3d04f9 esp32: fix WDT reset on the MCH2022 badge 2022-07-26 10:47:28 +02:00
Ayke van Laethem 4f729c323d darwin: don't clobber X18 and FP registers
These are reserved registers on MacOS so don't need to be clobbered, and
result in a compiler waring:

    ld.lld-14: warning: inline asm clobber list contains reserved registers: X18, FP
    Reserved registers on the clobber list may not be preserved across the asm statement, and clobbering them may lead to undefined behaviour.
2022-07-26 09:02:06 +02:00
deadprogram 1f43f32aae target: add gopherbot and gopherbot2 aliases to simplify for newer users
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-26 08:06:24 +02:00
Kenneth Bell 6d1cbe6fb9 rp2040: usb: reset device address on bus reset 2022-07-26 06:47:16 +02:00
sago35 7cd2890434 rp2040: add resetBlock for USBCTRL 2022-07-25 17:01:14 +02:00
sago35 13311da7e9 main: change to ignore PortReset failures 2022-07-25 14:04:14 +02:00
sago35 3047d8f321 samd51: improve TRNG 2022-07-22 09:27:43 +02:00
deadprogram 13ed58950f machine/usb/midi: add NoteOn, NoteOff, and SendCC methods for more complete API
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-21 11:05:53 +02:00
sago35 5271bd8cfa xiao-ble: add support for flash-1200-bps-reset 2022-07-21 08:31:28 +02:00
sago35 72137d663b usb: adjust buffer alignment (samd21, samd51, nrf52840) 2022-07-20 08:05:52 +02:00
sago35 740134197e samd51: add support for DAC1 2022-07-18 12:10:06 +02:00
Ayke van Laethem 610e7fd16a boards: Add MCH2022 badge
I haven't fully tested this badge because I don't have the physical
hardware but I have followed the pinout from the website.
2022-07-16 08:31:22 +02:00
Dan Kegel 69a6718b38 archFamily(): arm64 is aarch64, not arm; fixes #2985 2022-07-15 17:41:39 +02:00
Ayke van Laethem 7d31d98f0f runtime: rename printuint to printuintptr
This is arguably the correct name, and is consistent with other print
functions.
2022-07-15 15:44:40 +02:00
Ayke van Laethem 0a93347e1c machine: reorder pin definitions to improve pin list on tinygo.org 2022-07-15 14:46:33 +02:00
Ayke van Laethem 411333327e esp32c3: provide hardware pin constants 2022-07-15 14:46:33 +02:00
Ayke van Laethem 159f7ebbc3 esp32: provide hardware pin constants 2022-07-15 14:46:33 +02:00
Ayke van Laethem 153ff09cc5 esp8266: provide hardware pin constants like GPIO2 2022-07-15 14:46:33 +02:00
Ayke van Laethem 57cddf5657 clue: remove pins D21..D28
These pins do not appear in the pinout:
https://learn.adafruit.com/adafruit-clue/pinouts
2022-07-15 14:46:33 +02:00
Ayke van Laethem 6a35719594 avr: fix some apparent mistake in atmega1280/atmega2560 pin constants 2022-07-15 14:46:33 +02:00
Ayke van Laethem 20a46e1b28 nrf51: define and use P0_xx constants
This makes nrf51 consistent with nrf52 and other chips, which do provide
constants for hardware pin numbers.
I've also added the microbit to the smoketest because it is used on
play.tinygo.org. And removed PCA10040 and PCA10056 because they aren't
provided on play.tinygo.org anymore.
2022-07-15 14:46:33 +02:00
sago35 926c02b6ff rp2040: reduced allocations 2022-07-15 09:41:32 +02:00
sago35 f370cd18fc rp2040: add support for EnterBootloader() 2022-07-15 09:41:32 +02:00
sago35 a1d7cab080 rp2040: change volatile access to dpsram 2022-07-15 08:49:07 +02:00
deadprogram 15a9e2313a machine/usb/midi: correct reference to handler function
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-14 13:25:34 +02:00
sago35 58f2533f15 rp2040: change default for serial to usb 2022-07-14 09:18:21 +02:00
deadprogram 3c2d2a93d3 machine/usb: refactorings to move functionality under machine/usb package
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-14 07:20:50 +02:00
Federico G. Schwindt ea36fea5a9 Add support for printing slices via print/println
With help from @aykevl.
2022-07-13 14:44:23 +02:00
deadprogram 5fdb894760 usb: rename callback to handler to keep consistent
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-13 12:11:21 +02:00
sago35 8fed063820 usb: add support for midi 2022-07-12 19:13:12 +02:00
deadprogram 2f843af286 build: run tests on drivers and bluetooth repos after successful docker dev build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-07-12 17:14:49 +02:00
sago35 7afc47d67a usb: add DTR and RTS to serialer interface 2022-07-12 16:22:16 +02:00
sago35 0bc7c2a61f rp2040: add support for usb (#2973)
* rp2040: add support for usb
2022-07-12 15:41:56 +02:00
sago35 d434058aef samd21,samd51,nrf52840: move usbcdc to machine/usb/cdc (#2972)
* samd21,samd51,nrf52840: move usbcdc to machine/usb/cdc
2022-07-10 11:33:52 +02:00
Ayke van Laethem 56780c2691 ci: build Linux binary in Alpine container
This makes it easier to move the TinyGo compiler between Linux versions
because it doesn't depend on any system libraries anymore. For example,
binaries should be able to run on old Linux versions and on
distributions without glibc (such as Alpine Linux).
2022-07-08 15:05:50 +02:00
Kenneth Bell 1d99b1ed84 boards: add Challenger RP2040 LoRa 2022-07-08 13:01:14 +02:00
Kenneth Bell e1405640da all: git ignore smoketest output 2022-07-08 13:01:14 +02:00
Daniel Esteban 5996e113ad update list of boards supported to add Badger2040 2022-07-08 08:52:44 +02:00
sago35 f1e6997018 atsamd21,atsamd51,nrf52840: improve usb-device initialization 2022-07-07 21:04:41 +02:00
sago35 335a7ad0b7 samd21,samd51,nrf52840: refactor handleStandardSetup and initEndpoint (#2968)
* samd21,samd51,nrf52840: refactor handleStandardSetup and initEndpoint
2022-07-07 16:43:57 +02:00
sago35 17deac116f samd21,samd51,nrf52840: change usbSetup and sendZlp to public 2022-07-07 08:25:02 +02:00
Daniel Esteban b112477e95 Initial support for XIAO RP2040 2022-07-06 22:23:47 +02:00
sago35 2fa24ef752 samd21,samd51,nrf52840: refactor usb initialization 2022-07-06 17:55:25 +02:00
sago35 fcefcb191c samd21,samd51,nrf52840: unify bootloader entry process 2022-07-06 09:14:11 +02:00
sago35 ff7c71c99c serial: use common initialization for serial 2022-07-05 20:53:37 +02:00
sago35 7eaad62568 feather-rp2040,macropad-rp2040: fix qspi-flash settings 2022-07-05 16:37:45 +02:00
sago35 401bd89664 samd21, samd51: move USB-CDC code 2022-07-05 14:41:51 +02:00
Damian Gryski 24b1bfcecd tests/runtime: add benchmarks for runtime memhash 2022-07-05 08:54:55 +02:00
Ayke van Laethem 27162ebe32 cgo: add a check that we don't use different LLVM versions 2022-07-04 14:54:39 +02:00
Ayke van Laethem b347aea450 cgo: fix default LLVM version to LLVM 14
Without extra flags, we would try to use LLVM 13 for cgo and LLVM 14 for
other things since 873412b43a. That isn't
great. So fix this by only using LLVM 14 in the cgo package.
2022-07-04 14:54:39 +02:00
sago35 1766746c60 rp2040: add usb settings 2022-07-04 13:17:54 +02:00
Damian Gryski 07049b87b6 targets: make leveldb runtime hash default for wasi 2022-07-03 19:27:54 +02:00
sago35 f38603530d all: update version for next development iteration 2022-07-02 23:35:14 +02:00
deadprogram b65447c7d5 ci: use bash shell for making release artifacts
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-06-30 23:30:48 +02:00
Ayke van Laethem 0abc909739 ci: disable ccache on Windows 2022-06-30 23:30:48 +02:00
Ayke van Laethem d984b55311 all: update to version 0.24.0 2022-06-29 15:18:33 +02:00
sago35 446fe1f5b3 makefile: add badger2040, thingplus-rp2040 to smoketest 2022-06-29 12:06:23 +02:00
Ayke van Laethem 873412b43a all: use LLVM 14 by default
This also adds support for LLVM 14 from Homebrew on MacOS.
2022-06-28 22:07:45 +02:00
Kenneth Bell 8a5ab5ab12 rp2040: fix gpio interrupts 2022-06-26 12:14:52 +02:00
Ayke van Laethem 77cf60ef30 darwin: print full size information for -size=full
The MachO file format is a bit weird and doesn't store the DWARF debug
information directly in the file. Instead, it has to be looked up in the
original object file. This makes reading the DWARF debug information for
code size usage a bit more difficult. However, it works with this
change.
2022-06-24 13:50:30 +02:00
Ayke van Laethem a4e2e09457 compiler: drop support for macos syscalls via inline assembly
This has always been unsupported on MacOS and has in fact been removed
from upstream Go a few releases ago. So do the same for TinyGo.
Linux seems to be the only supported OS with a stable syscall interface.
2022-06-24 12:51:18 +02:00
Ayke van Laethem 4262f0ff1f compiler: really define runtime.mem* as LLVM intrinsic wrappers
This makes it possible to //go:linkname them from other places, like in
the reflect package. And is in my opinion a much cleaner solution.
2022-06-24 11:10:24 +02:00
Ayke van Laethem 1ceb63d14c compiler: really define runtime/volatile.* functions
This makes them available to deferred calls, among others.
2022-06-24 11:10:24 +02:00
Ayke van Laethem e1052f921c compiler: define atomic intrinsic functions directly
This changes the compiler from treating calls to sync/atomic.* functions
as special calls (emitted directly at the call site) to actually
defining their declarations when there is no Go SSA implementation. And
rely on the inliner to inline these very small functions.
This works a bit better in practice. For example, this makes it possible
to use these functions in deferred function calls.

This commit is a bit large because it also needs to refactor a few
things to make it possible to define such intrinsic functions.
2022-06-24 11:10:24 +02:00
Ayke van Laethem 6dff85c756 ci: fix CI failure due to missing apt-get update 2022-06-23 23:16:09 +02:00
ardnew afae6b3795 board/teensy40: Add I2C support (#1471)
* teensy40: add I2C support
2022-06-22 11:28:50 +02:00
Ayke van Laethem 2825b4fe74 compiler: update tests after adding new wasm features
I don't understand why this wasn't caught in CI. It should have. In any
case, because the llvm-features string was updated, these IR outputs
were updated.
2022-06-22 07:50:40 +02:00
Ayke van Laethem b5c5d95b68 wasm: use newer WebAssembly features
This commit will start to use a few more WebAssembly features, such as
bulk memory operations. This results in a significant code size saving.
How much it saves varies a lot but it's typically around 1300 bytes.

This change is possible by bumping our minimum Node.js version to 14.
The previous LTS version (12) has been marked end of life, so we can
start to depend on features in the current oldest LTS version, which is
version 14. Browsers have been supporting these features for a long time
now, it's just Node.js that prevented us doing this before.
2022-06-21 08:55:42 +02:00
Ayke van Laethem 633fe95187 wasm: update wasi-libc version
This is necessary for the next commit. It also results in a nice wasm
binary size saving of around 300 bytes.
2022-06-21 08:55:42 +02:00
Ayke van Laethem 64d7f1e436 all: run gofmt on all source code
Some source code wasn't part of `FMT_PATHS` so wasn't checked for
correct formatting. This change includes all this source code and
excludes cgo/testdata because it contains files that can't be parsed.
2022-06-19 13:00:44 +02:00
Ayke van Laethem 9af535bf98 avr: add support for recover()
You can see that it works with the following command:

    tinygo run -target=simavr ./testdata/recover.go

This also gets the following tests to pass again:

    go test -run=Build -target=simavr -v

Adding support for AVR was a bit more compliated because it's also
necessary to save and restore the Y register.
2022-06-19 11:51:12 +02:00
Ayke van Laethem 159f0051bb runtime: move *task.DeferFrame here
This is a refactor that makes the next commit simpler. Perhaps it should
have been like this from the beginning but I didn't like all the casts.
2022-06-19 11:51:12 +02:00
Ayke van Laethem 49e22fe678 runtime: load sp and pc inside tinygo_longjmp
This is a small change to make it easier to support architectures that
need to restore more than just the sp and pc registers. In particular,
it is needed for the AVR architecture that needs to restore the frame
pointer (Y register).
2022-06-19 11:51:12 +02:00
Yurii Soldak c119721e3b atmega2560: support UART1-3
+ example for uart
2022-06-18 09:26:12 +02:00
Ayke van Laethem 9294141d70 avr: fix race condition in stack write
If an interrupt happens between the writes to SPL and SPH, the stack
pointer is inconsistent and terrible things will happen. Therefore,
disable interrupts while updating the stack pointer.

Interrupts are restored _before_ the write to SPH. This is safe, because
interrupts are re-enabled with a one cycle delay. The avr-gcc and Clang
compilers do the same thing when they need to update the stack pointer.

It's almost impossible to test for this bug, but it should make firmware
just a little bit more reliable.
2022-06-17 19:17:21 +02:00
Damian Gryski bcf58c0840 runtime: add comments about the hash functions 2022-06-17 08:46:41 +02:00
Damian Gryski 7a61cb1bc3 src/runtime: add leveldb memhash 2022-06-17 08:46:41 +02:00
Damian Gryski 11e1b2148f src/runtime: switch to stronger hash function
Fixes #2713
2022-06-17 08:46:41 +02:00
Yurii Soldak a4599ba539 build: cancel in-progress builds 2022-06-16 22:26:29 +02:00
Ayke van Laethem 4c64784724 all: Go 1.19 support
This adds early Go 1.19 support. There are a number of things that don't
work yet, but the smoke tests pass so it's at least working for a
significant subset of programs.

This change also switches from CircleCI convenience images to upstream
Go images. This makes it a bit easier to use the latest Go versions.
Also, the convenience images are not updated anymore.
2022-06-16 12:34:56 +02:00
Ayke van Laethem 8d6b210c09 compiler: implement recover() built-in function 2022-06-16 07:59:21 +02:00
Ayke van Laethem 79ba6a50c3 compiler: insert basic blocks at an appropriate location
For example, this commit moves the 'throw' branch of an assertion (nil
check, slice index check, etc) to the end of the function while
inserting the "continue" branch right after the insert location. This
makes the resulting IR easier to follow.

For some reason, this also reduces code size a bit on average. The
TinyGo smoke tests saw a reduction of 0.22%, mainly from WebAssembly.
The drivers repo saw little average change in code size (-0.01%).

This commit also adds a few compiler tests for the defer keyword.
2022-06-16 07:59:21 +02:00
Ayke van Laethem 2fb5174910 compiler: fix basic block context
llvm.AddBasicBlock should never be used. Instead, we should use the
AddBasicBlock method of the current LLVM context.

This didn't lead to any bugs... yet. But probably would, eventually.
2022-06-16 07:59:21 +02:00
Ayke van Laethem b31281a5b6 runtime: scan all writable program segments
Previously we used to scan between _edata and _end. This is not correct:
the .data section starts *before* _edata.

Fixing this would mean changing _edata to _etext, but that didn't quite
work either. It appears that there are inaccessible pages between _etext
and _end on ARM. Therefore, a different solution was needed.

What I've implemented is similar to Windows and MacOS: namely, finding
writable segments by parsing the program header of the currently running
program. It's a lot more verbose, but it should be correct on all
architectures. It probably also reduces the globals to scan to those
that _really_ need to be scanned.

This bug didn't result in issues in CI, but did result in a bug in the
recover branch: https://github.com/tinygo-org/tinygo/pull/2331. This
patch fixes this bug.
2022-06-16 07:59:21 +02:00
Dan Kegel 8754f64f3b syscall.Getpagesize(): add test, implement for Linux and Windows 2022-06-12 01:15:42 +02:00
Ayke van Laethem caf405b01d reflect: add Value.UnsafePointer method
This was added in Go 1.18.
2022-06-12 01:08:02 +02:00
Ayke van Laethem bb65c5ce2b compiler: add support for type parameters (aka generics)
...that was surprisingly easy.
2022-06-11 20:41:16 +02:00
Ayke van Laethem 283fed16a5 builder: fix -no-debug linker flags
Show the correct error message when trying to strip debug information.

Also, remove the special case for GOOS=linux that was probably dead
code: it was only reachable on baremetal systems which were already
checked before.
2022-06-11 16:57:25 +02:00
sago35 76bba13963 usbhid: add support for mouse buttons (#2900)
* usbhid: add support for mouse buttons
2022-06-11 16:11:04 +02:00
Dan Kegel ada11090a2 smoketest: add regression test for 'tinygo test ./...', see #2892
tests/testing/recurse has two directories with tests;
"make smoketest" now does "tinygo test ./..." in that directory
and fails if it does not run both directories' tests.
2022-06-11 12:11:08 +02:00
José Carlos Chávez a07287d3c6 fix: fixes tinygo test ./... syntax. 2022-06-11 12:11:08 +02:00
sago35 1b2e764835 samd21,samd51,nrf52840: add support for USBHID (keyboard / mouse) 2022-06-11 09:44:09 +02:00
Nia Waldvogel 2c93a4085c transform (MakeGCStackSlots): do not move the stack chain pop earlier
Previously, the MakeGCStackSlots pass would attempt to pop the stack chain before a tail call.
This resulted in use-after-free bugs when the tail call allocated memory and used a value allocated by its caller.
Instead of trying to move the stack chain pop, remove the tail flag from the call.
2022-06-10 17:25:02 +02:00
sago35 906757603d wioterminal: fix I2C definition 2022-06-08 18:32:08 +02:00
Krzysztof Jagiello 5d16811199 Attach USB DP to the correct pin on Matrix Portal M4 2022-06-03 07:42:19 +02:00
Nia Waldvogel f2e576decf interp: do not unroll loops
This change triggers a revert whenever a basic block runs instructions at runtime twice.
As a result, a loop body with runtime-only instructions will no longer be unrolled.
This should help some extreme cases where loops can be expanded into hundreds or thousands of instructions.
2022-06-02 18:13:56 +02:00
Ayke van Laethem 2d61972475 gc: drop support for 'precise' globals
Precise globals require a whole program optimization pass that is hard
to support when building packages separately. This patch removes support
for these globals by converting the last use (Linux) to use
linker-defined symbols instead.

For details, see: https://github.com/tinygo-org/tinygo/issues/2870
2022-06-01 21:21:30 +02:00
Damian Gryski 5c488e3145 src/runtime: handle nil map write panics 2022-06-01 13:28:22 +02:00
Damian Gryski e45ff9c0e8 src/runtime: add per-map hash seeds 2022-06-01 13:28:22 +02:00
sago35 39805bca45 os, runtime: enable os.Stdin for baremetal target 2022-06-01 07:56:25 +02:00
Ayke van Laethem 97842b367c transform: run OptimizeMaps during package optimizations
This shrinks transform.Optimize() a little bit, working towards the goal
of https://github.com/tinygo-org/tinygo/issues/2870. I ran the smoke
tests and there is no practical downside: one test got smaller (??) and
one had a different .hex hash, but other than that there was no
difference.

This should also make TinyGo a liiitle bit faster but it's probably not
even measurable.
2022-05-30 20:39:42 +02:00
Ayke van Laethem 9246899b30 builder: move some code to transform package
The transform package is the more appropriate location for package-level
optimizations, to match `transform.Optimize` for whole-program
optimizations.
This is just a refactor, to make later changes easier to read.
2022-05-30 20:39:42 +02:00
Ayke van Laethem 04ace4de5f corpus: make non-working packages easy to uncomment
This makes it easier to test for changes, just remove the hash sign in
front of some packages to test them.
2022-05-30 14:21:35 +02:00
Ayke van Laethem 87a4676137 all: add support for the embed package 2022-05-30 10:41:17 +02:00
Ayke van Laethem fd20f63ee3 compiler: move createConst to compilerContext
Move it from *builder to *compilerContext, so that it can be called in
more places. This is necessary to create a string value (for the file
name) in createEmbedGlobal.
2022-05-30 10:41:17 +02:00
Ayke van Laethem 9dd249a431 builder: refactor package compile job
This commit moves the calculation of the package action ID (cache key)
into a separate job. At the moment, this won't have a big effect but
this change is necessary for some future changes I want to make.
2022-05-30 10:41:17 +02:00
Ayke van Laethem 777d3f3ea5 builder: free LLVM objects after use
This reduces the TinyGo memory consumption when running

  make tinygo-test

from 5.8GB to around 2GB on my laptop.
2022-05-30 07:53:28 +02:00
Ayke van Laethem ea3b5dc689 nintendoswitch: scan globals conservatively
This is a step towards #2870, similar to #2867 and #2869.
2022-05-29 21:00:09 +02:00
Olaf Flebbe 3dd502a928 align api for PortMaskSet, PortMaskClear 2022-05-26 21:37:03 +02:00
Ayke van Laethem 48242ba8d6 darwin: scan globals by reading MachO header
This replaces "precise" global scanning in LLVM with conservative
scanning of writable MachO segments. Eventually I'd like to get rid of
the AddGlobalsBitmap pass, and this is one step towards that goal.
2022-05-25 12:51:31 +02:00
Ayke van Laethem 7ea9eff406 interp: implement binary operators in markExternal* functions
This is necessary for the next commit. The next commit would otherwise
cause an issue with the following constant operation:

    i64 add (i64 ptrtoint (%runtime.machHeader* @_mh_execute_header to i64), i64 32)
2022-05-25 12:51:31 +02:00
Ayke van Laethem 80d94115dc interp: improve error handling of markExternal* functions 2022-05-25 12:51:31 +02:00
Ayke van Laethem 9de76fb42e avr: simplify timer-based time
Simplify the interrupt-based timer code in a few ways:

  - Do not recalibrate the timer every 100ms. Instead, rely on the fact
    that the machine package will calbrate the timer if necessary if it
    makes changes to Timer0.
  - Do not configure Timer0 and then set nanosecondsInTick based on that
    value. Instead, use a fixed value.

These two changes together mean that in code that doesn't use PWM,
nanosecondsInTick will be constant which makes the TIMER0_OVF interrupt
handler a lot smaller.

Together this reduces the code size of AVR binaries by about 1200 bytes,
making it pretty close to the pre-timer code size (only about 250 bytes
larger).

It also somehow fixes a problem with
tinygo.org/x/drivers/examples/ws2812 on the Arduino Uno. I'm not quite
sure what was going wrong, but bisecting pointed towards the timer code
(https://github.com/tinygo-org/tinygo/pull/2428) and with this
simplification the bug appears to be gone.
2022-05-25 11:53:30 +02:00
Steven Kabbes 52c61de19f compiler: alignof(func) is 1 pointer, not 2
This ensures that an embedded [0]func() never ends up being larger
than 1 pointer, which is requried by protobuf processing code.
2022-05-25 11:01:00 +02:00
deadprogram f308d7d28c machine/badger2040: support for Badger 2040
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-05-24 15:02:23 +02:00
Ayke van Laethem 7729a36782 windows: use ThinLTO
Switch Windows builds to use ThinLTO. This gets us closer to using
ThinLTO everywhere.
2022-05-23 21:24:14 +02:00
Ayke van Laethem 5404c81ffd windows: scan globals conservatively
Scan globals conservatively by reading writable sections from the PE
header.

I'd like to get rid of needing to precisely scan globals eventually, and
this brings us one step closer. It also avoids a bug with ThinLTO on
Windows.
2022-05-23 21:24:14 +02:00
Dylan Arbour b52310fed2 ci: Add arm64 build 2022-05-23 08:50:38 +02:00
Ayke van Laethem 046070074d darwin: add support for ThinLTO 2022-05-22 23:29:30 +02:00
Ayke van Laethem c23a5b65ef darwin: support -size= flag
This is just basic support. It doesn't add support for reading DWARF,
because that's a bit complicated on MacOS (it isn't stored in the file
itself but separately in the object files). But at least this change
makes it possible to easily print executable sizes by section type like
for other operating systems.
2022-05-22 18:07:57 +02:00
Ayke van Laethem b8e433821a interp: fix some buggy localValue handling
Bug:

 1. fn.locals[v.value] returns 0 (the default value) if v.value is not
    part of the fn.locals map.
 2. locals[fn.locals[v.value]] then returns the first local value, which
    is usually non-nil
 3. This incorrect value is then used as the operand value.

The manifestation of this convoluted bug was
https://github.com/tinygo-org/tinygo/issues/2842. It didn't occur more
often probably because it only seems to happen in practice with inline
assembly.

Fixes https://github.com/tinygo-org/tinygo/issues/2842
2022-05-22 15:08:17 +02:00
Ayke van Laethem dd1a836903 interp: do not try to interpret past task.Pause()
For context, see:
https://github.com/tinygo-org/tinygo/pull/2863#issuecomment-1133875237

Basically, testdata/goroutine.go was doing `time.Sleep()` inside an init
function which broke because doing that from a non-goroutine is not
allowed. However, we never hit this bug because of
https://github.com/tinygo-org/tinygo/issues/2842 (I didn't investigate
exactly why).
2022-05-22 15:08:17 +02:00
Dan Kegel 4ed0936c0e darwin: adjust syscall suffix for arm64 2022-05-20 18:47:30 +02:00
Ayke van Laethem 7a5d4c9537 darwin: add support for arm64 GOARCH (aka Apple Silicon)
This patch adds support for generating GOOS=darwin GOARCH=arm64
binaries. This means that it will become possible to run `go test` on
recent Macs, for example.
2022-05-20 08:35:18 +02:00
Dylan Arbour af6bbaf532 Use release built tinygo in Makefile
Closes #2795
2022-05-19 23:10:48 +02:00
Steven Kabbes 4c7449efe5 compiler: alignof [0]func() = 1
In the go protobuf code, a pattern is used to statically prevent
comparable structs by embedding:

```
type DoNotCompare [0]func()

type message struct {
  DoNotCompare
  data *uint32
}
```

Previously, sizezof(message{}) is 2 words large, but it only needs to be
1 byte.  Making it be 1 byte allows protobufs to compile slightly more
(though not all the way).
2022-05-19 08:02:32 +02:00
Ayke van Laethem 995e815b63 avr: enable testdata/map.go
The test needs a few changes to support low-memory devices but other
than that, it works fine.
2022-05-18 15:20:09 +02:00
Ayke van Laethem 109b5298c4 avr: use compiler-rt
This change adds support for compiler-rt, which supports float64 (unlike
libgcc for AVR). This gets a number of tests to pass that require
float64 support.

We're still using libgcc with this change, but libgcc will probably be
removed eventually once AVR support in compiler-rt is a bit more mature.

I've also pushed a fix for a small regression in our
xtensa_release_14.0.0-patched LLVM branch that has also been merged
upstream. Without it, a floating point comparison against zero always
returns true which is certainly a bug. It is necessary to correctly
print floating point values.
2022-05-18 15:20:09 +02:00
Ayke van Laethem a94e03eff2 avr: get go test -target=simavr to work
This patch changes two things:

 1. It changes the default stack size. Without this change, the
    goroutine.go test doesn't pass (apparently there's some memory
    corruption).
 2. It moves the excluded tests so that they are skipped with a regular
    `-target=simavr`, not just when running all tests (without
    `-target`).
2022-05-18 15:20:09 +02:00
Damian Gryski eb3d6261b4 builder: remove extra formatting verb from error message 2022-05-18 09:06:03 +02:00
deadprogram 15724848f9 build: install scoop without update to avoid bug ScoopInstaller/Scoop #4917
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-05-18 07:42:56 +02:00
Kenneth Bell 8f40b107d9 rp2040: replace sleep 'busy loop' with timer alarm 2022-05-17 12:41:24 +02:00
Ayke van Laethem fa673f0827 Makefile: fix forced rebuild of LLVM
This is a small change that makes sure not to force a rebuild of LLVM
every time.

For example, I might run:

    make llvm-source
    make llvm-build ASSERT=1

And then I might make some temporary changes to LLVM to test out a patch
for example. So I run:

    make llvm-build

...and my whole build cache gets destroyed.

This commit addresses this issue by not forcing a re-run of CMake with
every `make llvm-build` invocation.
2022-05-10 16:40:39 +02:00
Elliott Sales de Andrade e3fe6d8f37 Skip slice-copy test for LLVM < 14
Fixes #2836
2022-05-08 03:32:04 +02:00
Ayke van Laethem 5c23f6fb6c all: remove support for LLVM 11 and LLVM 12
This removes a lot of backwards compatibility cruft and makes it
possible to start using features that need LLVM 13 or newer.
For example:

  * https://github.com/tinygo-org/tinygo/pull/2637
  * https://github.com/tinygo-org/tinygo/pull/2830
2022-05-07 17:15:35 +02:00
Ayke van Laethem 5afb63df60 cgo: refactor
This is a large refactor of the cgo package. It should fix a number of
smaller problems and be a bit more strict (like upstream CGo): it for
example requires every Go file in a package to include the header files
it needs instead of piggybacking on imports in earlier files.

The main benefit is that it should be a bit more maintainable and easier
to add new features in the future (like static functions).

This breaks the tinygo.org/x/bluetooth package, which should be updated
before this change lands.
2022-05-06 17:22:22 +02:00
Dan Kegel 1d2c39c3b9 os: skip TestDirFSPathsValid on WASI to work around #2828 on windows 2022-05-03 05:36:55 +02:00
Dan Kegel 270a2f51fd os: skip TestDirFS on wasi until #2827 is fixed 2022-05-03 05:36:55 +02:00
Dan Kegel e87cd23e87 os: Drop support for go 1.15
1.15 specific files deleted.
1.16 specific files folded carefully into generic files, with goal of reducing diff with upstream.
Follows upstream 1.16 in making PathError etc. be aliases for the same errors in io/fs.

This fixes #2817 and lets us add io/ioutil to "make test-tinygo" on linux and mac.
2022-05-03 05:36:55 +02:00
deadprogram db389ba443 all: update version for next development iteration
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-05-03 04:57:08 +02:00
Ayke van Laethem d1dfa1155c ci: fix Go version in ARM build 2022-05-02 08:27:13 +02:00
Ayke van Laethem cf0b7edc78 all: release v0.23.0 2022-04-28 17:51:09 +02:00
Damian Gryski a32cda7a4c testdata: move map growth test to map.go 2022-04-28 09:14:45 +02:00
Damian Gryski b251ce7b33 src/runtime: return a nil pointer for compiler bugs in hashmap code
We'll still panic if there's a compiler bug, but at least we'll have smaller
code in all the cases where we don't.
2022-04-28 09:14:45 +02:00
Damian Gryski 1abe1203a3 src/runtime: make hashmap calculations more uintptr-size independent 2022-04-28 09:14:45 +02:00
Damian Gryski 8b360ec911 src/runtime: remove extra if check in hashmap set logic 2022-04-28 09:14:45 +02:00
Damian Gryski 93654544b3 src/runtime: prevent overflow when calculating hashmap growth limits 2022-04-28 09:14:45 +02:00
Damian Gryski 050d516264 testdata: add test for mapgrowth logic 2022-04-28 09:14:45 +02:00
Damian Gryski 9a8328fcb7 src/runtime/hashmap: comments for iterator structure 2022-04-28 09:14:45 +02:00
Damian Gryski 6812a4dc04 src/runtime: first darft of map growth code
Fixes #1553
2022-04-28 09:14:45 +02:00
Ayke van Laethem 8568d4f625 esp32: add support for running and debuggin using qemu-esp32 2022-04-28 07:50:03 +02:00
Ayke van Laethem bd56636d58 all: make emulator command a string instead of a []string
This matches the flash-command and is generally a bit easier to work
with.
This commit also prepares for allowing multiple formats to be used in
the emulator command, which is necessary for the esp32.
2022-04-28 07:50:03 +02:00
Ayke van Laethem 4fe3a379a5 ci: add ARM build, cross compiled on an amd64 host
I'm making this so I don't have to build all the releases on my
Raspberry Pi at home, and to make the process more reproducible.
2022-04-27 22:47:53 +02:00
deadprogram fce42fc7fa machine/thingplus: rename to the singular thing as that it the correct name
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-26 21:13:17 +02:00
Ayke van Laethem 5d177d1328 runtime: be able to deal with a very small heap
See the comment in the source for details.

Also see the discussion in
https://github.com/tinygo-org/tinygo/pull/2755, which originally
triggered this bug.

Somewhat surprising, this results in a slight code size decrease for ARM
targets of a few bytes.
2022-04-26 17:47:21 +02:00
lincolngill 9eb4a6268a Pico adc input ch support (#2737)
machine/rp2040: ADC changes, including
* Add rp2040 ADC mux channel support. Internal temp sensor reading and fix for incorrect setting of CS.AINSEL reg bits
* Reset ADC ref voltage in InitADC
2022-04-26 11:49:38 +02:00
deadprogram 11a402de95 docs: update list of currently supported boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-26 07:47:34 +02:00
Dan Kegel cdd9198888 github: also do tinygo-test-wasi-fast on windows 2022-04-25 17:59:39 +02:00
Dan Kegel 6055e6eb23 Makefile: compress/lzw fails on windows wasi, see #2800, not plain windows. 2022-04-25 17:59:39 +02:00
Dan Kegel 9239c61edb TestChdir: avoid cd .., as wasi does not really support it yet. Tiptoes around #2799. 2022-04-25 17:59:39 +02:00
deadprogram 008b373df4 build: use latest Windows hosted runner version
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-25 17:15:59 +02:00
deadprogram c387a09f54 build: use Go 1.18.1 for all builds
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-25 17:15:59 +02:00
deadprogram 5bb3ca2618 machine/circuitplay-bluefruit: move pin mappings so board can be compiled for WASM use in Playground
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-25 11:17:42 +02:00
Yurii Soldak a4ea85b303 xiao-ble: initial support 2022-04-24 14:50:02 +02:00
Olaf Flebbe 27d38a9663 machine/board_thingsplus_rp2040 targets/thingsplus-rp2040: support sparkfun thingsplus rp2040 board 2022-04-24 10:56:52 +02:00
deadprogram ee497a296b docker: update Dockerfile to use Go 1.18
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-04-23 18:42:00 +02:00
Ayke van Laethem 6b31ee1e93 all: update to LLVM 14
Switch over to LLVM 14 for static builds. Keep using LLVM 13 for regular
builds for now.

This uses a branch of the upstream Espressif branch to fix an issue,
see: https://github.com/espressif/llvm-project/pull/59
2022-04-23 08:45:46 +02:00
Ayke van Laethem cad6a57077 compiler: remove support for memory references in AsmFull
Memory references (`*m` in LLVM IR inline assembly) need a pointer type
starting in LLVM 14. This is a bit inconvenient and requires a new API
in the go-llvm package.

Instead of doing that, I'd like to remove support for memory references
from AsmFull (and possibly AsmFull entirely if possible: it's hard to
use correctly).

This breaks tinygo.org/x/drivers/ws2812 for AVR, ARM, and RISC-V which
need to be updated. Probably using CGo.
2022-04-21 15:18:18 +02:00
Ayke van Laethem 52233790cc mimxrt1062: simplify arm.AsmFull to arm.Asm
This means fewer instances of arm.AsmFull, which I'd like to remove
eventually if possible.
2022-04-21 15:18:18 +02:00
Ayke van Laethem 9160f3f16d main: use shared code for both run and test subcommands
This means that we don't need duplicate code to pass parameters to
wasmtime and that the following actually produces verbose output (it
didn't before this commit):

    tinygo test -v -target=cortex-m-qemu math
2022-04-20 08:22:46 +02:00
Dan Kegel 69d7ed5cda os: define ErrDeadlineExceeded; fixes go 1.18 compile error in net/http, #2782 2022-04-19 09:22:27 +02:00
Dan Kegel 111661658b .github: use proper name for Mac OS 11 (10.16 was unofficial; we could also use 10.15) 2022-04-18 22:52:14 +02:00
Dan Kegel 3000b2d15e gofmt src/machine/machine_mimxrt1062_spi.go to please 1.18 2022-04-18 22:52:14 +02:00
Dan Kegel c89f026532 Makefile: tinygo-test: skip compress/flate test on windows for now
Lets us move forward until
https://github.com/tinygo-org/tinygo/issues/2762
is fixed.
2022-04-18 22:52:14 +02:00
Dan Kegel e09b1d06f5 Smoke test 1.15 still until we drop support for it 2022-04-18 22:52:14 +02:00
Dan Kegel 0590ccb260 gofmt exec_posix.go 2022-04-18 22:52:14 +02:00
Dan Kegel fe0acb1670 ci: updated supported go versions from 1.15-1.17 to 1.16-1.18 2022-04-18 22:52:14 +02:00
Ayke van Laethem d58c7d2521 main: add support for command-line parameters to tinygo run
This is made easy by the refactor in the previous commit.
2022-04-16 18:37:03 +02:00
Ayke van Laethem 85f5411d60 main: unify how a given program runs
Refactor the code that runs a binary. With this change, the slightly
duplicated code between `tinygo run` and `TestBuild` is merged into one.
Apart from deduplication (which doesn't even gain much in terms of lines
removed), it makes it much easier to maintain this code. In particular,
passing command line arguments to programs to run now becomes trivial.

A future change might also merge `buildAndRun` and `runPackageTest`,
which currently have some overlap. In particular, flags like `-test.v`
don't need to be special-cased for wasmtime.
2022-04-16 18:37:03 +02:00
ardnew c5de68622e board/teensy40: Add SPI support (#1455)
machine/teensy40: add SPI support
2022-04-16 15:43:52 +02:00
Ayke van Laethem 8fb93fbac4 esp: support CGo
Without this patch, the include directory isn't found and picolibc.h
(used indirectly by stdint.h for example) can't be found.

I would like to add tests for this but we currently don't run Xtensa
tests. This should be possible however using https://github.com/espressif/qemu/wiki
(see also: https://github.com/tinygo-org/tinygo/pull/2780).
2022-04-15 23:28:26 +02:00
Ayke van Laethem ef3b3c0d6a transform: fix poison value in heap-to-stack transform
In https://github.com/tinygo-org/tinygo/issues/2777, a poison value
ended up in `runtime.alloc`. This shouldn't happen, especially not for
well written code. So I'm not sure why it happens. But here is a fix
anyway.
2022-04-15 22:54:25 +02:00
ardnew 2dc46a851b board/teensy40: Add ADC support (#1458)
machine/teensy40: add ADC support
2022-04-13 17:12:31 +02:00
Ron Evans f3afc7bbf3 Revert "fix: flash-command for maixbit board"
This reverts commit b02cea0321.
2022-04-12 17:13:32 +02:00
Elliott Sales de Andrade 4858b27120 Also disable asynchronous unwind tables
These seem to be enabled in LLVM 14, and cause undefined symbol errors.
2022-04-11 14:58:55 +02:00
Elliott Sales de Andrade 7f507a7026 Fix incorrect formatting arguments 2022-04-10 22:58:16 +02:00
Ayke van Laethem 83227e68df all: use compiler-rt from LLVM 2022-04-10 21:03:59 +02:00
sago35 09a3c6a16b flash: add openocd-verify 2022-04-09 17:49:54 +02:00
soypat f613cb41a3 rp2040: fix spurious i2c STOP during write+read transaction 2022-04-09 11:10:36 +02:00
Elias Naur e060e588ab goenv: look for Go version in $GOROOT/src/internal/buildcfg/zbootstrap.go
The old path, $GOROOT/runtime/internal/sys/zversion.go, no longer contains
the Go version.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2022-04-09 10:11:07 +02:00
Dan Kegel 8dfb317d28 Allow building with go 1.18 2022-04-09 09:16:37 +02:00
Elliott Sales de Andrade 9cedd78d9c Add a shim for internal/fuzz
This simply shadows the real code temporarily to see what else is
broken. It only defines a single type to fix testing/internal/testdeps.
2022-04-09 09:16:37 +02:00
Dan Kegel 20a27746b2 compiler: make RawSyscall an alias for Syscall per suggestion from Ayke. For #2474. 2022-04-08 08:29:30 +02:00
Dan Kegel c78df85015 os: Implement Pipe for darwin, add smoke test.
Evidently when you read from pipes in Go, you have to adjust your slice length to reflect the number of bytes read.
Verified upstream behaves the same way.
2022-04-08 08:29:30 +02:00
Ayke van Laethem c0d257d682 compiler: fix difference in aliases in interface methods
There used to be a difference between `byte` and `uint8` in interface
methods. These are aliases, so they should be treated the same.
This patch introduces a custom serialization format for types,
circumventing the `Type.String()` method that is slightly wrong for our
purposes.

This also fixes an issue with the `any` keyword in Go 1.18, which
suffers from the same problem (but this time actually leads to a crash).
2022-04-07 12:54:17 +02:00
Dan Kegel 7af24c7864 compiler: allow slices of empty structs.
Fixes https://github.com/tinygo-org/tinygo/issues/2749
2022-04-07 12:00:27 +02:00
Dan Kegel 3dc1e403ea runtime: stub {Lock,Unlock}OSThread. Makes 1.18 happier on windows. 2022-04-07 10:27:34 +02:00
sago35 1deee3ec5a m5stamp-c3: add pin setting of UART 2022-04-07 07:16:27 +02:00
Dan Kegel 0f9f316db2 main_test.go: fork testdata/testing.go for go 1.18 2022-04-06 20:03:04 +02:00
Dmitriy 0dd521e1d1 add support for esp32c3 to receive UART data 2022-04-06 19:25:24 +02:00
Ron Evans 1dcdd5f2d2 Revert "src/runtime: first darft of map growth code"
This reverts commit 7e05efa274.
2022-04-05 03:34:01 +02:00
Ron Evans dcd8ee63a8 Revert "src/runtime/hashmap: comments for iterator structure"
This reverts commit 8872229a0b.
2022-04-05 03:34:01 +02:00
Ron Evans b8bf0ac3f1 Revert "testdata: add test for mapgrowth logic"
This reverts commit 73571dd423.
2022-04-05 03:34:01 +02:00
Damian Gryski 73571dd423 testdata: add test for mapgrowth logic 2022-04-04 13:22:19 +02:00
Damian Gryski 8872229a0b src/runtime/hashmap: comments for iterator structure 2022-04-04 13:22:19 +02:00
Damian Gryski 7e05efa274 src/runtime: first darft of map growth code
Fixes #1553
2022-04-04 13:22:19 +02:00
Sai Sasidhar Maddali b02cea0321 fix: flash-command for maixbit board
Latest version of kflash tool requires a --Board/-B argument to
        be able to run the tool
2022-04-04 09:15:39 +02:00
Dan Kegel 8823a934a3 syscall: stub WaitStatus 2022-04-04 07:33:31 +02:00
Dan Kegel 6ac02cc34c syscall: wasi: more complete list of signals
Grepped straight out of the appropriate signal.h, with order preserved.

Makes 1.18 tests happier.

See comment on discrepancy for SIGCHLD.  Since wasi doesn't really support signals, this may not matter.
2022-04-03 19:22:43 +02:00
Dan Kegel e259598b68 syscall: darwin: more complete list of signals
Grepped straight out of the appropriate signal.h, with order and comments preserved verbatim.

Makes 1.18 tests happier.
2022-04-03 19:22:43 +02:00
Elliott Sales de Andrade f159573975 Add reflect.Value.FieldByIndexErr stub 2022-03-24 06:31:02 +01:00
sago35 234234af15 build: add JSON output to build command 2022-03-24 05:51:38 +01:00
Dmitriy 3d68804702 Add board support for ESP32-C3-12f Kit 2022-03-20 07:39:27 +01:00
Dan Kegel 38efca1e2d syscall: stub mmap(), munmap(), MAP_SHARED, PROT_READ, SIGBUS, etc. on nonhosted targets
Makes 1.18 tests a little happier.

Works around this error:

$ make test GOTESTFLAGS="-run TestTest/EmulatedCortexM3/Pass"
...
main_test.go:520: test error: could not compile: /usr/local/go/src/internal/fuzz/sys_posix.go:19:18: PROT_READ not declared by package syscall
2022-03-19 21:06:45 +01:00
Aayush Attri 0a75dd82b9 updating the comments for stub funcs 2022-03-19 19:09:20 +01:00
Aayush Attri fbc748f152 removing Version stub 2022-03-19 19:09:20 +01:00
Aayush Attri 881aba1785 add stub for runtime numcgocall, numgoroutine and version 2022-03-19 19:09:20 +01:00
Dan Kegel aa421bf655 compiler.go: createBuiltin: accept alias for slice. Helps 1.18 tests pass.
With proper fix by Ayke.
2022-03-19 19:05:57 +01:00
Dan Kegel 1fb1f08233 syscall: define MAP_SHARED and PROT_READ on wasi
Makes 1.18 tests a little happier.

Not sure mmap works on wasi, so these may be somewhat stubby.
2022-03-19 16:05:23 +01:00
ZauberNerd 0b5d300d94 targets/wasi: remove --export-dynamic linker flag
Exporting symbols seems to embed them in the WASM exports section which
causes wasmtime to fail: https://github.com/bytecodealliance/wasmtime/issues/2587
As a workaround, it is possible to specify the `--allow-unknown-exports`
flag on wasmtime.
But as discussed in the above linked issue, this seems to only be a
workaround. For the Rust compiler the fix was to remove the
`--export-dynamic` linker flag when targeting `wasm32-wasi`:
https://github.com/rust-lang/rust/pull/81255
Which is waht this commit does for Tinygo too.
2022-03-19 15:36:44 +01:00
ZauberNerd 2fdcabdcce src/runtime: add runtime.Version()
This adds the `Version()` function of the `runtime` package which embeds
the go version that was used to build tinygo.

For programs that are compiled with tinygo the version can be overriden
via the:
`tinygo build -ldflags="-X 'runtime.buildVersion=abc'"` flag.
Otherwise it will continue to use the go version with which tinygo was
compiled.
2022-03-19 15:36:44 +01:00
ZauberNerd d066b5c232 Move gitSha1 build time variable from main to goenv package
Moving and exporting this variable from the main to the goenv package
allows us to use it from both the main and the builder package.
This is done in preparation to include the value in `tinygo build`
linker flags, so that we can embed the version and git sha into binaries
built with tinygo.
2022-03-19 15:36:44 +01:00
Elliott Sales de Andrade 836ab95192 Rename reflect.Ptr to reflect.Pointer
This was done in plain Go for 1.18:
https://github.com/golang/go/commit/17910ed4ff5a3cb3dcf4367d4af23ad5a7fe5809
2022-03-18 15:27:28 +01:00
Dan Kegel cf8f4d65f2 Implement getpagesize and munmap. For go 1.18. 2022-03-18 13:44:30 +01:00
Damian Gryski 06b19cde2d interp: prevent an off-by-one during interp debug 2022-03-17 20:06:59 +01:00
Elliott Sales de Andrade 42ae9a665f os: Add some exec.ProcessState stubs 2022-03-17 12:33:59 +01:00
Dan Kegel c55c996c5d gc_leaking.go: don't inline alloc. Fixes #2674. 2022-03-17 11:26:01 +01:00
ZauberNerd 6fb90b6fc4 src/os: Add UserHomeDir() function to os package
This commit adds the `UserHomeDir()` function to the `os` package.
2022-03-16 22:19:05 +01:00
ZauberNerd 6f31712b7d test: write into a temp file and read from its fd
This test creates a new temp file and writes some bytes into it.
It then opens a new file for the file descriptor of the temp file and
tries to read some bytes out of it.
2022-03-16 15:40:04 +01:00
ZauberNerd e295770363 test: simple test to verify os.File.Fd() is working 2022-03-16 15:40:04 +01:00
ZauberNerd 486b99961d src/os: implement os.File.Fd() method
This commits adds a OS-specific `Fd()` function for `file_anyos.go` and
`file_other.go`, which returns a uintptr to the underlying file
descriptor.
2022-03-16 15:40:04 +01:00
Dan Kegel 4a98db4c86 Add regression test for #2666.
I didn't see how to run it easily from main_test.go, though I didn't try too hard.
And it doesn't really have a good place to go in Makefile.
So I added a new target tinygo-baremetal, and invoke it from CI at the end of assert-test-linux.
It only adds 7 seconds to the run, should be ok.
2022-03-15 05:59:00 +01:00
Dan Kegel c534fa1b6f On baremetal platforms, use simpler test matcher. Fixes #2666.
Uses same matcher in testdata (because now we can't replace it in testdata).
2022-03-15 05:59:00 +01:00
deadprogram eed78338e6 build: trigger builds of dev branches of repos in TinyGo ecosystem, e.g. Bluetooth, TinyFS, TinyFont, TinyDraw
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-03-14 20:44:43 +01:00
Elliott Sales de Andrade 5141638cbf Fix type of Signal constants on WASI 2022-03-13 12:53:23 +01:00
Elliott Sales de Andrade 5d4f795aec Add an empty os.Process.Signal implementation
This fixes compile of tests in Go 1.18, due to its use in
`src/internal/testenv/testenv.go`.
2022-03-13 12:53:23 +01:00
Elliott Sales de Andrade db8603e378 Add os Signal aliases
These are used in Go 1.18's `testing/internal/testdeps`. Though the
comment says they should exist _everywhere_, there is still a build
constraint, but that seems to be fine.
2022-03-13 12:53:23 +01:00
Elliott Sales de Andrade bc098da93f Implement all of os.Signal in arch-specific syscall
This is basically copied from `syscall_js.go` from the Go standard
library, since the existing parts were from there as well.
2022-03-13 12:53:23 +01:00
Ayke van Laethem e49e93f22c main: calculate default output path if -o is not specified
This matches the Go command and is generally convenient to have.
2022-03-13 01:08:20 +01:00
Ayke van Laethem 7d4bf09b1a builder: use correct permission bits when creating a library
Previously, the wrong permission bits were emitted by
`tinygo build-library`. This commit fixes that, by `chmod`'ing to
reasonable default permission bits.
2022-03-12 23:20:38 +01:00
Ayke van Laethem 320f21524e cgo: slightly improve error messages
Updating them to libclang-13-dev was a good change, but we can go even
further:

  * The suggestion didn't apply to MacOS.
  * The suggestion would need to be updated with every LLVM release,
    which is a maintenance burden.
  * The suggestion is wrong when compiling with `-tags=llvm12` for
    example to choose a different LLVM version.

Therefore, link to the build documentation instead.
2022-03-12 21:17:29 +01:00
Dan Kegel 4117055611 Makefile: chmod before fpm. For #2685 2022-03-12 17:24:16 +01:00
Ayke van Laethem 603fff78d4 all: add support for ThinLTO
ThinLTO optimizes across LLVM modules at link time. This means that
optimizations (such as inlining and const-propagation) are possible
between C and Go. This makes this change especially useful for CGo, but
not just for CGo. By doing some optimizations at link time, the linker
can discard some unused functions and this leads to a size reduction on
average. It does increase code size in some cases, but that's true for
most optimizations.

I've excluded a number of targets for now (wasm, avr, xtensa, windows,
macos). They can probably be supported with some more work, but that
should be done in separate PRs.

Overall, this change results in an average 3.24% size reduction over all
the tinygo.org/x/drivers smoke tests.

TODO: this commit runs part of the pass pipeline twice. We should set
the PrepareForThinLTO flag in the PassManagerBuilder for even further
reduced code size (0.7%) and improved compilation speed.
2022-03-12 12:55:38 +01:00
Ayke van Laethem d4b1467e4c build: support machine outlining pass in stacksize calculation
The machine outliner introduces a few new opcodes that weren't
previously emitted by LLVM. We need to support these.

This doesn't trigger very often, but it sometimes does. It triggers a
lot more often with ThinLTO enabled.
2022-03-12 12:55:38 +01:00
ZauberNerd 4cf8ad2bee Update libclang installation comment to libclang-13-dev
Tinygo bumped the default llvm version to v13 in:
tinygo-org/tinygo@3a4e0c9
2022-03-12 09:31:18 +01:00
sago35 96c60f9692 atsamd51: allow faster frequency setting when using SPI 2022-03-12 08:45:38 +01:00
Elliott Sales de Andrade 99ce46669b Fix LLVM build constraints 2022-03-11 07:51:44 +01:00
sago35 a1b4eafa07 samd21,samd51: fix usbcdc initialization when -serial=uart (#2631)
machine/samd21,samd51: fix usbcdc initialization when -serial=uart by using machine.USB.Configured()
2022-03-10 12:32:19 +01:00
deadprogram ccbe03795a build/windows: use fork with updated permissions for new scoop 2022-03-10 09:13:33 +01:00
ZauberNerd 3f69c32a55 src/os: export correct values for os.DevNull for each OS
This commit introduces `os.DevNull` exports for all supported OS
targets.
2022-03-08 14:49:14 +01:00
Dmitriy b176494e44 add support for GPIO interrupts on esp32c3
Update interrupt_esp32c3.go:
make callHandler inline
save and restore MSTATUS along with MEPC
save and restore actual threshold value and call fence
print additional data during exception
2022-03-08 09:13:15 +01:00
ZauberNerd 0243a5b8be src/os: add stubs for exec.ExitError and ProcessState.ExitCode
This commit adds stubs for the `ExitError` struct of the `exec` package
and `ProcessState.ExitCode()` of the `os` package.

Since the `os/exec` is listed as unsupported, stubbing these methods
and structs should be enough to get programs that use these to compile.
2022-03-08 06:45:53 +01:00
ZauberNerd 1fac41d535 src/runtime: add stub for runtime.NumCPU()
This adds a stub for the `NumCPU()` function from the `runtime`
package.
This change allows code to compile that tries to access this function.

I guess for most hardware boards and WASM setting this value to `1` is
fine. And as far as I can see it shouldn't break or change existing
applications, because the function previously did not exist at all.
2022-03-07 21:03:38 +01:00
ZauberNerd 1472fb6032 src/runtime: add stub for debug.ReadBuildInfo()
This adds the necessary structs and the `ReadBuildInfo()` function to
the runtime/debug module to allow to compile code that tries to access
it.
The stub itself returns ok=false, so that calling code should not try
to read from the nil pointer that is returned instead of the actual
BuildInfo struct.
2022-03-07 20:03:51 +01:00
Samuel Stauffer 0fd3d785a3 syscall/js: allow copyBytesTo(Go|JS) to use Uint8ClampedArray
From https://github.com/golang/go/commit/f0e8b81aa34120e21642c569912bde00ccd33393

Fixes https://github.com/tinygo-org/tinygo/issues/1941
2022-03-07 19:01:55 +01:00
Ayke van Laethem b9c0aa77bf runtime: implement memhash
This function is used by the hash/maphash package.

Unfortunately, I couldn't get the hash/maphash package to pass tests
because it's too slow. I think it hits the quadratic complexity of the
current map implementation.
2022-03-06 10:13:04 +01:00
Ayke van Laethem 4c28f1b875 runtime: add fastrand
This is needed for hash/maphash support.
2022-03-06 10:13:04 +01:00
Dan Kegel 0791603c86 Makefile: add report-stdlib-tests-pass 2022-03-05 22:22:22 +01:00
Damian Gryski 095312fa3f src/syscall: document Environ() single-allocation tradeoff 2022-03-04 15:26:47 +01:00
Damian Gryski 7e647a5e81 src/runtime: use memzero for leaking collector 2022-03-04 01:35:22 +01:00
Ayke van Laethem 29c1d7c68d compiler: fix incorrect unsafe.Alignof on some 32-bit architectures
This should fix https://github.com/tinygo-org/tinygo/issues/2643
2022-03-04 00:04:17 +01:00
Dan Kegel ecb7eebcff Makefile: add compress/lzw, debug/dwarf, debug/plan9obj, and net to list of tests 2022-03-02 18:25:16 +01:00
Elliott Sales de Andrade a680bfbb7a os: Use a uintptr for NewFile
This appears to have been how it is upstream for about 10 years. Using
an interface breaks if a file descriptor number is passed directly to
`NewFile`, e.g., `NewFile(3, "fuzz_in")` as used in Go 1.18 fuzzing
code.
2022-03-01 14:01:40 +01:00
Damian Gryski bf23839931 src/os,src/syscall: move env copy code to syscall.Environ() 2022-03-01 11:44:39 +01:00
Damian Gryski 6b15a72895 src/os: add back TestClearenv
Removed as flaky in #2603
2022-03-01 11:44:39 +01:00
Damian Gryski 08fd49fe60 src/os: make Environ() return a copy of the environment
Fixes #2646
2022-03-01 11:44:39 +01:00
sago35 d65e3deccf Revert "all: move stm32 files to separate repository"
This reverts commit 644356c220.
2022-02-28 10:19:26 +01:00
Damian Gryski cbfa85be6a testdata/corpus: add google/go-patchutils 2022-02-24 12:36:10 -05:00
Dan Kegel 6c23f27f73 Makefile: add testing/fstest to tinygo-test where supported 2022-02-24 12:35:40 -05:00
Dan Kegel 31a3a7c84b os: testTempDir: now that we have os.ReadDir, bring back one use of it in a test 2022-02-24 12:35:40 -05:00
Dan Kegel a9a225ba26 testing: nudge type TB closer to upstream; should be a no-op change. 2022-02-24 12:35:40 -05:00
Dan Kegel 58d0499e55 Makefile: add io/fs to tinygo-test where supported
Depends on t.TempDir(), which is why this wasn't enabled earlier.
2022-02-24 12:35:40 -05:00
Dan Kegel b24af78327 testing: implement testing.TempDir
TODO: enable test on windows and wasi once os.Readdir and os.RemoveAll are implemented there
2022-02-24 12:35:40 -05:00
Kyle Conroy b406422277 test: Add text/template smoke test 2022-02-24 12:32:40 -05:00
Kyle Conroy cfed3f0213 fix: Add stubs for more missing reflect methods
With these methods stubbed out, the text/template package can be
imported. These changes also allow code generated by protoc to compile.
2022-02-24 12:32:40 -05:00
Ayke van Laethem d75e14245b test: fix assertion for multiple packages
I see no reason why it isn't possible to run `tinygo test -c` with
multiple packages. It'll just create multiple test outputs. I think the
intended flag was the `-o` flag, which indeed doesn't make much sense
with multiple packages.
2022-02-21 05:53:03 +01:00
Dan Kegel af8244e868 Update macos-minimal-sdk to pick up updated dirent.h 2022-02-21 05:18:27 +01:00
Dan Kegel f962e2fd15 github: also run 'make tinygo-test' on mac 2022-02-21 05:18:27 +01:00
Ayke van Laethem 5746154cc0 all: add -work flag
This flag has the same behavior as in upstream Go. It can be useful
while debugging certain issues.
2022-02-20 16:35:20 +01:00
Dan Kegel e9d9ae8781 os: disable TestClearenv for now, it is very flaky. Also reduce verbosity. 2022-02-20 13:46:48 +01:00
BCG 52ffd6aa98 board: Adafruit MacroPad RP2040 2022-02-19 11:52:24 +01:00
Ayke van Laethem 644356c220 all: move stm32 files to separate repository 2022-02-18 23:39:26 +01:00
Dan Kegel 47a622a903 Implement os.RemoveAll()
TODO: enable test on windows once Readdir is implemented there
2022-02-18 04:47:19 +01:00
BCG 4417374b53 board: add definition for Teensy 4.1 (#2618)
* board: add definition for Teensy 4.1
2022-02-13 08:21:03 +01:00
Ayke van Laethem 262291a80a rp2040: fix incorrect inline assembly
The register r0 was used unconditionally. This is a bug: the compiler
doesn't know it is clobbered and might consider it alive across the
inline assembly expression.

The fix is simple. It could probably be optimized, but this should at
least fix the bug.
2022-02-13 07:34:40 +01:00
Ayke van Laethem cdd267fa10 builder: add support for cross compiling to Darwin
This means that it will be possible to generate a Darwin binary on any
platform (Windows, Linux, and MacOS of course), including CGo. Of
course, the resulting binaries can only run on MacOS itself.

The binary links against libSystem.dylib, which is a shared library. The
macos-minimal-sdk repository contains open source header files and
generated symbol stubs so we can generate a stub libSystem.dylib without
copying any closed source code.
2022-02-12 15:33:06 +01:00
Ayke van Laethem 850a5fdbfb loader: only add Clang header path for CGo
It should only be added at the point that it is needed, for example when
using libclang or using the built-in Clang. It isn't needed when running
an external tool.
2022-02-12 15:33:06 +01:00
Damian Gryski 4b2edc9a26 compiler: move allocations > 256 bytes to the heap 2022-02-11 19:46:37 +01:00
sago35 f2fef290c9 machine: add DefaultUART to wioterminal 2022-02-11 07:17:43 +01:00
Elliott Sales de Andrade 010cc13e9e Fix cross-Linux setup on non-amd64 arches
In that case, an emulator is needed for amd64, and tests should be run
for amd64 as a _cross_ test.
2022-02-07 11:05:47 +01:00
Yurii Soldak ac7e370c72 rp2040: i2c minor fixes 2022-02-05 18:18:20 +01:00
Ayke van Laethem 77ec9b6369 all: update build constraints to Go 1.17
Do it all at once in preparation for Go 1.18 support.

To make this commit, I've simply modified the `fmt-check` Makefile
target to rewrite files instead of listing the differences. So this is a
fully mechanical change, it should not have introduced any errors.
2022-02-04 07:49:46 +01:00
Dan Kegel aa8e0bb509 os: isWine: be compatible with older versions of wine, too
Turns out wine 5.x doesn't export WINEUSERNAME.
2022-02-03 19:12:19 +01:00
Ayke van Laethem 372d9e0f5e wasm: remove heap allocator from wasi-libc
This would conflict with our own heap. We previously defined all those
functions to make sure it's not used, but with a more recent wasi-libc
version (https://github.com/WebAssembly/wasi-libc/pull/250) we can
simply not compile the wasi-libc heap, which is the proper fix.
2022-02-03 18:28:02 +01:00
sago35 d139fa5e0f esp32c3: add support for input pin 2022-02-02 18:13:09 +01:00
soypat 367fb9d40e machine/rp2040: whole now correctly set at minimum 1 value for high frequency PWM 2022-02-02 09:52:13 +01:00
Dan Kegel 98a6ed8059 os: add DirFS, which is used by many programs to access readdir.
It's wafer-thin :-)

Includes smoke test from upstream.

TODO: once t.TempDir is implemented, add io/fs to the list of standard library tests to run; that's a better test.
2022-02-02 08:57:49 +01:00
Dan Kegel 641a7e5cb9 os: implement readdir for darwin and linux
readdir is disabled on linux for 386 and arm until syscall.seek is implemented there.

windows is hard, so leaving that for later.

File src/os/dir_other_go115.go can be deleted when we drop support for go 1.15.

Also adds TestReadNonDir, which was helpful while debugging.
2022-02-02 08:57:49 +01:00
Damian Gryski 3fa7d6cc40 src/runtime: assert that a gc block addr isn't inside the metadata 2022-02-01 20:26:35 +01:00
Damian Gryski e497b5c5ba src/runtime: prevent out-of-bounds memory access during b.state() 2022-02-01 20:26:35 +01:00
Damian Gryski 23dc861ddb src/runtime: use garbage collector constants when we have them 2022-02-01 20:26:35 +01:00
Damian Gryski b2ccf12e98 src/runtime: fix location of metadata in comment 2022-02-01 20:26:35 +01:00
Damian Gryski 23479c92d3 src/runtime: improve metadatasize calculation to avoid rounding issues 2022-02-01 20:26:35 +01:00
Yurii Soldak 3458726234 nano-33-ble: typo in LPS22HB peripheral definition and documentation (#2579) 2022-01-29 11:19:15 -05:00
Ayke van Laethem a7a69d38a4 builder: prefer GNU build ID over Go build ID
The GNU build ID covers the Go build ID, and probably some more.
2022-01-27 18:38:40 +01:00
sago35 4210200070 goenv: update version for start of 0.23.0 development cycle 2022-01-27 15:53:53 +01:00
Ayke van Laethem 3883550c44 build: fix build-library subcommand
This subcommand has been broken for a while, since libraries also use
the CPU flag. This commit fixes this.

Previously, libraries were usable for most Cortex-M cores. But with the
addition of the CPU field, I've limited it to three popular cores: the
Cortex-M0 (microbit), Cortex-M0+ (atsamd21), and Cortex-M4 (atsamd21,
nrf52, and many others).

In the future we might consider also building libraries for the current
OS/arch so that libraries like musl are already precompiled.
2022-01-26 00:27:33 +01:00
Ayke van Laethem 5ce072b827 all: release v0.22.0 2022-01-25 23:12:07 +01:00
deadprogram 4029b838ce all: update license year to 2022
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-25 17:13:34 +01:00
Dan Kegel 3fbab2ede3 builder/buildid.go: accept alternate name for buildid section on Linux
On Ubuntu, using standard go, both go and gnu buildid sections are present.
On Alpine, the gnu buildid section is absent, which caused tinygo to abort early.

It is possible that we could hit a situation where only the gnu
buildid section is present, so accept either one just in case.

Fixes https://github.com/tinygo-org/tinygo/issues/2580
2022-01-25 07:26:06 +01:00
Dan Kegel a29e1d43f1 Kludge: provide stub for syscall.seek on 386 and arm, #1906
This replaces an earlier kludge which was at the wrong level
and caused "GOARCH=386 tinygo test os" to fail to compile on linux.

Stubbing just the one missing function, syscall.seek, lets
os tests compile on linux 386, and skipping tests of seek and Fstat
(which has a cryptic dependency on syscall.Seek via time)
lets os tests pass on linux 386.

The stub can be removed once tinygo implements go assembly and picks up the real definition.
2022-01-24 18:23:40 +01:00
Dan Kegel ee663ccb96 Revert "Kludge: work around lack of syscall.seek on 386 and arm, #1906"
This reverts commit 60b483bd3b.
2022-01-24 18:23:40 +01:00
Ayke van Laethem cd867b72b9 interp: don't log from the interp package
We shouldn't be logging anything when not explicitly requested via a
flag or some other way.
2022-01-24 15:01:35 +01:00
Nia Waldvogel 8aa223aed9 main (test): integrate test corpus runner
This allows us to test a large corpus of external packages against the compiler.
2022-01-23 10:22:28 -05:00
Federico G. Schwindt 3a4e0c94e1 Switch default to llvm13 2022-01-23 02:03:27 +01:00
Dmitriy 0a0981a475 Provide Set/Get for each register field described in SVD files
- rename Bitfield to Constant
- add methods to the exiting types to set/get bitfields
- integrate clustered registers
- add cluster size to properly add filler at the end of the structure
- fix structures with leading filler (i.e. for FICR_Type.INFO in nfr9160)
- shorten the function name when prefix and suffix are identical. i.e. GetSTATE_STATE vs GetSTATE
2022-01-21 15:09:08 +01:00
Nia Waldvogel 2f57e4ff6d interp: handle type assertions on nil interfaces
Previously, a type assertion on a nil interface would result in an out-of-bounds operand access, as we assumed it was a ptrtoint.
This would usually result in an undefined value which happens not to have the same name as the asserted type (and therefore the assertion fails as expected).
However, with an LLVM build with asserts, LLVM throws an assertion error:
```
interp.test: /home/niaow/go/src/github.com/tinygo-org/tinygo/llvm-project/llvm/include/llvm/IR/User.h:170: llvm::Value* llvm::User::getOperand(unsigned int) const: Assertion `i < NumUserOperands && "getOperand() out of range!"' failed.
```

This change handles a type code of 0 specially.
2022-01-21 14:49:36 +01:00
deadprogram 5e33dccf1f build: trigger drivers repo build after successful docker dev build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-21 10:05:29 +01:00
Dan Kegel f4fdf8dce9 Makefile: detected TINYGO now works even if a rule changes directory 2022-01-21 07:39:47 +01:00
Dan Kegel 9c3f9537be os: add stubs for Readlink and File.Seek for baremetal targets, with smoke test.
Test currently enabled on pybadge (chosen at random)

TODO:
- enable test on arduino; currently fails with "interp: ptrtoint integer size..." (#2389)
- enable test on nintendoswitch; currently fails with many missing definitions (#2530)
2022-01-21 07:39:47 +01:00
deadprogram f5b7925047 docs: correct link for building development version of TinyGo
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-20 17:02:33 +01:00
Dmitriy Zakharkin 50401c05e8 move AVR interrupt related code to runtime
move AVR interrupt related code to runtime
address formatting
add volatile to access counters
2022-01-20 15:07:16 +01:00
Dan Kegel 7914a729a5 Makefile: exclude archive/zip from TEST_PACKAGES on windows until ReadAt supported 2022-01-20 11:14:41 +01:00
Dan Kegel 8eedd2b04b Makefile: add archive/zip to TEST_PACKAGES
Except on windows, where it fails because it needs ReadAt, which we don't implement on windows yet.
2022-01-20 11:14:41 +01:00
Dan Kegel 60b483bd3b Kludge: work around lack of syscall.seek on 386 and arm, #1906
Revert this once syscall.seek is implemented
cf. https://github.com/tinygo-org/tinygo/issues/1906
2022-01-20 11:14:41 +01:00
Damian Gryski 322abf6d22 src/{syscall, os}: add File.Stat, with smoke test
This is File.Stat from https://github.com/tinygo-org/tinygo/pull/2371,
plus the windows bits,
plus a smoke test more or less from upstream,
all pulled together and rebased by dkegel-fastly.
2022-01-20 11:14:41 +01:00
Dan Kegel b85cb55aab interpreter.go: double timeout to let a real world project build. Waiting is a bit less frustrating with breadcrumbs. 2022-01-20 10:07:48 +01:00
Federico G. Schwindt 03d83181ca Bump go-llvm to support llvm12 and 13 under macos 2022-01-20 09:29:04 +01:00
Yurii Soldak 31ee1637df nrf: fix stop condition race in i2c 2022-01-20 07:37:47 +01:00
deadprogram b7bcb256d7 docs: add GH Actions badge for Docker build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-19 22:18:26 +01:00
deadprogram 7516c5d69e build: rename file and cleanup names displayed for Docker dev build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-19 22:18:26 +01:00
Nia Waldvogel c6ae1c58fc compiler: remove parentHandle from calling convention
This removes the parentHandle argument from the internal calling convention.
It was formerly used to implment coroutines.
Now that coroutines have been removed, it is no longer necessary.
2022-01-19 14:42:02 -05:00
Nia Waldvogel 0c2fefa09b transform: remove switched func lowering
The switched func lowering was mainly necessary for coroutines.
With coroutines removed, this is no longer necessary.
2022-01-19 14:42:02 -05:00
Nia Waldvogel ea2a6b70b2 internal/task: remove coroutines 2022-01-19 14:42:02 -05:00
Ayke van Laethem d054d4d512 loader: respect $GOROOT when running go list
This makes it possible to select the Go version using GOROOT, and works
even if the `go` binary is not in $PATH.
2022-01-19 12:44:07 -05:00
Ayke van Laethem e7e1b755c9 Makefile: use absolute path for llvm-build/bin/* binaries
This un-breaks `make wasi-libc` on my system.
2022-01-19 09:44:30 -05:00
Nia Waldvogel 38cd5b80ec Makefile: fix tool autodetect conversion to absolute path
After the last change, $(abspath x) no longer returned the actual absolute path.
This uses which instead.
2022-01-19 07:40:16 +01:00
Nia Waldvogel 57ff3a5ca0 compiler: predeclare runtime.trackPointer
When a package only uses runtime.trackPointer to create interface packs, the compiler fails to find runtime.trackPointer.
This change predeclares it alongside runtime.alloc and updates the tests to use runtime.trackPointer when the test's target uses it.
2022-01-18 16:27:12 -05:00
Nia Waldvogel ecf7014f7e Makefile: reorganize tool detection
There are now a large number of paths that need to be searched, and this started to get a little bit unwieldy.
Additionally, brew paths were searched unconditionally, resulting in warnings every time the Makefile was run.
This reorganizes the detection paths into a parameterized list of search paths by version, which is appended to on Mac.
This list is then expanded across all versions.
The loop and filtering has been moved into the detect function.

Additionally, a helpful error message is displayed upon use of a missing tool:
Makefile:204: *** failed to locate llvm-blah at any of: llvm-build/bin/llvm-blah llvm-blah-13 llvm-blah-12 llvm-blah-11 llvm-blah.  Stop.
2022-01-18 20:37:29 +01:00
Nia Waldvogel 7c3a22d289 wasmtest: fix resource cleanup and add logging
The chromedp context was not cancelled, so resources may have been leaking.
Additionally this waits for the browser to start before the timer starts, and extends the timeout to 20 seconds.
Logging from chromedp has also been enabled, which may help identify possible issues?
2022-01-18 19:29:29 +01:00
Dan Kegel 2c7ea98ccf runtime: add stubs for Func.FileLine and Frame.PC
With this, 'tinygo test' in github.com/pkg/errors at least compiles and passes a few tests:

    $ git clone github.com/pkg/errors
    $ cd errors
    $ tinygo test -c
    $ for a in $(go test -list Test | grep Test); do ./errors.test -test.run $a -test.v  > $a.log 2>&1; done
    $ grep -l PASS *.log | wc -l
      19
    $ grep -l FAIL *.log | wc -l
      11

For https://github.com/tinygo-org/tinygo/issues/2445
2022-01-18 14:38:13 +01:00
Dan Kegel 57b8f7e667 os: implement os.Symlink and os.Readlink 2022-01-18 12:36:33 +01:00
Dan Kegel db0efc52c7 os: implement os.ExpandEnv 2022-01-18 10:12:40 +01:00
Dan Kegel 94b075e423 .github: test-linux-build: install wasmtime, make tinygo-test-wasi-fast 2022-01-18 08:18:13 +01:00
Dan Kegel ce5d52870f Makefile: tinygo-test: move slow tests to end, add -fast target to skip them 2022-01-18 08:18:13 +01:00
Dan Kegel dd6adcacb6 testing: --run now allows filtering of subtests
Also fix typo in error message in sub_test.go from upstream,
and move a few members from B to common where they belonged.

Note that testdata/testing.go seems to be pushing the edge of what
the emulated cortex-m3 target can handle; using regexp in that test
causes it to fail on that target with an out of memory error.

TODO: once tinygo supports runtime.Goexit, consider just using upstream's testing directory...
2022-01-17 21:54:20 +01:00
Dan Kegel 610a20c4d5 testing.go: hoist runTests() out of Run() to match upstream a bit better
Only trivial functional changes:
- gets rid of mistaken extra "no tests" warning (whoops)
- matches upstream's exit code better

In preparation for switching to fancy test filtering.
2022-01-17 21:54:20 +01:00
Pure White daf5d0b63a fix: makefile on macOS (#2535)
* fix: makefile on macOS
2022-01-17 19:32:36 +01:00
Damian Gryski 233f5c6af2 main: replace {root} for compiler tests too 2022-01-17 18:15:09 +01:00
Damian Gryski ca2f25ed48 compileopts: move {root} replacement to compileopts.Emulator() 2022-01-17 18:15:09 +01:00
Yurii Soldak cc1a95a489 nrf: fix race in i2c 2022-01-17 16:19:16 +01:00
Nia Waldvogel 431e223803 main (test): skip AVR tests
The AVR tests fail inconsistently now due to non-deterministic backend bugs.
This disables them until this can be understood and fixed.
2022-01-16 22:02:30 +01:00
deadprogram 1b46324456 testL update chromedp to v0.7.6 for stability
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-16 15:23:37 -05:00
Nia Waldvogel 751ac85488 ci (Windows/Mac): use binaryen from scoop/brew
The scoop and brew package managers now bundle up-to-date copies of binaryen.
As a result, there is no longer a strong need for us to build and package our own copy.
2022-01-15 22:46:20 +01:00
deadprogram 512fb1dae6 docs: update CI badges for GH actions, and correct count of supported boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-15 19:03:15 +01:00
Damian Gryski 0d20afa85f Makefile: add compress/flate and compress/zlib to wasi test packages 2022-01-15 17:29:33 +01:00
Damian Gryski c87bb0e9cc pass more --dirs to wasmtime so it can read the entire module tree
This allows compress/flate to pass on -target=wasi out of the box

Fixes #2367
2022-01-15 17:29:33 +01:00
Nia Waldvogel 6afceb5621 os (wasi): fix opening files in read-only mode
On wasi, O_RDWR is a bitwise or of read and write mode.
As a result, the bit test result was incorrect, and rewrote it to read-write mode.
However, the bit tests are not necessary (and upstream Go does not use them).
This passes the flags through directly.
2022-01-15 10:26:19 -05:00
Nia Waldvogel aa053b5fb0 interp: always run atomic and volatile loads/stores at runtime 2022-01-15 14:40:14 +01:00
Dan Kegel 0ed34e3cb0 testing: print duration
TODO: account for time taken in Cleanup().
2022-01-15 10:38:22 +01:00
Dan Kegel 78a36f7724 testing: nudge functions closer to upstream order, to make diffing easier. No functional change. 2022-01-15 10:38:22 +01:00
Nia Waldvogel a743580734 main (test): reorganize runTestWithConfig
This change updates the test runner to use exec.CommandContext for timeout handling.
The timeout has been raised to 1 minute to handle slow machines and (hopefully) Windows.
The test run also now acquires the semaphore to reserve CPU time for the test and (hopefully?????) reduce the number of timeouts in Windows CI.
2022-01-14 14:09:37 -05:00
Nia Waldvogel e2178ce682 compiler: work around AVR atomics bugs
The AVR backend has several critical atomics bugs.
This change invokes libcalls for all atomic operations on AVR.
Now `testdata/atomic.go` compiles and runs correctly.
2022-01-14 13:49:20 +01:00
Elliott Sales de Andrade b2ef7299b7 arm: Explicitly disable unwind tables
Some clang builds (e.g., Fedora's) enable unwind tables by default. As
tinygo does not need nor support them, that leads to undefined symbols
when linking.
2022-01-14 07:34:36 +01:00
Kenneth Bell 14ce531498 stm32: add blues wireless swan 2022-01-13 07:56:08 +01:00
Dan Kegel 21c76c0cb0 testing: benchmarks: implement -benchtime flag 2022-01-12 21:49:27 +01:00
Dan Kegel fbd72a4b2c testing: benchmarks: -bench: allow filtering subbenchmarks
Pull in testing/match.go verbatim from upstream and use it to filter benchmarks.

TODO: also update testing.go to filter tests similarly.
2022-01-12 21:49:27 +01:00
Pure White 93e0636c03 feat: support build on darwin arm64 (#2439)
main: support build on darwin arm64
2022-01-12 12:10:08 +01:00
Dan Kegel ef77b645b9 testing: implement testing.Cleanup
Also reorder and regroup common's fields slightly to match upstream.

TODO: pull in more upstream tests once this package is goroutine-safe
2022-01-12 08:59:09 +01:00
Dan Kegel 0b939f93bc testing: gather duplicate code into tRunner
No change in behavior, just preparing for next commit, and gently nudging code closer to upstream.
2022-01-12 08:59:09 +01:00
Dan Kegel 798085e866 testdata/testing.go: update so it can be run with go 1.16 for comparison 2022-01-12 08:59:09 +01:00
Dan Kegel 69bf6e3c89 interp: show breadcrumbs to help developer find slow init functions; raise timeout. 2022-01-11 22:09:15 +01:00
Elliott Sales de Andrade 8f8d83bffe Run go mod tidy 2022-01-11 16:09:45 +01:00
Dan Kegel 998f01608c os: implement file.Seek, add smoke test 2022-01-11 14:23:14 +01:00
Cameron Eagans 84279ab2ec Add JSON output to info command (#2501)
main: Add json output flag to tinygo info
2022-01-11 13:02:58 +01:00
Dan Kegel a888d6245d testing: replace spaces with underscores in test/benchmark names, as upstream does 2022-01-11 11:53:24 +01:00
Dan Kegel f80efa5b8b testing: support b.SetBytes(); implement sub-benchmarks. 2022-01-11 11:53:24 +01:00
Dan Kegel 29f7ebc63e os: pull in os.Rename and some of its tests from upstream
Skip part of the test on Windows because of https://github.com/tinygo-org/tinygo/issues/2480

TODO: fix 2480 and unskip test
TODO: pull in rest of upstream tests, fix problems they find

Requested in https://github.com/tinygo-org/tinygo/issues/2109
2022-01-11 09:58:38 +01:00
deadprogram 72e15af1fa ci: use GH action to perform build for macos
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-01-10 22:50:52 +01:00
sago35 6cb604c752 board: add M5Stamp C3 2022-01-10 11:10:06 +01:00
Nia Waldvogel cb01d4d63e builder (env): update clang header search path to look in /usr/lib
Arch Linux stores the clang executable seperately from its data, so the search based on the executable does not work.
This change searches /usr/lib as a backup.
2022-01-09 18:46:15 +01:00
Nia Waldvogel fe21650010 builder (musl): add -fno-stack-protector
Arch Linux has turned on the stack protector by default.
This causes a crash in libc init because the stack protector uses TLS before it is initialized.
2022-01-09 18:46:15 +01:00
Ayke van Laethem ebd4969cde all: switch to LLVM 13
This adds support for building with `-tags=llvm13` and switches to LLVM
13 for tinygo binaries that are statically linked against LLVM.

Some notes on this commit:

  * Added `-mfloat-abi=soft` to all Cortex-M targets because otherwise
    nrfx would complain that floating point was enabled on Cortex-M0.
    That's not the case, but with `-mfloat-abi=soft` the `__SOFTFP__`
    macro is defined which silences this warning.
    See: https://reviews.llvm.org/D100372
  * Changed from `--sysroot=<root>` to `-nostdlib -isystem <root>` for
    musl because with Clang 13, even with `--sysroot` some system
    libraries are used which we don't want.
  * Changed all `-Xclang -internal-isystem -Xclang` to simply
    `-isystem`, for consistency with the above change. It appears to
    have the same effect.
  * Moved WebAssembly function declarations to the top of the file in
    task_asyncify_wasm.S because (apparently) the assembler has become
    more strict.
2022-01-09 11:04:10 +01:00
Ayke van Laethem 32a7b8cc4e avr: use a stack size of 512 bytes for testing
The goroutine tests are failing with the default 256 byte stack size.
2022-01-09 11:04:10 +01:00
Dan Kegel b4fa658705 .github: asset-test-linux: show cpuinfo for troubleshooting. 2022-01-07 10:39:30 +01:00
Dan Kegel ee4e42ba1f src/testing: support -bench option to run benchmarks matching the given pattern. 2022-01-07 10:39:30 +01:00
Dan Kegel c6678525a9 src/testing/benchmark.go: reorder functions to make diffing against go easier
On the theory that tinygo is tending towards smaller diffs with go...

Also adds placeholder for ReportAllocs(), otherwise zero semantic changes.
2022-01-07 10:39:30 +01:00
Dan Kegel 8d75b58bdf .github: update apt before installing, in case it is stale
Symptom: assert-test-linux failed in https://github.com/tinygo-org/tinygo/runs/4721983373
with following errors:

E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/main/c/ceph/librados2_15.2.14-0ubuntu0.20.04.1_amd64.deb  404  Not Found [IP: 52.154.174.208 80]
E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/main/c/ceph/librbd1_15.2.14-0ubuntu0.20.04.1_amd64.deb  404  Not Found [IP: 52.154.174.208 80]
E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/main/q/qemu/qemu-block-extra_4.2-3ubuntu6.18_amd64.deb  404  Not Found [IP: 52.154.174.208 80]
E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/main/q/qemu/qemu-system-common_4.2-3ubuntu6.18_amd64.deb  404  Not Found [IP: 52.154.174.208 80]
E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/main/q/qemu/qemu-system-data_4.2-3ubuntu6.18_all.deb  404  Not Found [IP: 52.154.174.208 80]
E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/main/q/qemu/qemu-system-arm_4.2-3ubuntu6.18_amd64.deb  404  Not Found [IP: 52.154.174.208 80]
E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/main/q/qemu/qemu-system-misc_4.2-3ubuntu6.18_amd64.deb  404  Not Found [IP: 52.154.174.208 80]
E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/universe/q/qemu/qemu-user_4.2-3ubuntu6.18_amd64.deb  404  Not Found [IP: 52.154.174.208 80]
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

This usually means those packages have been updated and you have to run apt-get update first, as recommended at
https://github.com/actions/virtual-environments/issues/1757
2022-01-06 16:29:53 +01:00
Dan Kegel ec97313239 When running tests under wasmtime, provide a fresh TMPDIR.
Also fix a couple os tests that wrote to current directory to write to os.TempDir() instead.

After this, os tests pass in wasi, so add them to the list run by "make tinygo-test-wasi".
2022-01-04 21:43:38 +01:00
Kenneth Bell e046b23773 stm32l552ze: use supported stlink interface 2022-01-04 20:27:41 +01:00
Kenneth Bell 0099d47002 all: show error if platform has no rng 2022-01-04 20:27:41 +01:00
Kenneth Bell 5c3ad004ab stm32: add more MCUs with h/w RNG 2022-01-04 20:27:41 +01:00
Dan Kegel 61be9189f1 os: add a few upstream tests for Read and ReadAt, fix problems they exposed.
There are more upstream tests to pull in, but this is plenty for today.
2022-01-04 15:45:49 +01:00
Damian Gryski 1e2791b216 src/os: loop in File.ReadAt to handle short reads
This matches what upstream Go does.  This also means len(b) == 0 successfully
reads 0 bytes without any extra logic.  The tests in archive/zip test for this
behaviour.
2022-01-04 15:45:49 +01:00
Nia Waldvogel d86dd642b3 main (test): add tests to tinygo test 2022-01-03 18:59:19 -05:00
Ayke van Laethem 21b89ef327 compiler: fix emission of large object layouts
Large object layouts don't fit in a pointer-sized integer and therefore
need to be stored in a global instead. However, the way the data was
stored in these globals was not correct for buffers that don't have
pointers near the end. This commit fixes this issue by using math/big
FillBytes() instead of Bytes().

This gets the unicode package to compile on AVR.
2022-01-03 21:22:49 +01:00
Ayke van Laethem 39c8711332 compiler: add correct debug location to init instructions
This adds proper debug locations to interp errors. For example, when
trying to use the unicode package on AVR (which currently doesn't work),
the following error is shown with this commit:

    /usr/local/go1.17/src/unicode/casetables.go:13:31: interp: ptrtoint integer size does not equal pointer size

Before this commit, that error was a lot less helpful:

    unicode/<init>:13:31: interp: ptrtoint integer size does not equal pointer size
2022-01-03 17:58:02 +01:00
Nia Waldvogel edc9319e0d main (tinygo test): fail tests on build error
This fixes a bug where build errors (e.g. linker errors) would be ignored by tinygo test.
2022-01-03 10:12:14 -05:00
Ayke van Laethem fcd88356db avr: fix time.Sleep() in init code
In the early days of TinyGo, the idea of `postinit` was to enable
interrupts only after initializers have run. Which kind of makes
sense... except that `time.Sleep` is allowed in init code and
`time.Sleep` requires interrupts to be enabled. Therefore, interrupts
must be enabled while initializers are being run.

This commit simply moves the enabling of interrupts to a point right
before running package initializers. It also removes `runtime.postinit`,
which is not necessary anymore (and was only used on AVR).
2022-01-02 19:41:44 +01:00
Nia e536676a67 main (test): run tests on AVR 2022-01-01 15:58:03 +01:00
Tobias Theel 342c438586 remove multi core support non-goal 2022-01-01 00:17:51 -05:00
sago35 6b7ecf1f52 readme: unify the notation of micros with tinygo.org 2021-12-31 16:44:45 +01:00
Elias Naur bd7ab8ddd5 targets,runtime,machine: add support for the stm32f469-disco board
The LEDs and button work; I haven't tested the SPI and I2C
configuration.
2021-12-31 10:30:48 +00:00
Elias Naur 302e72e84f machine: add PG* and PK* pins
They're used for LEDs on the STM32F469-Discovery board.
2021-12-31 10:30:48 +00:00
Elias Naur 55ca5287fe runtime: separate runtime initialization for STM32F4 boards
The STM32F469 can use the same initialization as the existing STM32F407
with a few frequency tweaks. This change splits the generic
initialization code into a separate runtime_stm32f4.go file, leaving
only the 407 board specific constants in the existing
runtime_stm32f407.go file.

Note that runtime_stm32f405.go initialization seems semantically similar
to the 407, but I don't have enough confidence in merging 405 with 407
in this change.
2021-12-31 10:30:48 +00:00
Elias Naur 11ee0969b6 machine: merge stm32f405/407
They're no longer functionally different.
2021-12-31 10:30:48 +00:00
Elias Naur 81dbbc89d3 machine: make machine_stm32f407.go equivalent to machine_stm32f405.go
The only differences are a more general SPI.getBaudRate and a different
frequency limit in I2C.getFreqRange.

This is a first step towards adding stm32f469 support: a follow-up
merges machine_stm32f407.go and machine_stm32f405.go, another adds
frequency tweaks for stm32f469.
2021-12-31 10:30:48 +00:00
Nia Waldvogel a4f9e5e552 targets (wasi/wasm): raise default stack size to 16 KiB
In some cases, 8 KiB is not enough for both the C stack and the asyncify stack.
This gets the compress/zlib tests to fail without crashing.
2021-12-30 12:20:04 -05:00
Nia Waldvogel f9f2349850 tinygo test: simplify output buffering 2021-12-30 12:03:12 -05:00
Nia Waldvogel f1b15db258 main (tinygo test): reduce memory use when compiling a large number of packages
This change adds an additional semaphore to tinygo test that limits the number of tests being processed simultaneously (in addition to the existing limit on build jobs and runs).
When running a large number of tests, this limits the number of copies of per-test data stored in memory (avoiding an OOM in CI).
2021-12-30 12:03:12 -05:00
Nia Waldvogel 12e314ccc9 main (tinygo test): build and run tests in concurrently 2021-12-30 12:03:12 -05:00
Nia Waldvogel e594dbc133 builder: refactor job runner and use a shared semaphore across build jobs
Switching to a shared semaphore allows multi-build operations (compiler tests, package tests, etc.) to use the expected degree of parallelism efficiently.

While refactoring the job runner, the time complexity was also reduced from O(n^2) to O(n+m) (where n is the number of jobs, and m is the number of dependencies).
2021-12-30 12:03:12 -05:00
Nia Waldvogel bb08a25edc main (test): remove global build lock 2021-12-30 12:03:12 -05:00
sago35 b7b7713526 docker: update Dockerfile for xtensa-esp32-elf-ld 2021-12-30 15:50:43 +01:00
Dmitriy 92150bd1c5 Interrupt based time. Adjust tick cost when timer-0 is reconfigured (the time precision affected when timer-0 reconfigured). Keep all time in nanoseconds.
Interrupt based time. Adjust tick cost every 1 minute and when timer-0 is reconfigured (the time precision affected when timer-0 reconfigured). Keep all time in nanoseconds.
2021-12-30 11:39:28 +01:00
Kenneth Bell d0633f6228 all: go-llvm that defaults to llvm-12 2021-12-29 16:53:25 +01:00
Arsen Musayelyan d46933abf2 Use os.Stat instead of os.ReadDir as that was added in 1.16 2021-12-29 12:05:51 +01:00
Arsen Musayelyan 26625f5a22 Check for /run/media on Linux for non-debian-based distros 2021-12-29 12:05:51 +01:00
Ayke van Laethem 3e109fca5f builder: use build ID as cache key
Instead of storing an increasing version number in relevant packages
(compiler.Version, interp.Version, cgo.Version, ...), read the build ID
from the currently running executable. This has several benefits:

  * All changes relevant to the compiled packages are caught.
  * No need to bump the version for each change to these packages.
    This avoids merge conflicts.
  * During development, `go install` is enough. No need to run
    `tinygo clean` all the time.

Of course, the drawback is that it might be updated a bit more often
than necessary but I think the overall benefit is big.

Regular release users shouldn't see any difference. Because the tinygo
binary stays the same, the cache works well.
2021-12-28 18:29:05 -05:00
Nia Waldvogel 763a86cd8e loader: elminate goroot cache inconsistency
This change breaks the merged goroot creation process into 2 steps:
1. List all overrides
2. Construct a goroot with the specified overrides

Now step 2 is cached using a hash of the results from step 1.
This eliminates cache inconsistency, but means that step 1 needs to be run on every build.
This is relatively acceptable, as step 1 only takes about 3 ms (assuming the directory tree is in the OS filesystem cache).
2021-12-28 18:01:15 -05:00
Nia Waldvogel 13a3c4b155 Makefile: update tool search for LLVM 12 2021-12-28 17:33:22 -05:00
Nia Waldvogel 9fa667ce63 rumtime: implement __sync libcalls as critical sections
This change implements __sync atomic polyfill libcalls by disabling interrupts.
This was previously done in a limited capacity on some targets, but this change uses a go:generate to emit all of the calls on all microcontroller targets.
2021-12-28 22:12:03 +01:00
kenbell 8bd39d2fc2 Merge pull request #2427 from eliasnaur/remove-arrtype
Remove unused arrtype from package runtime
2021-12-28 19:18:35 +00:00
Nia Waldvogel c685e0696a os: add Perm stub on Go 1.15
This adds a stub for Perm on Go 1.15, which allows the OS package to compile again.
2021-12-26 16:04:19 -05:00
Nia Waldvogel 9db8826b3b interp: run goroutine starts and checks at runtime
This change prevents interp from trying to execute goroutine starts or checks.
This fixes a bug where a goroutine started by an init function would run before the init function.
2021-12-24 09:10:21 +01:00
Dan Kegel 0aed62efe4 Makefile: add tinygo-test-wasi; like tinygo-test but with -target wasi 2021-12-24 01:20:59 +01:00
Olivier Fauchon 2b1a72d112 stm32wlx: I2C implementation for gnse,lora-e5,nucleo-wl55jc boards 2021-12-23 23:45:28 +01:00
Elias Naur a6837f05a4 runtime: remove unused arrtype type aliases
The arrtype aliases are used in the machine package.
2021-12-23 22:07:49 +01:00
Dmitriy c35ce761aa Merge duplicate registers into a single record and merge they bitfields. 2021-12-23 15:14:06 +01:00
Dmitriy d2963b153e Add *_Msk for each bit field and avoid duplicate fields in the output file 2021-12-23 15:14:06 +01:00
Nia Waldvogel f9293645af builder: use flock to avoid double-compiles
This change uses flock (when available) to acquire locks for build operations.
This allows multiple tinygo processes to run concurrently without building the same thing twice.
2021-12-23 08:28:08 +01:00
Nia Waldvogel 38305399a3 sync: add tests 2021-12-22 11:02:45 +01:00
deadprogram 8f2082df69 docker: remove only subdirectories (which are updated as submodules) from lib to keep picolibc file in its correct place
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-22 08:06:28 +01:00
deadprogram da8eb521e1 build: update XCode version for CircleCI builds to 11.4.1 due to deprecations
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-21 19:01:19 +01:00
deadprogram dc53a59c49 docker: have to copy build results to GOPATH at the very end of docker build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-20 13:36:08 -05:00
Nia Waldvogel f21fdd1f76 sync: add a package doc 2021-12-20 13:35:57 -05:00
Nia Waldvogel 5e719b0d3d sync: fix concurrent read-lock on write-locked RWMutex
This bug can be triggered by the following series of events:
A acquires a write lock
B starts waiting for a read lock
C starts waiting for a read lock
A releases the write lock

After this, both B and C are supposed to be resumed as a read-lock is available.
However, with the previous implementation, only C would be resumed immediately.
Other goroutines could immediately acquire the read lock, but B would not be resumed until C released the read lock.
2021-12-20 13:35:57 -05:00
Damian Gryski 9eb13884de compileopts,targets: replace '{root}' in target files 2021-12-20 13:13:32 -05:00
Damian Gryski 85031d6df7 tinygo: set cmd.Dir even when running emulators
This allows compress/bzip2 to pass with -target=wasi

Fixes #2367
2021-12-20 13:13:32 -05:00
Alan Wang 58b44f9f17 Update board_microbit-v2.go 2021-12-18 14:03:19 +01:00
Damian Gryski c0ea21ece7 src/reflect: add test for indirect array indexing 2021-12-18 10:02:36 +01:00
Damian Gryski 81edf577a3 src/reflect: add test for indirect pointer fix 2021-12-18 10:02:36 +01:00
Damian Gryski 484bb8f13d src/reflect: fix stripPrefix comment 2021-12-18 10:02:36 +01:00
Damian Gryski ae1e7731a4 src/reflect: comment out a now-failing test
Keys() is unimplemented, which is required to compare
these two maps.
2021-12-18 10:02:36 +01:00
Damian Gryski 518745ea79 src/reflect: make sure indirect pointers are handled correctly
Fixes #2370
Fixes #2323
2021-12-18 10:02:36 +01:00
Damian Gryski 38b14706e2 internal/task: fix two missed instances of extalloc 2021-12-17 17:36:49 -05:00
Nia Waldvogel 747336f0a9 runtime: remove extalloc
The extalloc collector has been broken for a while, and it doesn't seem reasonable to fix right now.
In addition, after a recent change it no longer compiles.
In the future similar functionality can hopefully be reintroduced, but for now this seems to be the most reasonable option.
2021-12-17 18:15:18 +01:00
Nia Waldvogel e4de7b4957 internal/task: swap stack chain when switching goroutines
This change swaps the stack chain when switching goroutines, ensuring that the chain is maintained consistently.
This is only really currently necessary with asyncify on wasm.
2021-12-17 10:01:11 +01:00
Nia Waldvogel d5c0083085 builder: handle concurrent library header rename
When a library is built concurrently by multiple TinyGo processes, they may sometimes both build the headers.
In that case a directory rename may fail due to conflict.
This change detects and handles the conflict similar to how GOROOT construction does.
2021-12-17 09:33:28 +01:00
Nia Waldvogel e6fbad13c6 runtime (gc): correct scan bounds
This fixes 2 bugs in the GC scan bounds:
1. On AVR, the GC could sometimes read one byte past the end of a block due to the difference between pointer size and alignment.
2. On WASM, the linker does not properly align the marker for the end of the globals section. A manual alignment operation has been added to markGlobals to work around this.
2021-12-17 09:26:44 +01:00
Dan Kegel 62bda8e129 os: os_chmod_test.go: fix copyright 2021-12-16 16:36:53 -05:00
Dan Kegel 51d6ffb3be os: Chmod: don't test on wasi yet, wasi-libc does not yet support it
Lets "tinygo test -target wasi os" compile, if not pass.

For https://github.com/tinygo-org/tinygo/issues/2369
2021-12-16 16:36:53 -05:00
deadprogram 964aa7058a build: use GHA cache and dockerx for docker dev build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-15 19:26:32 +01:00
deadprogram 0f9d2ac0e4 docker: update Dockerfile for dev build for LLVM 12 changes
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-15 19:26:32 +01:00
deadprogram 5264469cbd machine/stm32wl: unify implementation for RNG for stm32wl with other STM32 processors
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-15 18:33:41 +01:00
Nia Waldvogel c096f35224 runtime: handle negative sleep times
This change fixes the edge case where a negative sleep time is provided.
When this happens, the call now returns immediately (as specified by the docs for time.Sleep).
2021-12-15 17:52:48 +01:00
Dan Kegel 929cd767c1 os/path_windows_test.go: don't fail on Wine, which allows dots for cur dir even in extended length paths 2021-12-15 12:23:28 +01:00
deadprogram e1df2510d4 machine/stm32f4, stm32f7, stm32l4: implement TRNG for randomness
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-15 11:38:40 +01:00
deadprogram 2ebaa9f520 machine/samd51: implement TRNG for randomness
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-14 14:55:19 +01:00
deadprogram 5159eab694 examples: add example to exercise random number generation
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-14 14:55:19 +01:00
Dan Kegel 75dfb26452 os: skip TestMkdirTempBadDir on windows until TestStatBadDir passes 2021-12-14 09:25:27 +01:00
Dan Kegel 971da0bc09 os: implement and test os.MkdirTemp 2021-12-14 09:25:27 +01:00
Dan Kegel 0420842f4d os: skip TestStatBadPath on windows for now
I'm not up enough on how syscall errors work on windows to figure this out yet.
2021-12-14 09:25:27 +01:00
Dan Kegel d30f8b6ed6 os.Stat: returned error on nonexistent path did not satisfy IsNotExist
Add direct test for the problem to make the fix commit clearer.

Noticed while implementing MkdirTemp on mac; the upstream tests for MkdirTemp fail without this.
2021-12-14 09:25:27 +01:00
Dan Kegel 1f6b4a5e7b os_test.go: use CreateTemp now that it is implemented 2021-12-14 09:25:27 +01:00
Dan Kegel 51fc78c100 os: implement and smoketest os.Clearenv 2021-12-13 23:05:17 +01:00
Dan Kegel e4f2b9c003 os: implement and smoketest os.Unsetenv 2021-12-13 23:05:17 +01:00
Dan Kegel cff4493ca0 os: implement and smoketest os.Setenv 2021-12-13 23:05:17 +01:00
Olivier Fauchon 93ac7cec0d stm32/stm32wlx: Add support for stm32wl55_cm4
board/stm32: Add support for GNSE (Generic Node Sensor Edition)

 Thanks to @jamestait for his help on GNSE port
2021-12-13 16:02:00 +01:00
Olivier Fauchon b4503c1e37 stm32wl: STM32WL TRNG implementation in crypto/rand 2021-12-11 12:25:08 +01:00
Ayke van Laethem 3e6410f323 interp: work around AVR function pointers in globals
Not sure how to test this, since we don't really have any AVR tests
configured.
2021-12-11 11:24:19 +01:00
Rouven Broszeit 0f69d016a0 Added realloc implementation to GCs
When using the latest wasi-libc I experienced a
panic on an attempt to call realloc. My first attempt to
add it to arch_tinygowasm.go was obviously not good (PR #2194). So here
is another suggestion.
2021-12-10 17:51:08 +01:00
Ayke van Laethem ef8c1a187d transform: allocate the correct amount of bytes in an alloca
When I wrote the code originally, I didn't know about SetAlignment so I
hacked a way around it by allocating [...]uintptr types. However, this
allocates a few too many bytes in some cases.
This commit changes this to only allocate the space that we actually
need.

The code size effect is mixed, but generally positive. The combined
average is reduced by 0.27% with more programs being reduced in size
than are increasing in size.
2021-12-10 10:48:24 +01:00
Federico G. Schwindt 08d0dc0d25 Enable Getwd() in wasi and add tests 2021-12-10 09:50:38 +01:00
Dan Kegel 039186a2a3 src/os/stat.go: get build tags right, maybe
Should fix https://github.com/tinygo-org/tinygo/issues/2354

Untested with wasi
2021-12-09 22:14:29 +01:00
Damian Gryski d6c892fe7b src/runtime: fix nil map dereference
Operations on nil maps are accepted and shouldn't
panic. The base hashmapGet/hashmapDelete handled
nil-maps correctly, but the hashmapBinary versions
could segfault accessing the nil map while trying
to hash the key.

Fixes #2341
2021-12-09 18:23:49 +01:00
Federico G. Schwindt cfe6b9765f Test net.Buffers{} 2021-12-09 14:35:52 +01:00
Federico G. Schwindt 539495ef45 Add net.Buffers
Should fix https://github.com/mailru/easyjson/issues/335, for the
most part.
2021-12-09 14:35:52 +01:00
Ayke van Laethem b13c993565 compiler: fix ranging over maps with particular map types
Some map keys are hard to compare, such as floats. They are stored as if
the map keys are of interface type instead of the key type itself. This
makes working with them in the runtime package easier: they are compared
as regular interfaces.

Iterating over maps didn't care about this special case though. It just
returns the key, value pair as it is stored in the map. This is buggy,
and this commit fixes this bug.
2021-12-09 00:14:20 +01:00
Ayke van Laethem 449bfe04f3 compiler: move *ssa.Next lowering for maps to compiler/map.go
This moves it to the most logical place, as a preparation to fixing a
bug in the next commit.
2021-12-09 00:14:20 +01:00
Damian Gryski 1903cf23c9 src/runtime: improve float/complex hashing
This allows positive and negative zero to hash to the same value,
as required by Go.

This is not perfect, but the best I could do without
revamping all the hash funtions to take a seed.

Fixes #2356
2021-12-08 22:38:22 +01:00
deadprogram 9734f349a3 net/interface: use internal implementation for itoa.Uitoa
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-08 14:43:45 +01:00
soypat d87ff838eb net: add bare Interface implementation 2021-12-08 12:34:08 +01:00
Damian Gryski a360c82b40 src/runtime: strengthen hash function for structs and arrays
Using `|` to combine hash values will slowly turn every bit on.
Hashes combined with `^` with keep more entropy.
2021-12-08 10:33:35 +01:00
deadprogram 4a2faeb2c5 machine/stm32f103: initial implementation on ADC interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-07 20:12:23 +01:00
deadprogram 99f00d396d machine/bluepill: add definitions for ADC pins
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-07 20:12:23 +01:00
deadprogram 049c5ed3b1 machine/stm32f4: initial implementation for ADC interface
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-07 20:12:23 +01:00
deadprogram cce02cd046 machine/stm32f4disco: add definitions for ADC pins
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-12-07 20:12:23 +01:00
Dan Kegel be7bbba4ca os: implement and smoketest os.Chmod 2021-12-07 10:54:02 +01:00
Dan Kegel e668c8c1a7 os: implement and smoketest os.Chdir 2021-12-07 10:54:02 +01:00
Dan Kegel d62c9696fb os_unix_test.go: rename to os_anyos_test.go, add windows build tag
Also remove now-unsupported freebsd build tag.
2021-12-06 21:56:41 +01:00
Damian Gryski 343146f35c src/testing: stub b.RunParallel() and PB.Next() 2021-12-06 20:09:36 +01:00
sago35 0285171484 main: improve help 2021-12-03 16:14:41 +01:00
Dan Kegel 1a22d92217 os: remove as-yet unused function splitPath 2021-12-03 09:38:40 +01:00
Dan Kegel 8416bb61d8 os: implement MkdirAll 2021-12-03 09:38:40 +01:00
Damian Gryski 85ad157f3f src/os: fix build tags for non-windows PathSeparator 2021-12-01 18:39:37 +01:00
Dan Kegel b123ffcea4 os: implement CreateTemp
Until tinygo implements fastrand(), use a placeholder RNG here.
2021-12-01 12:53:04 +01:00
Dan Kegel ec9fd3fb38 os, syscall: implement Stat and Lstat
File.Stat is left as a stub for now.

Tests are a bit stubbed down because os.ReadDir, os.Symlink, and t.TempDir are not yet (fully) implemented.
TODO: reimport tests from upstream as those materialize.
2021-12-01 00:23:23 +01:00
Ayke van Laethem 5127b9d65b all: add LLVM 12 support
Originally based on a PR by @QuLogic, but extended a lot to get all
tests to pass.
2021-11-30 21:53:16 +01:00
Ayke van Laethem 74b20ca234 runtime: use LLVM intrinsic to read the stack pointer
This should result in smaller code.
2021-11-30 10:01:44 +01:00
Ayke van Laethem 3d73ee77d3 machine: add Device constant
This field contains the microcontroller name that we're compiling for,
or "generic" if we're not running on a microcontroller.
2021-11-30 00:47:11 +01:00
Dan Kegel 6b0f2cd697 os: TempDir(): obey TMPDIR on unix, TMP on win, etc
Uses upstream go code, lightly adjusted.

Adds smoke test.
2021-11-30 00:10:09 +01:00
Dan Kegel e354a3523b os.Remove: avoid double-wrapping err; fixes TODO in test 2021-11-29 20:49:28 +01:00
Dan Kegel f79f6b0e62 os, syscall: implement ReadAt for unix
Windows will take more work, so test is skipped there.
2021-11-29 20:13:29 +01:00
Damian Gryski 47db50b273 os: add a stub for File.Truncate 2021-11-26 18:53:27 +01:00
Olivier Fauchon b0fce80b50 Improvements for stm32wle targets :
- board/stm32: Add STM32 Nucleo WL55JC board
- stm32/stm32wl: Set 48Mhz HSE32/PLL as default Clock, SPI implementation
2021-11-26 14:15:11 +01:00
Ayke van Laethem 718746dd21 os: stub out support for some more features
This is necessary for the following:

  - to make sure os/exec can be imported
  - to make sure internal/testenv can be imported

The internal/testenv package (which imports os/exec) is used by a lot of
tests. By adding support for it, more tests can be run.

This commit adds a bunch of new packages that now pass all tests.
2021-11-26 08:05:35 +01:00
Kenneth Bell 6cbaed75c8 stm32: fix timeout for i2c comms
ticks changed to 16ns causing timeouts to be very, very short.  This change updates timeouts for 16ns ticks.
2021-11-26 00:38:00 +01:00
Kenneth Bell a6200920f7 stm32: pull-up on I2C lines
fixes #2310
2021-11-24 23:57:46 +01:00
Ayke van Laethem 79467baf12 all: remove FreeBSD support
FreeBSD support has been broken for a long time, probably since
https://github.com/tinygo-org/tinygo/pull/1860 (merged in May). Nobody
has complained yet, so I am going to assume nobody uses it.

This doesn't remove support for FreeBSD entirely: the code necessary to
build TinyGo on FreeBSD is still there. It just removes the code
necessary to build binaries targetting FreeBSD. But again, it could very
well be broken as we don't test it.

If anybody wants to re-enable support for FreeBSD, they would be welcome
to do that. But I think it would at the very least need a smoke test of
some sort.
2021-11-24 22:21:22 +01:00
Ayke van Laethem c31aef06ba cgo: add support for C.CString and related functions 2021-11-24 21:09:29 +01:00
Ayke van Laethem 6bd18af5ef cgo: simplify construction of in-memory AST
Instead of writing the entire AST by hand, write it in Go code and parse
it to create the base AST to build upon.
2021-11-24 21:09:29 +01:00
Ayke van Laethem 1789570f52 cgo: add //go: pragmas to generated functions and globals
This patch adds //go: pragmas directly to declared functions and
globals found during CGo processing. This simplifies the logic in the
compiler: it no longer has to consider special "C." prefixed function
names. It also makes the cgo pass more flexible in the pragmas it emits
for functions and global variables.
2021-11-24 21:09:29 +01:00
Damian Gryski a536ddcda8 tinygo: support -run for tests
Fixes #2294
2021-11-24 17:27:11 +01:00
Damian Gryski 18242bc26a runtime: allow comparing interfaces in reflectValueEqual() 2021-11-24 14:17:47 +01:00
Ayke van Laethem 18f4ffd656 ci: move Linux release builds to GitHub Actions 2021-11-24 13:00:15 +01:00
Ayke van Laethem 7238c0a16f ci: cache Go cache for faster build times 2021-11-22 19:43:03 +01:00
Ayke van Laethem c177e4dbc0 ci: move assert-test-linux to GitHub Actions 2021-11-21 12:17:34 +01:00
Ayke van Laethem 1d2c17753a tests: improve wasm tests slightly
These wasm tests weren't passing in GitHub Actions and also weren't
passing on my laptop. I'm not sure why, I think there are a few race
conditions that are going on.

This commit attempts to fix this at least to a degree:

  - The context deadline is increased from 5 seconds to 10 seconds.
  - The tests are not running in parallel anymore.
  - Some `Sleep` calls were removed, they do not appear to be necessary
    (and if they were, sleeping is the wrong solution to solve race
    conditions).

Overall the tests are taking a few seconds more, but on the other hand
they seem to be passing more reliable. At least for me, on my laptop
(and hopefully also in CI).
2021-11-21 12:17:34 +01:00
Kenneth Bell 470cbd5f53 housekeeping: wasm optional in smoketest and fix make clean 2021-11-20 13:30:50 -05:00
Kenneth Bell 62d4a6a77f stm32: add minimal stm32wlex5 / lorae5 target
credit to ofauchon
2021-11-20 12:07:11 +01:00
Dan Kegel 339301b709 os: Implement and smoke test Mkdir() and Remove() 2021-11-20 10:39:27 +01:00
Dan Kegel aea4f57a2b syscall: hoist cstring() out of two functions to reduce repetition and allocations 2021-11-20 10:39:27 +01:00
sago35 2a17a3e56c board: add M5Stack 2021-11-20 09:37:24 +01:00
Ayke van Laethem 34011c4800 targets: change LLVM features to match vanilla Clang
I mistakenly believed the difference was in LLVM version 11.0.0 vs LLVM
11.1.0. However, the difference is in whether we use the Debian version
of Clang.

The Debian version has had lots of patches. I'm not sure which is to
blame, but it could be this one:
https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/blob/snapshot/debian/patches/clang-arm-default-vfp3-on-armv7a.patch
2021-11-20 02:48:23 +01:00
Damian Gryski f8206b9bcc syscall: fix array size for mmap slice creation 2021-11-20 00:43:24 +01:00
Ayke van Laethem b01ce95cb5 ci: run stdlib tests on macos 2021-11-20 00:43:24 +01:00
Ayke van Laethem 0658e4896f syscall: add support for Mmap and Mprotect
This is necessary to run crypto/sha1 tests.
2021-11-20 00:43:24 +01:00
Damian Gryski 9d87d658ba testing: add a stub for CoverMode
This allows the strings package test to compile.
2021-11-20 00:36:42 +01:00
Ayke van Laethem ec95d3560f ci: fix Binaryen cache on Windows
The wrong path was used to cache binaryen, so it wasn't actually getting
cached. Therefore, wasm-opt was rebuilt on every new PR (slowing down
the "Build TinyGo release tarball" a lot).
2021-11-19 14:46:20 -05:00
Ayke van Laethem bf076aed61 ci: only build wasm-opt, don't build other Binaryen tools 2021-11-19 14:46:20 -05:00
Ayke van Laethem dee5602e56 builder: fix off-by-one in size calculation
> There are two hard things in computer science: cache invalidation,
> naming things, and off-by-one errors.

Because of this bug, sometimes the last object in a section might not be
attributed correctly to a source location.
2021-11-19 12:14:32 +01:00
Ayke van Laethem 4ef340f228 windows: add support for the -size= flag
Like WebAssembly, it misses information on strings and other anonymous
symbols. However, most code (.text) is covered.
2021-11-19 00:21:21 +01:00
Damian Gryski 843a7ac445 add asyncify to scheduler flag help 2021-11-18 18:09:48 -05:00
deadprogram 8ed7d197a7 docs: update CONTRIBUTING links to point to web site. Also replace Azure build badge with Windows build on GH Actions.
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-11-18 17:49:13 -05:00
Nia Waldvogel 39ce7111bd goenv: update version for start of 0.22.0 development cycle 2021-11-18 23:19:48 +01:00
Ayke van Laethem 06df31944c all: release v0.21.0 2021-11-18 14:20:59 +01:00
Damian Gryski 3ba8bc92cd testdata: update binop.go for string comparison tests 2021-11-18 11:07:45 +01:00
Damian Gryski 0e7a129de7 compiler: update testdata/string.ll
$ go test ./compiler -update
2021-11-18 11:07:45 +01:00
Damian Gryski aeddcd9c5f compiler: fix string compare functions
Before:
	x < x false
	x <= x true
	x == x true
	x >= x false
	x > x true

After:
	x < x false
	x <= x true
	x == x true
	x >= x true
	x > x false
2021-11-18 11:07:45 +01:00
Patricio Whittingslow bf0b05e32c machine/rp2040: refactor PWM code. fix Period calculation 2021-11-18 10:22:26 +01:00
Damian Gryski 348a02d697 src/runtime/debug: stub debug.Stack() 2021-11-17 19:25:52 +01:00
Damian Gryski 7273a2b5fd src/testing stub AllocsPerRun 2021-11-17 19:25:52 +01:00
Damian Gryski 44bb381220 src/runtime/debug: add SetMaxStack to allow compress/flate tests to build 2021-11-17 19:25:52 +01:00
Damian Gryski 2e6b92fc56 src/testing: add testing.Verbose() 2021-11-17 19:25:52 +01:00
Ayke van Laethem 51290e5842 wasm: support -scheduler=none
Previously, -scheduler=none wasn't possible for WASM targets:

    $ tinygo run -target=wasm -scheduler=none ./testdata/stdlib.go
    src/runtime/runtime_wasm_js.go:34:2: attempted to start a goroutine without a scheduler

With this commit, it works just fine:

    $ tinygo run -target=wasm -scheduler=none ./testdata/stdlib.go
    stdin:  /dev/stdin
    stdout: /dev/stdout
    stderr: /dev/stderr
    pseudorandom number: 1298498081
    strings.IndexByte: 2
    strings.Replace: An-example-string

Supporting `-scheduler=none` has some benefits:

  * it reduces file size a lot compared to having a scheduler
  * it allows JavaScript to call exported functions
2021-11-17 19:03:20 +01:00
Ayke van Laethem 22c35c8e31 ci: move all cross compilation tests to Linux
The idea here is as follows:
  - Run all Linux and cross compilation tests in the asser-test-linux
    job.
  - Only run native tests on MacOS and Windows.

This reduces testing time on MacOS and Windows, which are generally more
expensive in CI. Also, by not duplicating tests in Windows and MacOS we
can reduce overall CI usage a bit.

I've also changed the assert-test-linux job a bit to so that the tests
that are more likely to break and the tests that are only run in
assert-test-linux are run first.
2021-11-17 14:52:32 +01:00
Ayke van Laethem 2081380b5c ci: simplify build-linux job
Split building the release and smoke-testing the release in two, and
don't redo some tests that are already done by assert-test-linux.

Some benefits:
  - Lower overall CI time because tests aren't done multiple times.
  - TinyHCI can run earlier because the build-linux job is finished as
    soon as the build artifact is ready.

It does however have the downside of an extra job, which costs a few
seconds to spin up and a few seconds to push and pull the workspace. But
even with this, overall CI time is down by a few minutes per workflow
run.
2021-11-16 18:43:32 +01:00
Ayke van Laethem 3d0c6dd02d ci: simplify test-linux jobs
Instead of doing lots of repetitive tests in test-llvm11-go115 and
test-llvm11-go116, do those tests only once in assert-test-linux and
only run smoke tests for older Go versions.

Benefits:
  - This should reduce total CI time, because these jobs don't do tests
    that are done elsewere anyway. They only do the minimal work
    necessary to prove that the given Go/LLVM version works.
  - Doing all tests in assert-test-linux hopefully catches bugs that
    might not be found in regular LLVM builds.
2021-11-16 16:23:59 +01:00
Ayke van Laethem 869e917dc6 all: add support for windows/amd64
This uses Mingw-w64, which seems to be the de facto standard for porting
Unixy programs to Windows.
2021-11-16 11:08:30 +01:00
Ayke van Laethem 41bcad9c19 runtime: only use CRLF on baremetal systems
We should only do this on baremetal systems, not on Linux, macOS, and
Windows. In fact, Windows will convert LF into CRLF in its putchar
function.
2021-11-16 11:08:30 +01:00
Ayke van Laethem 73ab44c178 builder: support -size= flag on the esp32
This fixes a small mistake when calculating binary size for an Xtensa
file. Previously it would exit with the following error:

    $ tinygo build -o test.elf -size=short -target=esp32-mini32 examples/serial
    panic: runtime error: index out of range [65521] with length 18

Now it runs as expected:

    $ tinygo build -o test.elf -size=short -target=esp32-mini32 examples/serial
       code    data     bss |   flash     ram
       2897       0    4136 |    2897    4136
2021-11-16 07:42:58 +01:00
Dan Kegel b70b6076e3 net/ip, syscall/errno: Reduce code duplication by switching to internal/itoa.
internal/itoa wasn't around back in go 1.12 days when tinygo's syscall/errno.go was written.
It was only added as of go 1.17 ( https://github.com/golang/go/commit/061a6903a232cb868780b )
so we have to have an internal copy for now.
The internal copy should be deleted when tinygo drops support for go 1.16.

FWIW, the new version seems nicer.
It uses no allocations when converting 0,
and although the optimizer might make this moot, uses
a multiplication x 10 instead of a mod operation.
2021-11-16 02:13:52 +01:00
sago35 7b41d92198 device: add build tag for go1.17 2021-11-16 02:10:03 +01:00
Ayke van Laethem 2f4f3bd1ba wasi: restore support for -scheduler=none
The assembly symbols were not marked as hidden and so were exported,
leading to unreferenced symbols.

Example error message:

    Error: failed to run main module `/tmp/tinygo3961039405/main`

    Caused by:
        0: failed to instantiate "/tmp/tinygo3961039405/main"
        1: unknown import: `asyncify::stop_rewind` has not been defined

This commit fixes this issue.
2021-11-15 22:17:40 +01:00
Ayke van Laethem 7cb44fb373 all: add support for GOARM
This environment variable can be set to 5, 6, or 7 and controls which
ARM version (ARMv5, ARMv6, ARMv7) is used when compiling for GOARCH=arm.

I have picked the default value ARMv6, which I believe is supported on
most common single board computers including all Raspberry Pis. The
difference in code size is pretty big.

We could even go further and support ARMv4 if anybody is interested. It
should be pretty simple to add this if needed.
2021-11-15 11:53:44 +01:00
Ayke van Laethem 73ad825b67 ci: update Windows runner to windows-2019
The windows-2016 runner will soon be removed:
https://github.blog/changelog/2021-10-19-github-actions-the-windows-2016-runner-image-will-be-removed-from-github-hosted-runners-on-march-15-2022/
Therefore, switch to the next version.
2021-11-14 13:18:54 +01:00
Nia Waldvogel 539e1324c8 fix binaryen build in docker
Oops I forgot to install cmake and ninja.
2021-11-14 10:49:28 +01:00
Nia Waldvogel 641dcd7c16 internal/task: use asyncify on webassembly
This change implements a new "scheduler" for WebAssembly using binaryen's asyncify transform.
This is more reliable than the current "coroutines" transform, and works with non-Go code in the call stack.

runtime (js/wasm): handle scheduler nesting

If WASM calls into JS which calls back into WASM, it is possible for the scheduler to nest.
The event from the callback must be handled immediately, so the task cannot simply be deferred to the outer scheduler.
This creates a minimal scheduler loop which is used to handle such nesting.
2021-11-14 10:49:28 +01:00
Yurii Soldak 523d1f28cf nano-33-ble: internal i2c config, power led and sensors switch 2021-11-13 12:46:54 +01:00
Damian Gryski 782c57cc11 pass testing arguments to wasmtime 2021-11-13 12:01:20 +01:00
Ayke van Laethem c1d697f868 compiler: fix indices into strings and arrays
This PR fixes two bugs at once:

 1. Indices were incorrectly extended to a bigger type. Specifically,
    unsigned integers were sign extended and signed integers were zero
    extended. This commit swaps them around.
 2. The getelementptr instruction was given the raw index, even if it
    was a uint8 for example. However, getelementptr assumes the indices
    are signed, and therefore an index of uint8(200) was interpreted as
    an index of int8(-56).
2021-11-13 11:04:24 +01:00
Ayke van Laethem 335fb71d2f reflect: add support for DeepEqual
The implementation has been mostly copied from the Go reference
implementation with some small changes to fit TinyGo.

Source: https://github.com/golang/go/blob/77a11c05d6a6f766c75f804ea9b8796f9a9f85a3/src/reflect/deepequal.go

In addition, this commit also contains the following:

  - A set of tests copied from the Go reflect package.
  - An increased stack size for the riscv-qemu and hifive1-qemu targets
    (because they otherwise fail to run the tests). Because these
    targets are only used for testing, this seems fine to me.
2021-11-12 21:27:27 +01:00
Ayke van Laethem 5866a47e77 reflect: fix Value.Index() in a specific case
In the case where:

 - Value.Index() was called on an array
 - that array was bigger than a pointer
 - the element type fits in a pointer
 - the 'indirect' flag isn't set

the Value.Index() method would still (incorrectly) load the value.
This commit fixes that.

The next commit adds a test which would have triggered this bug so works
as a regression test.
2021-11-12 21:27:27 +01:00
Ayke van Laethem 823c9c25cf reflect: implement Value.Elem() for interface values 2021-11-12 21:27:27 +01:00
Ayke van Laethem d15e32fb89 reflect: don't construct an interface-in-interface value
v.Interaface() could construct an interface in interface value if v was
of type interface. This is not correct, and doesn't follow upstream Go
behavior. Instead, it should return the interface value itself.
2021-11-12 21:27:27 +01:00
soypat b534dd67e0 machine/rp2040: add interrupt API 2021-11-12 10:38:02 +01:00
Ayke van Laethem 6c02b4956c interp: fix reverting of extractvalue/insertvalue with multiple indices 2021-11-11 10:36:22 +01:00
Ayke van Laethem 1681ed02d3 interp: take care of constant globals
Constant globals can't have been modified, even if a pointer is passed
externally. Therefore, don't treat it as such in hasExternalStore.

In addition, it doesn't make sense to update values of constant globals
after the interp pass is finished. So don't do this.

TODO: track whether objects are actually modified and only update the
globals if this is the case.
2021-11-11 08:59:32 +01:00
Ayke van Laethem 7e68980c39 ci: improve caching for GitHub Actions
Previously the cache would be stale for every new branch.
With this change, PRs use the cache from the base branch and therefore
don't need to rebuild LLVM from scratch.
2021-11-10 18:55:17 +01:00
Ayke van Laethem cf640290a3 compiler: add "target-cpu" and "target-features" attributes
This matches Clang, and with that, it adds support for inlining between
Go and C because LLVM only allows inlining if the "target-cpu" and
"target-features" string attributes match.

For example, take a look at the following code:

    // int add(int a, int b) {
    //   return a + b;
    // }
    import "C"

    func main() {
        println(C.add(3, 5))
    }

The 'add' function is not inlined into the main function before this
commit, but after it, it can be inlined and trivially be optimized to
`println(8)`.
2021-11-10 11:16:13 +01:00
Ayke van Laethem 78fec3719f all: add target-features string to all targets
This makes sure that the LLVM target features match the one generated by
Clang:

  - This fixes a bug introduced when setting the target CPU for all
    targets: Cortex-M4 would now start using floating point operations
    while they were disabled in C.
  - This will make it possible in the future to inline C functions in Go
    and vice versa. This will need some more work though.

There is a code size impact. Cortex-M4 targets are increased slightly in
binary size while Cortex-M0 targets tend to be reduced a little bit.
Other than that, there is little impact.
2021-11-07 09:26:46 +01:00
Ayke van Laethem af4d0fe191 compileopts: fix reversed append in the target file
With this fix, `cflags` in the target JSON files is correctly ordered.
Previously, the cflags of a parent JSON file would come after the ones
in the child JSON file, which makes it hard to override properties in
the child JSON file.

Specifically, this fixes the case where targets/riscv32.json sets
`-march=rv32imac` and targets/esp32c3.json wants to override this using
`-march=rv32imc` but can't do this because its `-march` comes before the
riscv32.json one.
2021-11-07 09:26:46 +01:00
Ayke van Laethem 7caf0732fa transform: add debug info in interface lowering pass
This is fake debug info. It doesn't point to a source location because
there is no source location. However, it helps to correctly attribute
code size usage to particular packages.

I've also updated builder/sizes.go with some debugging helpers.
2021-11-06 10:50:55 +01:00
Ayke van Laethem edcece33ca transform: refactor interrupt lowering
Instead of doing everything in the interrupt lowering pass, generate
some more code in gen-device to declare interrupt handler functions and
do some work in the compiler so that interrupt lowering becomes a lot
simpler.

This has several benefits:

  - Overall code is smaller, in particular the interrupt lowering pass.
  - The code should be a bit less "magical" and instead a bit easier to
    read. In particular, instead of having a magic
    runtime.callInterruptHandler (that is fully written by the interrupt
    lowering pass), the runtime calls a generated function like
    device/sifive.InterruptHandler where this switch already exists in
    code.
  - Debug information is improved. This can be helpful during actual
    debugging but is also useful for other uses of DWARF debug
    information.

For an example on debug information improvement, this is what a
backtrace might look like before this commit:

    Breakpoint 1, 0x00000b46 in UART0_IRQHandler ()
    (gdb) bt
    #0  0x00000b46 in UART0_IRQHandler ()
    #1  <signal handler called>
    [..etc]

Notice that the debugger doesn't see the source code location where it
has stopped.

After this commit, breaking at the same line might look like this:

    Breakpoint 1, (*machine.UART).handleInterrupt (arg1=..., uart=<optimized out>) at /home/ayke/src/github.com/tinygo-org/tinygo/src/machine/machine_nrf.go:200
    200			uart.Receive(byte(nrf.UART0.RXD.Get()))
    (gdb) bt
    #0  (*machine.UART).handleInterrupt (arg1=..., uart=<optimized out>) at /home/ayke/src/github.com/tinygo-org/tinygo/src/machine/machine_nrf.go:200
    #1  UART0_IRQHandler () at /home/ayke/src/github.com/tinygo-org/tinygo/src/device/nrf/nrf51.go:176
    #2  <signal handler called>
    [..etc]

By now, the debugger sees an actual source location for UART0_IRQHandler
(in the generated file) and an inlined function.
2021-11-06 09:40:15 +01:00
jaap aarts 30bbdd5aeb Make the frequency selection more flexible on stm32f103 2021-11-05 18:11:43 +01:00
jaap aarts 03383760d6 Fix SPI on stm32f103 2021-11-05 18:11:43 +01:00
Ayke van Laethem fce403b7a0 targets: match LLVM triple to the one Clang uses
The target triples have to match mostly to be able to link LLVM modules.
Linking LLVM modules is already possible (the triples already match),
but testing becomes much easier when they match exactly.

For macOS, I picked "macosx10.12.0". That's an old and unsupported
version, but I had to pick _something_. Clang by default uses
"macos10.4.0", which is much older.
2021-11-05 09:42:00 +01:00
Ayke van Laethem fb33f3813d runtime: only initialize os.runtime_args when needed
This generally means that code size is reduced, especially when the os
package is not imported.

Specifically:

  - On Linux (which currently statically links musl), it avoids calling
    malloc, which avoids including the musl C heap for small programs
    saving around 1.6kB.
  - On WASI, it avoids initializing the args slice when the os package
    is not used. This reduces binary size by around 1kB.
2021-11-05 08:50:36 +01:00
Ayke van Laethem 670fcf59d8 linux: reduce binary size in the common case
This commit changes the runtime.putchar implementation to directly call
the `write` system call. This reduces the binary size by around 2.7kB.
2021-11-05 08:50:36 +01:00
Ayke van Laethem cceb655874 cgo: run CGo parser for all CGo fragments in a file
Previously, libclang was run on each fragment (import "C") separately.
However, in regular Go it's possible for later fragments to refer to
types in earlier fragments so they must have been parsed as one.

This commit changes the behavior to run only one C parser invocation for
each Go file.
2021-11-04 22:26:33 +01:00
Damian Gryski 13891d428f os: add File.WriteString and File.WriteAt
WriteString just does the simple and and converts the passed string
to a byte-slice.  This can be made zero-copy later with unsafe, if needed.

WriteAt returns ErrNotImplemented, to match Seek() and ReadAt().

Fixes #2157
2021-11-04 21:47:57 +01:00
Ayke van Laethem 6c9bb96bca wasm: update wasi-libc dependency
The latest version allows overriding the default CFLAGS. By default,
they're `-O2 -DNDEBUG`, thus not including DWARF debug information. This
commit changes this to include the `-g` flag.

Apart from an improved debug experience, this lets -size=full attribute
code to wasi-libc.

Before:

    $ tinygo build -o test.wasm -size=full ./testdata/alias.go
       code  rodata    data     bss |   flash     ram | package
    ------------------------------- | --------------- | -------
       1780       0     188  130733 |    1968  130921 | (unknown)
         84       0       0       0 |      84       0 | internal/task
        281       0       0       0 |     281       0 | main
       2374       0       4     147 |    2378     151 | runtime
    ------------------------------- | --------------- | -------
       4519       0     192  130880 |    4711  131072 | total

After:

    $ tinygo build -o test.wasm -size=full ./testdata/alias.go
       code  rodata    data     bss |   flash     ram | package
    ------------------------------- | --------------- | -------
         40       0     188  130733 |     228  130921 | (unknown)
       1740       0       0       0 |    1740       0 | C wasi-libc
         84       0       0       0 |      84       0 | internal/task
        281       0       0       0 |     281       0 | main
       2374       0       4     147 |    2378     151 | runtime
    ------------------------------- | --------------- | -------
       4519       0     192  130880 |    4711  131072 | total

The main difference here is the `(unknown)` code, which turns out to be
mostly wasi-libc in this trivial example.
2021-11-04 21:10:42 +01:00
Ayke van Laethem 403d93560b builder: build static binaries using musl on Linux
This commit adds support for musl-libc and uses it by default on Linux.
The main benefit of it is that binaries are always statically linked
instead of depending on the host libc, even when using CGo.

Advantages:
  - The resulting binaries are always statically linked.
  - No need for any tools on the host OS, like a compiler, linker, or
    libc in a release build of TinyGo.
  - This also simplifies cross compilation as no cross compiler is
    needed (it's all built into the TinyGo release build).

Disadvantages:
  - Binary size increases by 5-6 kilobytes if -no-debug is used. Binary
    size increases by a much larger margin when debugging symbols are
    included (the default behavior) because musl is built with debugging
    symbols enabled.
  - Musl does things a bit differently than glibc, and some CGo code
    might rely on the glibc behavior.
  - The first build takes a bit longer because musl needs to be built.

As an additional bonus, time is now obtained from the system in a way
that fixes the Y2038 problem because musl has been a bit more agressive
in switching to 64-bit time_t.
2021-11-04 17:15:38 +01:00
Ayke van Laethem b344d65781 builder: reduce number of open files
MacOS X 10.14 has a soft limit of 256 open files by default, at least on
CircleCI. So don't keep object files open while writing the ar file to
reduce the number of open files at once.

Context: the musl libc has more than 256 object files in the .a file.
This resulted in the error "too many open files" on MacOS X 10.14 when
running in CircleCI.
2021-11-04 17:15:38 +01:00
Ayke van Laethem c638f03b3c main: add -p flag to set parallelism
This is very useful for debugging.
2021-11-04 17:15:38 +01:00
Ayke van Laethem 79bdd3f79a picolibc: add include directory to build artefact
This is really just a preparatory commit for musl support. The idea is
to store not just the archive file (.a) but also an include directory.
This is optional for picolibc but required for musl, so the main purpose
of this commit is the refactor needed for this change.
2021-11-04 17:15:38 +01:00
Ayke van Laethem 39ff13fd1a wasm: specify wasi-libc in code, not in the JSON target file
This brings a bit more consistency to libc configuration. It seems
better to me to set the header flags all in the same place, instead of
some in Go code and some in JSON target files (depending on the target).
2021-11-04 17:15:38 +01:00
Ayke van Laethem de6f831983 ci: switch to GitHub Actions for Windows builds
GitHub Actions is faster and much better integrated into GitHub than
Azure Pipelines, and is in general easier to use. Therefore, switch to
GitHub Actions for our Windows builds and tests.
2021-11-04 13:54:21 +01:00
Ayke van Laethem fb6571e405 builder: add support for -size= flag for WebAssembly 2021-11-04 12:34:23 +01:00
Ayke van Laethem 29206cf0a4 targets: add CPU property everywhere
This is for consistency with Clang, which always adds a CPU flag even if
it's not specified in CFLAGS.

This commit also adds some tests to make sure the Clang target-cpu
matches the CPU property in the JSON files.

This does have an effect on the generated binaries. The effect is very
small though: on average just 0.2% increase in binary size, apparently
because Cortex-M3 and Cortex-M4 are compiled a bit differently. However,
when rebased on top of https://github.com/tinygo-org/tinygo/pull/2218
(minsize), the difference drops to -0.1% (a slight decrease on average).
2021-11-03 23:03:44 +01:00
Yurii Soldak c2165f74d8 nano-33-ble: SoftDevice s140v7 support 2021-11-03 20:54:40 +01:00
Ayke van Laethem 02ef64f012 stacksize: hardcode some more frame sizes for __aeabi_* functions
These functions are defined in compiler-rt in assembly and therefore
don't have stack size information. However, they're often called so
these missing functions often inhibit stack size calculation.

Example, before:

    $ tinygo build -o test.elf -target=cortex-m-qemu -print-stacks ./testdata/float.go
    function                         stack usage (in bytes)
    Reset_Handler                    unknown, __aeabi_memclr does not have stack frame information
    runtime.run$1                    unknown, __aeabi_dcmpgt does not have stack frame information

After:

    $ tinygo build -o test.elf -target=cortex-m-qemu -print-stacks ./testdata/float.go
    function                         stack usage (in bytes)
    Reset_Handler                    260
    runtime.run$1                    224
2021-11-03 18:42:16 +01:00
Ayke van Laethem 5792f3a1cf builder: improve accuracy of the -size=full flag
This commit improves accuracy of the -size=full flag in a big way.
Instead of relying on symbol names to figure out by which package
symbols belong, it will instead mostly use DWARF debug information
(specifically, debug line tables and debug information for global
variables) relying on symbols only for some specific things. This is
much more accurate: it also accounts for inlined functions.

For example, here is how it looked previously when compiling a personal
project:

     code  rodata    data     bss |   flash     ram | package
     1902     333       0       0 |    2235       0 | (bootstrap)
       46     256       0       0 |     302       0 | github
        0     454       0       0 |     454       0 | handleHardFault$string
      154      24       4       4 |     182       8 | internal/task
     2498      83       5    2054 |    2586    2059 | machine
        0      16      24     130 |      40     154 | machine$alloc
     1664      32      12       8 |    1708      20 | main
        0       0       0     200 |       0     200 | main$alloc
     2476      79       0      36 |    2555      36 | runtime
      576       0       0       0 |     576       0 | tinygo
     9316    1277      45    2432 |   10638    2477 | (sum)
    11208       -      48    6548 |   11256    6596 | (all)

And here is how it looks now:

     code  rodata    data     bss |   flash     ram | package
  ------------------------------- | --------------- | -------
     1509       0      12      23 |    1521      35 | (unknown)
      660       0       0       0 |     660       0 | C compiler-rt
       58       0       0       0 |      58       0 | C picolibc
        0       0       0    4096 |       0    4096 | C stack
      174       0       0       0 |     174       0 | device/arm
        6       0       0       0 |       6       0 | device/sam
      598     256       0       0 |     854       0 | github.com/aykevl/ledsgo
      320      24       0       4 |     344       4 | internal/task
     1414      99      24    2181 |    1537    2205 | machine
      726     352      12     208 |    1090     220 | main
     3002     542       0      36 |    3544      36 | runtime
      848       0       0       0 |     848       0 | runtime/volatile
       70       0       0       0 |      70       0 | time
      550       0       0       0 |     550       0 | tinygo.org/x/drivers/ws2812
  ------------------------------- | --------------- | -------
     9935    1273      48    6548 |   11256    6596 | total

There are some notable differences:

  * Odd packages like main$alloc and handleHardFault$string are gone,
    instead their code is put in the correct package.
  * C libraries and the stack are now included in the list, they were
    previously part of the (bootstrap) pseudo-package.
  * Unknown bytes are slightly reduced. It should be possible to reduce
    it significantly more in the future: most of it is now caused by
    interface invoke wrappers.
  * Inlined functions are now correctly attributed. For example, the
    runtime/volatile package is normally entirely inlined.
  * There is no difference between (sum) and (all) anymore. A better
    code size algorithm now counts the code/data sizes correctly.
  * And last (but not least) there is a stylistic change: the table now
    looks more like a table. Especially the summary should be clearer
    now.

Future goals:

  * Improve debug information so that the (unknown) pseudo-package is
    reduced in size or even eliminated altogether.
  * Add support for other file formats, most importantly WebAssembly.
  * Perhaps provide a way to expand this report per file, or in a
    machine-readable format like JSON or CSV.
2021-11-03 16:28:04 +01:00
Ayke van Laethem f63c389f1a compiler: change symbol name for string and packed data constants
This new symbol name format (package name + "$string" or "$pack" suffix)
is easier to parse for analysis.
2021-11-03 16:28:04 +01:00
Ayke van Laethem 7c24925aa7 compiler: add minsize attribute for -Oz
This matches the behavior of Clang, which uses optsize for -Os and adds
minsize for -Oz.

The code size change is all over the map, but using a hacked together
size comparison tool I've found that there is a slight reduction in
binary size overall (-1.6% with the tinygo smoke tests and -0.8% for the
drivers smoke test).
2021-11-03 13:40:13 +01:00
Ayke van Laethem d7b7583e83 compiler: refactor when the optsize attribute is set
This commit has a few related changes:

  * It sets the optsize attribute immediately in the compiler instead of
    adding it to each function afterwards in a loop. This seems to me
    like the more appropriate way to do it.
  * It centralizes setting the optsize attribute in the transform
    package, to make later changes easier.
  * It sets the optsize in a few more places: to runtime.initAll and to
    WebAssembly i64 wrappers.

This commit does not affect the binary size of any of the smoke tests,
so should be risk-free.
2021-11-03 13:40:13 +01:00
Ayke van Laethem 1869efe954 interp: use object layout information for LLVM types
This commit will use the memory layout information for heap allocations
added in the previous commit to determine LLVM types, instead of
guessing their types based on the content. This fixes a bug in which
recursive data structures (such as doubly linked lists) would result in
a compiler stack overflow due to infinite recursion.

Not all heap allocations have a memory layout yet, but this can be
incrementally fixed in the future. So far, this commit should fix
(almost?) all cases of this stack overflow issue.
2021-11-02 22:16:15 +01:00
Ayke van Laethem 54dd75f7b3 interp: simplify pointer arithmetic in getLLVMValue
Instead of doing lots of complicated calculations to get the shortest
GEP, I'll just cast it to i8*, do the GEP, and optionally cast to the
requested type.

This currently produces ugly constant expressions, but once LLVM
switches to opaque pointer types all of this shouldn't matter anymore.
2021-11-02 22:16:15 +01:00
Ayke van Laethem 27cbb53538 interp: support const getelementptr with non-zero first offset
This is uncommon, but it does happen if the source pointer is a bitcast
of a global. For example, if a struct is cast to an i8*, it's possible
to index beyond what would appear to be the size of the pointer (i8*).
2021-11-02 22:16:15 +01:00
Ayke van Laethem 0704794def compiler: add object layout information to heap allocations
This commit adds object layout information to new heap allocations. It
is not yet used anywhere: the next commit will make use of it.

Object layout information will eventually be used for a (mostly) precise
garbage collector. This is what the data is made for. However, it is
also useful in the interp package which can work better if it knows the
memory layout and thus the approximate LLVM type of heap-allocated
objects.
2021-11-02 22:16:15 +01:00
Ayke van Laethem f24a93c51d compiler, runtime: add layout parameter to runtime.alloc
This layout parameter is currently always nil and ignored, but will
eventually contain a pointer to a memory layout.

This commit also adds module verification to the transform tests, as I
found out that it didn't (and therefore didn't initially catch all
bugs).
2021-11-02 22:16:15 +01:00
Ayke van Laethem c454568688 loader: fix true path detection on Windows
This is necessary to display error messages on Windows. For example,
this command invocation is not correct (esp32 doesn't define
machine.LED, you need esp32-coreboard-v2 for example):

    tinygo run -target=esp32 examples/blinky1

It results in the following hard-to-read error message:

    # examples/blinky1
    ..\..\..\..\..\AppData\Local\tinygo\goroot-go1.16-24cb853b66a5367bf6d65bc08b2cb665c75bd9971f0be8f8b73f69d1a33e04a1-syscall\src\examples\blinky1\blinky1.go:11:17: LED not declared by package machine

With this commit, this error message becomes much easier to read:

    # examples/blinky1
    C:\Users\Ayke\go\src\github.com\tinygo-org\tinygo\src\examples\blinky1\blinky1.go:11:17: LED not declared by package machine
2021-10-31 19:10:26 +01:00
Nia Waldvogel d46bf2e5e0 transform (interface): fix merge error from #2202 2021-10-31 17:35:58 +01:00
Ayke van Laethem 9e1b4de999 compiler: add support for the go keyword on interface methods
This is a feature that was long missing, but because of the previous
refactor, it is now trivial to implement.
2021-10-31 14:17:25 +01:00
Ayke van Laethem a4afc3b4b0 compiler: simplify interface lowering
This commit simplifies the IR a little bit: instead of calling
pseudo-functions runtime.interfaceImplements and
runtime.interfaceMethod, real declared functions are being called that
are then defined in the interface lowering pass. This should simplify
the interaction between various transformation passes. It also reduces
the number of lines of code, which is generally a good thing.
2021-10-31 14:17:25 +01:00
Ayke van Laethem 90076f9401 all: drop support for LLVM 10 2021-10-31 10:44:17 +01:00
Ayke van Laethem afd49e7cdd compiler: add support for recursive function types
This adds support for a construct like this:

    type foo func(fn foo)

Unfortunately, LLVM cannot create function pointers that look like this.
LLVM only supports named types for structs (not for pointers) and thus
can't add a pointer to a function type of the same type to a parameter
of that function type.

The fix is simple: cast all function pointers to a void function, in
LLVM IR:

    void ()*

Raw function pointers are cast to this type before storing, and cast
back to the regular function type before calling. This means that
function parameters will never refer to its own type because raw
function types are fixed at that one type.

Somehow, this does have an effect on binary size in some cases. The
effect is small and goes both ways. On top of that, there is work
underway in LLVM which would make all pointer types opaque (without a
pointee type). This would make this whole commit useless and therefore
should fix any size increases that might happen.
https://llvm.org/docs/OpaquePointers.html
2021-10-30 15:55:20 +02:00
Ayke van Laethem 4199be9780 ci: increase timeout to 20 minutes 2021-10-28 17:44:51 +02:00
Ayke van Laethem 86f1e6aec4 compiler: properly implement div and rem operations
The division and remainder operations were lowered directly to LLVM IR.
This is wrong however because the Go specification defines exactly what
happens on a divide by zero or signed integer overflow and LLVM IR
itself treats those cases as undefined behavior. Therefore, this commit
implements divide by zero and signed integer overflow according to the
Go specification.

This does have an impact on the generated code, but it is surprisingly
small. I've used the drivers repo to test the code before and after, and
to my surprise most driver smoke tests are not changed at all. Those
that are, have only a small increase in code size. At the same time,
this change makes TinyGo more compliant to the Go specification.
2021-10-28 15:55:02 +02:00
Ayke van Laethem f99c600ad8 transform: work around renamed return type after merging LLVM modules
This fix is very similar to
https://github.com/tinygo-org/tinygo/pull/1768, but now for the return
type. It fixes the issue in
https://github.com/tinygo-org/tinygo/issues/1887.

Like #1768, I'm not sure how to test this as it is very specific to
certain renames that LLVM does and that don't seem very reproducable.
2021-10-28 09:20:08 +02:00
Ayke van Laethem 15d3f5f609 machine: support Pin.Get() function when the pin is configured as output
To my surprise, this is supported on all the devices I could test so
therefore it makes sense to change the API to allow this.
2021-10-28 07:22:19 +02:00
Yurii Soldak c8719f8d14 docker: add picolibc-include directory 2021-10-27 20:49:06 +02:00
Dmitriy Zakharkin e848f47ad4 Fix gen-device-svd to handle 64-bit 2021-10-27 14:52:27 +02:00
Ast-x64 3fe7ab19f6 bump go.bug.st/serial to version 1.1.3
Bump version to 1.1.3 in order to support riscv64 within tinygo.
See https://github.com/bugst/go-serial/pull/100 for more information.
2021-10-27 14:43:38 +02:00
Ayke van Laethem b5d61760f7 transform: remove some dead code
This showed up in the linter and it makes sense to just remove it.
2021-10-26 18:11:58 +02:00
Ayke van Laethem 14bb90c3c0 cgo: add support for stdio in picolibc and wasi-libc
This adds support for stdio in picolibc and fixes wasm_exec.js so that
it can also support C puts. With this, C stdout works on all supported
platforms.
2021-10-26 17:08:30 +02:00
Ayke van Laethem 1645f45c1a esp32c3: use tasks scheduler by default
Now that the tasks scheduler has been implemented for 32-bit RISC-V, it
can be used for the ESP32-C3.
2021-10-26 11:24:41 +02:00
Ayke van Laethem 38b9c55ae6 sam: move I2S0 to machine file
There is no need to put these in the board files as the I2S is the same
on all Microchip SAM D21 chips. This simplifies the code and avoids some
special *_baremetal.go files.

This change does not change the resulting binaries.
2021-10-25 14:49:02 +02:00
Ayke van Laethem 497c74e4a9 sam: simplify SPI peripheral declaration
This has practically no effect on the resulting binaries, the only
difference I could find was for the flash/console/spi driver example.
I'm not sure how to test that one, but I think it's very unlikely that
code will have changed in any meaningful way (apart from reordering some
globals).
2021-10-25 14:49:02 +02:00
Ayke van Laethem ae864bdf0c sam: simplify I2C peripheral declarations
This commit changes the I2C declarations so that the objects are
instantiated in each chip file (e.g. machine_atsamd21e18.go) and used to
define I2C0 (and similar) in the board file (e.g. board_qtpy.go). This
should make it easier to define new board files, and reduces the need
for separate *_baremetal.go files.

I have tested this the following way:

  - With the LIS3DH driver example on the Circuit Playground Express and
    the PyBadge.
  - With the LSM6DS3 driver example on the Arduino Nano 33 IoT.

They both still work fine.
2021-10-25 14:49:02 +02:00
Ayke van Laethem e50885a6f2 sam: simplify definition of SERCOM UART peripherals
Instead of defining them separately for each board, define them once in
the chip definition and later simply use &sercomUART1 etc. to refer to
them. This is simpler and less error-prone.

I found two bugs while working on this:

  - The P1AM-100 board mixed SERCOM 5 and SERCOM 3. It looks like SERCOM
    5 was intended, based on the used pins.
  - The Adafruit Matrix Portal appears to have configured the wrong
    interrupt.

Unfortunately, I can't test these fixes. However, they make it clear
that such a change is important to avoid bugs.

I tested this commit on the PyBadge and the Circuit Playground Express.
2021-10-25 14:49:02 +02:00
Ayke van Laethem 478dd3a28d compiler: add nounwind attribute
This attribute is also set by Clang when it compiles C source files
(unless -fexceptions is set). The advantage is that no unwind tables are
emitted on Linux (and perhaps other systems). It also avoids
__aeabi_unwind_cpp_pr0 on ARM when using the musl libc.
2021-10-25 13:39:54 +02:00
Rouven Broszeit 112b369636 Call __wasm_call_ctors() in wasi init function 2021-10-25 13:12:23 +02:00
Dmitriy 43efe94041 add support for CPU interrupts for ESP32-C3 2021-10-23 03:31:37 +02:00
Ayke van Laethem b5b2600b7b fe310: add support for bit banging drivers
This is necessary to add support for WS2812.
2021-10-21 08:14:34 +02:00
Ayke van Laethem 3f89fa0bee fe310: increase CPU frequency from 16MHz to 320MHz
This chip can run so much faster! Let's update the default frequency.

Also, change the UART implementation to be more fexible regarding the
clock frequency.
2021-10-21 07:13:57 +02:00
Yurii Soldak a5d905f19b rp2040: i2c SetBaudRate spelling 2021-10-21 00:29:16 +02:00
Yurii Soldak d1f1f267a3 rp2040: i2c baud rate handling improvements 2021-10-21 00:29:16 +02:00
sago35 d21ffc63b9 board: add M5Stack Core2 2021-10-20 20:28:47 +02:00
Damian Gryski 90f4b0a266 Makefile: add more TEST_PACKAGES that currently pass 2021-10-16 01:49:25 +02:00
Damian Gryski a88530b785 src/testing: stub B.ReportAllocs()
This allows test packages that use this feature in their benchmarks
to build and run (if not the benchmarks themselves).
2021-10-16 01:49:25 +02:00
Damian Gryski 18aaed63b9 src/runtime: add another set of invalid unicode runes to encodeUTF8() 2021-10-16 01:37:48 +02:00
Damian Gryski a413d5dfe9 rutime/gc_leaking: ensure heapptr is aligned on wasm 2021-10-14 01:56:05 +02:00
Ayke van Laethem 4d5ec6c57b main: use emulator exit code instead of parsing test output
This commit changes `tinygo test` to always look at the exit code of the
running test, instead of looking for a "PASS" string at the end of the
output. This is possible now that the binaries running under
qemu-system-arm or qemu-system-riscv32 will signal the correct exit code
when they exit.

As a side effect, this also makes it possible to avoid the "PASS" line
between successful tests. Before:

    $ tinygo test container/heap container/list
    PASS
    ok  	container/heap	0.001s
    PASS
    ok  	container/list	0.001s

After:

    $ tinygo test container/heap container/list
    ok  	container/heap	0.001s
    ok  	container/list	0.001s

The new behavior is more in line with upstream Go:

    go test container/heap container/list
    ok  	container/heap	0.004s
    ok  	container/list	0.004s
2021-10-06 09:04:06 +02:00
Ayke van Laethem 98f84a497d qemu: signal correct exit code to QEMU
There were a few issues that were causing qemu-system-arm and
qemu-system-riscv to give the wrong exit codes. They are in fact capable
of exiting with 0 or 1 signalled from the running application, but this
functionality wasn't used. This commit changes this in the following
ways:

  * It fixes SemiHosting codes, which were incorrectly written in
    decimal while they should have been written in hexadecimal (oops!).
  * It modifies all the baremetal main functions (aka reset handlers) to
    exit with `exit(0)` instead of `abort()`.
  * It changes `syscall.Exit` to call `exit(code)` instead of `abort()`
    on baremetal targets.
  * It adds these new exit functions where necessary, implemented in a
    way that signals the correct exit status if running under QEMU.

All in all, this means that `tinygo test` doesn't have to look at the
output of a test to determine the outcome. It can simply look at the
exit code.
2021-10-06 09:04:06 +02:00
sago35 00c73d62ad rp2040: add CPUFrequency() 2021-10-05 07:17:36 +02:00
Ayke van Laethem dbfaaf7c13 main: implement tinygo lldb subcommand
LLDB mostly works on most platforms, but it is still lacking in some
features. For example, it doesn't seem to support RISC-V yet (coming in
LLVM 12), it only partially supports AVR (no stacktraces), and it
doesn't seem to support the Ctrl-C keyboard command when running a
binary for another platform (e.g. with GOOS=arm64). However, it does
mostly work, even on baremetal systems.
2021-10-05 06:26:21 +02:00
Ayke van Laethem 878b62bbe8 riscv: switch to tasks-based scheduler
This is only supported for RV32 at the moment. RV64 can be added at a
later time.
2021-10-05 05:52:03 +02:00
Ayke van Laethem 5d8f25a622 hifive1-qemu: increase memory to 64K
Somehow this is accepted by QEMU. I'm doing this so that tests for
-target=hifive1-qemu still work with the RISC-V tasks scheduler (with a
stack size of 2048 bytes).
2021-10-05 05:52:03 +02:00
Ayke van Laethem c7413837aa riscv: align the heap to 16 bytes
This may be expected by the ABI. In particular, it means that stacks
allocated on the heap will be 16-byte aligned.
2021-10-05 05:52:03 +02:00
Federico G. Schwindt b1ec8eb2e0 os: implement Getwd 2021-10-05 00:14:09 +02:00
deadprogram 98fbf7ff25 build: double timeout period without output for make test
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-10-04 23:51:25 +02:00
Ayke van Laethem af00e218a8 riscv: implement 32-bit atomic operations
This is necessary to support the ESP32-C3, which lacks the A (atomic)
extension and thus requires these 32-bit atomic operations.
With this commit, flashing ./testdata/atomic.go to the ESP32-C3 works
correctly and produces the expected output on the serial console.
2021-10-04 21:27:00 +02:00
Ayke van Laethem b31d241388 riscv: use MSTATUS.MIE bit instead of MIE to disable interrupts
This should behave the same but is compatible with the ESP32-C3 which
lacks the MIE CSR (but does have the MSTATUS CSR).
2021-10-04 21:27:00 +02:00
Ayke van Laethem a6246e60f3 main: remove -target flag for LLVM targets
It is better to use environment variables (GOOS and GOARCH) for
consistency instead of providing two slightly incompatible ways. This
-target flag should only be used to specify a .json file (either
directly or in the TinyGo targets directory). Previously it was possible
to specify the LLVM target as well but that was never really fully
supported.

So:

  - To specify a different OS/arch like you would in regular Go, use
    GOOS and GOARCH.
  - To specify a microcontroller chip or board, use the -target flag.

Also remove the old `os.Setenv` which might have had a purpose long ago
but doesn't have a purpose now.
2021-10-04 18:22:55 +02:00
Ayke van Laethem 0a80da46b1 main: test other architectures by specifying a different GOARCH
... instead of setting a special -target= value. This is more robust and
makes sure that the test actually tests different arcitectures as they
would be compiled by TinyGo. As an example, the bug of the bugfix in the
previous commit ("arm: use armv7 instead of thumbv7") would have been
caught if this change was applied earlier.

I've decided to put GOOS/GOARCH in compileopts.Options, as it makes
sense to me to treat them the same way as command line parameters.
2021-10-04 18:22:55 +02:00
Ayke van Laethem 36f1517e8d arm: use armv7 instead of thumbv7
At the moment, thumbv7 is crashing. I'm not exactly sure why, but it
appears that there is an unknown instruction in __aeabi_uldivmod
(probably from libgcc).

I've fixed this by switching to armv7, which is also somewhat modern.
Maybe we can switch back to Thumb2 (aka thumbv7) once we start using
musl and compiler-rt. In the meantime, this does fix a miscompilation
(illegal instruction).
2021-10-04 18:22:55 +02:00
learnforpractice 04040453b4 fix export math functions issue 2021-10-03 16:28:34 +02:00
Ayke van Laethem 2b453db4da esp32c3: add support for GDB debugging
You can now debug the ESP32-C3 from the TinyGo command line, like this:

    tinygo flash -target=esp32c3 examples/serial
    tinygo gdb -target=esp32c3 examples/serial

It's important to flash before running `tinygo gdb`, because loading a
new firmware from GDB has not yet been implemented.

Probably the easiest way to connect to the ESP32-C3 is by using the
built-in JTAG connection. See:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/jtag-debugging/configure-builtin-jtag.html

You will need to make sure that the `openocd` command in your $PATH is
the one from Espressif. Otherwise GDB will hang. You can debug this by
supplying the -ocd-output flag:

    $ tinygo gdb -target=esp32c3 -ocd-output examples/serial
    Open On-Chip Debugger 0.10.0
    openocd: Licensed under GNU GPL v2
    openocd: For bug reports, read
    openocd: 	http://openocd.org/doc/doxygen/bugs.html
    openocd: embedded:startup.tcl:60: Error: Can't find interface/esp_usb_jtag.cfg
    openocd: in procedure 'script'
    openocd: at file "embedded:startup.tcl", line 60

Make sure to configure OpenOCD correctly, until you get the correct
version (that includes the string "esp32"):

    $ openocd --version
    Open On-Chip Debugger  v0.10.0-esp32-20210721 (2021-07-21-13:33)
    Licensed under GNU GPL v2
    For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html

If you are on Linux, you may also get the following error:

    $ tinygo gdb -target=esp32c3 -ocd-output examples/serial
    Open On-Chip Debugger  v0.10.0-esp32-20210721 (2021-07-21-13:33)
    openocd: Licensed under GNU GPL v2
    openocd: For bug reports, read
    openocd: 	http://openocd.org/doc/doxygen/bugs.html
    openocd: Info : only one transport option; autoselect 'jtag'
    openocd: adapter speed: 40000 kHz
    openocd:
    openocd: Warn : Transport "jtag" was already selected
    openocd: Info : Listening on port 6666 for tcl connections
    openocd: Info : Listening on port 4444 for telnet connections
    openocd: Error: libusb_open() failed with LIBUSB_ERROR_ACCESS
    openocd: Error: esp_usb_jtag: could not find or open device!

The error LIBUSB_ERROR_ACCESS means that there is a permission error.
You can fix this by creating the following file:

    $ cat /etc/udev/rules.d/50-esp.rules
    # ESP32-C3
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="0666"

For more details, see:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-guides/jtag-debugging/index.html
2021-10-02 09:24:13 +02:00
Ayke van Laethem 29d3e10dc9 ci: fix wasmtime.dev expiry issue by upgrading some packages
Hopefully this will fix the CI breakage after curl and wget refuse to
download anything from wasmtime.dev (which is signed by Let's Encrypt).

- wget needs and updated libgnutls30
- curl needs and updated libssl1.0.2
2021-10-01 17:45:54 +02:00
sago35 06c60b4ecf esp32: remove extra configuration 2021-09-29 14:51:04 +02:00
Ayke van Laethem 5c0a337c4f cgo: implement rudimentary C array decaying
This is just a first step. It's not complete, but it gets some real
world C code to parse.

This signature, from the ESP-IDF:

    esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]);

Was previously converted to something like this (pseudocode):

    C.esp_err_t esp_wifi_get_mac(ifx C.wifi_interface_t, mac [6]uint8)

But this is not correct. C array parameters will decay. The array is
passed by reference instead of by value. Instead, this would be the
correct signature:

    C.esp_err_t esp_wifi_get_mac(ifx C.wifi_interface_t, mac *uint8)

So that it can be called like this (using CGo):

    var mac [6]byte
    errCode := C.esp_wifi_get_mac(C.ESP_IF_WIFI_AP, &mac[0])

This stores the result in the 6-element array mac.
2021-09-29 13:38:33 +02:00
Ayke van Laethem 04e8f44370 os: don't try to read executable path on baremetal
Baremetal systems usually pretend to be GOOS=linux, so an extra build
tag is needed here.
2021-09-28 20:28:15 +02:00
Ayke van Laethem e02727679f builder, cgo: support function definitions in CGo headers
For example, the following did not work before but does work with this
change:

    // int add(int a, int b) {
    //   return a + b;
    // }
    import "C"

    func main() {
        println("add:", C.add(3, 5))
    }

Even better, the functions in the header are compiled together with the
rest of the Go code and so they can be optimized together! Currently,
inlining is not yet allowed but const-propagation across functions
works. This should be improved in the future.
2021-09-28 18:44:11 +02:00
Ayke van Laethem 138add2b96 cgo: fix line/column reporting in syntax error messages 2021-09-28 18:44:11 +02:00
Ayke van Laethem bf9dab36f7 build: normalize target triples to match Clang
This commit changes a target triple like "armv6m-none-eabi" to
"armv6m-unknown-unknow-eabi". The reason is that while the former is
correctly parsed in Clang (due to normalization), it wasn't parsed
correctly in LLVM meaning that the environment wasn't set to EABI.

This change normalizes all target triples and uses the EABI environment
(-eabi in the triple) for Cortex-M targets.

This change also drops the `--target=` flag in the target JSON files,
the flag is now added implicitly in `(*compileopts.Config).CFlags()`.
This removes some duplication in target JSON files.

Unfortunately, this change also increases code size for Cortex-M
targets. It looks like LLVM now emits calls like __aeabi_memmove instead
of memmove, which pull in slightly more code (they basically just call
the regular C functions) and the calls themself don't seem to be as
efficient as they could be. Perhaps this is a LLVM bug that will be
fixed in the future, as this is a very common occurrence.
2021-09-28 18:44:11 +02:00
Ayke van Laethem 6234bf9a88 all: use -opt flag for optimization level in CFlags (-Os, etc)
This brings some consistency to the CFlags and fixes the issue that on
some platforms (Linux, MacOS), no optimization level was set and
therefore C files in packages were not optimized at all.
2021-09-28 18:44:11 +02:00
Damian Gryski 32899d1cc3 testing: add a stub for t.Parallel() 2021-09-27 20:02:02 +02:00
Damian Gryski 0dfb336563 add support for -test.short flag 2021-09-27 20:02:02 +02:00
Damian Gryski d9ad500cf7 src/reflect: fix type.Size() to account for struct padding
Fixes #2141
2021-09-27 17:04:16 +02:00
Ayke van Laethem 49dd2ce393 all: fix staticcheck warnings
This is a loose collection of small fixes flagged by staticcheck:

  - dead code
  - regexp expressions not using backticks (`foobar` / "foobar")
  - redundant types of slice and map initializers
  - misc other fixes

Not all of these seem very useful to me, but in particular dead code is
nice to fix. I've fixed them all just so that if there are problems,
they aren't hidden in the noise of less useful issues.
2021-09-27 15:47:12 +02:00
sago35 7df8e8db42 feather-stm32f405, feather-rp2040: add I2C pin names 2021-09-27 12:37:26 +02:00
Damian Gryski 25011c5078 src/internal/bytealg: fix indexing error in Compare()
Fixes #2139
2021-09-26 11:07:19 +02:00
sago35 54867f901a version: update TinyGo version to 0.21.0-dev 2021-09-23 21:08:44 +02:00
Nia Waldvogel 1573826005 transform (coroutines): move any misplaced entry-block allocas to the start of the entry block before lowering 2021-09-21 20:08:30 +02:00
Nia Waldvogel ecd8c2d902 transform (coroutines): fix memory corruption for tail calls that reference stack allocations
This change fixes a bug in which `alloca` memory lifetimes would not extend past the suspend of an asynchronous tail call.
This would typically manifest as memory corruption, and could happen with or without normal suspending calls within the function.
2021-09-21 20:08:30 +02:00
Ayke van Laethem a116fd0dc6 main: release version 0.20.0 2021-09-21 18:05:21 +02:00
Ayke van Laethem a590d791bd builder: simplify running of jobs
Instead of keeping a slice of jobs to run, let the runJobs function
determine which jobs should be run by investigating all dependencies.
This has two benefits:

  - The code is somewhat cleaner, as no 'jobs' slice needs to be
    maintained while constructing the dependency graph.
  - Eventually, some jobs might not be required by any dependency.
    While it's possible to avoid adding them to the slice, the simpler
    solution is to build a new slice from the dependencies which will
    only include required dependencies by design.
2021-09-17 22:22:27 +02:00
Ayke van Laethem cb147b9475 esp32c3: add support for this chip
This change adds support for the ESP32-C3, a new chip from Espressif. It
is a RISC-V core so porting was comparatively easy.

Most peripherals are shared with the (original) ESP32 chip, but with
subtle differences. Also, the SVD file I've used gives some
peripherals/registers a different name which makes sharing code harder.
Eventually, when an official SVD file for the ESP32 is released, I
expect that a lot of code can be shared between the two chips.

More information: https://www.espressif.com/en/products/socs/esp32-c3

TODO:
  - stack scheduler
  - interrupts
  - most peripherals (SPI, I2C, PWM, etc)
2021-09-16 20:13:04 +02:00
Ayke van Laethem c830f878c6 stm32: add support for PortMask* functions for WS2812 support
This also requires support in the tinygo.org/x/drivers/ws2812 package,
which I've already partially written.
2021-09-16 18:29:14 +02:00
Ayke van Laethem c7c874a487 loader: fix panic in CGo files with syntax errors
If all of the Go files presented to the compiler have syntax errors,
cgo.Process gets an empty files slice and will panic:

    panic: runtime error: index out of range [0] with length 0

    goroutine 1 [running]:
    github.com/tinygo-org/tinygo/cgo.Process({0x0, 0x4e8e36, 0x0}, {0xc000024104, 0x18}, 0xc000090fc0, {0xc000899780, 0x7, 0xc00018ce68})
    	/home/ayke/src/github.com/tinygo-org/tinygo/cgo/cgo.go:186 +0x22ee
    github.com/tinygo-org/tinygo/loader.(*Package).parseFiles(0xc0001ccf00)
    	/home/ayke/src/github.com/tinygo-org/tinygo/loader/loader.go:400 +0x51e

This is simple to work around: just don't try to run CGo when there are
no files to process. It just means there are bugs to fix before CGo can
properly run.

(This is perhaps not the nicest solution but certainly the simplest).
2021-09-15 19:04:26 +02:00
Ayke van Laethem c528a168ee os: add SEEK_SET, SEEK_CUR, and SEEK_END
These are deprecated but still used by some code.
2021-09-15 18:58:17 +02:00
Ayke van Laethem 88b9c27dbf unix: check for mmap error and act accordingly
At startup, a large chunk of virtual memory is used up by the heap. This
works fine in emulation (qemu-arm), but doesn't work so well on an
actual Raspberry Pi. Therefore, this commit reduces the requested amount
until a heap size is found that works on the system.

This can certainly be improved, but for now it's an important fix
because it allows TinyGo built binaries to actually run on a Raspberry
Pi with just 1GB RAM.
2021-09-15 17:06:21 +02:00
Ayke van Laethem 37ee4bea40 arm: switch to Thumb instruction set on ARM
This reduces binary size substantially, for two reasons:

  - It switches to a much more architecture ARMv4 vs ARMv7.
  - It switches to Thumb2, which is a lot denser than regular ARM.

Practically all modern and not-so-modern ARM chips support Thumb2, so
this seems like a safe change to me.

The size in numbers:

  - Code size for testdata/stdlib.go is reduced by about 35%.
  - Binary size for testdata/stdlib.go (when compiling with -no-debug to
    strip debug information) is reduced by about 16%.
2021-09-15 15:28:10 +02:00
ardnew ca4f251050 relax restriction on configuration with duplicate settings 2021-09-13 09:29:20 +02:00
ardnew 1e92e5f6c6 teensy40: enable hardware UART reconfiguration, fix receive watermark interrupt 2021-09-13 09:29:20 +02:00
Damian Gryski 3eb9dca695 machine: fix copy-paste error for atsamd21/51 calibTrim block
Fixes #2097
2021-09-10 18:07:17 +02:00
sago35 53794cf339 target: fix pid for mdbt50qrx-uf2 2021-09-09 18:40:03 +02:00
Damian Gryski da6c14481f runtime: fix a suspicious bitwise operation
The `0 << nxp.SIM_CLKDIV1_OUTDIV1_Pos` term was duplicated.
No effect other than triggering a static analysis check.
2021-09-09 17:51:46 +02:00
sago35 fb5516604d targets: add DefaultUART to adafruit boards 2021-09-09 15:58:35 +02:00
Ayke van Laethem e9f1ed701a cgo: don't normalize CGo tests anymore
Normalization was required because previously we supported Go 1.13 and
Go 1.14 at the same time. Now we've dropped support for both so this
normalization is not necessary anymore.

CGo support remains the same. It's just the test outputs that aren't
normalized anymore.
2021-09-09 13:28:50 +02:00
Ayke van Laethem 6315db21f7 compiler: avoid zero-sized alloca in channel operations
This works around a bug in LLVM
(https://bugs.llvm.org/show_bug.cgi?id=49916) but seems like a good
change in general.
2021-09-09 11:24:52 +02:00
Damian Gryski 485a9284e7 builder: add missing error check for ioutil.TempFile() 2021-09-08 15:21:31 +02:00
BCG 602d3d7c78 board: add Raytac MDBT50Q-RX Dongle with TinyUF2 2021-09-08 12:40:49 +02:00
Ayke van Laethem 409688e67a compiler: fix equally named structs in different scopes
For example, in this code:

    type kv struct {
           v float32
    }

    func foo(a *kv) {
           type kv struct {
                   v byte
           }
    }

Both 'kv' types would be given the same LLVM type, even though they are
different types! This is fixed by only creating a LLVM type once per Go
type (types.Type).

As an added bonus, this change gives a performance improvement of about
0.4%. Not that much, but certainly not nothing for such a small change.
2021-09-08 10:02:57 +02:00
Damian Gryski d348db4a0d tinygo: add a flag for creating cpu profiles 2021-09-08 01:09:10 +02:00
Damian Gryski 95ab7cb8d1 Makefile: add smoke test with gc=leaking to test dead asm code 2021-09-07 08:00:11 +02:00
Damian Gryski 32de906f6d internal/task, runtime: add subsections_via_symbols to assembly files on darwin
This allows the assembly routines in these files to be stripped as dead
code if they're not referenced.  This solves the link issues on MacOS
when the `leaking` garbage collector or the `coroutines` scheduler
are selected.

Fixes #2081
2021-09-07 08:00:11 +02:00
Ron Evans eaab05fc43 Revert "Minor changes to support go 1.17"
This reverts commit 2d224ae049.
2021-09-06 12:39:40 +02:00
sago35 4d1945b467 nrf52840: fix ram size 2021-09-05 23:54:26 +02:00
Mike Mogenson fd9422d218 fix GBA ROM header
Populate the GBA ROM header so that emulators and physical Game Boy
Advance consoles recognize the ROM as a valid game.

Note: The reserve space at the end of the header was hand-tuned. Why
this magic value?
2021-09-05 19:59:26 +02:00
sago35 bbbe7d43ce machine/arduino_mkrwifi1010: fix pin definition of NINA_RESETN 2021-09-05 14:10:25 +02:00
Damian Gryski b3f1dacbb9 interp: remove unused gepOperands slice 2021-09-05 12:00:07 +02:00
Damian Gryski 5fa1e7163a src/runtime: reset heapptr to heapStart after preinit()
heapptr is assinged to heapStart (which is 0) when it's declared, but preinit()
may have moved the heap somewhere else.  Set heapptr to the proper value
of heapStart when we initialize the heap properly.

This allows the leaking allocator to work on unix.
2021-09-04 12:13:53 +02:00
deadprogram 4b1f92600f docker: use go 1.17 for docker dev build
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-09-02 11:18:52 +02:00
sago35 ca39bc9f35 machine/feather-rp2040: add pin name definition for feather 2021-09-01 20:55:35 +02:00
sago35 f985f2c376 targets: add openocd configuration for rp2040 2021-09-01 19:37:23 +02:00
Federico G. Schwindt f0936ffccb Implement os.Executable
For now this is a stub for everything but linux, which is a slightly
modified copy of the official implementation.

Should address #1778.
2021-09-01 19:01:35 +02:00
Yurii Soldak 97d48e5c02 board/nano-rp2040: define NINA_SPI and fix wifinina pins 2021-09-01 17:24:19 +02:00
Patricio Whittingslow a7c53cce06 machine/rp2040: add PWM implementation (#2015)
machine/rp2040: add PWM implementation
2021-09-01 16:58:13 +02:00
Federico G. Schwindt 2d224ae049 Minor changes to support go 1.17 2021-08-31 16:04:42 +02:00
Olivier Fauchon 6c6fea5387 BlackMagic (BMP) ARM JTAG/SWD debugger:
- Flashing and debugging with BMP can be done with -programmer=bmp
- New getBMPPorts() function was added to properly detect BMP USB serial ports.
2021-08-31 10:03:40 +02:00
sago35 98bd947817 machine/arduino_mkrwifi1010: add board definition for Arduino MKR WiFi 1010 2021-08-30 15:45:47 +02:00
Ayke van Laethem 255f35671d compiler: add support for new language features of Go 1.17 2021-08-30 09:18:58 +02:00
Ayke van Laethem 8e88e560a1 all: add support for Go 1.17 2021-08-30 09:18:58 +02:00
Ayke van Laethem d45497691f reflect: add StructField.IsExported method
This field was introduced in Go 1.17 and is used by the encoding/json
package (starting with Go 1.17).
2021-08-30 09:18:58 +02:00
Ayke van Laethem ad73986070 goenv: improve Go version detection
First look at the VERSION file, only then look at
src/runtime/internal/sys/zversion.go. This makes it possible to
correctly detect the Go version for release candidates.
2021-08-30 09:18:58 +02:00
deadprogram 931f87f96a docker: golang default images now based on bullseye
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-08-18 20:28:36 +02:00
deadprogram 192a32f8d9 docker: use autoremove to tr to cleanup broken packages
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-08-18 20:19:33 +02:00
deadprogram 972f4254eb docker: add GH actions build on fix-docker-llvm-build branch to sort out build issues
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-08-18 20:18:16 +02:00
deadprogram 7d83e2ee5c docker: apt clean before apt get of llvm to avoid broken packages
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-08-18 20:01:50 +02:00
Ayke van Laethem 0f2f73be53 compiler: fix max possible slice
This commit improves make([]T, len) to be closer to upstream Go. The
difference is unlikely to have much real-world effect, but previously
certain make([]T, len) expressions would not result in a slice out of
bounds error in TinyGo while they would have done such a thing in Go
proper. In practice, available RAM is likely to be a bigger limiting
factor.
2021-08-17 08:16:27 +02:00
Ayke van Laethem a2cc5715ba compiler: add *ssa.MakeSlice bounds tests
There are some bugs in it. This commit adds the tests, so that the next
commit can show what changed.
2021-08-17 08:16:27 +02:00
Ayke van Laethem 59d53182bb all: use new testing features of Go 1.14 and 1.15
This simplifies the tests a bit.
2021-08-16 21:19:26 +02:00
Ayke van Laethem 25c7bfd404 ci: drop support for Go 1.13 and 1.14
They aren't supported anymore in CI, and because untested code is broken
code, let's remove support for these Go versions altogether.
2021-08-16 21:19:26 +02:00
Ayke van Laethem 04f520040e testing: add support for the -test.v flag
This flag is passed automatically with the (new) -v flag for TinyGo. For
example, this prints all the test outputs:

    $ tinygo test -v crypto/md5
    === RUN   TestGolden
    --- PASS: TestGolden
    === RUN   TestGoldenMarshal
    --- PASS: TestGoldenMarshal
    === RUN   TestLarge
    --- PASS: TestLarge
    === RUN   TestBlockGeneric
    --- PASS: TestBlockGeneric
    === RUN   TestLargeHashes
    --- PASS: TestLargeHashes
    PASS
    ok  	crypto/md5	0.002s

This prints just a summary:

    $ tinygo test crypto/md5
    PASS
    ok  	crypto/md5	0.002s

(The superfluous 'PASS' message may be removed in the future).

This is especially useful when testing a large number of packages:

    $ tinygo test crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
    PASS
    ok  	crypto/md5	0.002s
    PASS
    ok  	crypto/sha1	0.043s
    PASS
    ok  	crypto/sha256	0.002s
    PASS
    ok  	crypto/sha512	0.003s

At the moment, the -test.v flag is not supplied to binaries running in
emulation. I intend to fix this after
https://github.com/tinygo-org/tinygo/pull/2038 lands by refactoring
runPackageTest, Run, and runTestWithConfig in the main package which all
do something similar.
2021-08-13 08:53:40 +02:00
Ayke van Laethem f57e9622fd baremetal,wasm: support command line params and environment variables
This is mainly useful to be able to run `tinygo test`, for example:

    tinygo test -target=cortex-m-qemu -v math

This is not currently supported, but will be in the future.
2021-08-12 21:19:24 +02:00
Ayke van Laethem c25a7cc747 testing: test testing package using tinygo test 2021-08-12 13:23:41 +02:00
Ayke van Laethem 5e5ce98d42 compiler: add aliases for many hashing packages
This commit adds support for the following packages:

  - crypto/md5
  - crypto/sha1
  - crypto/sha256
  - crypto/sha512

They would normally need assembly implementations, but with these
aliases they already work everywhere.
2021-08-10 20:08:27 +02:00
Ayke van Laethem a3c4421f39 compiler: move math aliases from the runtime to the compiler
This makes them more flexible, especially with Go 1.17 making the
situation more complicated (see
https://github.com/golang/go/commit/1d20a362d0ca4898d77865e314ef6f73582daef0).
It also makes it possible to do the same for many other functions, such
as assembly implementations of cryptographich functions which are
similarly dependent on the architecture.
2021-08-10 20:08:27 +02:00
Ayke van Laethem 58565b42cc compiler: move LLVM math builtin support into the compiler
This simplifies src/runtime/math.go, which I eventually want to remove
entirely by moving the given functionality into the compiler.
2021-08-10 20:08:27 +02:00
Ayke van Laethem ca7c849da3 386: bump minimum requirement to the Pentium 4
Previously we used the i386 target, probably with all optional features
disabled. However, the Pentium 4 has been released a _long_ time ago and
it seems reasonable to me to take that as a minimum requirement.

Upstream Go now also seems to move in this direction:
https://github.com/golang/go/issues/40255

The main motivation for this is that there were floating point issues
when running the tests for the math package:

    GOARCH=386 tinygo test math

I haven't investigated what's the issue, but I strongly suspect it's
caused by the weird x87 80-bit floating point format. This could perhaps
be fixed in a different way (by setting the FPU precision to 64 bits)
but I figured that just setting the minimum requirement to the Pentium 4
would probably be fine. If needed, we can respect the GO386 environment
variable to support these very old CPUs.

To support this newer CPU, I had to make sure that the stack is aligned
to 16 bytes everywhere. This was not yet always the case.
2021-08-10 20:08:27 +02:00
Ayke van Laethem 6c1301688b math: fix math.Max and math.Min
The math package failed the package tests on arm64 and wasm:

    GOARCH=arm64 tinygo test math

Apparently the builtins llvm.maximum.f64 and llvm.minimum.f64 have
slightly different behavior on arm64 and wasm compared to what Go
expects.
2021-08-10 20:08:27 +02:00
Ayke van Laethem d05103668f crypto/rand: switch to arc4random_buf
This doesn't have the potential blocking issue of the getentropy call
(which calls WASI random_get when using wasi-libc) and should therefore
be a lot faster.

For context, this is what the random_get documentation says:

> Write high-quality random data into a buffer. This function blocks
> when the implementation is unable to immediately provide sufficient
> high-quality random data. This function may execute slowly, so when
> large mounts of random data are required, it's advisable to use this
> function to seed a pseudo-random number generator, rather than to
> provide the random data directly.
2021-08-09 15:20:39 +02:00
Patricio Whittingslow 4f7b23c2b7 machine/rp2040: add I2C support (#2013)
machine/rp2040: add i2c support
2021-08-06 17:22:50 +02:00
Dan Kegel cfae2d4f9a Makefile: add src/testing to FMT_PATHS 2021-08-06 08:19:15 +02:00
Dan Kegel 55789fd2c2 src/testing/benchmark.go: add subset implementation of Benchmark
Partially fixes #1808

Allows the following to succeed:

curl "https://golang.org/test/fibo.go?m=text" > fibo.go
tinygo build -o fibo fibo.go
./fibo -bench
2021-08-06 08:19:15 +02:00
Ayke van Laethem 478c592b13 wasm: add support for the crypto/rand package
This is done via wasi-libc and the WASI interface, for ease of
maintenance (only one implementation for both WASI and JS/browsers).
2021-08-05 19:01:14 +02:00
Ayke van Laethem ab47cea055 transform: improve GC stack slot pass to work around a bug
Bug 1790 ("musttail call must precede a ret with an optional bitcast")
is caused by the GC stack slot pass inserting a store instruction
between a musttail call and a return instruction. This is not allowed in
LLVM IR.

One solution would be to remove the musttail. That would probably work,
but 1) the go-llvm API doesn't support this and 2) this might have
unforeseen consequences. What I've done in this commit is to move the
store instruction to a position earlier in the basic block, just after
the last access to the GC stack slot alloca.

Thanks to @fgsch for a very small repro, which I've used as a regression
test.
2021-08-04 20:06:59 +02:00
soypat 98e70c9b19 machine/rp2040: add SPI support
spi working with loopback

SPI working

apply @deadprogram's suggestions

consolidate SPI board pin naming

fix up SPI configuration

add feather-rp2040 SPI pins

add arduino connect SPI pins

add SPI handle variables
2021-07-31 22:11:08 +02:00
Ayke van Laethem 7434e5a2c7 main: strip debug information at link time instead of at compile time
Stripping debug information at link time also allows relocation
compression (aka linker relaxations). Keeping debug information at
compile time and optionally stripping it at link time has some
advantages:

  * Automatic stack sizes on Cortex-M rely on the presence of debug
    information.
  * Some parts of the compiler now rely on the presence of debug
    information for proper diagnostics.
  * It works better with the cache: there is no distinction between
    debug and no-debug builds.
  * It makes it easier (or possible at all) to enable debug information
    in the wasi-libc library without big downsides.
2021-07-31 18:33:52 +02:00
Ayke van Laethem 65c1978965 wasm: align heap to 16 bytes
This commit fixes two things:

  * It changes the alignment to 16 bytes (from 4), to match max_align_t
    in C.
  * It manually aligns heapStart on WebAssembly, to work around a bug in
    wasm-ld with --stack-first (see https://reviews.llvm.org/D106499).
2021-07-30 08:38:51 +02:00
Federico G. Schwindt e834d78871 Fix undefined symbols error
Currently TinyGo does not process SFiles (assembly files), which
are needed by math/big. Add math_big_pure_go to the build tags to
unbreak it.
2021-07-27 14:14:39 +02:00
Ayke van Laethem 03481789b0 runtime: fix time base for time.Now()
This function previously returned the atomic time, that isn't affected
by system time changes but also has a time base at some arbitrary time
in the past. This makes sense for baremetal platforms (which typically
don't know the wall time) but it gives surprising results on Linux and
macOS: time.Now() usually returns a time somewhere near the start of
1970.

This commit fixes this by obtaining both time values: the monotonic time
and the wall clock time. This is also how the Go runtime implements the
time.now function.
2021-07-20 22:19:13 +02:00
sago35 73cf187552 machine/feather-nrf52: fix pin definition of uart 2021-07-20 17:45:41 +02:00
Ayke van Laethem b40703e986 wasm: override dlmalloc heap implementation from wasi-libc
These two heaps conflict with each other, so that if any function uses
the dlmalloc heap implementation it will eventually result in memory
corruption.

This commit fixes this by implementing all heap-related functions. This
overrides the functions that are implemented in wasi-libc. That's why
all of them are implemented (even if they just panic): to make sure no
program accidentally uses the wrong one.
2021-07-15 00:13:17 +02:00
Ayke van Laethem 00ea0b1d57 build: list libraries at the end of the linker command
Static libraries should be added at the end of the linker command, after
all object files. If that isn't done, that's _usually_ not a problem,
unless there are duplicate symbols. In that case, weird dependency
issues can arise. To solve that, object files (that may include symbols
to override symbols in the library) should be listed first on the
command line and then the static libraries should be listed.

This fixes an issue with overriding some symbols in wasi-libc.
2021-07-15 00:13:17 +02:00
Ayke van Laethem efa0410075 interp: fix bug in compiler-time/run-time package initializers
Make sure that if a package initializer cannot be run, later package
initializers won't try to access any global variables touched by the
uninterpretable package initializer.
2021-07-14 22:33:32 +02:00
Ayke van Laethem 607d824211 interp: keep reverted package initializers in order
Previously, a package initializer that could not be reverted correctly
would be called at runtime. But the initializer would be called in the
wrong order: after later packages are initialized.

This commit fixes this oversight and adds a test to verify the new
behavior.
2021-07-14 22:33:32 +02:00
Ayke van Laethem 8cc7c6d572 interp: populate Inst field in interp.Error
It is used in the main package but wasn't actually set anywhere.
2021-07-14 22:33:32 +02:00
Ayke van Laethem cdba4fa8cc interp: don't ignore array indices for untyped objects
This fixes https://github.com/tinygo-org/tinygo/issues/1884.
My original plan to fix this was much more complicated, but then I
realized that the output type doesn't matter anyway and I can simply
cast the type to an *i8 and perform a GEP on that pointer.
2021-07-14 07:55:05 +02:00
Ayke van Laethem 0565b7c0e0 cortexm: fix stack overflow because of unaligned stacks
On ARM, the stack has to be aligned to 8 bytes on function calls, but
not necessarily within a function. Leaf functions can take advantage of
this by not keeping the stack aligned so they can avoid pushing one
register. However, because regular functions might expect an aligned
stack, the interrupt controller will forcibly re-align the stack when an
interrupt happens in such a leaf function (controlled by the STKALIGN
flag, defaults to on). This means that stack size calculation (as used
in TinyGo) needs to make sure this extra space for stack re-alignment is
available.

This commit fixes this by aligning the stack size that will be used for
new goroutines.

Additionally, it increases the stack canary size from 4 to 8 bytes, to
keep the stack aligned. This is not strictly necessary but is required
by the AAPCS so let's do it anyway just to be sure.
2021-07-07 09:25:47 +02:00
soypat 444dded92c move xtoi2 to parse.go 2021-07-02 18:49:14 +02:00
Patricio Whittingslow 42785e08e8 add MAC address implementation to net 2021-07-02 18:49:14 +02:00
sago35 2d633e3a28 version: update TinyGo version to 0.20.0-dev 2021-07-02 18:47:30 +02:00
Ayke van Laethem 64d048c47c main: release version 0.19.0 2021-06-30 20:05:10 +02:00
sago35 c8e231bc0b targets: add serial and serial-port key to JSON files for seeed boards 2021-06-29 09:07:02 +02:00
sago35 b00cfc001e targets: add serial and serial-port key to JSON files for adafruit boards 2021-06-29 09:07:02 +02:00
sago35 e127ceac67 machine/feather-nrf52840-sense: fix msd-volume-name 2021-06-28 11:38:10 +02:00
sago35 e5453ebe27 machine/feather-nrf52840-sense: add board definition for Adafruit Feather nRF52840 Sense 2021-06-26 15:37:17 +02:00
deadprogram 0e267dd230 targets: add serial key to JSON files for newly added rp2040 boards, and also nano-33-ble board
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-06-25 22:06:16 +02:00
Ayke van Laethem 96e863f0f3 all: add a flag to the command line to select the serial implementation
This can be very useful for some purposes:

  * It makes it possible to disable the UART in cases where it is not
    needed or needs to be disabled to conserve power.
  * It makes it possible to disable the serial output to reduce code
    size, which may be important for some chips. Sometimes, a few kB can
    be saved this way.
  * It makes it possible to override the default, for example you might
    want to use an actual UART to debug the USB-CDC implementation.

It also lowers the dependency on having machine.Serial defined, which is
often not defined when targeting a chip. Eventually, we might want to
make it possible to write `-target=nrf52` or `-target=atmega328p` for
example to target the chip itself with no board specific assumptions.

The defaults don't change. I checked this by running `make smoketest`
before and after and comparing the results.
2021-06-25 17:58:39 +02:00
Ayke van Laethem 75298bb84b os: implement process related functions
This commit implements various process related functions like
os.Getuid() and os.Getpid(). It also implements or improves this support
in the syscall package if it isn't available yet.
2021-06-25 16:14:47 +02:00
Ayke van Laethem e65592599c compiler: implement syscall.rawSyscallNoError in inline assembly
This makes it possible to call syscall.Getpid() on Linux, for example.
These syscalls never return an error so don't need any error checking.
2021-06-25 16:14:47 +02:00
Yurii Soldak e02f308d43 rp2040: fix for nano-rp2040 board 2021-06-24 17:34:14 +02:00
Yurii Soldak bfe3f68647 smoke&readme: add missing boards 2021-06-24 17:34:14 +02:00
Ayke van Laethem 2bb70812a8 compiler: add function and global section pragmas
This patch adds a new pragma for functions and globals to set the
section name. This can be useful to place a function or global in a
special device specific section, for example:

  * Functions may be placed in RAM to make them run faster, or in flash
    (if RAM is the default) to not let them take up RAM.
  * DMA memory may only be placed in a special memory area.
  * Some RAM may be faster than other RAM, and some globals may be
    performance critical thus placing them in this special RAM area can
    help.
  * Some (large) global variables may need to be placed in external RAM,
    which can be done by placing them in a special section.

To use it, you have to place a function or global in a special section,
for example:

    //go:section .externalram
    var externalRAMBuffer [1024]byte

This can then be placed in a special section of the linker script, for
example something like this:

    .bss.extram (NOLOAD) : {
        *(.externalram)
    } > ERAM
2021-06-24 15:00:30 +02:00
Ayke van Laethem 293f4ea7bc compiler: add tests for pragmas
These pragmas weren't really tested anywhere, except that some code
might break if they are not properly applied.

These tests make it easy to see they work correctly and also provide a
logical place to add new pragma tests.

I've also made a slight change to how functions and globals are created:
with the change they're also created in the IR even if they're not
referenced. This makes testing easier.
2021-06-24 15:00:30 +02:00
Ayke van Laethem c3032660c9 wasi: remove wasm build tag
The wasm build tag together with GOARCH=arm was causing problems in the
internal/cpu package. In general, I think having two architecture build
tag will only cause problems (in this case, wasm and arm) so I've
removed the wasm build tag and replaced it with tinygo.wasm.

This is similar to the tinygo.riscv build tag, which is used for older
Go versions that don't yet have RISC-V support in the standard library
(and therefore pretend to be GOARCH=arm instead).
2021-06-22 09:03:23 +02:00
Ayke van Laethem d94f42f6e2 crypto/rand: replace this package with a TinyGo version
This package provides access to an operating system resource
(cryptographic numbers) and so needs to be replaced with a TinyGo
version that does this in a different way.

I've made the following choices while adding this feature:

  - I'm using the getentropy call whenever possible (most POSIX like
    systems), because it is easier to use and more reliable. Linux is
    the exception: it only added getentropy relatively recently.
  - I've left bare-metal implementations to a future patch. This because
    it's hard to reliably get cryptographically secure random numbers on
    embedded devices: most devices do not have a hardware PRNG for this
    purpose.
2021-06-21 18:22:31 +02:00
Ayke van Laethem d8ac7ccaae interp: fix a bug in pointer cast workaround
This was triggered by the following code:

    var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365)

It is part of the new TinyGo version of the crypto/rand package.
2021-06-21 18:22:31 +02:00
Federico G. Schwindt 64058c3efb net: os: add more stubs for 1.15
Fix importing net/http.
2021-06-21 16:21:44 +02:00
Ayke van Laethem e107efa63f main: detect specific serial port IDs based on USB vid/pid
This makes it possible to flash a board even when there are multiple
different kinds of boards attached, e.g. an Arduino Uno and a Circuit
Playground Express. You can find the VID/PID pair in several ways:

 1. By running `lsusb` before and after attaching the board and looking
    at the new USB device.
 2. By grepping for `usb_PID` and `usb_VID` in the TinyGo source code.
 3. By checking the Arduino IDE boards.txt from the vendor.

Note that one board may have multiple VID/PID pairs:

  * The bootloader and main program may have a different PID, so far
    I've seen that the main program generally has the bootloader PID
    with 0x8000 added.
  * The software running on the board may have an erroneous PID, for
    example from a different board. I've seen this happen a few times.
  * A single board may have had some revisions which changed the PID.
    This is particularly true for the Arduino Uno.

As a fallback, if the given VID/PID pair isn't found, the whole set of
serial ports will be used.

There are many boards which I haven't included yet simply because I
couldn't test them.
2021-06-19 16:45:56 +02:00
Kenneth Bell 8e33f1c9eb rp2040: support Adafruit Feather RP2040 2021-06-19 12:34:40 +02:00
Ayke van Laethem 1913cb76a5 cortexm: bump default stack size to 2048 bytes
Previously it was 1024 bytes, which occasionally ran into a stack
overflow. I hope that 2048 bytes will be enough for most purposes.

I've also removed some 2048-byte stack size settings in JSON files,
which are unnecessary now that the parent (cortex-m.json) sets them.
2021-06-18 13:23:50 +02:00
Ayke van Laethem cd628bcde6 nrf52840: add support for flashing with the BOSSA tool
This only works with a custom bossac build from Arduino, not with the
upstream version. It avoids needing the manual "double tap" to enter
bootloader mode before flashing firmware.
2021-06-18 13:00:00 +02:00
Ayke van Laethem d1f445735c syscall: fix int type in libc version
Int in Go and C are two different types (hence why CGo has C.int). The
code in syscall assumed they were of the same type, which led to a bug:
https://github.com/tinygo-org/tinygo/issues/1957

While the C standard makes no guarantees on the size of int, in most
modern operating systems it is 32-bits so Go int32 would be the correct
choice.
2021-06-18 08:07:01 +02:00
Yurii Soldak 28a2ad4757 gdb: use "extended-remote" instead of "remote", allows connect from another client
My gdb complains bare "remote" command is deprecated
On top of that "extended-remote" allows "disconnect" command that enables attaching from another debug client, like an IDE
See https://sourceware.org/gdb/current/onlinedocs/gdb/Connecting.html
2021-06-17 23:52:44 +02:00
Ayke van Laethem f2e8d7112c compiler: refactor method names
This commit includes two changes:

  * It makes unexported interface methods package-private, so that it's
    not possible to type-assert on an unexported method in a different
    package.
  * It makes the globals used to identify interface methods defined
    globals, so that they can (eventually) be left in the program for an
    eventual non-LTO build mode.
2021-06-17 12:17:32 +02:00
Kenneth Bell 52d640967b rp2040: patch elf to checksum 2nd stage boot 2021-06-17 12:10:04 +02:00
deadprogram 87e48c1057 machine/rp2040: implement UART0/UART1, can be used on all rp2040 boards
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-06-16 19:13:01 +02:00
sago35 b406b81416 machine: add definition for ws2812 2021-06-16 07:32:39 +02:00
Ayke van Laethem 3a458ec75c main: make flash-command portable and safer to use
Previously, flash-command would assume it could execute a command
straight via /bin/sh, at least on non-Windows systems. Otherwise it
would just split the command using `strings.Split`. This is all a bit
hacky, so I've replaced it with a proper solution: splitting the command
_before_ substituting various paths using a real shell splitter
(shlex.Split, from Google). This solves a few things:

  * It guards against special characters in path names. This can be an
    issue on Windows where the temporary path may contain spaces (this
    is uncommon on POSIX systems).
  * It is more portable, by disallowing the use of a shell. That way, it
    doesn't differentiate between Windows and non-Windows anymore.
2021-06-15 14:36:54 +02:00
Yurii Soldak 7764797061 board/nano-33-ble: pins, blinking leds and serial 2021-06-14 00:06:59 +02:00
Kenneth Bell 5f9e339cf3 stm32: support pin input interrupts 2021-06-11 09:07:32 +02:00
Kenneth Bell c017ed2242 bluepill: GPIO PinInputPullup / PinInputPulldown
Other chips support explicit control of pull-up vs pull-down for GPIO input.  Support that with bluepill also.  PinInputPullUpDown is maintained for back-compat.  It is implicit pull-down.
2021-06-11 09:07:32 +02:00
Yurii Soldak d62a9e24e5 runtime: expose memory stats 2021-06-10 22:03:00 +02:00
Federico G. Schwindt b092856238 Add more net compatibility
Required for net/http.
2021-06-10 15:33:46 +02:00
Yurii Soldak 15d77119c9 board/nano-rp2040: pins and blinking led 2021-06-09 19:01:02 +02:00
Yurii Soldak 95af444896 machine/rp2040: gpio and adc pin definitions 2021-06-09 12:27:05 +02:00
Olaf Flebbe 1f5e4e79aa support flashing pca10059 from windows 2021-06-08 14:17:04 +02:00
deadprogram 9912dd6db1 machine/rp2040: add basic support for ADC
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-06-08 09:22:51 +02:00
deadprogram 42ec3e2469 docker: use github actions to build/publish tinygo-dev dockerfile
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-06-08 07:37:31 +02:00
Ayke van Laethem 4e610a0ee7 main: escape commands while printing them with the -x flag
This should make issues such as the one in
https://github.com/tinygo-org/tinygo/issues/1910 more obvious.
2021-06-02 16:29:30 +02:00
Ayke van Laethem af65c006e6 loader: fix testing a main package
This was broken because multiple packages in the program were named
'main', even one that was imported (by the generated main package).

This fixes tests for main packages.
2021-06-02 15:50:28 +02:00
Ayke van Laethem 98f117fca4 main: add -test flag for tinygo list
This matches `go list` and is convenient for debugging.
2021-06-02 15:50:28 +02:00
Ayke van Laethem 4c95febeee main: don't consider compile-only tests as failing
Previously a command like the following would incorrectly print FAIL:

    tinygo test -c math

This commit fixes this issue by defaulting to a passing test (the test
is marked as passed if it isn't run).
2021-06-02 14:27:55 +02:00
Federico G. Schwindt 793a3175d3 reflect: add stubs required for net/http 2021-06-02 13:28:38 +02:00
Federico G. Schwindt 78d030aa7a Add os stubs required for net/http 2021-06-01 15:20:58 +02:00
Federico G. Schwindt 62f9f61664 Add runtime stubs required for net/http
Continued from #1911.
2021-06-01 15:15:12 +02:00
Federico G. Schwindt 5b82125765 Add sync.NewCond
Required by net/http.
2021-06-01 15:02:11 +02:00
Kenneth Bell 2f248bbf8b scheduler: task.Data made 64bit to avoid overflow 2021-06-01 15:00:07 +02:00
sago35 c5ea1fde61 increase stack size for access to sdcard 2021-06-01 09:16:34 +02:00
deadprogram 36dffb5554 machine/rp2040: add support for GPIO input 2021-05-31 11:43:00 +02:00
Ayke van Laethem e8c4c4a865 nrf: don't trigger a heap allocation in SPI.Transfer
By using a 1-byte buffer, two heap allocations each `SPI.Transfer` call
can be avoided.
2021-05-30 20:56:01 +02:00
Ayke van Laethem 8b79e82686 nrf: avoid heap allocation in waitForEvent
Because arm.SVCall1 lets pointers escape, the return value of
sd_softdevice_is_enabled (passed as a pointer in a parameter) will
escape and thus this value will be heap allocated.

Use a global variable for this purpose instead to avoid the heap
allocation. This is safe as waitForEvent may only be called outside of
interrupts.
2021-05-30 20:56:01 +02:00
sago35 22eeed2da1 qtpy: add pin for neopixels 2021-05-30 11:01:19 +02:00
Kenneth Bell cfbc9be9bf rp2040: git ignore generated device files 2021-05-29 19:56:50 +02:00
Rajiv Kanchan 722a3a5c94 add rp2040, pico
adds preliminary support (just enough to run blinky1) for the Raspberry Pi Pico board along with the rp2040 mcu.
2021-05-28 18:29:04 +02:00
deadprogram ed2db8a26d Revert "scheduler: task.Data made 64bit to avoid overflow"
This reverts commit fd8938c634.
2021-05-28 07:38:59 +02:00
Kenneth Bell fd8938c634 scheduler: task.Data made 64bit to avoid overflow 2021-05-28 00:02:46 +02:00
Kenneth Bell fa3dd41a4f stm32: Use TIM for runtime clock 2021-05-28 00:02:46 +02:00
Kenneth Bell 003c96edc0 stm32f103 (bluepill): add pwm 2021-05-28 00:02:46 +02:00
Kenneth Bell ac54302301 stm32f7: add pwm 2021-05-28 00:02:46 +02:00
Kenneth Bell c43a41165a stm32l4: add pwm 2021-05-28 00:02:46 +02:00
Kenneth Bell 3145c2747e stm32l0: add pwm 2021-05-28 00:02:46 +02:00
Kenneth Bell 2c4b507d34 stm32l5: add pwm 2021-05-28 00:02:46 +02:00
Kenneth Bell ee167f15de stm32: add pwm for f4 series 2021-05-28 00:02:46 +02:00
Yurii Soldak 422ebeeec7 Do not disable interrupts on abort
Allows panic messages to be printed fully into serial console
2021-05-27 09:28:08 +02:00
Ayke van Laethem c93ddb630b compiler: skip context parameter when starting regular goroutine
Do not store the context parameter (which is used for closures and
function pointers) in the goroutine start parameter bundle for direct
functions that don't need a context parameter. This avoids storing the
(undef) context parameter and thus makes the IR to start a new goroutine
simpler in most cases.

This reduces code size in the channel.go and goroutines.go tests.
Surprisingly, all test cases (when compiled with -target=microbit) have
a changed binary, I haven't investigated why but I suppose the codegen
is slightly different for the runtime.run function (which starts the
main goroutine).
2021-05-26 20:21:08 +02:00
Ayke van Laethem 3edcdb5f0d compiler: do not emit nil checks for loading closure variables
Closure variables are allocated in a parent function and are thus never
nil. Don't do a nil check before reading or modifying the value.

This commit results in a slight reduction in code size in some test
cases: calls.go, channel.go, goroutines.go, json.go, sort.go -
presumably wherever closures are used.
2021-05-26 20:21:08 +02:00
Ayke van Laethem ec325c0643 compiler: add support for running a builtin in a goroutine
Not sure why you would ever do this, but it appears to be allowed by the
Go specification and previously TinyGo would crash with an unhelpful
error message when you would do this. I don't see any practical use of
it.

The implementation simply runs the builtin directly.
2021-05-26 20:21:08 +02:00
Ayke van Laethem 87c2ccb0b9 compiler: add tests for starting a goroutine
This commit adds a test for both WebAssembly and Cortex-M targets (which
use a different way of goroutine lowering) to show how they lower
goroutines. It makes it easier to show how the output changes in future
commits.
2021-05-26 20:21:08 +02:00
Ayke van Laethem 6e1eb28ed0 main: rename goroutine tests
While LLVM coroutines are one implementation of goroutines, it is not
the only one. Therefore, rename the tests to 'goroutines' to better
describe what they're for.
2021-05-26 20:21:08 +02:00
Ayke van Laethem 45cf2a5a1a compiler: refactor goroutine code
Move the code from the compiler.go file to the goroutine.go file, which
is a more appropriate place. This keeps all the goroutine related code
in one file, to make it easier to find.
2021-05-26 20:21:08 +02:00
deadprogram 423cae86df docker: update dev dockerfile to Go 1.16
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-05-26 17:33:50 +02:00
deadprogram ea6b65e360 cmsis-svd: update with latest to sync with upstream repo
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-05-25 22:50:08 +02:00
Kenneth Bell e3b98dabfd Support chained interrupt handlers
Multiple calls to interrupt.New are permitted with handlers called sequentially in undefined order.
2021-05-25 20:44:49 +02:00
sago35 e312cb0fe7 os: add FileMode constants from Go 1.16 2021-05-23 21:44:27 +02:00
Ayke van Laethem 541d8dcd2e reflect: implement AppendSlice
This implementation of AppendSlice simply calls through to the version
used in the runtime: runtime.sliceAppend.
2021-05-22 21:41:06 +02:00
Ayke van Laethem c8742e2b96 reflect: use SliceHeader and StringHeader variant for internal use
These variants uses an unsafe.Pointer instead of uintptr so that the
pointer/non-pointer fields match those of real slices and strings. This
may be necessary in the future once we switch to a precise garbage
collector.
2021-05-22 21:41:06 +02:00
Ayke van Laethem 711889bc3f cgo: implement prefix parsing
This implements expressions such as "-5" and "-5 - 2", in other words,
negative numbers.
2021-05-21 17:54:13 +02:00
Ayke van Laethem 70f8eeaca0 cgo: parse binary operators
This follows the Pratt parser design.
2021-05-21 17:54:13 +02:00
Ayke van Laethem 3339d0f47e cgo: create skeleton of a Pratt parser
This converts the existing const parser to the basics of a Pratt parser,
following the book "Writing An Interpreter In Go" by Thorsten Ball. It
doesn't really do anything interesting yet, it simply converts the
existing code (with existing tests) to the new structure.
2021-05-21 17:54:13 +02:00
Federico G. Schwindt a38b5c4e01 Add a stub for os.ReadDir()
This is needed by crypto/x509 in some configuration.
Related to #1888.
2021-05-20 14:14:04 +02:00
Federico G. Schwindt b20905da13 Add support for net.IP 2021-05-20 13:46:19 +02:00
Ayke van Laethem 95e4dcfb53 interp: ignore inline assembly in markExternal
The markExternal function is used when a global (function or global
variable) is somehow run at runtime. All the other globals it refers to
are from then on no longer known at compile time, so can't be used by
the interp package anymore.

This can also include inline assembly. While it is possible to modify
globals that way, it is only possible to modify exported globals:
similar to calling an undefined function (in C for example).
2021-05-20 07:42:19 +02:00
Ayke van Laethem 841f19f49e ci: disable building some optional Clang components
This commit disables the Clang static analyzer and ARCMigrate components
of Clang. These aren't used at the moment in TinyGo so don't need to be
enabled. This reduces the build by 200 files (2909 -> 2709).

The idea comes from here (via LLVM weekly):
https://www.cambus.net/speedbuilding-llvm-clang-in-5-minutes/
2021-05-19 19:12:26 +02:00
sago35 2085ffb334 version: update TinyGo version to 0.19.0-dev 2021-05-14 11:47:07 +02:00
Ayke van Laethem b67351babe machine: define Serial as the default output
Previously, the machine.UART0 object had two meanings:

  - it was the first UART on the chip
  - it was the default output for println

These two meanings conflict, and resulted in workarounds like:

  - Defining UART0 to refer to the USB-CDC interface (atsamd21,
    atsamd51, nrf52840), even though that clearly isn't an UART.
  - Defining NRF_UART0 to avoid a conflict with UART0 (which was
    redefined as a USB-CDC interface).
  - Defining aliases like UART0 = UART1, which refer to the same
    hardware peripheral (stm32).

This commit changes this to use a new machine.Serial object for the
default serial port. It might refer to the first or second UART
depending on the board, or even to the USB-CDC interface. Also, UART0
now really refers to the first UART on the chip, no longer to a USB-CDC
interface.

The changes in the runtime package are all just search+replace. The
changes in the machine package are a mixture of search+replace and
manual modifications.

This commit does not affect binary size, in fact it doesn't affect the
resulting binary at all.
2021-05-13 16:43:37 +02:00
Ayke van Laethem aa5b8d0df7 machine: make UART objects pointer receivers
This means that machine.UART0, machine.UART1, etc are of type
*machine.UART, not machine.UART. This makes them easier to pass around
and avoids surprises when they are passed around by value while they
should be passed around by reference.

There is a small code size impact in some cases, but it is relatively
minor.
2021-05-13 16:43:37 +02:00
Ayke van Laethem 7c949ad386 machine: make USBCDC global a pointer
Make the USBCDC use a pointer receiver everywhere. This makes it easier
to pass around the object in the future.

This commit sometimes changes code size, but not significantly (a few
bytes) and usually in a positive way.

My eventual goal is the following:

  - Declare `machine.USB` (or similar, name TBD) as a pointer receiver
    for the USB-CDC interface.
  - Let `machine.UART0` always point to an UART, never actually to a
    USBCDC object.
  - Define `machine.Serial`, which is either a real UART or an USB-CDC,
    depending on the board.

This way, if you want a real UART you can use machine.UARTx and if you
just want to print to the default serial port, you can use
machine.Serial.

This change does have an effect on code size and memory consumption.
There is often a small reduction (-8 bytes) in RAM consumption and an
increase in flash consumption.
2021-05-13 16:43:37 +02:00
sago35 1646326164 Update README.md 2021-05-12 12:22:08 +02:00
Ayke van Laethem e44cb7e519 main: version 0.18.0 2021-05-12 07:23:49 +02:00
Ayke van Laethem d1e96fd0a8 wasm: scan globals conservatively
Make the GC globals scan phase conservative instead of precise on
WebAssembly. This reduces code size at the risk of introducing some
false positives.

This is a stopgap measure to mitigate an issue with the precise scanning
of globals that doesn't track all pointers. It works for regular globals
but globals created in the interp package don't always have a type and
therefore may be missed by the AddGlobalsBitmap pass.
The same issue is present on Linux and macOS, but is not as noticeable
there.
2021-05-11 18:15:36 +02:00
Ayke van Laethem ff5d0c9886 compiler: only check for default stack size with tasks scheduler
With -scheduler=none, there are no goroutines so there is no stack size
anywhere. Therefore, don't check whether the default stack size is set.
2021-05-11 00:17:03 +02:00
Yurii Soldak d7ec9ddcd2 Discover USB ports only
This will ignore f.ex. bluetooth
2021-05-10 13:27:59 +02:00
sago35 e7c6bd3730 atsame5x: add support for CAN 2021-05-10 12:27:10 +02:00
Ayke van Laethem 9f5066aa6f runtime: use the tasks scheduler instead of coroutines
This results in smaller and likely more efficient code. It does require
some architecture specific code for each architecture, but I've kept the
amount of code as small as possible.
2021-05-09 17:40:13 +02:00
Ayke van Laethem 3b24fedf92 compiler: use wasm for tests
The next commit will change the implementation of func values on Linux
as a result of switching to a task-based scheduler. To keep the
compiler/testdata/func.go test working as expected, switch to
WebAssembly tests.
2021-05-09 17:40:13 +02:00
Ayke van Laethem 8cd2a462b9 runtime: remove the asyncScheduler constant
There is no reason to specialize this per chip as it is only ever used
for JavaScript. Not only that, it is causing confusion and is yet
another quirk to learn when porting the runtime to a new
microcontroller.
2021-05-08 23:08:12 +02:00
Ayke van Laethem 25b045d0a7 runtime: improve timers on nrf, and samd chips
This commit improves the timers on various microcontrollers to better
deal with counter wraparound. The result is a reduction in RAM size of
around 12 bytes and a small effect (sometimes positive, sometimes
negative) on flash consumption. But perhaps more importantly: getting
the current time is now interrupt-safe (it previously could result in a
race condition) and the timer will now be correct when the timer isn't
retrieved for a long duration. Before this commit, a call to `time.Now`
more than 8 minutes after the previous call could result in an incorrect
time.

For more details, see:
https://www.eevblog.com/forum/microcontrollers/correct-timing-by-timer-overflow-count/msg749617/#msg749617
2021-05-08 20:59:40 +02:00
Ayke van Laethem 78acbdf0d9 main: match go test output
This commit makes the output of `tinygo test` similar to that of `go
test`. It changes the following things in the process:

  * Running multiple tests in a single command is now possible. They
    aren't paralellized yet.
  * Packages with no test files won't crash TinyGo, instead it logs it
    in the same way the Go toolchain does.
2021-05-06 20:04:16 +02:00
Federico G. Schwindt 617e2791ef Add -llvm-features parameter
With this is possible to enable e.g., SIMD in WASM using -llvm-features
+simd128.  Multiple features can be specified separated by comma,
e.g., -llvm-features +simd128,+tail-call

With help from @deadprogram and @aykevl.
2021-05-06 18:07:14 +02:00
Kenneth Bell a0908ff55b compiler: openocd commands in tinygo command line 2021-05-06 15:09:41 +02:00
Ayke van Laethem 2f1f8fb075 machine: move PinMode to central location
It is always implemented exactly the same way (as an uint8) so there is
no reason to implement it in each target separately.

This also makes it easier to add some documentation to it.
2021-05-06 13:59:12 +02:00
sago35 6f61b83ad5 atsamd21: remove special handling for SPI-24mhz 2021-05-06 10:32:24 +02:00
Dan Kegel 8dfefb46d1 wasi: do not crash if argc is 0
Instead, leave args at its default value (which provides a fake argv[0] as it has for a long time).

linux and mac do not seem affected.

Fixes #1862 (tinygo apps after v0.17.0-113-g7b761fa crash if run without argv[0])
2021-05-05 19:16:28 +02:00
Ayke van Laethem 959442dc82 unix: use conservative GC by default
This commit does two things:

 1. It makes it possible to grow the heap on Linux and MacOS by
    allocating 1GB of virtual memory on startup and then slowly using it
    as necessary, when running out of available heap space.
 2. It switches the default GC to be the conservative GC (previously
    extalloc). This is good for consistency with other platforms that
    all use this same GC.

This makes the extalloc GC unused by default.
2021-05-05 17:20:15 +02:00
Ayke van Laethem c1aa152a63 unix: avoid possible heap allocation with -opt=0
This heap allocation would normally be optimized away, but with -opt=0
perhaps not. This is a problem if the conservative GC is used, because
the conservative GC needs to be initialized before use.
2021-05-05 17:20:15 +02:00
sago35 dd3d8a363a qtpy: fix i2c setting 2021-05-05 10:12:08 +02:00
sago35 bb509ec91d atsamd51, atsamd21: fix ADC.Get() value at 8bit and 10bit 2021-05-05 06:51:09 +02:00
Ayke van Laethem 944f022060 interp: support extractvalue/insertvalue with multiple operands
TinyGo doesn't emit these instructions, but they can occur as a result
of optimizations.
2021-05-04 21:21:56 +02:00
Ayke van Laethem cd517a30af transform: split interface and reflect lowering
These two passes are related, but can definitely work independently.
Which is what this change does: it splits the two passes. This should
make it easier to change these two new passes in the future.

This change now also enables slightly better testing by testing these
two passes independently. In particular, the reflect lowering pass got
some actual tests: it was barely unit-tested before.

I have verified that this doesn't really change code size, at least not
on the microbit target. Two tests do change, but in a very minor way
(and in opposite direction).
2021-05-03 20:10:49 +02:00
Olivier Fauchon 52d8655eec Patch Cleanup 2021-05-03 18:16:46 +02:00
Olivier Fauchon f5786941e5 Fix bad I2C0/I2C1 declaration 2021-05-03 18:16:46 +02:00
Ayke van Laethem 1f73941c43 ci: bump Xcode version to use macOS 10.14
The CircleCI macOS builds are failing, probably due to the old macOS
version that's used. This version (10.13 High Sierra) isn't supported
anymore on Homebrew so it seems best to me to simply bump the version.

I picked Xcode 11.1.0 because 10.3.0 is somehow triggering an error
while trying to install QEMU (the Python install fails).

Because of this newer Xcode version, I had to add an extra flag
(-isysroot) to the default command line for MacOS. The reason is that
this newer Xcode version no longer stores header files in /usr/local, an
SDK must be specified manually. With this change, the default SDK is
used.
2021-05-02 23:55:10 +02:00
Raqbit abeab51d00 Add Arduino Nano w/ New Bootloader target
Since 2018, Arduino Nanos and clones are sold with a new bootloader, which
requires programming at 115200 baud instead of the 57600 baud required
by the old one.
2021-05-01 17:09:46 +02:00
sago35 9ef75f17bf atsamd51, atsame5x: unify samd51 and same5x 2021-04-29 09:20:44 +02:00
Ayke van Laethem c3992bd77b compiler: improve position information
In many cases, position information is not stored in Go SSA instructions
because they don't exit directly in the source code. This includes
implicit type conversions, implicit returns at the end of a function,
the creation of a (hidden) slice when calling a variadic function, and
many other cases. I'm not sure where this information is supposed to
come from, but this patch takes the value (usually) from the value the
instruction refers to. This seems to work well for these implicit
conversions.

I've also added a few extra tests to the heap-to-stack transform pass,
of which one requires this improved position information.
2021-04-26 16:15:57 +02:00
Ayke van Laethem f79e66ac2e cortexm: disable FPU on Cortex-M4
On some boards the FPU is already enabled on startup, probably as part
of the bootloader. On other chips it was enabled as part of the runtime
startup code. In all these cases, enabling the FPU is currently
unsupported: the automatic stack sizing of goroutines assumes that the
processor won't need to reserve space for FPU registers. Enabling the
FPU therefore can lead to a stack overflow.

This commit either removes the code that enables the FPU, or simply
disables it in startup code. A future change should fully enable the FPU
so that operations on float32 can be performed by the FPU instead of in
software, greatly speeding up such code.
2021-04-24 18:41:40 +02:00
Ayke van Laethem 4eac212695 gen-device: add extra constants and rename them to be Go style
- Add some extra fields: FPUPresent, CPU and NVICPrioBits which may
    come in handy at a later time (and are easy to add).
  - Rename DEVICE to Device, to match Go style.

This is in preparation to the next commit, which requires the FPUPresent
flag.
2021-04-24 18:41:40 +02:00
deadprogram b661882391 machine/usbcdc: remove remaining heap allocations for USB CDC implementations
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-04-23 23:37:24 +02:00
Ayke van Laethem 321488dcfe machine: avoid heap allocations in USB code
This commit replaces most heap allocations in USB related code with
stack allocations. This is important for several reasons:

  - It avoids running the GC unnecessarily.
  - It reduces code size by 400-464 bytes.
  - USB code might be called from interrupt handlers. The heap may be in
    an inconsistent state when that happens if main thread code also
    performs heap allocations.

The last one is by far the most important one: not doing heap
allocations in interrupts is critical for correctness. But the code size
reduction alone should be worth it.

There are two heap allocations in USB related code left: in the function
receiveUSBControlPacket (SAMD21 and SAMD51). This heap allocation must
also be removed because it runs in an interrupt, but I've left that for
a future change.
2021-04-23 23:37:24 +02:00
Ayke van Laethem 80caf2dab2 copiler: add function attributes to some runtime calls
This allows better escape analysis even without being able to see the
entire program. This makes the stack allocation test case more complete
but probably won't have much of an effect outside of that (as the
compiler is able to infer these attributes in the whole-program
functionattrs pass).
2021-04-22 19:53:42 +02:00
Ayke van Laethem c466465c32 main: add -print-allocs flag that lets you print all heap allocations
This flag, if set, is a regexp for function names. If there are heap
allocations in the matching function names, these heap allocations will
be printed with an explanation why the heap allocation exists (and why
the object can't be stack allocated).
2021-04-22 19:53:42 +02:00
Ayke van Laethem 404b65941a transform: move tests to transform_test package
This allows for adding more advanced tests, for example tests that use
the compiler package so that test sources can be written in Go instead
of LLVM IR.
2021-04-22 19:53:42 +02:00
Kenneth Bell 25f3adb47e stm32: support SPI on L4 series 2021-04-21 21:09:41 +02:00
sago35 b9043b649d atsamd51: fix PWM support in atsamd51p20
This change is related to the following commit
72acda22b0
2021-04-21 15:02:47 +02:00
Ayke van Laethem 7b761fac78 runtime: implement command line arguments in hosted environments
Implement command line arguments for Linux, MacOS and WASI.
2021-04-21 10:32:09 +02:00
Ayke van Laethem c47cdfa66f runtime: implement environment variables for Linux 2021-04-21 10:32:09 +02:00
Ayke van Laethem 768a15c1dd interp: remove map support
The interp package is in many cases able to execute map functions in the
runtime directly. This is probably slower than adding special support
for them in the interp package and also doesn't cover all cases (most
importantly, map keys that contain pointers) but removing this code also
removes a large amount of code that needs to be maintained and is
susceptible to hard-to-find bugs.

As a side effect, this resulted in different output of the
testdata/map.go test because the test relied on the existing iteration
order of TinyGo maps. I've updated the test to not rely on this test,
making the output compatible with what the Go toolchain would output.
2021-04-21 07:37:22 +02:00
Ayke van Laethem c1c3be1aa7 interp: fix phi instruction
I've discovered a bug in the implementation of the PHI instruction in
the interp package. This commit fixes the bug.

I've found this issue while investigating an issue with maps after
running interp per package.
2021-04-21 07:37:22 +02:00
sago35 b2e72c96f4 ci: improve llvm-build cache 2021-04-19 17:24:52 +02:00
Ayke van Laethem f706219996 builder: hard code Clang compiler
At the moment, all targets use the Clang compiler to compile C and
assembly files. There is no good reason to make this configurable
anymore and in fact it will make future changes more complicated (and
thus more likely to have bugs). Therefore, I've removed support for
setting the compiler.

Note that the same is not true for the linker. While it makes sense to
standardize on the Clang compiler (because if Clang doesn't support a
target, TinyGo is unlikely to support it either), linkers will remain
configurable for the foreseeable future. One example is Xtensa, which is
supported by the Xtensa LLVM fork but doesn't have support in ld.lld
yet.

I've also fixed a bug in compileAndCacheCFile: it wasn't using the right
CFlags for caching purposes. This could lead to using stale caches. This
commit fixes that too.
2021-04-19 13:14:33 +02:00
sago35 6152a661e8 ci: improve llvm-source cache 2021-04-19 00:55:42 +02:00
Dan Kegel f1a5743f77 Make fmt-check happy again 2021-04-17 00:01:37 +02:00
sago35 9f52fe4e4a atsame51: add initial support for feather-m4-can 2021-04-16 17:49:46 +02:00
developer cb886a35c9 PWM Support for atmega1280
Add arduino mega 1280 PWM test
2021-04-16 17:47:31 +02:00
Tobias Theel 5707022951 add goroot for snap installs 2021-04-15 17:34:21 +02:00
sago35 bd212cc000 atsame54: add initial support for atsame54-xpro 2021-04-15 15:43:37 +02:00
Ayke van Laethem 6dd5666ed1 wasm: use WASI ABI for exit function
This improves compatibility between the regular browser target
(-target=wasm) and the WASI target (-target=wasi). Specifically, it
allows running WASI tests like this:

    tinygo test -target=wasi encoding/base32
2021-04-15 08:45:08 +02:00
Ayke van Laethem f145663464 cortexm: add __isr_vector symbol
This doesn't change the firmware, but it does make the disassembly of
the ELF files. Before:

    Disassembly of section .text:

    00000000 <(machine.UART).Write-0x100>:
           0:       20001000        .word   0x20001000
           4:       000009db        .word   0x000009db
           8:       00000f05        .word   0x00000f05
           c:       00000f0b        .word   0x00000f0b
          10:       00000f05        .word   0x00000f05

After:

    Disassembly of section .text:

    00000000 <__isr_vector>:
           0:       20001000        .word   0x20001000
           4:       000009db        .word   0x000009db
           8:       00000f05        .word   0x00000f05
           c:       00000f0b        .word   0x00000f0b
          10:       00000f05        .word   0x00000f05

The difference is that the disassembler will now use a proper symbol name
instead of using the closest by symbol (in this case, (machine.UART).Write).
This makes the disassembly easier to read.
2021-04-15 07:38:52 +02:00
Ayke van Laethem 0d66475e10 nrf52833: add PWM support
This chip wasn't included in the PR for PWM support. Adding this support
is very easy, luckily.
2021-04-14 23:42:02 +02:00
Ayke van Laethem 22b143eba8 microbit-v2: add support for S113 SoftDevice
This currently doesn't work with `tinygo flash` yet (even with
`-programmer=openocd`), you can use pyocd instead. For example, from the
Bluetooth package:

    tinygo build -o test.hex -target=microbit-v2-s113v7 ./examples/advertisement/
    pyocd flash --target=nrf52 test.hex

I intend to add support for pyocd to work around this issue, so that a simple
`tinygo flash` suffices.
2021-04-14 22:55:52 +02:00
Ayke van Laethem 3fe13a72bd microbit: remove LED constant
There doesn't appear to be a user-controllable LED outside of the LED
matrix. In fact, the pin assigned for this was P13, which was connected
to the SPI SCK pin.
2021-04-14 17:40:32 +02:00
Ayke van Laethem d919905c96 all: clean up Cortex-M target files
In this commit I've moved all core-specific flags to files for that
specific core. This is a bit of a cleanup (less duplicated JSON) but
should also help in the future when core-specific changes are made, such
as core specific build tags or when the FPU finally gets supported in
TinyGo.

Some notable specific changes:

  - I've removed floating point flags from the Teensy 3.6 target. The
    reason is that the FPU is not yet supported in TinyGo (in goroutine
    stack switching for example) and floating point numbers would only
    be supported by C files, not Go files (because the LLVM FPU feature
    flags aren't used). This would create an ABI mismatch across CGo.
  - I've added the "cpu":"cortex-m7" to the cortex-m7.json file to match
    the configuration for the Teensy 4.0. This implies a change to the
    nucleo-f722ze (because now it has its CPU field set). Somehow that
    reduces the code size, so it looks like a good change.

I don't believe any of these changes should have any practical
consequences.

One issue I've found is in the Cortex-M33 target: it uses armv7m, which
is incorrect: it should be armv8m. But the chip is backwards compatible
so this should mostly work. Switching to armv8m led to a compilation
failure because PRIMASK isn't defined, this may be an actual bug.
2021-04-14 09:17:54 +02:00
Ayke van Laethem 96b1b76483 all: use -Qunused-arguments only for assembly files
The -Qunused-arguments flag disables the warning where some flags are
not relevant to a compilation. This commonly happens when compiling
assembly files (.s or .S files) because some flags are specific to C and
not relevant to assembly.
Because practically all baremetal targets need some form of assembly,
this flag is added to most CFlags. This creates a lot of noise. And it
is also added for compiling C code where it might hide bugs (by hiding
the fact a flag is actually unused).

This commit adds the flag to all assembly compilations and removes them
from all target JSON files.
2021-04-14 09:17:54 +02:00
sago35 f234df7a50 cmsis-svd: add svd file for the atsame5x 2021-04-14 06:39:36 +02:00
Agurato e6d5c26df5 Fix RGBA color interpretation for GameBoyAdvance 2021-04-13 18:51:14 +02:00
Kenneth Bell ae59e7703e stm32: make SPI CLK fast to fix data issue
See "STM32F40x and STM32F41x Errata sheet" - SPI CLK port must be 'fast' or 'very fast' to avoid data corruption on last bit (at the APB clocks we configure).
2021-04-13 07:38:30 +02:00
Ayke van Laethem e587b1d1b4 reflect: implement New function
This is very important for some use cases, for example for Vecty.
2021-04-12 14:49:26 +02:00
Ayke van Laethem 57271d7eaa compiler: decouple func lowering from interface type codes
There is no good reason for func values to refer to interface type
codes. The only thing they need is a stable identifier for function
signatures, which is easily created as a new kind of globals. Decoupling
makes it easier to change interface related code.
2021-04-12 12:07:42 +02:00
Ayke van Laethem 8383552552 compiler: add func tests
This is basically just a golden test for the "switch" style of func
lowering. The next commit will make changes to this lowering, which will
be visible in the test output.
2021-04-12 12:07:42 +02:00
developer aa8e12c464 Arduino Mega 1280 support
Fix ldflags

Update targets/arduino-mega1280.json

Co-authored-by: Ayke <aykevanlaethem@gmail.com>

Update atmega1280.json

Update Makefile
2021-04-12 11:03:13 +02:00
Ayke van Laethem e7a05b6e74 transform: do not lower zero-sized alloc to alloca
The LLVM CoroFrame pass appears to be tripping over this zero-sized
alloca. Therefore, do what the runtime would do: return a pointer to
runtime.zeroSizedAlloc. Or just don't deal with this case. But don't
emit a zero sized alloca to avoid this LLVM bug.

More information: https://bugs.llvm.org/show_bug.cgi?id=49916
2021-04-12 08:11:28 +02:00
Ayke van Laethem 2fd8f103ab transform: fix func lowering assertion failure
The func-lowering pass has started to fail in the dev branch, probably
as a result of replacing the ConstPropagation pass with the IPSCCP pass.
This commit makes the code a bit more robust and should be able to
handle all possible cases (not just ptrtoint).
2021-04-12 08:11:28 +02:00
Ayke van Laethem 33f76d1c2e main: implement -ldflags="-X ..."
This commit implements replacing some global variables with a different
value, if the global variable has no initializer. For example, if you
have:

    package main

    var version string

you can replace the value with -ldflags="-X main.version=0.2".

Right now it only works for uninitialized globals. The Go tooling also
supports initialized globals (var version = "<undefined>") but that is a
bit hard to combine with how initialized globals are currently
implemented.

The current implementation still allows caching package IR files while
making sure the values don't end up in the build cache. This means
compiling a program multiple times with different values will use the
cached package each time, inserting the string value only late in the
build process.

Fixes #1045
2021-04-09 18:33:48 +02:00
Ayke van Laethem ea8f7ba1f9 main: add tests for less common build configurations
Don't run the entire test suite for these options, as that would quickly
explode the testing time (making it less likely people actually run it).
Instead, run just one test for each configuration that should check for
most issues.
2021-04-09 18:33:48 +02:00
Ayke van Laethem 0ffe5ac2fa main: clean up tests
- Explicitly list all test cases. This makes it possible to store
    tests in testdata/ that aren't tested on all platforms.
  - Clean up filesystem and env test, by running them in a subtest and
    deduplicating some code and removing the additionalArgs parameter.
2021-04-09 18:33:48 +02:00
Ayke van Laethem 7bac93aab3 main: remove -cflags and -ldflags flags
These are unnecessary now that they are supported in CGo.
2021-04-09 18:33:48 +02:00
Ayke van Laethem b61751e429 compiler: check for errors
Some errors were generated but never returned or never checked in the
test function. That's a problem. Therefore this commit fixes this
oversight (by me).
2021-04-09 14:05:44 +02:00
Ayke van Laethem 25dac32a88 transform: use IPSCCP pass instead of the constant propagation pass
The constant propagation pass is removed in LLVM 12, so this pass needs
to be replaced anyway. The direct replacement would be the SCCP (sparse
conditional constant propagation) pass, but perhaps a better replacement
is the IPSCCP pass, which is an interprocedural version of the SCCP
pass and propagates constants across function calls if possible.

This is not always a code size reduction, but it appears to reduce code
size in a majority of cases. It certainly reduces code size in almost
all WebAssembly tests I did.
2021-04-08 12:31:26 +02:00
Ayke van Laethem 56cf69a66b builder: run function passes per package
This should result in a small compile time reduction for incremental
builds, somewhere around 5-9%.

This commit, while small, required many previous commits to not regress
binary size. Right now binary size is basically identical with very few
changes in size (the only baremetal program that changed in size did so
with a 4 byte increase).

This commit is one extra step towards doing as much work as possible in
the parallel and cached package build step, out of the serial LTO phase.
Later improvements in this area have this change as a prerequisite.
2021-04-08 11:40:59 +02:00
Ayke van Laethem 04d12bf2ba interp: add support for switch statement
A switch statement is not normally emitted by the compiler package, but
LLVM function passes may convert a series of if/else pairs to a switch
statement. A future change will run function passes in the package
compile phase, so the interp package (which is also run after all
modules are merged together) will need to deal with these new switch
statements.
2021-04-08 11:40:59 +02:00
Ayke van Laethem 0b7957d612 compiler: optimize string literals and globals
This commit optimizes string literals and globals by setting the
appropriate alignment and using a nil pointer in zero-length strings.

  - Setting the alignment for string values has a surprisingly large
    effect, up to around 2% in binary size. I suspect that LLVM will
    pick some default alignment for larger byte arrays if no alignment
    has been specified and forcing an alignment of 1 will pack all
    strings closer together.
  - Using nil for zero-length strings also has a positive effect, but
    I'm not sure why. Perhaps it makes some optimizations more trivial.
  - Always setting the alignment on globals improves code size slightly,
    probably for the same reasons setting the alignment of string
    literals improves code size. The effect is much smaller, however.

This commit might have an effect on performance, but if it does this
should be tested separately and such a large win in binary size should
definitely not be ignored for small embedded systems.
2021-04-08 11:40:59 +02:00
Ayke van Laethem 61243f6c57 transform: don't rely on struct name of runtime.typecodeID
Sometimes, LLVM may rename named structs when merging modules.
Therefore, we can't rely on typecodeID structs to retain their struct
names.

This commit changes the interface lowering pass to not rely on these
names. The interp package does however still rely on this name, but I
hope to fix that in the future.
2021-04-08 11:40:59 +02:00
Ayke van Laethem 49ec3eb58e builder: add optsize attribute while building the package
This simplifies future changes. While the move itself is very simple, it
required some other changes to a few transforms that create new
functions to add the optsize attribute manually. It also required
abstracting away the optimization level flags (based on the -opt flag)
so that it can easily be retrieved from the config object.

This commit does not impact binary size on baremetal and WebAssembly.
I've seen a few tests on linux/amd64 grow slightly in size, but I'm not
too worried about those.
2021-04-08 11:40:59 +02:00
sago35 fa6c1b69ce build: improve error messages in getDefaultPort(), support for multiple ports 2021-04-08 10:32:20 +02:00
deadprogram 1e9a41dc94 modules: add latest go-llvm because seems like older SHA is missing?
Signed-off-by: deadprogram <ron@hybridgroup.com>
2021-04-07 18:10:43 +02:00
Kenneth Bell a30671751f stm32: add nucleo-l031k6 support
Adds i2c for all L0 series

UART, Blinky (LED) and i2c tested
2021-04-07 17:20:19 +02:00
Ayke van Laethem c246978dd7 ci: limit test runs of assert-test-linux to two jobs
Instead of the regular build, it's the `make test` line that fails due
to OOM. This is because testing means that a lot of test binaries need
to be built while the regular build only needs to link one binary.

This improves https://github.com/tinygo-org/tinygo/pull/1774 and should
hopefully actually fix the OOM errors.
2021-04-07 08:08:40 +02:00
Ayke van Laethem 72acda22b0 machine: refactor PWM support
This commit refactors PWM support in the machine package to be more
flexible. The new API can be used to produce tones at a specific
frequency and control servos in a portable way, by abstracting over
counter widths and prescalers.
2021-04-06 20:36:10 +02:00
Ayke van Laethem f880950c3e ci: limit number of jobs for assert-test-linux
This job is causing OOM errors on CircleCI so limit it to just two jobs
(which should be fine on a 2CPU executor). Hopefully this fixes the
errors in CI that have occured recently.
2021-04-06 12:57:43 +02:00
Ayke van Laethem 1bed192de0 cgo: add support for CFLAGS in .c files
This patch adds support for passing CFLAGS added in #cgo lines of the
CGo preprocessing phase to the compiler when compiling C files inside
packages. This is expected and convenient but didn't work before.
2021-04-06 10:57:50 +02:00
Ayke van Laethem 896a848001 builder: add support for -x flag
Print commands as they are executed with the -x flag. This is not yet
complete: library builds don't print commands yet. But it's a step
closer.
2021-04-05 20:52:04 +02:00
Ayke van Laethem fb03787b73 builder: cache C and assembly file outputs
This probably won't speed up the build on multicore systems (the build
is still dominated by the whole-program optimization step) but should be
useful at a later date for other optimizations. For example, I intend to
eventually optimize each package individually including C files, which
should enable cross-language optimizations (inlining C functions into Go
functions, for example). For that to work, accurate dependency tracking
is important.
2021-04-05 20:52:04 +02:00
Ayke van Laethem 83a949647f builder: refactor link file inputs
Add a 'result' member to the compileJob struct which is used by the link
job to get all the paths that should be linked together. This is not yet
necessary (the paths are fixed), but soon the paths are only known after
a linker dependency has run.
2021-04-05 20:52:04 +02:00
Ayke van Laethem 99a41bec4e transform: fix bug in interface lowering when signatures are renamed
In rare cases the signature might change as a result of LLVM renaming
some named struct types when multiple LLVM modules are merged. The
easiest workaround is to detect such mismatched signatures and adding a
bitcast: this should be safe as the underlying data is effectively of
the same type.
2021-04-05 11:44:00 +02:00
Ayke van Laethem 312f5d3833 builder: run interp per package
This results in a significant speedup in some cases. For example, this
runs over twice as fast with a warm cache:

    tinygo build -o test.elf ./testdata/stdlib.go

This should help a lot with edit-compile-test cycles, that typically
only modify a single package.

This required some changes to the interp package to deal with globals
created in a previous run of the interp package and to deal with
external globals (that can't be loaded from or stored to).
2021-04-02 13:43:57 +02:00
Ayke van Laethem 35bf0746a1 interp: make toLLVMValue return an error instead of panicking
This commit replaces a number of panics with returning an error value as
a result of changing the toLLVMValue method signature. This should make
it easier to diagnose issues.
2021-04-02 13:43:57 +02:00
sago35 8d93b9e545 atsamd21, atsamd51, nrf52840: unify usbcdc code 2021-03-29 10:31:58 +02:00
Ayke van Laethem b44d41d9ec compiler: fix "fragment covers entire variable" bug
This bug could sometimes be triggered by syscall/js code it seems. But
it's a generic bug, not specific to WebAssembly.
2021-03-29 10:16:59 +02:00
Tobias Theel 4be9802d26 throw an error on windows builds with no target specified 2021-03-29 09:35:19 +02:00
Ayke van Laethem 90b42799a2 machine: make machine.I2C0 and similar objects pointers
This makes it possible to assign I2C objects (machine.I2C0,
machine.I2C1, etc.) without needing to take a pointer.

This is important especially in the future when I2C may be driven using
DMA and the machine.I2C type needs to store some state.
2021-03-29 02:02:04 +02:00
Ayke van Laethem 71bbe93ab2 avr: remove I2C stubs from attiny support
These stubs don't really belong there: attiny currently doesn't directly
support I2C at all (although it has hardware to support a software
implementation).
2021-03-29 02:02:04 +02:00
Elliott Sales de Andrade 0535c1bbad Group together STM32 smoke tests.
And then allow them to be disabled with one option.
2021-03-29 01:46:54 +02:00
Ayke van Laethem 4f6d598ea8 reflect: implement Sizeof and Alignof for func values
This is a small change that appears to be necessary for encoding/json
support. It's simple enough to implement.
2021-03-29 01:04:11 +02:00
sago35 16e7dd83a3 gdb: enable to specify multiple candidates for gdb 2021-03-29 00:21:38 +02:00
Olaf Flebbe f23ba3b023 initial support for pca10059
Using the official USB Vendor name even for other boards.
2021-03-28 21:38:05 +02:00
Ayke van Laethem 2aa2e750b9 reflect: implement Value.CanAddr
It is used in the crypto/sha512 test, for example. And it is very simple
to implement.
2021-03-28 19:28:55 +02:00
Ayke van Laethem bcce296ca3 transform: optimize reflect.Type Implements() method
This commit adds a new transform that converts reflect Implements()
calls to runtime.interfaceImplements. At the moment, the Implements()
method is not yet implemented (how ironic) but if the value passed to
Implements is known at compile time the method call can be optimized to
runtime.interfaceImplements to make it a regular interface assert.

This commit is the last change necessary to add basic support for the
encoding/json package. The json package is certainly not yet fully
supported, but some trivial objects can be converted to JSON.
2021-03-28 14:00:37 +02:00
Ayke van Laethem c5ec955081 compiler: fix lack of method name in interface matching
This is required for correctly differentiating between interface types.
2021-03-28 14:00:37 +02:00
Ayke van Laethem 5d334922d7 compiler: add interface IR test
This is important as golden test output and to verify that the output is
correct. Later improvements and bug fixes are clearly visible in the IR,
and unintentional changes will also be immediately spotted.
2021-03-28 14:00:37 +02:00
Ayke van Laethem e9f9a4b750 reflect: fix AssignableTo and Implements methods
They both reversed the direction of the check, in a way that mostly
cancelled each other out. Of course they're still mostly unimplemented,
but it's better if they're not wrong.
2021-03-28 14:00:37 +02:00
Takeshi Yoneda 1406453350 WASI & darwin: support basic file io based on libc
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2021-03-28 12:37:15 +02:00
Ayke van Laethem 6d3c11627c compiler: fix use of global context: llvm.Int32Type()
This patch fixes a use of the global context. I've seen a few instances
of crashes in the llvm.ConstInt function when called from
makeStructTypeFields, which I believe are caused by this bug.
2021-03-25 13:05:09 +01:00
Ayke van Laethem f800f7507c reflect: check for access in the Interface method call
This fixes a type system loophole. The following program would
incorrectly run in TinyGo, while it would trigger a panic in Go:

    package main

    import "reflect"

    func main() {
        v := reflect.ValueOf(struct {
            x int
        }{})
        x := v.Field(0).Interface()
        println("x:", x.(int))
    }

Playground link: https://play.golang.org/p/nvvA18XFqFC

The panic in Go is the following:

    panic: reflect.Value.Interface: cannot return value obtained from unexported field or method

I've shortened it in TinyGo to save a little bit of space.
2021-03-24 12:19:16 +01:00
Kenneth Bell 46a7993fb8 stm32: i2c implementation for F7, L5 and L4 MCUs 2021-03-24 08:35:34 +01:00
Ayke van Laethem 9f3dcf3733 reflect: implement a number of stub functions
These stub functions are necessary for the encoding/json package. They
don't seem to be called in trivial cases, so leave them as simple stubs
for now.
2021-03-23 15:48:33 +01:00
Ayke van Laethem c849bccb83 reflect: let reflect.Type be of interface type
This matches the main Go implementation and (among others) fixes a
compatibility issue with the encoding/json package. The encoding/json
package compares reflect.Type variables against nil, which does not work
as long as reflect.Type is of integer type.

This also adds a reflect.RawType() function (like reflect.Type()) that
makes it easier to avoid working with interfaces in the runtime package.
It is internal only, but exported to let the runtime package use it.

This change introduces a small code size increase when working with the
reflect package, but I've tried to keep it to a minimum. Most programs
that don't make extensive use of the reflect package (and don't use
package like fmt) should not be impacted by this.
2021-03-23 14:32:33 +01:00
Ayke van Laethem cffe424849 interp: add support for runtime.interfaceMethod
This is necessary so that when reflect.Type is converted from a concrete
type to an interface type, the errors package can still be interpreted.
Without this change, basically every program would grow in size by a few
bytes.
2021-03-23 14:32:33 +01:00
Ayke van Laethem 51938e9d1c interp: handle (reflect.Type).Elem()
The errors package has a call like this in the package initializer. This
commit adds support for running it at compile time, avoiding the call at
runtime.

This doesn't always help (the call is already optimized away in many
small programs) but it does help to shave off some binary size in larger
programs. Perhaps more importantly, it will avoid a penalty in code size
when the reflect package will convert reflect.Type from a regular type
to an interface type.
2021-03-23 14:32:33 +01:00
Ayke van Laethem 19dec048b0 compiler: do not check for impossible type asserts
Previously there was code to avoid impossible type asserts but it wasn't
great and in fact was too aggressive when combined with reflection.

This commit improves this by checking all types that exist in the
program that may appear in an interface (even struct fields and the
like) but without creating runtime.typecodeID objects with the type
assert. This has two advantages:

  * As mentioned, it optimizes impossible type asserts away.
  * It allows methods on types that were only asserted on (in
    runtime.typeAssert) but never used in an interface to be optimized
    away using GlobalDCE. This may have a cascading effect so that other
    parts of the code can be further optimized.

This sometimes massively improves code size and mostly negates the code
size regression of the previous commit.
2021-03-23 14:32:33 +01:00
Ayke van Laethem bbb2909283 compiler: merge runtime.typecodeID and runtime.typeInInterface
This distinction was useful before when reflect wasn't properly
supported. Back then it made sense to only include method sets that were
actually used in an interface. But now that it is possible to get to
other values (for example, by extracting fields from structs) and it is
possible to turn them back into interfaces, it is necessary to preserve
all method sets that can possibly be used in the program in a type
assert, interface assert or interface method call.

In the future, this logic will need to be revisited again when
reflect.New or reflect.Zero gets implemented.

Code size increases a bit in some cases, but usually in a very limited
way (except for one outlier in the drivers smoke tests). The next commit
will improve the situation significantly.
2021-03-23 14:32:33 +01:00
Kenneth Bell aa7c7b7bd9 lgt92: update to new UART structure 2021-03-23 08:33:59 +01:00
Kenneth Bell c7bd5405c3 Add support for nucleol432 board
LED and UART are working
2021-03-23 08:33:59 +01:00
Kenneth Bell dc981ce509 stm32: separate altfunc selection for UART Tx/Rx
This is needed for stm32l432 nucleo with different altfun for tx and rx
2021-03-23 08:33:59 +01:00
Ayke van Laethem c522569378 wasm: only export explicitly exported functions
Previously we used the --export-all linker flag to export most
functions. However, this is not needed and possibly increases binary
size. Instead, we should be exporting the specific functions to be
exported.
2021-03-22 13:48:12 +01:00
Ayke van Laethem 0db4b13e37 compiler: do not emit nil checks for *ssa.Alloc instructions
An allocated object is never nil, so there is no need for a nil check.
This probably does not result in any better optimization (the nil check
is easily optimized away by LLVM because the result of runtime.alloc is
marked nonnull) but it makes the slice tests a bit cleaner.
2021-03-22 11:35:06 +01:00
Ayke van Laethem 2709d38d63 compiler: add some more slice tests 2021-03-22 11:35:06 +01:00
Ayke van Laethem 71d1b70ab7 compiler: only run tests on LLVM 11 or above
It's difficult to create clean test cases while remaining compatible
with multiple LLVM versions. Most test outputs are much more readable
after an instcombine pass but instcombine rules change between LLVM
versions, leading to different (but semantically equivalent) test
outputs.

This reduces the test coverage a little bit (because old LLVM versions
aren't tested as well), but it als makes it easier to add more complex
tests.

In the future it might be a good idea to make the compiler output a bit
less messy so these workarounds are not needed.
2021-03-22 11:35:06 +01:00
Ayke van Laethem 24676d4366 compiler: add tests for strings
This tests a few common operations on strings.
2021-03-22 11:35:06 +01:00
Ayke van Laethem e2f532709f builder, compiler: compile and cache packages in parallel
This commit switches from the previous behavior of compiling the whole
program at once, to compiling every package in parallel and linking the
LLVM bitcode files together for further whole-program optimization.
This is a small performance win, but it has several advantages in the
future:

  - There are many more things that can be done per package in parallel,
    avoiding the bottleneck at the end of the compiler phase. This
    should speed up the compiler futher.
  - This change is a necessary step towards a non-LTO build mode for
    fast incremental builds that only rebuild the changed package, when
    compiler speed is more important than binary size.
  - This change refactors the compiler in such a way that it will be
    easier to inspect the IR for one package only. Inspecting this IR
    will be very helpful for compiler developers.
2021-03-21 11:51:35 +01:00
Ayke van Laethem dc1ff80e10 compiler: remove SimpleDCE pass
The SimpleDCE pass was previously used to only compile the parts of the
program that were in use. However, lately the only real purpose has been
to speed up the compiler a bit by only compiling the necessary
functions.

This pass however is a problem for compiling (and caching) packages in
parallel. Therefore, this commit removes it as a preparatory step
towards that goal.
2021-03-21 11:51:35 +01:00
Kenneth Bell b5205cc3ca stm32: move f103 (bluepill) to common i2c code 2021-03-21 11:25:10 +01:00
akif999 a075cbedf5 fix msd-volume-name (qtpy)
at issue #1713
2021-03-21 10:00:43 +01:00
Kenneth Bell ef613a5db7 stm32: housekeeping - remove empty file 2021-03-21 00:45:29 +01:00
sago35 1571b8fd34 Add special handling when SPI Freq is 24Mhz 2021-03-19 17:34:49 +01:00
sago35 a41b72578b atsamd21: improve SPI 2021-03-19 17:34:49 +01:00
Kenneth Bell 9f3f9d05b8 housekeeping: ignore files generated by smoketests 2021-03-19 12:42:09 +01:00
Ayke van Laethem f9865a08bc transform: optimize string comparisons against ""
This optimizes a common pattern like:

    if s != "" {
        ...
    }

to:

    if len(s) != 0 {
        ...
    }

This avoids a runtime call and thus produces slightly better code.
2021-03-18 17:22:00 +01:00
Ayke van Laethem 13db2c13e5 compiler: do not use llvm.GlobalContext()
This is a leftover from a long time ago, when everything was still in
the global context. The fact that this uses the global context is most
certainly a bug.

I have seen occasional crashes in the build-packages-indepedently branch
(and PRs based on it) which I suspect are caused by this bug. I think
this is a long-dormant bug that only surfaced when doing the compilation
steps in parallel.
2021-03-18 16:49:33 +01:00
Kenneth Bell ce8ad3650a stm32l0: use unified UART logic 2021-03-18 12:10:36 +01:00
kenbell b0b84c48ec Harmonize stm32 ticks and sleep (#1673)
machine/stm32f*: move to harmonized tick / sleep logic code
2021-03-18 11:54:15 +01:00
Ayke van Laethem 5a4dcfb367 builder: add support for -opt=0
This optimization level wasn't working before because some passes expect
some globals to be cleaned up afterwards. Cleaning these globals is
easy, just add the pass necessary for it. This shouldn't reduce the
usefulness of the -opt=0 build flag as most optimizations are still
skipped.
2021-03-15 19:36:21 +01:00
1540 changed files with 123227 additions and 26581 deletions
+69 -338
View File
@@ -6,391 +6,122 @@ commands:
- run:
name: "Pull submodules"
command: git submodule update --init
apt-dependencies:
parameters:
llvm:
type: string
steps:
- run:
name: "Install apt dependencies"
command: |
echo 'deb https://apt.llvm.org/buster/ llvm-toolchain-buster-<<parameters.llvm>> main' | sudo tee /etc/apt/sources.list.d/llvm.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo apt-get update
sudo apt-get install \
llvm-<<parameters.llvm>>-dev \
clang-<<parameters.llvm>> \
libclang-<<parameters.llvm>>-dev \
lld-<<parameters.llvm>> \
gcc-arm-linux-gnueabihf \
gcc-aarch64-linux-gnu \
qemu-system-arm \
qemu-user \
gcc-avr \
avr-libc
sudo apt-get install --no-install-recommends libc6-dev-i386 lib32gcc-8-dev
install-node:
steps:
- run:
name: "Install node.js"
command: |
wget https://nodejs.org/dist/v10.15.1/node-v10.15.1-linux-x64.tar.xz
sudo tar -C /usr/local -xf node-v10.15.1-linux-x64.tar.xz
sudo ln -s /usr/local/node-v10.15.1-linux-x64/bin/node /usr/bin/node
rm node-v10.15.1-linux-x64.tar.xz
install-chrome:
steps:
- run:
name: "Install Chrome"
command: |
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt install ./google-chrome-stable_current_amd64.deb
install-wasmtime:
steps:
- run:
name: "Install wasmtime"
command: |
curl https://wasmtime.dev/install.sh -sSf | bash
sudo ln -s ~/.wasmtime/bin/wasmtime /usr/local/bin/wasmtime
install-xtensa-toolchain:
parameters:
variant:
type: string
steps:
- run:
name: "Install Xtensa toolchain"
command: |
curl -L https://github.com/espressif/crosstool-NG/releases/download/esp-2020r2/xtensa-esp32-elf-gcc8_2_0-esp-2020r2-<<parameters.variant>>.tar.gz -o xtensa-esp32-elf-gcc8_2_0-esp-2020r2-<<parameters.variant>>.tar.gz
sudo tar -C /usr/local -xf xtensa-esp32-elf-gcc8_2_0-esp-2020r2-<<parameters.variant>>.tar.gz
sudo ln -s /usr/local/xtensa-esp32-elf/bin/xtensa-esp32-elf-ld /usr/local/bin/xtensa-esp32-elf-ld
rm xtensa-esp32-elf-gcc8_2_0-esp-2020r2-<<parameters.variant>>.tar.gz
llvm-source-linux:
steps:
- restore_cache:
keys:
- llvm-source-11-v1
- llvm-source-19-v1
- run:
name: "Fetch LLVM source"
command: make llvm-source
- save_cache:
key: llvm-source-11-v1
key: llvm-source-19-v1
paths:
- llvm-project
build-wasi-libc:
- llvm-project/clang/lib/Headers
- llvm-project/clang/include
- llvm-project/compiler-rt
- llvm-project/lld/include
- llvm-project/llvm/include
hack-ninja-jobs:
steps:
- run:
name: "Hack Ninja to use less jobs"
command: |
echo -e '#!/bin/sh\n/usr/bin/ninja -j3 "$@"' > /go/bin/ninja
chmod +x /go/bin/ninja
build-binaryen-linux:
steps:
- restore_cache:
keys:
- wasi-libc-sysroot-v4
- binaryen-linux-v3
- run:
name: "Build wasi-libc"
command: make wasi-libc
name: "Build Binaryen"
command: |
make binaryen
- save_cache:
key: wasi-libc-sysroot-v4
key: binaryen-linux-v3
paths:
- lib/wasi-libc/sysroot
- build/wasm-opt
test-linux:
parameters:
llvm:
type: string
fmt-check:
type: boolean
default: true
steps:
- checkout
- submodules
- apt-dependencies:
llvm: "<<parameters.llvm>>"
- install-node
- install-chrome
- install-wasmtime
- run:
name: "Install apt dependencies"
command: |
echo 'deb https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-<<parameters.llvm>> main' > /etc/apt/sources.list.d/llvm.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
apt-get update
apt-get install --no-install-recommends -y \
llvm-<<parameters.llvm>>-dev \
clang-<<parameters.llvm>> \
libclang-<<parameters.llvm>>-dev \
lld-<<parameters.llvm>> \
cmake \
ninja-build
- hack-ninja-jobs
- build-binaryen-linux
- restore_cache:
keys:
- go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
- go-cache-v2-{{ checksum "go.mod" }}
- go-cache-v4-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
- go-cache-v4-{{ checksum "go.mod" }}
- llvm-source-linux
- run: go install -tags=llvm<<parameters.llvm>> .
- restore_cache:
keys:
- wasi-libc-sysroot-systemclang-v3
- wasi-libc-sysroot-systemclang-v7
- run: make wasi-libc
- save_cache:
key: wasi-libc-sysroot-systemclang-v3
key: wasi-libc-sysroot-systemclang-v7
paths:
- lib/wasi-libc/sysroot
- run: go test -v -tags=llvm<<parameters.llvm>> ./cgo ./compileopts ./compiler ./interp ./transform .
- when:
condition: <<parameters.fmt-check>>
steps:
- run:
# Do this before gen-device so that it doesn't check the
# formatting of generated files.
name: Check Go code formatting
command: make fmt-check lint
- run: make gen-device -j4
# TODO: change this to -skip='TestErrors|TestWasm' with Go 1.20
- run: go test -tags=llvm<<parameters.llvm>> -short -run='TestBuild|TestTest|TestGetList|TestTraceback'
- run: make smoketest XTENSA=0
- run: make tinygo-test
- run: make wasmtest
- save_cache:
key: go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
paths:
- ~/.cache/go-build
- /go/pkg/mod
- run: make fmt-check
assert-test-linux:
steps:
- checkout
- submodules
- run:
name: "Install apt dependencies"
command: |
sudo apt-get update
sudo apt-get install \
gcc-arm-linux-gnueabihf \
libc6-dev-armel-cross \
gcc-aarch64-linux-gnu \
libc6-dev-arm64-cross \
qemu-system-arm \
qemu-user \
gcc-avr \
avr-libc
sudo apt-get install --no-install-recommends libc6-dev-i386 lib32gcc-6-dev
- install-node
- install-wasmtime
- install-xtensa-toolchain:
variant: "linux-amd64"
- restore_cache:
keys:
- go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
- go-cache-v2-{{ checksum "go.mod" }}
- llvm-source-linux
- restore_cache:
keys:
- llvm-build-11-linux-v2-assert
- run:
name: "Build LLVM"
command: |
if [ ! -f llvm-build/lib/liblldELF.a ]
then
# install dependencies
sudo apt-get install cmake ninja-build
# hack ninja to use less jobs
echo -e '#!/bin/sh\n/usr/bin/ninja -j3 "$@"' > /go/bin/ninja
chmod +x /go/bin/ninja
# build!
make ASSERT=1 llvm-build
fi
- save_cache:
key: llvm-build-11-linux-v2-assert
paths:
llvm-build
- run: make ASSERT=1
- build-wasi-libc
- run:
name: "Test TinyGo"
command: make ASSERT=1 test
- save_cache:
key: go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
paths:
- ~/.cache/go-build
- /go/pkg/mod
- run: make gen-device -j4
- run: make smoketest TINYGO=build/tinygo
build-linux:
steps:
- checkout
- submodules
- run:
name: "Install apt dependencies"
command: |
sudo apt-get update
sudo apt-get install \
gcc-arm-linux-gnueabihf \
libc6-dev-armel-cross \
gcc-aarch64-linux-gnu \
libc6-dev-arm64-cross \
qemu-system-arm \
qemu-user \
gcc-avr \
avr-libc
sudo apt-get install --no-install-recommends libc6-dev-i386 lib32gcc-6-dev
- install-node
- install-wasmtime
- install-xtensa-toolchain:
variant: "linux-amd64"
- restore_cache:
keys:
- go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
- go-cache-v2-{{ checksum "go.mod" }}
- llvm-source-linux
- restore_cache:
keys:
- llvm-build-11-linux-v2-noassert
- run:
name: "Build LLVM"
command: |
if [ ! -f llvm-build/lib/liblldELF.a ]
then
# install dependencies
sudo apt-get install cmake ninja-build
# hack ninja to use less jobs
echo -e '#!/bin/sh\n/usr/bin/ninja -j3 "$@"' > /go/bin/ninja
chmod +x /go/bin/ninja
# build!
make llvm-build
fi
- save_cache:
key: llvm-build-11-linux-v2-noassert
paths:
llvm-build
- build-wasi-libc
- run:
name: "Test TinyGo"
command: make test
- run:
name: "Install fpm"
command: |
sudo apt-get install ruby ruby-dev
sudo gem install --no-document fpm
- run:
name: "Build TinyGo release"
command: |
make release deb -j3
cp -p build/release.tar.gz /tmp/tinygo.linux-amd64.tar.gz
cp -p build/release.deb /tmp/tinygo_amd64.deb
- store_artifacts:
path: /tmp/tinygo.linux-amd64.tar.gz
- store_artifacts:
path: /tmp/tinygo_amd64.deb
- save_cache:
key: go-cache-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
paths:
- ~/.cache/go-build
- /go/pkg/mod
- run:
name: "Extract release tarball"
command: |
mkdir -p ~/lib
tar -C ~/lib -xf /tmp/tinygo.linux-amd64.tar.gz
ln -s ~/lib/tinygo/bin/tinygo /go/bin/tinygo
tinygo version
- run: make smoketest
build-macos:
steps:
- checkout
- submodules
- run:
name: "Install dependencies"
command: |
curl https://dl.google.com/go/go1.16.darwin-amd64.tar.gz -o go1.16.darwin-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.16.darwin-amd64.tar.gz
ln -s /usr/local/go/bin/go /usr/local/bin/go
HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu
- install-xtensa-toolchain:
variant: "macos"
- restore_cache:
keys:
- go-cache-macos-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_PREVIOUS_BUILD_NUM }}
- go-cache-macos-v2-{{ checksum "go.mod" }}
- restore_cache:
keys:
- llvm-source-11-macos-v1
- run:
name: "Fetch LLVM source"
command: make llvm-source
- save_cache:
key: llvm-source-11-macos-v1
paths:
- llvm-project
- restore_cache:
keys:
- llvm-build-11-macos-v2
- run:
name: "Build LLVM"
command: |
if [ ! -f llvm-build/lib/liblldELF.a ]
then
# install dependencies
HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake ninja
# build!
make llvm-build
fi
- save_cache:
key: llvm-build-11-macos-v2
paths:
llvm-build
- restore_cache:
keys:
- wasi-libc-sysroot-macos-v3
- run:
name: "Build wasi-libc"
command: make wasi-libc
- save_cache:
key: wasi-libc-sysroot-macos-v3
paths:
- lib/wasi-libc/sysroot
- run:
name: "Test TinyGo"
command: make test
- run:
name: "Build TinyGo release"
command: |
make release -j3
cp -p build/release.tar.gz /tmp/tinygo.darwin-amd64.tar.gz
- store_artifacts:
path: /tmp/tinygo.darwin-amd64.tar.gz
- run:
name: "Extract release tarball"
command: |
mkdir -p ~/lib
tar -C /usr/local/opt -xf /tmp/tinygo.darwin-amd64.tar.gz
ln -s /usr/local/opt/tinygo/bin/tinygo /usr/local/bin/tinygo
tinygo version
- run: make smoketest AVR=0
- save_cache:
key: go-cache-macos-v2-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
key: go-cache-v4-{{ checksum "go.mod" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
paths:
- ~/.cache/go-build
- /go/pkg/mod
jobs:
test-llvm10-go113:
test-llvm15-go119:
docker:
- image: circleci/golang:1.13-buster
- image: golang:1.19-bullseye
steps:
- test-linux:
llvm: "10"
test-llvm10-go114:
llvm: "15"
# "make lint" fails before go 1.21 because internal/tools/go.mod specifies packages that require go 1.21
fmt-check: false
resource_class: large
test-llvm19-go124:
docker:
- image: circleci/golang:1.14-buster
- image: golang:1.24-bullseye
steps:
- test-linux:
llvm: "10"
test-llvm11-go115:
docker:
- image: circleci/golang:1.15-buster
steps:
- test-linux:
llvm: "11"
test-llvm11-go116:
docker:
- image: circleci/golang:1.16-buster
steps:
- test-linux:
llvm: "11"
assert-test-linux:
docker:
- image: circleci/golang:1.14-stretch
steps:
- assert-test-linux
build-linux:
docker:
- image: circleci/golang:1.14-stretch
steps:
- build-linux
build-macos:
macos:
xcode: "10.1.0"
steps:
- build-macos
llvm: "19"
resource_class: large
workflows:
test-all:
jobs:
- test-llvm10-go113
- test-llvm10-go114
- test-llvm11-go115
- test-llvm11-go116
- build-linux
- build-macos
- assert-test-linux
# This tests our lowest supported versions of Go and LLVM, to make sure at
# least the smoke tests still pass.
- test-llvm15-go119
# This tests LLVM 19 support when linking against system libraries.
- test-llvm19-go124
+5
View File
@@ -0,0 +1,5 @@
build/
llvm-*/
.github
.circleci
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
open_collective: tinygo
+157
View File
@@ -0,0 +1,157 @@
name: macOS
on:
pull_request:
push:
branches:
- dev
- release
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-macos:
name: build-macos
strategy:
matrix:
# macos-13: amd64 (oldest supported version as of 18-10-2024)
# macos-14: arm64 (oldest arm64 version)
os: [macos-13, macos-14]
include:
- os: macos-13
goarch: amd64
- os: macos-14
goarch: arm64
runs-on: ${{ matrix.os }}
steps:
- name: Install Dependencies
run: |
HOMEBREW_NO_AUTO_UPDATE=1 brew install qemu binaryen
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Extract TinyGo version
id: version
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Restore LLVM source cache
uses: actions/cache/restore@v4
id: cache-llvm-source
with:
key: llvm-source-19-${{ matrix.os }}-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Save LLVM source cache
uses: actions/cache/save@v4
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Restore LLVM build cache
uses: actions/cache/restore@v4
id: cache-llvm-build
with:
key: llvm-build-19-${{ matrix.os }}-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
run: |
# fetch LLVM source
rm -rf llvm-project
make llvm-source
# install dependencies
HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake ninja
# build!
make llvm-build
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Save LLVM build cache
uses: actions/cache/save@v4
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
path: llvm-build
- name: Cache wasi-libc sysroot
uses: actions/cache@v4
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-${{ matrix.os }}-v1
path: lib/wasi-libc/sysroot
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
run: make wasi-libc
- name: make gen-device
run: make -j3 gen-device
- name: Test TinyGo
run: make test GOTESTFLAGS="-short"
- name: Build TinyGo release tarball
run: make release -j3
- name: Test stdlib packages
run: make tinygo-test
- name: Make release artifact
run: cp -p build/release.tar.gz build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz
- name: Publish release artifact
# Note: this release artifact is double-zipped, see:
# https://github.com/actions/upload-artifact/issues/39
# We can essentially pick one of these:
# - have a double-zipped artifact when downloaded from the UI
# - have a very slow artifact upload
# We're doing the former here, to keep artifact uploads fast.
uses: actions/upload-artifact@v4
with:
name: darwin-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}
path: build/tinygo${{ steps.version.outputs.version }}.darwin-${{ matrix.goarch }}.tar.gz
- name: Smoke tests
run: make smoketest TINYGO=$(PWD)/build/tinygo
test-macos-homebrew:
name: homebrew-install
runs-on: macos-latest
strategy:
matrix:
version: [16, 17, 18, 19]
steps:
- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Fix Python symlinks
run: |
# Github runners have broken symlinks, so relink
# see: https://github.com/actions/setup-python/issues/577
brew list -1 | grep python | while read formula; do brew unlink $formula; brew link --overwrite $formula; done
- name: Install LLVM
run: |
brew install llvm@${{ matrix.version }}
- name: Checkout
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Build TinyGo (LLVM ${{ matrix.version }})
run: go install -tags=llvm${{ matrix.version }}
- name: Check binary
run: tinygo version
- name: Build TinyGo (default LLVM)
if: matrix.version == 19
run: go install
- name: Check binary
if: matrix.version == 19
run: tinygo version
+110
View File
@@ -0,0 +1,110 @@
# This is the Github action to build and push the tinygo/tinygo-dev Docker image.
# If you are looking for the tinygo/tinygo "release" Docker image please see
# https://github.com/tinygo-org/docker
#
name: Docker
on:
push:
branches: [ dev, fix-docker-llvm-build ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
push_to_registry:
name: build-push-dev
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Free Disk space
shell: bash
run: |
df -h
sudo rm -rf /opt/hostedtoolcache
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf /usr/local/graalvm
sudo rm -rf /usr/local/share/boost
df -h
- name: Check out the repo
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
tinygo/tinygo-dev
ghcr.io/${{ github.repository_owner }}/tinygo-dev
tags: |
type=sha,format=long
type=raw,value=latest
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Log in to Github Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Trigger Drivers repo build on Github Actions
run: |
curl -X POST \
-H "Authorization: Bearer ${{secrets.GHA_ACCESS_TOKEN}}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/tinygo-org/drivers/actions/workflows/build.yml/dispatches \
-d '{"ref": "dev"}'
- name: Trigger Bluetooth repo build on Github Actions
run: |
curl -X POST \
-H "Authorization: Bearer ${{secrets.GHA_ACCESS_TOKEN}}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/tinygo-org/bluetooth/actions/workflows/linux.yml/dispatches \
-d '{"ref": "dev"}'
- name: Trigger TinyFS repo build on Github Actions
run: |
curl -X POST \
-H "Authorization: Bearer ${{secrets.GHA_ACCESS_TOKEN}}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/tinygo-org/tinyfs/actions/workflows/build.yml/dispatches \
-d '{"ref": "dev"}'
- name: Trigger TinyFont repo build on Github Actions
run: |
curl -X POST \
-H "Authorization: Bearer ${{secrets.GHA_ACCESS_TOKEN}}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/tinygo-org/tinyfont/actions/workflows/build.yml/dispatches \
-d '{"ref": "dev"}'
- name: Trigger TinyDraw repo build on Github Actions
run: |
curl -X POST \
-H "Authorization: Bearer ${{secrets.GHA_ACCESS_TOKEN}}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/tinygo-org/tinydraw/actions/workflows/build.yml/dispatches \
-d '{"ref": "dev"}'
- name: Trigger TinyTerm repo build on Github Actions
run: |
curl -X POST \
-H "Authorization: Bearer ${{secrets.GHA_ACCESS_TOKEN}}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/tinygo-org/tinyterm/actions/workflows/build.yml/dispatches \
-d '{"ref": "dev"}'
+413
View File
@@ -0,0 +1,413 @@
name: Linux
on:
pull_request:
push:
branches:
- dev
- release
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-linux:
# Build Linux binaries, ready for release.
# This runs inside an Alpine Linux container so we can more easily create a
# statically linked binary.
runs-on: ubuntu-latest
container:
image: golang:1.24-alpine
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Install apk dependencies
# tar: needed for actions/cache@v4
# git+openssh: needed for checkout (I think?)
# ruby: needed to install fpm
run: apk add tar git openssh make g++ ruby-dev
- name: Work around CVE-2022-24765
# We're not on a multi-user machine, so this is safe.
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Extract TinyGo version
id: version
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
- name: Cache Go
uses: actions/cache@v4
with:
key: go-cache-linux-alpine-v1-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- name: Restore LLVM source cache
uses: actions/cache/restore@v4
id: cache-llvm-source
with:
key: llvm-source-19-linux-alpine-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Save LLVM source cache
uses: actions/cache/save@v4
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Restore LLVM build cache
uses: actions/cache/restore@v4
id: cache-llvm-build
with:
key: llvm-build-19-linux-alpine-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
run: |
# fetch LLVM source
rm -rf llvm-project
make llvm-source
# install dependencies
apk add cmake samurai python3
# build!
make llvm-build
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Save LLVM build cache
uses: actions/cache/save@v4
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
path: llvm-build
- name: Cache Binaryen
uses: actions/cache@v4
id: cache-binaryen
with:
key: binaryen-linux-alpine-v1
path: build/wasm-opt
- name: Build Binaryen
if: steps.cache-binaryen.outputs.cache-hit != 'true'
run: |
apk add cmake samurai python3
make binaryen STATIC=1
- name: Cache wasi-libc
uses: actions/cache@v4
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-linux-alpine-v2
path: lib/wasi-libc/sysroot
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
run: make wasi-libc
- name: Install fpm
run: |
gem install --version 4.0.7 public_suffix
gem install --version 2.7.6 dotenv
gem install --no-document fpm
- name: Run linter
run: make lint
- name: Run spellcheck
run: make spell
- name: Build TinyGo release
run: |
make release deb -j3 STATIC=1
cp -p build/release.tar.gz /tmp/tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz
cp -p build/release.deb /tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb
- name: Publish release artifact
uses: actions/upload-artifact@v4
with:
name: linux-amd64-double-zipped-${{ steps.version.outputs.version }}
path: |
/tmp/tinygo${{ steps.version.outputs.version }}.linux-amd64.tar.gz
/tmp/tinygo_${{ steps.version.outputs.version }}_amd64.deb
test-linux-build:
# Test the binaries built in the build-linux job by running the smoke tests.
runs-on: ubuntu-latest
needs: build-linux
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Install wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
version: "29.0.1"
- name: Install wasm-tools
uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Download release artifact
uses: actions/download-artifact@v4
with:
name: linux-amd64-double-zipped-${{ needs.build-linux.outputs.version }}
- name: Extract release tarball
run: |
mkdir -p ~/lib
tar -C ~/lib -xf tinygo${{ needs.build-linux.outputs.version }}.linux-amd64.tar.gz
ln -s ~/lib/tinygo/bin/tinygo ~/go/bin/tinygo
- run: make tinygo-test-wasip1-fast
- run: make tinygo-test-wasip2-fast
- run: make tinygo-test-wasm
- run: make smoketest
assert-test-linux:
# Run all tests that can run on Linux, with LLVM assertions enabled to catch
# potential bugs.
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Install apt dependencies
run: |
echo "Show cpuinfo; sometimes useful when troubleshooting"
cat /proc/cpuinfo
sudo apt-get update
sudo apt-get install --no-install-recommends \
qemu-system-arm \
qemu-system-riscv32 \
qemu-user \
simavr \
ninja-build
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
version: "29.0.1"
- name: Setup `wasm-tools`
uses: bytecodealliance/actions/wasm-tools/setup@v1
- name: Restore LLVM source cache
uses: actions/cache/restore@v4
id: cache-llvm-source
with:
key: llvm-source-19-linux-asserts-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Save LLVM source cache
uses: actions/cache/save@v4
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Restore LLVM build cache
uses: actions/cache/restore@v4
id: cache-llvm-build
with:
key: llvm-build-19-linux-asserts-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
run: |
# fetch LLVM source
rm -rf llvm-project
make llvm-source
# build!
make llvm-build ASSERT=1
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Save LLVM build cache
uses: actions/cache/save@v4
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
path: llvm-build
- name: Cache Binaryen
uses: actions/cache@v4
id: cache-binaryen
with:
key: binaryen-linux-asserts-v1
path: build/wasm-opt
- name: Build Binaryen
if: steps.cache-binaryen.outputs.cache-hit != 'true'
run: make binaryen
- name: Cache wasi-libc
uses: actions/cache@v4
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-linux-asserts-v6
path: lib/wasi-libc/sysroot
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
run: make wasi-libc
- run: make gen-device -j4
- name: Test TinyGo
run: make ASSERT=1 test
- name: Build TinyGo
run: |
make ASSERT=1
echo "$(pwd)/build" >> $GITHUB_PATH
- name: Test stdlib packages
run: make tinygo-test
- run: make smoketest
- run: make wasmtest
- run: make tinygo-test-baremetal
build-linux-cross:
# Build ARM Linux binaries, ready for release.
# This intentionally uses an older Linux image, so that we compile against
# an older glibc version and therefore are compatible with a wide range of
# Linux distributions.
# It is set to "needs: build-linux" because it modifies the release created
# in that process to avoid doing lots of duplicate work and to avoid
# complications around precompiled libraries such as compiler-rt shipped as
# part of the release tarball.
strategy:
matrix:
goarch: [ arm, arm64 ]
include:
- goarch: arm64
toolchain: aarch64-linux-gnu
libc: arm64
- goarch: arm
toolchain: arm-linux-gnueabihf
libc: armhf
runs-on: ubuntu-22.04 # note: use the oldest image available! (see above)
needs: build-linux
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get TinyGo version
id: version
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
- name: Install apt dependencies
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends \
qemu-user \
g++-${{ matrix.toolchain }} \
libc6-dev-${{ matrix.libc }}-cross
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Restore LLVM source cache
uses: actions/cache/restore@v4
id: cache-llvm-source
with:
key: llvm-source-19-linux-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Save LLVM source cache
uses: actions/cache/save@v4
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Restore LLVM build cache
uses: actions/cache/restore@v4
id: cache-llvm-build
with:
key: llvm-build-19-linux-${{ matrix.goarch }}-v3
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
run: |
# fetch LLVM source
rm -rf llvm-project
make llvm-source
# Install build dependencies.
sudo apt-get install --no-install-recommends ninja-build
# build!
make llvm-build CROSS=${{ matrix.toolchain }}
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Save LLVM build cache
uses: actions/cache/save@v4
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
path: llvm-build
- name: Cache Binaryen
uses: actions/cache@v4
id: cache-binaryen
with:
key: binaryen-linux-${{ matrix.goarch }}-v4
path: build/wasm-opt
- name: Build Binaryen
if: steps.cache-binaryen.outputs.cache-hit != 'true'
run: |
sudo apt-get install --no-install-recommends ninja-build
git submodule update --init lib/binaryen
make CROSS=${{ matrix.toolchain }} binaryen
- name: Install fpm
run: |
sudo gem install --version 4.0.7 public_suffix
sudo gem install --version 2.7.6 dotenv
sudo gem install --no-document fpm
- name: Build TinyGo binary
run: |
make CROSS=${{ matrix.toolchain }}
- name: Download amd64 release
uses: actions/download-artifact@v4
with:
name: linux-amd64-double-zipped-${{ needs.build-linux.outputs.version }}
- name: Extract amd64 release
run: |
mkdir -p build/release
tar -xf tinygo${{ needs.build-linux.outputs.version }}.linux-amd64.tar.gz -C build/release tinygo
- name: Modify release
run: |
cp -p build/tinygo build/release/tinygo/bin
cp -p build/wasm-opt build/release/tinygo/bin
- name: Create ${{ matrix.goarch }} release
run: |
make release deb RELEASEONLY=1 DEB_ARCH=${{ matrix.libc }}
cp -p build/release.tar.gz /tmp/tinygo${{ steps.version.outputs.version }}.linux-${{ matrix.goarch }}.tar.gz
cp -p build/release.deb /tmp/tinygo_${{ steps.version.outputs.version }}_${{ matrix.libc }}.deb
- name: Publish release artifact
uses: actions/upload-artifact@v4
with:
name: linux-${{ matrix.goarch }}-double-zipped-${{ steps.version.outputs.version }}
path: |
/tmp/tinygo${{ steps.version.outputs.version }}.linux-${{ matrix.goarch }}.tar.gz
/tmp/tinygo_${{ steps.version.outputs.version }}_${{ matrix.libc }}.deb
+64
View File
@@ -0,0 +1,64 @@
# This is the Github action to build and push the LLVM Docker image
# used by the tinygo/tinygo-dev Docker image.
#
# It only needs to be rebuilt when updating the LLVM version.
#
# To update, make any needed changes to this file,
# then push to the "build-llvm-image" branch.
#
# The needed image will be rebuilt, which will very likely take at least 1-2 hours.
name: LLVM
on:
push:
branches: [ build-llvm-image ]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-push-llvm:
name: build-push-llvm
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Check out the repo
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
tinygo/llvm-19
ghcr.io/${{ github.repository_owner }}/llvm-19
tags: |
type=sha,format=long
type=raw,value=latest
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Log in to Github Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
target: tinygo-llvm-build
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
+48
View File
@@ -0,0 +1,48 @@
name: Nix
on:
pull_request:
push:
branches:
- dev
- release
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
nix-test:
runs-on: ubuntu-latest
steps:
- name: Uninstall system LLVM
# Hack to work around issue where we still include system headers for
# some reason.
# See: https://github.com/tinygo-org/tinygo/pull/4516#issuecomment-2416363668
run: sudo apt-get remove llvm-18
- name: Checkout
uses: actions/checkout@v4
- name: Pull musl
run: |
git submodule update --init lib/musl
- name: Restore LLVM source cache
uses: actions/cache/restore@v4
id: cache-llvm-source
with:
key: llvm-source-19-linux-nix-v1
path: |
llvm-project/compiler-rt
- name: Download LLVM source
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Save LLVM source cache
uses: actions/cache/save@v4
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
path: |
llvm-project/compiler-rt
- uses: cachix/install-nix-action@v22
- name: Test
run: |
nix develop --ignore-environment --keep HOME --command bash -c "go install && ~/go/bin/tinygo version && ~/go/bin/tinygo build -o test ./testdata/cgo"
+12
View File
@@ -0,0 +1,12 @@
# Command that's part of sizediff.yml. This is put in a separate file so that it
# still works after checking out the dev branch (that is, when going from LLVM
# 16 to LLVM 17 for example, both Clang 16 and Clang 17 are installed).
echo 'deb https://apt.llvm.org/noble/ llvm-toolchain-noble-19 main' | sudo tee /etc/apt/sources.list.d/llvm.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install --no-install-recommends -y \
llvm-19-dev \
clang-19 \
libclang-19-dev \
lld-19
+93
View File
@@ -0,0 +1,93 @@
name: Binary size difference
on:
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
sizediff:
# Note: when updating the Ubuntu version, also update the Ubuntu version in
# sizediff-install-pkgs.sh
runs-on: ubuntu-24.04
permissions:
pull-requests: write
steps:
# Prepare, install tools
- name: Add GOBIN to $PATH
run: |
echo "$HOME/go/bin" >> $GITHUB_PATH
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # fetch all history (no sparse checkout)
submodules: true
- name: Install apt dependencies
run: ./.github/workflows/sizediff-install-pkgs.sh
- name: Restore LLVM source cache
uses: actions/cache@v4
id: cache-llvm-source
with:
key: llvm-source-19-sizediff-v1
path: |
llvm-project/compiler-rt
- name: Download LLVM source
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Cache Go
uses: actions/cache@v4
with:
key: go-cache-linux-sizediff-v2-${{ hashFiles('go.mod') }}
path: |
~/.cache/go-build
~/go/pkg/mod
- run: make gen-device -j4
- name: Download drivers repo
run: git clone https://github.com/tinygo-org/drivers.git
- name: Save HEAD
run: git branch github-actions-saved-HEAD HEAD
# Compute sizes for the PR branch
- name: Build tinygo binary for the PR branch
run: go install
- name: Determine binary sizes on the PR branch
run: (cd drivers; make smoke-test XTENSA=0 | tee sizes-pr.txt)
# Compute sizes for the dev branch
- name: Checkout dev branch
run: |
git reset --hard origin/dev
git checkout --no-recurse-submodules `git merge-base HEAD origin/dev`
- name: Install apt dependencies on the dev branch
# this is only needed on a PR that changes the LLVM version
run: ./.github/workflows/sizediff-install-pkgs.sh
- name: Build tinygo binary for the dev branch
run: go install
- name: Determine binary sizes on the dev branch
run: (cd drivers; make smoke-test XTENSA=0 | tee sizes-dev.txt)
# Create comment
# TODO: add a summary, something like:
# - overall size difference (percent)
# - number of binaries that grew / shrank / remained the same
# - don't show the full diff when no binaries changed
- name: Calculate size diff
run: ./tools/sizediff drivers/sizes-dev.txt drivers/sizes-pr.txt | tee sizediff.txt
- name: Create comment
run: |
echo "Size difference with the dev branch:" > comment.txt
echo "<details><summary>Binary size difference</summary>" >> comment.txt
echo "<pre>" >> comment.txt
cat sizediff.txt >> comment.txt
echo "</pre></details>" >> comment.txt
- name: Comment contents
run: cat comment.txt
- name: Add comment
if: ${{ github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name }}
uses: thollander/actions-comment-pull-request@v2.3.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
filePath: comment.txt
comment_tag: sizediff
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
# Extract the version string from the source code, to be stored in a variable.
grep 'const version' goenv/version.go | sed 's/^const version = "\(.*\)"$/version=\1/g'
+237
View File
@@ -0,0 +1,237 @@
name: Windows
on:
pull_request:
push:
branches:
- dev
- release
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-windows:
runs-on: windows-2022
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Configure pagefile
uses: al-cheb/configure-pagefile-action@v1.4
with:
minimum-size: 8GB
maximum-size: 24GB
disk-root: "C:"
- uses: brechtm/setup-scoop@v2
with:
scoop_update: 'false'
- name: Install Dependencies
shell: bash
run: |
scoop install ninja binaryen
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Extract TinyGo version
id: version
shell: bash
run: ./.github/workflows/tinygo-extract-version.sh | tee -a "$GITHUB_OUTPUT"
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Restore cached LLVM source
uses: actions/cache/restore@v4
id: cache-llvm-source
with:
key: llvm-source-19-windows-v1
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Download LLVM source
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
run: make llvm-source
- name: Save cached LLVM source
uses: actions/cache/save@v4
if: steps.cache-llvm-source.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-source.outputs.cache-primary-key }}
path: |
llvm-project/clang/lib/Headers
llvm-project/clang/include
llvm-project/compiler-rt
llvm-project/lld/include
llvm-project/llvm/include
- name: Restore cached LLVM build
uses: actions/cache/restore@v4
id: cache-llvm-build
with:
key: llvm-build-19-windows-v1
path: llvm-build
- name: Build LLVM
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
shell: bash
run: |
# fetch LLVM source
rm -rf llvm-project
make llvm-source
# build!
make llvm-build CCACHE=OFF
# Remove unnecessary object files (to reduce cache size).
find llvm-build -name CMakeFiles -prune -exec rm -r '{}' \;
- name: Save cached LLVM build
uses: actions/cache/save@v4
if: steps.cache-llvm-build.outputs.cache-hit != 'true'
with:
key: ${{ steps.cache-llvm-build.outputs.cache-primary-key }}
path: llvm-build
- name: Cache wasi-libc sysroot
uses: actions/cache@v4
id: cache-wasi-libc
with:
key: wasi-libc-sysroot-v5
path: lib/wasi-libc/sysroot
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
run: make wasi-libc
- name: Cache Go cache
uses: actions/cache@v4
with:
key: go-cache-windows-v1-${{ hashFiles('go.mod') }}
path: |
C:/Users/runneradmin/AppData/Local/go-build
C:/Users/runneradmin/go/pkg/mod
- name: Install wasmtime
run: |
scoop install wasmtime@29.0.1
- name: make gen-device
run: make -j3 gen-device
- name: Test TinyGo
shell: bash
run: make test GOTESTFLAGS="-short"
- name: Build TinyGo release tarball
shell: bash
run: make build/release -j4
- name: Make release artifact
shell: bash
working-directory: build/release
run: 7z -tzip a tinygo${{ steps.version.outputs.version }}.windows-amd64.zip tinygo
- name: Publish release artifact
# Note: this release artifact is double-zipped, see:
# https://github.com/actions/upload-artifact/issues/39
# We can essentially pick one of these:
# - have a dobule-zipped artifact when downloaded from the UI
# - have a very slow artifact upload
# We're doing the former here, to keep artifact uploads fast.
uses: actions/upload-artifact@v4
with:
name: windows-amd64-double-zipped-${{ steps.version.outputs.version }}
path: build/release/tinygo${{ steps.version.outputs.version }}.windows-amd64.zip
smoke-test-windows:
runs-on: windows-2022
needs: build-windows
steps:
- name: Configure pagefile
uses: al-cheb/configure-pagefile-action@v1.4
with:
minimum-size: 8GB
maximum-size: 24GB
disk-root: "C:"
- uses: brechtm/setup-scoop@v2
with:
scoop_update: 'false'
- name: Install Dependencies
shell: bash
run: |
scoop install binaryen
- name: Checkout
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Download TinyGo build
uses: actions/download-artifact@v4
with:
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
path: build/
- name: Unzip TinyGo build
shell: bash
working-directory: build
run: 7z x tinygo*.windows-amd64.zip -r
- name: Smoke tests
shell: bash
run: make smoketest TINYGO=$(PWD)/build/tinygo/bin/tinygo
stdlib-test-windows:
runs-on: windows-2022
needs: build-windows
steps:
- name: Configure pagefile
uses: al-cheb/configure-pagefile-action@v1.4
with:
minimum-size: 8GB
maximum-size: 24GB
disk-root: "C:"
- name: Checkout
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Download TinyGo build
uses: actions/download-artifact@v4
with:
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
path: build/
- name: Unzip TinyGo build
shell: bash
working-directory: build
run: 7z x tinygo*.windows-amd64.zip -r
- name: Test stdlib packages
run: make tinygo-test TINYGO=$(PWD)/build/tinygo/bin/tinygo
stdlib-wasi-test-windows:
runs-on: windows-2022
needs: build-windows
steps:
- name: Configure pagefile
uses: al-cheb/configure-pagefile-action@v1.4
with:
minimum-size: 8GB
maximum-size: 24GB
disk-root: "C:"
- uses: brechtm/setup-scoop@v2
with:
scoop_update: 'false'
- name: Install Dependencies
shell: bash
run: |
scoop install binaryen && scoop install wasmtime@29.0.1
- name: Checkout
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache: true
- name: Download TinyGo build
uses: actions/download-artifact@v4
with:
name: windows-amd64-double-zipped-${{ needs.build-windows.outputs.version }}
path: build/
- name: Unzip TinyGo build
shell: bash
working-directory: build
run: 7z x tinygo*.windows-amd64.zip -r
- name: Test stdlib packages on wasip1
run: make tinygo-test-wasip1-fast TINYGO=$(PWD)/build/tinygo/bin/tinygo
+26 -2
View File
@@ -1,4 +1,8 @@
build
.DS_Store
.vscode
go.work
go.work.sum
docs/_build
src/device/avr/*.go
src/device/avr/*.ld
@@ -16,6 +20,26 @@ src/device/stm32/*.go
src/device/stm32/*.s
src/device/kendryte/*.go
src/device/kendryte/*.s
vendor
src/device/renesas/*.go
src/device/renesas/*.s
src/device/rp/*.go
src/device/rp/*.s
./vendor
llvm-build
llvm-project
build/*
# Ignore files generated by smoketest
test
test.bin
test.elf
test.exe
test.gba
test.hex
test.nro
test.uf2
test.wasm
wasm.wasm
*.uf2
*.elf
+22 -6
View File
@@ -9,17 +9,33 @@
url = https://github.com/avr-rust/avr-mcu.git
[submodule "lib/cmsis-svd"]
path = lib/cmsis-svd
url = https://github.com/tinygo-org/cmsis-svd
[submodule "lib/compiler-rt"]
path = lib/compiler-rt
url = https://github.com/llvm-mirror/compiler-rt.git
branch = release_80
url = https://github.com/cmsis-svd/cmsis-svd-data.git
branch = main
[submodule "lib/wasi-libc"]
path = lib/wasi-libc
url = https://github.com/CraneStation/wasi-libc
url = https://github.com/WebAssembly/wasi-libc
[submodule "lib/picolibc"]
path = lib/picolibc
url = https://github.com/keith-packard/picolibc.git
[submodule "lib/stm32-svd"]
path = lib/stm32-svd
url = https://github.com/tinygo-org/stm32-svd
[submodule "lib/musl"]
path = lib/musl
url = git://git.musl-libc.org/musl
[submodule "lib/binaryen"]
path = lib/binaryen
url = https://github.com/WebAssembly/binaryen.git
[submodule "lib/mingw-w64"]
path = lib/mingw-w64
url = https://github.com/mingw-w64/mingw-w64.git
[submodule "lib/macos-minimal-sdk"]
path = lib/macos-minimal-sdk
url = https://github.com/aykevl/macos-minimal-sdk.git
[submodule "src/net"]
path = src/net
url = https://github.com/tinygo-org/net.git
branch = dev
[submodule "lib/wasi-cli"]
path = lib/wasi-cli
url = https://github.com/WebAssembly/wasi-cli
+18 -7
View File
@@ -11,19 +11,15 @@ lld so that the binary can be easily moved between systems. It also shows how to
build a release tarball that includes this binary and all necessary extra files.
**Note**: this documentation describes how to build a statically linked release
tarball. If you want to develop TinyGo, you will probably want to follow a
different guide:
* [Linux](https://tinygo.org/getting-started/linux/#source-install)
* [macOS](https://tinygo.org/getting-started/macos/#source-install)
* [Windows](https://tinygo.org/getting-started/windows/#source-install)
tarball. If you want to help with development of TinyGo itself, you should follow the guide located at https://tinygo.org/docs/guides/build/
## Dependencies
LLVM, Clang and LLD are quite light on dependencies, requiring only standard
build tools to be built. Go is of course necessary to build TinyGo itself.
* Go (1.13+)
* Go (1.19+)
* GNU Make
* Standard build tools (gcc/clang)
* git
* CMake
@@ -32,6 +28,21 @@ build tools to be built. Go is of course necessary to build TinyGo itself.
The rest of this guide assumes you're running Linux, but it should be equivalent
on a different system like Mac.
## Using GNU Make
The static build of TinyGo is driven by GNUmakefile, which provides a help target for quick reference:
% make help
clean Remove build directory
fmt Reformat source
fmt-check Warn if any source needs reformatting
gen-device Generate microcontroller-specific sources
llvm-source Get LLVM sources
llvm-build Build LLVM
tinygo Build the TinyGo compiler
lint Lint source tree
spell Spellcheck source tree
## Download the source
The first step is to download the TinyGo sources (use `--recursive` if you clone
+1483 -3
View File
File diff suppressed because it is too large Load Diff
+1 -52
View File
@@ -1,52 +1 @@
# How to contribute
Thank you for your interest in improving TinyGo.
We would like your help to make this project better, so we appreciate any contributions. See if one of the following descriptions matches your situation:
### New to TinyGo
We'd love to get your feedback on getting started with TinyGo. Run into any difficulty, confusion, or anything else? You are not alone. We want to know about your experience, so we can help the next people. Please open a Github issue with your questions, or you can also get in touch directly with us on our Slack channel at [https://gophers.slack.com/messages/CDJD3SUP6](https://gophers.slack.com/messages/CDJD3SUP6).
### Something in TinyGo is not working as you expect
Please open a Github issue with your problem, and we will be happy to assist.
### Something in Go that you want/need does not appear to be in TinyGo
We probably have not implemented it yet. Please take a look at our [Roadmap](https://github.com/tinygo-org/tinygo/wiki/Roadmap). Your pull request adding the functionality to TinyGo would be greatly appreciated.
Please open a Github issue. We want to help, and also make sure that there is no duplications of efforts. Sometimes what you need is already being worked on by someone else.
A long tail of small (and large) language features haven't been implemented yet. In almost all cases, the compiler will show a `todo:` error from `compiler/compiler.go` when you try to use it. You can try implementing it, or open a bug report with a small code sample that fails to compile.
### Some specific hardware you want to use does not appear to be in TinyGo
As above, we probably have not implemented it yet. Your contribution adding the hardware support to TinyGo would be greatly appreciated.
Please start by opening a Github issue. We want to help you to help us to help you.
Lots of targets/boards are still unsupported. Adding an architecture often requires a few compiler changes, but if the architecture is supported you can try implementing support for a new chip or board in `src/runtime`. For details, see [this wiki entry on adding archs/chips/boards](https://github.com/tinygo-org/tinygo/wiki/Adding-a-new-board).
Microcontrollers have lots of peripherals (I2C, SPI, ADC, etc.) and many don't have an implementation yet in the `machine` package. Adding support for new peripherals is very useful.
## How to use our Github repository
The `release` branch of this repo will always have the latest released version of TinyGo. All of the active development work for the next release will take place in the `dev` branch. TinyGo will use semantic versioning and will create a tag/release for each release.
Here is how to contribute back some code or documentation:
- Fork repo
- Create a feature branch off of the `dev` branch
- Make some useful change
- Make sure the tests still pass
- Submit a pull request against the `dev` branch.
- Be kind
## How to run tests
To run the tests:
```
make test
```
Please take a look at our [Contributing](https://tinygo.org/docs/guides/contributing/) page on our web site for details. Thank you.
+34 -70
View File
@@ -1,79 +1,43 @@
# TinyGo base stage installs the most recent Go 1.15.x, LLVM 11 and the TinyGo compiler itself.
FROM golang:1.15 AS tinygo-base
# tinygo-llvm stage obtains the llvm source for TinyGo
FROM golang:1.24 AS tinygo-llvm
RUN wget -O- https://apt.llvm.org/llvm-snapshot.gpg.key| apt-key add - && \
echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-11 main" >> /etc/apt/sources.list && \
apt-get update && \
apt-get install -y llvm-11-dev libclang-11-dev lld-11 git
RUN apt-get update && \
apt-get install -y apt-utils make cmake clang-15 ninja-build && \
rm -rf \
/var/lib/apt/lists/* \
/var/log/* \
/var/tmp/* \
/tmp/*
COPY ./GNUmakefile /tinygo/GNUmakefile
RUN cd /tinygo/ && \
make llvm-source
# tinygo-llvm-build stage build the custom llvm with xtensa support
FROM tinygo-llvm AS tinygo-llvm-build
RUN cd /tinygo/ && \
make llvm-build
# tinygo-compiler-build stage builds the compiler itself
FROM tinygo-llvm-build AS tinygo-compiler-build
COPY . /tinygo
# remove submodules directories and re-init them to fix any hard-coded paths
# after copying the tinygo directory in the previous step.
# build the compiler and tools
RUN cd /tinygo/ && \
rm -rf ./lib/* && \
git submodule sync && \
git submodule update --init --recursive --force
git submodule update --init && \
make gen-device -j4 && \
make build/release
COPY ./lib/picolibc-include/* /tinygo/lib/picolibc-include/
# tinygo-compiler copies the compiler build over to a base Go container (without
# all the build tools etc).
FROM golang:1.24 AS tinygo-compiler
RUN cd /tinygo/ && \
go install /tinygo/
# tinygo-wasm stage installs the needed dependencies to compile TinyGo programs for WASM.
FROM tinygo-base AS tinygo-wasm
COPY --from=tinygo-base /go/bin/tinygo /go/bin/tinygo
COPY --from=tinygo-base /tinygo/src /tinygo/src
COPY --from=tinygo-base /tinygo/targets /tinygo/targets
RUN cd /tinygo/ && \
apt-get update && \
apt-get install -y make clang-11 libllvm11 lld-11 && \
make wasi-libc
# tinygo-avr stage installs the needed dependencies to compile TinyGo programs for AVR microcontrollers.
FROM tinygo-base AS tinygo-avr
COPY --from=tinygo-base /go/bin/tinygo /go/bin/tinygo
COPY --from=tinygo-base /tinygo/src /tinygo/src
COPY --from=tinygo-base /tinygo/targets /tinygo/targets
COPY --from=tinygo-base /tinygo/Makefile /tinygo/
COPY --from=tinygo-base /tinygo/tools /tinygo/tools
COPY --from=tinygo-base /tinygo/lib /tinygo/lib
RUN cd /tinygo/ && \
apt-get update && \
apt-get install -y apt-utils make binutils-avr gcc-avr avr-libc && \
make gen-device-avr && \
apt-get autoremove -y && \
apt-get clean
# tinygo-arm stage installs the needed dependencies to compile TinyGo programs for ARM microcontrollers.
FROM tinygo-base AS tinygo-arm
COPY --from=tinygo-base /go/bin/tinygo /go/bin/tinygo
COPY --from=tinygo-base /tinygo/src /tinygo/src
COPY --from=tinygo-base /tinygo/targets /tinygo/targets
COPY --from=tinygo-base /tinygo/Makefile /tinygo/
COPY --from=tinygo-base /tinygo/tools /tinygo/tools
COPY --from=tinygo-base /tinygo/lib /tinygo/lib
RUN cd /tinygo/ && \
apt-get update && \
apt-get install -y apt-utils make clang-11 && \
make gen-device-nrf && make gen-device-stm32
# tinygo-all stage installs the needed dependencies to compile TinyGo programs for all platforms.
FROM tinygo-wasm AS tinygo-all
COPY --from=tinygo-base /tinygo/Makefile /tinygo/
COPY --from=tinygo-base /tinygo/tools /tinygo/tools
COPY --from=tinygo-base /tinygo/lib /tinygo/lib
RUN cd /tinygo/ && \
apt-get update && \
apt-get install -y apt-utils make clang-11 binutils-avr gcc-avr avr-libc && \
make gen-device
# Copy tinygo build.
COPY --from=tinygo-compiler-build /tinygo/build/release/tinygo /tinygo
# Configure the container.
ENV PATH="${PATH}:/tinygo/bin"
CMD ["tinygo"]
+1080
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
TinyGo Team Members
===================
The team of humans who maintain TinyGo.
* **Purpose**: To maintain the community, code, documentation, and tools for the TinyGo compiler.
* **Board**: The group of people who share responsibility for key decisions for the TinyGo organization.
* **Majority Voting**: The board makes decisions by majority vote.
* **Membership**: The board elects its own members.
* **Do-ocracy**: Those who step forward to do a given task propose how it should be done. Then other interested people can make comments.
* **Proof of Work**: Power in decision-making is slightly weighted based on a participant's labor for the community.
* **Initiation**: We need to establish a procedure for how people join the team of maintainers.
* **Transparency**: Important information should be made publicly available, ideally in a way that allows for public comment.
* **Code of Conduct**: Participants agree to abide by the current project Code of Conduct.
## Members
* Ayke van Laethem (@aykevl)
* Daniel Esteban (@conejoninja)
* Ron Evans (@deadprogram)
* Damian Gryski (@dgryski)
* Masaaki Takasago (@sago35)
* Patricio Whittingslow (@soypat)
* Yurii Soldak (@ysoldak)
## Experimental
* **Monthly Meeting**: A monthly meeting for the team and any other interested participants.
Duration: 1 hour
Facilitation: @deadprogram
Schedule: See https://github.com/tinygo-org/tinygo/wiki/Meetings for more information
+2 -2
View File
@@ -1,7 +1,7 @@
Copyright (c) 2018-2021 TinyGo Authors. All rights reserved.
Copyright (c) 2018-2025 The TinyGo Authors. All rights reserved.
TinyGo includes portions of the Go standard library.
Copyright (c) 2009-2021 The Go Authors. All rights reserved.
Copyright (c) 2009-2024 The Go Authors. All rights reserved.
TinyGo includes portions of LLVM, which is under the Apache License v2.0 with
LLVM Exceptions. See https://llvm.org/LICENSE.txt for license information.
-442
View File
@@ -1,442 +0,0 @@
# aliases
all: tinygo
# Default build and source directories, as created by `make llvm-build`.
LLVM_BUILDDIR ?= llvm-build
LLVM_PROJECTDIR ?= llvm-project
CLANG_SRC ?= $(LLVM_PROJECTDIR)/clang
LLD_SRC ?= $(LLVM_PROJECTDIR)/lld
# Try to autodetect LLVM build tools.
detect = $(shell command -v $(1) 2> /dev/null && echo $(1))
CLANG ?= $(word 1,$(abspath $(call detect,llvm-build/bin/clang))$(call detect,clang-11)$(call detect,clang-10)$(call detect,clang))
LLVM_AR ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-ar))$(call detect,llvm-ar-11)$(call detect,llvm-ar-10)$(call detect,llvm-ar))
LLVM_NM ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-nm))$(call detect,llvm-nm-11)$(call detect,llvm-nm-10)$(call detect,llvm-nm))
# Go binary and GOROOT to select
GO ?= go
export GOROOT = $(shell $(GO) env GOROOT)
# md5sum binary
MD5SUM = md5sum
# tinygo binary for tests
TINYGO ?= $(word 1,$(call detect,tinygo)$(call detect,build/tinygo))
# Use CCACHE for LLVM if possible
ifneq (, $(shell command -v ccache 2> /dev/null))
LLVM_OPTION += '-DLLVM_CCACHE_BUILD=ON'
endif
# Allow enabling LLVM assertions
ifeq (1, $(ASSERT))
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=ON'
else
LLVM_OPTION += '-DLLVM_ENABLE_ASSERTIONS=OFF'
endif
.PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-nxp gen-device-avr
LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf executionengine frontendopenmp instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target
ifeq ($(OS),Windows_NT)
EXE = .exe
START_GROUP = -Wl,--start-group
END_GROUP = -Wl,--end-group
# LLVM compiled using MinGW on Windows appears to have problems with threads.
# Without this flag, linking results in errors like these:
# libLLVMSupport.a(Threading.cpp.obj):Threading.cpp:(.text+0x55): undefined reference to `std::thread::hardware_concurrency()'
LLVM_OPTION += -DLLVM_ENABLE_THREADS=OFF -DLLVM_ENABLE_PIC=OFF
CGO_CPPFLAGS += -DCINDEX_NO_EXPORTS
CGO_LDFLAGS += -static -static-libgcc -static-libstdc++
CGO_LDFLAGS_EXTRA += -lversion
LIBCLANG_NAME = libclang
else ifeq ($(shell uname -s),Darwin)
MD5SUM = md5
LIBCLANG_NAME = clang
else ifeq ($(shell uname -s),FreeBSD)
MD5SUM = md5
LIBCLANG_NAME = clang
START_GROUP = -Wl,--start-group
END_GROUP = -Wl,--end-group
else
LIBCLANG_NAME = clang
START_GROUP = -Wl,--start-group
END_GROUP = -Wl,--end-group
endif
# Libraries that should be linked in for the statically linked Clang.
CLANG_LIB_NAMES = clangAnalysis clangARCMigrate clangAST clangASTMatchers clangBasic clangCodeGen clangCrossTU clangDriver clangDynamicASTMatchers clangEdit clangFormat clangFrontend clangFrontendTool clangHandleCXX clangHandleLLVM clangIndex clangLex clangParse clangRewrite clangRewriteFrontend clangSema clangSerialization clangStaticAnalyzerCheckers clangStaticAnalyzerCore clangStaticAnalyzerFrontend clangTooling clangToolingASTDiff clangToolingCore clangToolingInclusions
CLANG_LIBS = $(START_GROUP) $(addprefix -l,$(CLANG_LIB_NAMES)) $(END_GROUP) -lstdc++
# Libraries that should be linked in for the statically linked LLD.
LLD_LIB_NAMES = lldCOFF lldCommon lldCore lldDriver lldELF lldMachO lldMinGW lldReaderWriter lldWasm lldYAML
LLD_LIBS = $(START_GROUP) $(addprefix -l,$(LLD_LIB_NAMES)) $(END_GROUP)
# Other libraries that are needed to link TinyGo.
EXTRA_LIB_NAMES = LLVMInterpreter
# These build targets appear to be the only ones necessary to build all TinyGo
# dependencies. Only building a subset significantly speeds up rebuilding LLVM.
# The Makefile rules convert a name like lldELF to lib/liblldELF.a to match the
# library path (for ninja).
# This list also includes a few tools that are necessary as part of the full
# TinyGo build.
NINJA_BUILD_TARGETS = clang llvm-config llvm-ar llvm-nm $(addprefix lib/lib,$(addsuffix .a,$(LIBCLANG_NAME) $(CLANG_LIB_NAMES) $(LLD_LIB_NAMES) $(EXTRA_LIB_NAMES)))
# For static linking.
ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","")
CGO_CPPFLAGS+=$(shell $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include
CGO_CXXFLAGS=-std=c++14
CGO_LDFLAGS+=$(abspath $(LLVM_BUILDDIR))/lib/lib$(LIBCLANG_NAME).a -L$(abspath $(LLVM_BUILDDIR)/lib) $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA)
endif
clean:
@rm -rf build
FMT_PATHS = ./*.go builder cgo compiler interp loader src/device/arm src/examples src/machine src/os src/reflect src/runtime src/sync src/syscall src/internal/reflectlite transform
fmt:
@gofmt -l -w $(FMT_PATHS)
fmt-check:
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
gen-device: gen-device-avr gen-device-esp gen-device-nrf gen-device-sam gen-device-sifive gen-device-stm32 gen-device-kendryte gen-device-nxp
gen-device-avr:
@if [ ! -e lib/avr/README.md ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
$(GO) build -o ./build/gen-device-avr ./tools/gen-device-avr/
./build/gen-device-avr lib/avr/packs/atmega src/device/avr/
./build/gen-device-avr lib/avr/packs/tiny src/device/avr/
@GO111MODULE=off $(GO) fmt ./src/device/avr
build/gen-device-svd: ./tools/gen-device-svd/*.go
$(GO) build -o $@ ./tools/gen-device-svd/
gen-device-esp: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Espressif-Community -interrupts=software lib/cmsis-svd/data/Espressif-Community/ src/device/esp/
GO111MODULE=off $(GO) fmt ./src/device/esp
gen-device-nrf: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/NordicSemiconductor/nrfx/tree/master/mdk lib/nrfx/mdk/ src/device/nrf/
GO111MODULE=off $(GO) fmt ./src/device/nrf
gen-device-nxp: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/NXP lib/cmsis-svd/data/NXP/ src/device/nxp/
GO111MODULE=off $(GO) fmt ./src/device/nxp
gen-device-sam: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel lib/cmsis-svd/data/Atmel/ src/device/sam/
GO111MODULE=off $(GO) fmt ./src/device/sam
gen-device-sifive: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/SiFive-Community -interrupts=software lib/cmsis-svd/data/SiFive-Community/ src/device/sifive/
GO111MODULE=off $(GO) fmt ./src/device/sifive
gen-device-kendryte: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/Kendryte-Community -interrupts=software lib/cmsis-svd/data/Kendryte-Community/ src/device/kendryte/
GO111MODULE=off $(GO) fmt ./src/device/kendryte
gen-device-stm32: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/tinygo-org/stm32-svd lib/stm32-svd/svd src/device/stm32/
GO111MODULE=off $(GO) fmt ./src/device/stm32
# Get LLVM sources.
$(LLVM_PROJECTDIR)/README.md:
git clone -b xtensa_release_11.0.0 --depth=1 https://github.com/tinygo-org/llvm-project $(LLVM_PROJECTDIR)
llvm-source: $(LLVM_PROJECTDIR)/README.md
# Configure LLVM.
TINYGO_SOURCE_DIR=$(shell pwd)
$(LLVM_BUILDDIR)/build.ninja: llvm-source
mkdir -p $(LLVM_BUILDDIR); cd $(LLVM_BUILDDIR); cmake -G Ninja $(TINYGO_SOURCE_DIR)/$(LLVM_PROJECTDIR)/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;RISCV;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR;Xtensa" -DCMAKE_BUILD_TYPE=Release -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF -DLLVM_ENABLE_OCAMLDOC=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF $(LLVM_OPTION)
# Build LLVM.
$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja
cd $(LLVM_BUILDDIR); ninja $(NINJA_BUILD_TARGETS)
# Build wasi-libc sysroot
.PHONY: wasi-libc
wasi-libc: lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a
lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a:
@if [ ! -e lib/wasi-libc/Makefile ]; then echo "Submodules have not been downloaded. Please download them using:\n git submodule update --init"; exit 1; fi
cd lib/wasi-libc && make -j4 WASM_CC=$(CLANG) WASM_AR=$(LLVM_AR) WASM_NM=$(LLVM_NM)
# Build the Go compiler.
tinygo:
@if [ ! -f "$(LLVM_BUILDDIR)/bin/llvm-config" ]; then echo "Fetch and build LLVM first by running:"; echo " make llvm-source"; echo " make $(LLVM_BUILDDIR)"; exit 1; fi
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -buildmode exe -o build/tinygo$(EXE) -tags byollvm -ldflags="-X main.gitSha1=`git rev-parse --short HEAD`" .
test: wasi-libc
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test -v -buildmode exe -tags byollvm ./cgo ./compileopts ./compiler ./interp ./transform .
# Test known-working standard library packages.
# TODO: do this in one command, parallelize, and only show failing tests (no
# implied -v flag).
.PHONY: tinygo-test
tinygo-test:
$(TINYGO) test container/heap
$(TINYGO) test container/list
$(TINYGO) test container/ring
$(TINYGO) test crypto/des
$(TINYGO) test encoding/ascii85
$(TINYGO) test encoding/base32
$(TINYGO) test encoding/hex
$(TINYGO) test hash/adler32
$(TINYGO) test hash/fnv
$(TINYGO) test hash/crc64
$(TINYGO) test math
$(TINYGO) test math/cmplx
$(TINYGO) test text/scanner
$(TINYGO) test unicode/utf8
.PHONY: smoketest
smoketest:
$(TINYGO) version
# test all examples (except pwm)
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/adc
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/blinkm
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/blinky2
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/button
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/button2
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/echo
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/i2s
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/mcp3008
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=microbit examples/microbit-blink
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=microbit-v2 examples/microbit-blink
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/pininterrupt
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/serial
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/systick
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/test
@$(MD5SUM) test.hex
# test simulated boards on play.tinygo.org
$(TINYGO) build -o test.wasm -tags=arduino examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -o test.wasm -tags=hifive1b examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -o test.wasm -tags=reelboard examples/blinky1
@$(MD5SUM) test.wasm
$(TINYGO) build -o test.wasm -tags=pca10040 examples/blinky2
@$(MD5SUM) test.wasm
$(TINYGO) build -o test.wasm -tags=pca10056 examples/blinky2
@$(MD5SUM) test.wasm
$(TINYGO) build -o test.wasm -tags=circuitplay_express examples/blinky1
@$(MD5SUM) test.wasm
# test all targets/boards
$(TINYGO) build -size short -o test.hex -target=pca10040-s132v6 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=microbit examples/echo
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=microbit-s110v8 examples/echo
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nrf52840-mdk examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10031 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=bluepill examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=reelboard examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=reelboard examples/blinky2
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10056 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10056 examples/blinky2
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-m0 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=trinket-m0 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=stm32f4disco examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=stm32f4disco examples/blinky2
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=stm32f4disco-1 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-stm32f405 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=circuitplay-bluefruit examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/i2s
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=clue-alpha examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.gba -target=gameboy-advance examples/gba-display
@$(MD5SUM) test.gba
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m4 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-m4 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pybadge examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=metro-m4-airlift examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pyportal examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=particle-argon examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=particle-boron examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=particle-xenon examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nucleo-f103rb examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pinetime-devkit0 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=lgt92 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=x9pro examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10056-s140v7 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=reelboard-s140v7 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=wioterminal examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pygamer examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=xiao examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/dac
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pyportal examples/dac
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=itsybitsy-nrf52840 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=qtpy examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=teensy40 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=teensy36 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nucleo-f722ze examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=nucleo-l552ze examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=p1am-100 examples/blinky1
@$(MD5SUM) test.hex
# test pwm
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m4 examples/pwm
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-m4 examples/pwm
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pyportal examples/pwm
@$(MD5SUM) test.hex
ifneq ($(AVR), 0)
$(TINYGO) build -size short -o test.hex -target=atmega1284p examples/serial
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=arduino examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=arduino examples/pwm
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=arduino -scheduler=tasks examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=arduino-nano examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=digispark examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=digispark -gc=leaking examples/blinky1
@$(MD5SUM) test.hex
endif
ifneq ($(XTENSA), 0)
$(TINYGO) build -size short -o test.bin -target=esp32-mini32 examples/blinky1
@$(MD5SUM) test.bin
$(TINYGO) build -size short -o test.bin -target=nodemcu examples/blinky1
@$(MD5SUM) test.bin
endif
$(TINYGO) build -size short -o test.hex -target=hifive1b examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=hifive1-qemu examples/serial
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=maixbit examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/export
$(TINYGO) build -o wasm.wasm -target=wasm examples/wasm/main
# test various compiler flags
$(TINYGO) build -size short -o test.hex -target=pca10040 -gc=none -scheduler=none examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=1 examples/blinky1
@$(MD5SUM) test.hex
$(TINYGO) build -o test.nro -target=nintendoswitch examples/serial
@$(MD5SUM) test.nro
wasmtest:
$(GO) test ./tests/wasm
build/release: tinygo gen-device wasi-libc
@mkdir -p build/release/tinygo/bin
@mkdir -p build/release/tinygo/lib/clang/include
@mkdir -p build/release/tinygo/lib/CMSIS/CMSIS
@mkdir -p build/release/tinygo/lib/compiler-rt/lib
@mkdir -p build/release/tinygo/lib/nrfx
@mkdir -p build/release/tinygo/lib/picolibc/newlib/libc
@mkdir -p build/release/tinygo/lib/wasi-libc
@mkdir -p build/release/tinygo/pkg/armv6m-none-eabi
@mkdir -p build/release/tinygo/pkg/armv7m-none-eabi
@mkdir -p build/release/tinygo/pkg/armv7em-none-eabi
@echo copying source files
@cp -p build/tinygo$(EXE) build/release/tinygo/bin
@cp -p $(abspath $(CLANG_SRC))/lib/Headers/*.h build/release/tinygo/lib/clang/include
@cp -rp lib/CMSIS/CMSIS/Include build/release/tinygo/lib/CMSIS/CMSIS
@cp -rp lib/CMSIS/README.md build/release/tinygo/lib/CMSIS
@cp -rp lib/compiler-rt/lib/builtins build/release/tinygo/lib/compiler-rt/lib
@cp -rp lib/compiler-rt/LICENSE.TXT build/release/tinygo/lib/compiler-rt
@cp -rp lib/compiler-rt/README.txt build/release/tinygo/lib/compiler-rt
@cp -rp lib/nrfx/* build/release/tinygo/lib/nrfx
@cp -rp lib/picolibc/newlib/libc/ctype build/release/tinygo/lib/picolibc/newlib/libc
@cp -rp lib/picolibc/newlib/libc/include build/release/tinygo/lib/picolibc/newlib/libc
@cp -rp lib/picolibc/newlib/libc/locale 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-include build/release/tinygo/lib
@cp -rp lib/wasi-libc/sysroot build/release/tinygo/lib/wasi-libc/sysroot
@cp -rp src build/release/tinygo/src
@cp -rp targets build/release/tinygo/targets
./build/tinygo build-library -target=armv6m-none-eabi -o build/release/tinygo/pkg/armv6m-none-eabi/compiler-rt.a compiler-rt
./build/tinygo build-library -target=armv7m-none-eabi -o build/release/tinygo/pkg/armv7m-none-eabi/compiler-rt.a compiler-rt
./build/tinygo build-library -target=armv7em-none-eabi -o build/release/tinygo/pkg/armv7em-none-eabi/compiler-rt.a compiler-rt
./build/tinygo build-library -target=armv6m-none-eabi -o build/release/tinygo/pkg/armv6m-none-eabi/picolibc.a picolibc
./build/tinygo build-library -target=armv7m-none-eabi -o build/release/tinygo/pkg/armv7m-none-eabi/picolibc.a picolibc
./build/tinygo build-library -target=armv7em-none-eabi -o build/release/tinygo/pkg/armv7em-none-eabi/picolibc.a picolibc
release: build/release
tar -czf build/release.tar.gz -C build/release tinygo
deb: build/release
@mkdir -p build/release-deb/usr/local/bin
@mkdir -p build/release-deb/usr/local/lib
cp -ar build/release/tinygo build/release-deb/usr/local/lib/tinygo
ln -sf ../lib/tinygo/bin/tinygo build/release-deb/usr/local/bin/tinygo
fpm -f -s dir -t deb -n tinygo -v $(shell grep "const Version = " goenv/version.go | awk '{print $$NF}') -m '@tinygo-org' --description='TinyGo is a Go compiler for small places.' --license='BSD 3-Clause' --url=https://tinygo.org/ --deb-changelog CHANGELOG.md -p build/release.deb -C ./build/release-deb
+55 -63
View File
@@ -1,11 +1,13 @@
# TinyGo - Go compiler for small places
[![CircleCI](https://circleci.com/gh/tinygo-org/tinygo/tree/dev.svg?style=svg)](https://circleci.com/gh/tinygo-org/tinygo/tree/dev) [![Build Status](https://dev.azure.com/tinygo/tinygo/_apis/build/status/tinygo-CI?branchName=dev)](https://dev.azure.com/tinygo/tinygo/_build/latest?definitionId=1&branchName=dev)
[![Linux](https://github.com/tinygo-org/tinygo/actions/workflows/linux.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/linux.yml) [![macOS](https://github.com/tinygo-org/tinygo/actions/workflows/build-macos.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/build-macos.yml) [![Windows](https://github.com/tinygo-org/tinygo/actions/workflows/windows.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/windows.yml) [![Docker](https://github.com/tinygo-org/tinygo/actions/workflows/docker.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/docker.yml) [![Nix](https://github.com/tinygo-org/tinygo/actions/workflows/nix.yml/badge.svg?branch=dev)](https://github.com/tinygo-org/tinygo/actions/workflows/nix.yml) [![CircleCI](https://circleci.com/gh/tinygo-org/tinygo/tree/dev.svg?style=svg)](https://circleci.com/gh/tinygo-org/tinygo/tree/dev)
TinyGo is a Go compiler intended for use in small places such as microcontrollers, WebAssembly (Wasm), and command-line tools.
TinyGo is a Go compiler intended for use in small places such as microcontrollers, WebAssembly (wasm/wasi), and command-line tools.
It reuses libraries used by the [Go language tools](https://golang.org/pkg/go/) alongside [LLVM](http://llvm.org) to provide an alternative way to compile programs written in the Go programming language.
## Embedded
Here is an example program that blinks the built-in LED when run directly on any supported board with onboard LED:
```go
@@ -35,73 +37,64 @@ The above program can be compiled and run without modification on an Arduino Uno
tinygo flash -target arduino examples/blinky1
```
## WebAssembly
TinyGo is very useful for compiling programs both for use in browsers (WASM) as well as for use on servers and other edge devices (WASI).
TinyGo programs can run in [Fastly Compute](https://www.fastly.com/documentation/guides/compute/go/), [Fermyon Spin](https://developer.fermyon.com/spin/go-components), [wazero](https://wazero.io/languages/tinygo/) and many other WebAssembly runtimes.
Here is a small TinyGo program for use by a WASI host application:
```go
package main
//go:wasmexport add
func add(x, y uint32) uint32 {
return x + y
}
```
This compiles the above TinyGo program for use on any WASI Preview 1 runtime:
```shell
tinygo build -buildmode=c-shared -o add.wasm -target=wasip1 add.go
```
You can also use the same syntax as Go 1.24+:
```shell
GOARCH=wasip1 GOOS=wasm tinygo build -buildmode=c-shared -o add.wasm add.go
```
## Installation
See the [getting started instructions](https://tinygo.org/getting-started/) for information on how to install TinyGo, as well as how to run the TinyGo compiler using our Docker container.
## Supported boards/targets
## Supported targets
You can compile TinyGo programs for microcontrollers, WebAssembly and Linux.
### Embedded
The following 55 microcontroller boards are currently supported:
You can compile TinyGo programs for over 94 different microcontroller boards.
* [Adafruit Circuit Playground Bluefruit](https://www.adafruit.com/product/4333)
* [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)
* [Adafruit CLUE](https://www.adafruit.com/product/4500)
* [Adafruit Feather M0](https://www.adafruit.com/product/2772)
* [Adafruit Feather M4](https://www.adafruit.com/product/3857)
* [Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
* [Adafruit Feather STM32F405 Express](https://www.adafruit.com/product/4382)
* [Adafruit ItsyBitsy M0](https://www.adafruit.com/product/3727)
* [Adafruit ItsyBitsy M4](https://www.adafruit.com/product/3800)
* [Adafruit ItsyBitsy nRF52840](https://www.adafruit.com/product/4481)
* [Adafruit Matrix Portal M4](https://www.adafruit.com/product/4745)
* [Adafruit Metro M4 Express Airlift](https://www.adafruit.com/product/4000)
* [Adafruit PyBadge](https://www.adafruit.com/product/4200)
* [Adafruit PyGamer](https://www.adafruit.com/product/4242)
* [Adafruit PyPortal](https://www.adafruit.com/product/4116)
* [Adafruit QT Py](https://www.adafruit.com/product/4600)
* [Adafruit Trinket M0](https://www.adafruit.com/product/3500)
* [Arduino Mega 2560](https://store.arduino.cc/arduino-mega-2560-rev3)
* [Arduino MKR1000](https://store.arduino.cc/arduino-mkr1000-wifi)
* [Arduino Nano](https://store.arduino.cc/arduino-nano)
* [Arduino Nano33 IoT](https://store.arduino.cc/nano-33-iot)
* [Arduino Uno](https://store.arduino.cc/arduino-uno-rev3)
* [Arduino Zero](https://store.arduino.cc/usa/arduino-zero)
* [BBC micro:bit](https://microbit.org/)
* [BBC micro:bit v2](https://microbit.org/new-microbit/)
* [Digispark](http://digistump.com/products/1)
* [Dragino LoRaWAN GPS Tracker LGT-92](http://www.dragino.com/products/lora-lorawan-end-node/item/142-lgt-92.html)
* [ESP32](https://www.espressif.com/en/products/socs/esp32)
* [ESP8266](https://www.espressif.com/en/products/socs/esp8266)
* [Game Boy Advance](https://en.wikipedia.org/wiki/Game_Boy_Advance)
* [Makerdiary nRF52840-MDK](https://wiki.makerdiary.com/nrf52840-mdk/)
* [Makerdiary nRF52840-MDK USB Dongle](https://wiki.makerdiary.com/nrf52840-mdk-usb-dongle/)
* [nice!nano](https://docs.nicekeyboards.com/#/nice!nano/)
* [Nintendo Switch](https://www.nintendo.com/switch/)
* [Nordic Semiconductor PCA10031](https://www.nordicsemi.com/eng/Products/nRF51-Dongle)
* [Nordic Semiconductor PCA10040](https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF52-DK)
* [Nordic Semiconductor PCA10056](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK)
* [Particle Argon](https://docs.particle.io/datasheets/wi-fi/argon-datasheet/)
* [Particle Boron](https://docs.particle.io/datasheets/cellular/boron-datasheet/)
* [Particle Xenon](https://docs.particle.io/datasheets/discontinued/xenon-datasheet/)
* [Phytec reel board](https://www.phytec.eu/product-eu/internet-of-things/reelboard/)
* [PineTime DevKit](https://www.pine64.org/pinetime/)
* [PJRC Teensy 3.6](https://www.pjrc.com/store/teensy36.html)
* [PJRC Teensy 4.0](https://www.pjrc.com/store/teensy40.html)
* [ProductivityOpen P1AM-100](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html)
* [Seeed Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html)
* [Seeed Seeeduino XIAO](https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html)
* [Seeed Sipeed MAix BiT](https://www.seeedstudio.com/Sipeed-MAix-BiT-for-RISC-V-AI-IoT-p-2872.html)
* [SiFIve HiFive1](https://www.sifive.com/boards/hifive1)
* [ST Micro "Nucleo" F103RB](https://www.st.com/en/evaluation-tools/nucleo-f103rb.html)
* [ST Micro "Nucleo" F722ZE](https://www.st.com/en/evaluation-tools/nucleo-f722ze.html)
* [ST Micro "Nucleo" L552ZE](https://www.st.com/en/evaluation-tools/nucleo-l552ze-q.html)
* [ST Micro STM32F103XX "Bluepill"](https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill)
* [ST Micro STM32F407 "Discovery"](https://www.st.com/en/evaluation-tools/stm32f4discovery.html)
* [X9 Pro smartwatch](https://github.com/curtpw/nRF5x-device-reverse-engineering/tree/master/X9-nrf52832-activity-tracker/)
For more information, please see https://tinygo.org/docs/reference/microcontrollers/
For more information, see [this list of boards](https://tinygo.org/microcontrollers/). Pull requests for additional support are welcome!
### WebAssembly
TinyGo programs can be compiled for both WASM and WASI targets.
For more information, see https://tinygo.org/docs/guides/webassembly/
### Operating Systems
You can also compile programs for Linux, macOS, and Windows targets.
For more information:
- Linux https://tinygo.org/docs/guides/linux/
- macOS https://tinygo.org/docs/guides/macos/
- Windows https://tinygo.org/docs/guides/windows/
## Currently supported features:
@@ -126,7 +119,7 @@ should arrive fairly quickly (under 1 min): https://invite.slack.golangbridge.or
Your contributions are welcome!
Please take a look at our [CONTRIBUTING.md](./CONTRIBUTING.md) document for details.
Please take a look at our [Contributing](https://tinygo.org/docs/guides/contributing/) page on our web site for details.
## Project Scope
@@ -140,7 +133,6 @@ Goals:
Non-goals:
* Using more than one core.
* Be efficient while using zillions of goroutines. However, good goroutine support is certainly a goal.
* Be as fast as `gc`. However, LLVM will probably be better at optimizing certain things so TinyGo might actually turn out to be faster for number crunching.
* Be able to compile every Go program out there.
-88
View File
@@ -1,88 +0,0 @@
# Avoid lengthy LLVM rebuilds on each newly pushed branch. Pull requests will
# be built anyway.
trigger:
- release
- dev
jobs:
- job: Build
timeoutInMinutes: 240 # 4h
pool:
vmImage: 'VS2017-Win2016'
steps:
- task: GoTool@0
inputs:
version: '1.16'
- checkout: self
fetchDepth: 1
- task: Cache@2
displayName: Cache LLVM source
inputs:
key: llvm-source-11-windows-v1
path: llvm-project
- task: Bash@3
displayName: Download LLVM source
inputs:
targetType: inline
script: make llvm-source
- task: CacheBeta@0
displayName: Cache LLVM build
inputs:
key: llvm-build-11-windows-v4
path: llvm-build
- task: Bash@3
displayName: Build LLVM
inputs:
targetType: inline
script: |
if [ ! -f llvm-build/lib/liblldELF.a ]
then
# install dependencies
choco install ninja
# hack ninja to use fewer jobs
echo -e 'C:\\ProgramData\\Chocolatey\\bin\\ninja -j4 %*' > /usr/bin/ninja.bat
# build!
make llvm-build
fi
- task: Bash@3
displayName: Install QEMU
inputs:
targetType: inline
script: choco install qemu --version=2020.06.12
- task: CacheBeta@0
displayName: Cache wasi-libc sysroot
inputs:
key: wasi-libc-sysroot-v4
path: lib/wasi-libc/sysroot
- task: Bash@3
displayName: Build wasi-libc
inputs:
targetType: inline
script: PATH=/usr/bin:$PATH make wasi-libc
- task: Bash@3
displayName: Test TinyGo
inputs:
targetType: inline
script: |
export PATH="$PATH:./llvm-build/bin:/c/Program Files/qemu"
unset GOROOT
make test
- task: Bash@3
displayName: Build TinyGo release tarball
inputs:
targetType: inline
script: |
export PATH="$PATH:./llvm-build/bin:/c/Program Files/qemu"
unset GOROOT
make build/release -j4
- publish: $(System.DefaultWorkingDirectory)/build/release/tinygo
displayName: Publish zip as artifact
artifact: tinygo
- task: Bash@3
displayName: Smoke tests
inputs:
targetType: inline
script: |
export PATH="$PATH:./llvm-build/bin:/c/Program Files/qemu"
unset GOROOT
make smoketest TINYGO=build/tinygo AVR=0 XTENSA=0
+101 -49
View File
@@ -3,31 +3,29 @@ package builder
import (
"bytes"
"debug/elf"
"debug/pe"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"time"
wasm "github.com/aykevl/go-wasm"
"github.com/blakesmith/ar"
)
// makeArchive creates an arcive for static linking from a list of object files
// makeArchive creates an archive for static linking from a list of object files
// given as a parameter. It is equivalent to the following command:
//
// ar -rcs <archivePath> <objs...>
func makeArchive(archivePath string, objs []string) error {
// ar -rcs <archivePath> <objs...>
func makeArchive(arfile *os.File, objs []string) error {
// Open the archive file.
arfile, err := os.Create(archivePath)
if err != nil {
return err
}
defer arfile.Close()
arwriter := ar.NewWriter(arfile)
err = arwriter.WriteGlobalHeader()
err := arwriter.WriteGlobalHeader()
if err != nil {
return &os.PathError{"write ar header", archivePath, err}
return &os.PathError{Op: "write ar header", Path: arfile.Name(), Err: err}
}
// Open all object files and read the symbols for the symbol table.
@@ -35,43 +33,82 @@ func makeArchive(archivePath string, objs []string) error {
name string // symbol name
fileIndex int // index into objfiles
}{}
objfiles := make([]struct {
file *os.File
archiveOffset int32
}, len(objs))
archiveOffsets := make([]int32, len(objs))
for i, objpath := range objs {
objfile, err := os.Open(objpath)
if err != nil {
return err
}
objfiles[i].file = objfile
// Read the symbols and add them to the symbol table.
dbg, err := elf.NewFile(objfile)
if err != nil {
return err
}
symbols, err := dbg.Symbols()
if err != nil {
return err
}
for _, symbol := range symbols {
bind := elf.ST_BIND(symbol.Info)
if bind != elf.STB_GLOBAL && bind != elf.STB_WEAK {
// Don't include local symbols (STB_LOCAL).
continue
if dbg, err := elf.NewFile(objfile); err == nil {
symbols, err := dbg.Symbols()
if err != nil {
return err
}
if elf.ST_TYPE(symbol.Info) != elf.STT_FUNC {
// Not a function.
// TODO: perhaps globals variables should also be included?
continue
for _, symbol := range symbols {
bind := elf.ST_BIND(symbol.Info)
if bind != elf.STB_GLOBAL && bind != elf.STB_WEAK {
// Don't include local symbols (STB_LOCAL).
continue
}
if elf.ST_TYPE(symbol.Info) != elf.STT_FUNC && elf.ST_TYPE(symbol.Info) != elf.STT_OBJECT {
// Not a function.
continue
}
// Include in archive.
symbolTable = append(symbolTable, struct {
name string
fileIndex int
}{symbol.Name, i})
}
// Include in archive.
symbolTable = append(symbolTable, struct {
name string
fileIndex int
}{symbol.Name, i})
} else if dbg, err := pe.NewFile(objfile); err == nil {
for _, symbol := range dbg.Symbols {
if symbol.StorageClass != 2 {
continue
}
if symbol.SectionNumber == 0 {
continue
}
symbolTable = append(symbolTable, struct {
name string
fileIndex int
}{symbol.Name, i})
}
} else if dbg, err := wasm.Parse(objfile); err == nil {
for _, s := range dbg.Sections {
switch section := s.(type) {
case *wasm.SectionLinking:
for _, symbol := range section.Symbols {
if symbol.Flags&wasm.LinkingSymbolFlagUndefined != 0 {
// Don't list undefined functions.
continue
}
if symbol.Flags&wasm.LinkingSymbolFlagBindingLocal != 0 {
// Don't include local symbols.
continue
}
if symbol.Kind != wasm.LinkingSymbolKindFunction && symbol.Kind != wasm.LinkingSymbolKindData {
// Link functions and data symbols.
// Some data symbols need to be included, such as
// __log_data.
continue
}
// Include in the archive.
symbolTable = append(symbolTable, struct {
name string
fileIndex int
}{symbol.Name, i})
}
}
}
} else {
return fmt.Errorf("failed to open file %s as WASM, ELF or PE/COFF: %w", objpath, err)
}
// Close file, to avoid issues with too many open files (especially on
// MacOS X).
objfile.Close()
}
// Create the symbol table buffer.
@@ -113,7 +150,7 @@ func makeArchive(archivePath string, objs []string) error {
}
// Keep track of the start of the symbol table.
symbolTableStart, err := arfile.Seek(0, os.SEEK_CUR)
symbolTableStart, err := arfile.Seek(0, io.SeekCurrent)
if err != nil {
return err
}
@@ -125,25 +162,32 @@ func makeArchive(archivePath string, objs []string) error {
}
// Add all object files to the archive.
for i, objfile := range objfiles {
var copyBuf bytes.Buffer
for i, objpath := range objs {
objfile, err := os.Open(objpath)
if err != nil {
return err
}
defer objfile.Close()
// Store the start index, for when we'll update the symbol table with
// the correct file start indices.
offset, err := arfile.Seek(0, os.SEEK_CUR)
offset, err := arfile.Seek(0, io.SeekCurrent)
if err != nil {
return err
}
if int64(int32(offset)) != offset {
return errors.New("large archives (4GB+) not supported: " + archivePath)
return errors.New("large archives (4GB+) not supported: " + arfile.Name())
}
objfiles[i].archiveOffset = int32(offset)
archiveOffsets[i] = int32(offset)
// Write the file header.
st, err := objfile.file.Stat()
st, err := objfile.Stat()
if err != nil {
return err
}
err = arwriter.WriteHeader(&ar.Header{
Name: filepath.Base(objfile.file.Name()),
Name: filepath.Base(objfile.Name()),
ModTime: time.Unix(0, 0),
Uid: 0,
Gid: 0,
@@ -155,22 +199,30 @@ func makeArchive(archivePath string, objs []string) error {
}
// Copy the file contents into the archive.
n, err := io.Copy(arwriter, objfile.file)
// First load all contents into a buffer, then write it all in one go to
// the archive file. This is a bit complicated, but is necessary because
// io.Copy can't deal with files that are of an odd size.
copyBuf.Reset()
n, err := io.Copy(&copyBuf, objfile)
if err != nil {
return err
return fmt.Errorf("could not copy object file into ar file: %w", err)
}
if n != st.Size() {
return errors.New("file modified during ar creation: " + archivePath)
return errors.New("file modified during ar creation: " + arfile.Name())
}
_, err = arwriter.Write(copyBuf.Bytes())
if err != nil {
return fmt.Errorf("could not copy object file into ar file: %w", err)
}
// File is not needed anymore.
objfile.file.Close()
objfile.Close()
}
// Create symbol indices.
indicesBuf := &bytes.Buffer{}
for _, sym := range symbolTable {
err = binary.Write(indicesBuf, binary.BigEndian, objfiles[sym.fileIndex].archiveOffset)
err = binary.Write(indicesBuf, binary.BigEndian, archiveOffsets[sym.fileIndex])
if err != nil {
return err
}
+1101 -248
View File
File diff suppressed because it is too large Load Diff
-105
View File
@@ -1,105 +0,0 @@
package builder
import (
"io"
"os"
"path/filepath"
"time"
"github.com/tinygo-org/tinygo/goenv"
)
// Return the newest timestamp of all the file paths passed in. Used to check
// for stale caches.
func cacheTimestamp(paths []string) (time.Time, error) {
var timestamp time.Time
for _, path := range paths {
st, err := os.Stat(path)
if err != nil {
return time.Time{}, err
}
if timestamp.IsZero() {
timestamp = st.ModTime()
} else if timestamp.Before(st.ModTime()) {
timestamp = st.ModTime()
}
}
return timestamp, nil
}
// Try to load a given file from the cache. Return "", nil if no cached file can
// be found (or the file is stale), return the absolute path if there is a cache
// and return an error on I/O errors.
func cacheLoad(name string, sourceFiles []string) (string, error) {
cachepath := filepath.Join(goenv.Get("GOCACHE"), name)
cacheStat, err := os.Stat(cachepath)
if os.IsNotExist(err) {
return "", nil // does not exist
} else if err != nil {
return "", err // cannot stat cache file
}
sourceTimestamp, err := cacheTimestamp(sourceFiles)
if err != nil {
return "", err // cannot stat source files
}
if cacheStat.ModTime().After(sourceTimestamp) {
return cachepath, nil
} else {
os.Remove(cachepath)
// stale cache
return "", nil
}
}
// Store the file located at tmppath in the cache with the given name. The
// tmppath may or may not be gone afterwards.
func cacheStore(tmppath, name string, sourceFiles []string) (string, error) {
// get the last modified time
if len(sourceFiles) == 0 {
panic("cache: no source files")
}
// TODO: check the config key
dir := goenv.Get("GOCACHE")
err := os.MkdirAll(dir, 0777)
if err != nil {
return "", err
}
cachepath := filepath.Join(dir, name)
err = copyFile(tmppath, cachepath)
if err != nil {
return "", err
}
return cachepath, nil
}
// copyFile copies the given file from src to dst. It can copy over
// a possibly already existing file at the destination.
func copyFile(src, dst string) error {
inf, err := os.Open(src)
if err != nil {
return err
}
defer inf.Close()
outpath := dst + ".tmp"
outf, err := os.Create(outpath)
if err != nil {
return err
}
_, err = io.Copy(outf, inf)
if err != nil {
os.Remove(outpath)
return err
}
err = outf.Close()
if err != nil {
return err
}
return os.Rename(dst+".tmp", dst)
}
+178
View File
@@ -0,0 +1,178 @@
package builder
import (
"fmt"
"os"
"path/filepath"
"runtime"
"testing"
"github.com/tinygo-org/tinygo/compileopts"
"tinygo.org/x/go-llvm"
)
// Test whether the Clang generated "target-cpu" and "target-features"
// attributes match the CPU and Features property in TinyGo target files.
func TestClangAttributes(t *testing.T) {
var targetNames = []string{
// Please keep this list sorted!
"atmega328p",
"atmega1280",
"atmega1284p",
"atmega2560",
"attiny85",
"cortex-m0",
"cortex-m0plus",
"cortex-m3",
"cortex-m33",
"cortex-m4",
"cortex-m7",
"esp32c3",
"fe310",
"gameboy-advance",
"k210",
"nintendoswitch",
"riscv-qemu",
"tkey",
"wasip1",
"wasip2",
"wasm",
"wasm-unknown",
}
if hasBuiltinTools {
// hasBuiltinTools is set when TinyGo is statically linked with LLVM,
// which also implies it was built with Xtensa support.
targetNames = append(targetNames, "esp32", "esp8266")
}
for _, targetName := range targetNames {
targetName := targetName
t.Run(targetName, func(t *testing.T) {
testClangAttributes(t, &compileopts.Options{Target: targetName})
})
}
for _, options := range []*compileopts.Options{
{GOOS: "linux", GOARCH: "386"},
{GOOS: "linux", GOARCH: "amd64"},
{GOOS: "linux", GOARCH: "arm", GOARM: "5,softfloat"},
{GOOS: "linux", GOARCH: "arm", GOARM: "6,softfloat"},
{GOOS: "linux", GOARCH: "arm", GOARM: "7,softfloat"},
{GOOS: "linux", GOARCH: "arm", GOARM: "5,hardfloat"},
{GOOS: "linux", GOARCH: "arm", GOARM: "6,hardfloat"},
{GOOS: "linux", GOARCH: "arm", GOARM: "7,hardfloat"},
{GOOS: "linux", GOARCH: "arm64"},
{GOOS: "linux", GOARCH: "mips", GOMIPS: "hardfloat"},
{GOOS: "linux", GOARCH: "mipsle", GOMIPS: "hardfloat"},
{GOOS: "linux", GOARCH: "mips", GOMIPS: "softfloat"},
{GOOS: "linux", GOARCH: "mipsle", GOMIPS: "softfloat"},
{GOOS: "darwin", GOARCH: "amd64"},
{GOOS: "darwin", GOARCH: "arm64"},
{GOOS: "windows", GOARCH: "amd64"},
{GOOS: "windows", GOARCH: "arm64"},
} {
name := "GOOS=" + options.GOOS + ",GOARCH=" + options.GOARCH
if options.GOARCH == "arm" {
name += ",GOARM=" + options.GOARM
}
if options.GOARCH == "mips" || options.GOARCH == "mipsle" {
name += ",GOMIPS=" + options.GOMIPS
}
t.Run(name, func(t *testing.T) {
testClangAttributes(t, options)
})
}
}
func testClangAttributes(t *testing.T, options *compileopts.Options) {
testDir := t.TempDir()
ctx := llvm.NewContext()
defer ctx.Dispose()
target, err := compileopts.LoadTarget(options)
if err != nil {
t.Fatalf("could not load target: %s", err)
}
config := compileopts.Config{
Options: options,
Target: target,
}
// Create a very simple C input file.
srcpath := filepath.Join(testDir, "test.c")
err = os.WriteFile(srcpath, []byte("int add(int a, int b) { return a + b; }"), 0o666)
if err != nil {
t.Fatalf("could not write target file %s: %s", srcpath, err)
}
// Compile this file using Clang.
outpath := filepath.Join(testDir, "test.bc")
flags := append([]string{"-c", "-emit-llvm", "-o", outpath, srcpath}, config.CFlags(false)...)
if config.GOOS() == "darwin" {
// Silence some warnings that happen when testing GOOS=darwin on
// something other than MacOS.
flags = append(flags, "-Wno-missing-sysroot", "-Wno-incompatible-sysroot")
}
err = runCCompiler(flags...)
if err != nil {
t.Fatalf("failed to compile %s: %s", srcpath, err)
}
// Read the resulting LLVM bitcode.
mod, err := ctx.ParseBitcodeFile(outpath)
if err != nil {
t.Fatalf("could not parse bitcode file %s: %s", outpath, err)
}
defer mod.Dispose()
// Check whether the LLVM target matches.
if mod.Target() != config.Triple() {
t.Errorf("target has LLVM triple %#v but Clang makes it LLVM triple %#v", config.Triple(), mod.Target())
}
// Check the "target-cpu" and "target-features" string attribute of the add
// function.
add := mod.NamedFunction("add")
var cpu, features string
cpuAttr := add.GetStringAttributeAtIndex(-1, "target-cpu")
featuresAttr := add.GetStringAttributeAtIndex(-1, "target-features")
if !cpuAttr.IsNil() {
cpu = cpuAttr.GetStringValue()
}
if !featuresAttr.IsNil() {
features = featuresAttr.GetStringValue()
}
if cpu != config.CPU() {
t.Errorf("target has CPU %#v but Clang makes it CPU %#v", config.CPU(), cpu)
}
if features != config.Features() {
if hasBuiltinTools || runtime.GOOS != "linux" {
// Skip this step when using an external Clang invocation on Linux.
// The reason is that Debian has patched Clang in a way that
// modifies the LLVM features string, changing lots of FPU/float
// related flags. We want to test vanilla Clang, not Debian Clang.
t.Errorf("target has LLVM features\n\t%#v\nbut Clang makes it\n\t%#v", config.Features(), features)
}
}
}
// This TestMain is necessary because TinyGo may also be invoked to run certain
// LLVM tools in a separate process. Not capturing these invocations would lead
// to recursive tests.
func TestMain(m *testing.M) {
if len(os.Args) >= 2 {
switch os.Args[1] {
case "clang", "ld.lld", "wasm-ld":
// Invoke a specific tool.
err := RunTool(os.Args[1], os.Args[2:]...)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
os.Exit(0)
}
}
// Run normal tests.
os.Exit(m.Run())
}
+127
View File
@@ -0,0 +1,127 @@
package builder
import (
"bytes"
"debug/elf"
"debug/macho"
"encoding/binary"
"fmt"
"io"
"os"
"runtime"
)
// ReadBuildID reads the build ID from the currently running executable.
func ReadBuildID() ([]byte, error) {
executable, err := os.Executable()
if err != nil {
return nil, err
}
f, err := os.Open(executable)
if err != nil {
return nil, err
}
defer f.Close()
switch runtime.GOOS {
case "linux", "freebsd", "android":
// Read the GNU build id section. (Not sure about FreeBSD though...)
file, err := elf.NewFile(f)
if err != nil {
return nil, err
}
var gnuID, goID []byte
for _, section := range file.Sections {
if section.Type != elf.SHT_NOTE ||
(section.Name != ".note.gnu.build-id" && section.Name != ".note.go.buildid") {
continue
}
buf := make([]byte, section.Size)
n, err := section.ReadAt(buf, 0)
if uint64(n) != section.Size || err != nil {
return nil, fmt.Errorf("could not read build id: %w", err)
}
if section.Name == ".note.gnu.build-id" {
gnuID = buf
} else {
goID = buf
}
}
if gnuID != nil {
return gnuID, nil
} else if goID != nil {
return goID, nil
}
case "darwin":
// Read the LC_UUID load command, which contains the equivalent of a
// build ID.
file, err := macho.NewFile(f)
if err != nil {
return nil, err
}
for _, load := range file.Loads {
// Unfortunately, the debug/macho package doesn't support the
// LC_UUID command directly. So we have to read it from
// macho.LoadBytes.
load, ok := load.(macho.LoadBytes)
if !ok {
continue
}
raw := load.Raw()
command := binary.LittleEndian.Uint32(raw)
if command != 0x1b {
// Looking for the LC_UUID load command.
// LC_UUID is defined here as 0x1b:
// https://opensource.apple.com/source/xnu/xnu-4570.71.2/EXTERNAL_HEADERS/mach-o/loader.h.auto.html
continue
}
return raw[4:], nil
}
// Normally we would have found a build ID by now. But not on Nix,
// unfortunately, because Nix adds -no_uuid for some reason:
// https://github.com/NixOS/nixpkgs/issues/178366
// Fall back to the same implementation that we use for Windows.
id, err := readRawGoBuildID(f, 32*1024)
if len(id) != 0 || err != nil {
return id, err
}
default:
// On other platforms (such as Windows) there isn't such a convenient
// build ID. Luckily, Go does have an equivalent of the build ID, which
// is stored as a special symbol named go.buildid. You can read it
// using `go tool buildid`, but the code below extracts it directly
// from the binary.
// Unfortunately, because of stripping with the -w flag, no symbol
// table might be available. Therefore, we have to scan the binary
// directly. Luckily the build ID is always at the start of the file.
// For details, see:
// https://github.com/golang/go/blob/master/src/cmd/internal/buildid/buildid.go
id, err := readRawGoBuildID(f, 4096)
if len(id) != 0 || err != nil {
return id, err
}
}
return nil, fmt.Errorf("could not find build ID in %v", executable)
}
// The Go toolchain stores a build ID in the binary that we can use, as a
// fallback if binary file specific build IDs can't be obtained.
// This function reads that build ID from the binary.
func readRawGoBuildID(f *os.File, prefixSize int) ([]byte, error) {
fileStart := make([]byte, prefixSize)
_, err := io.ReadFull(f, fileStart)
if err != nil {
return nil, fmt.Errorf("could not read build id from %s: %v", f.Name(), err)
}
index := bytes.Index(fileStart, []byte("\xff Go build ID: \""))
if index < 0 || index > len(fileStart)-103 {
return nil, fmt.Errorf("could not find build id in %s", f.Name())
}
buf := fileStart[index : index+103]
if bytes.HasPrefix(buf, []byte("\xff Go build ID: \"")) && bytes.HasSuffix(buf, []byte("\"\n \xff")) {
return buf[len("\xff Go build ID: \"") : len(buf)-1], nil
}
return nil, nil
}
+86 -21
View File
@@ -1,17 +1,21 @@
package builder
import (
"strings"
"os"
"path/filepath"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
)
// These are the GENERIC_SOURCES according to CMakeList.txt.
// These are the GENERIC_SOURCES according to CMakeList.txt except for
// divmodsi4.c and udivmodsi4.c.
var genericBuiltins = []string{
"absvdi2.c",
"absvsi2.c",
"absvti2.c",
"adddf3.c",
"addsf3.c",
"addtf3.c",
"addvdi3.c",
"addvsi3.c",
"addvti3.c",
@@ -36,13 +40,12 @@ var genericBuiltins = []string{
"divdf3.c",
"divdi3.c",
"divmoddi4.c",
"divmodsi4.c",
//"divmodsi4.c",
"divmodti4.c",
"divsc3.c",
"divsf3.c",
"divsi3.c",
"divtc3.c",
"divti3.c",
"divtf3.c",
"extendsfdf2.c",
"extendhfsf2.c",
"ffsdi2.c",
@@ -72,6 +75,7 @@ var genericBuiltins = []string{
"floatunsisf.c",
"floatuntidf.c",
"floatuntisf.c",
"fp_mode.c",
//"int_util.c",
"lshrdi3.c",
"lshrti3.c",
@@ -87,7 +91,6 @@ var genericBuiltins = []string{
"mulsc3.c",
"mulsf3.c",
"multi3.c",
"multf3.c",
"mulvdi3.c",
"mulvsi3.c",
"mulvti3.c",
@@ -107,13 +110,11 @@ var genericBuiltins = []string{
"popcountti2.c",
"powidf2.c",
"powisf2.c",
"powitf2.c",
"subdf3.c",
"subsf3.c",
"subvdi3.c",
"subvsi3.c",
"subvti3.c",
"subtf3.c",
"trampoline_setup.c",
"truncdfhf2.c",
"truncdfsf2.c",
@@ -122,7 +123,7 @@ var genericBuiltins = []string{
"ucmpti2.c",
"udivdi3.c",
"udivmoddi4.c",
"udivmodsi4.c",
//"udivmodsi4.c",
"udivmodti4.c",
"udivsi3.c",
"udivti3.c",
@@ -131,6 +132,38 @@ var genericBuiltins = []string{
"umodti3.c",
}
// These are the GENERIC_TF_SOURCES as of LLVM 18.
// They are not needed on all platforms (32-bit platforms usually don't need
// these) but they seem to compile fine so it's easier to include them.
var genericBuiltins128 = []string{
"addtf3.c",
"comparetf2.c",
"divtc3.c",
"divtf3.c",
"extenddftf2.c",
"extendhftf2.c",
"extendsftf2.c",
"fixtfdi.c",
"fixtfsi.c",
"fixtfti.c",
"fixunstfdi.c",
"fixunstfsi.c",
"fixunstfti.c",
"floatditf.c",
"floatsitf.c",
"floattitf.c",
"floatunditf.c",
"floatunsitf.c",
"floatuntitf.c",
"multc3.c",
"multf3.c",
"powitf2.c",
"subtf3.c",
"trunctfdf2.c",
"trunctfhf2.c",
"trunctfsf2.c",
}
var aeabiBuiltins = []string{
"arm/aeabi_cdcmp.S",
"arm/aeabi_cdcmpeq_check_nan.c",
@@ -149,22 +182,54 @@ var aeabiBuiltins = []string{
"arm/aeabi_memset.S",
"arm/aeabi_uidivmod.S",
"arm/aeabi_uldivmod.S",
// These two are not technically EABI builtins but are used by them and only
// seem to be used on ARM. LLVM seems to use __divsi3 and __modsi3 on most
// other architectures.
// Most importantly, they have a different calling convention on AVR so
// should not be used on AVR.
"divmodsi4.c",
"udivmodsi4.c",
}
// CompilerRT is a library with symbols required by programs compiled with LLVM.
// These symbols are for operations that cannot be emitted with a single
var avrBuiltins = []string{
"avr/divmodhi4.S",
"avr/divmodqi4.S",
"avr/mulhi3.S",
"avr/mulqi3.S",
"avr/udivmodhi4.S",
"avr/udivmodqi4.S",
}
// libCompilerRT is a library with symbols required by programs compiled with
// LLVM. These symbols are for operations that cannot be emitted with a single
// instruction or a short sequence of instructions for that target.
//
// For more information, see: https://compiler-rt.llvm.org/
var CompilerRT = Library{
name: "compiler-rt",
cflags: func() []string { return []string{"-Werror", "-Wall", "-std=c11", "-nostdlibinc"} },
sourceDir: "lib/compiler-rt/lib/builtins",
sources: func(target string) []string {
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
builtins = append(builtins, aeabiBuiltins...)
var libCompilerRT = Library{
name: "compiler-rt",
cflags: func(target, headerPath string) []string {
return []string{"-Werror", "-Wall", "-std=c11", "-nostdlibinc"}
},
sourceDir: func() string {
llvmDir := filepath.Join(goenv.Get("TINYGOROOT"), "llvm-project/compiler-rt/lib/builtins")
if _, err := os.Stat(llvmDir); err == nil {
// Release build.
return llvmDir
}
return builtins
// Development build.
return filepath.Join(goenv.Get("TINYGOROOT"), "lib/compiler-rt-builtins")
},
librarySources: func(target string) ([]string, error) {
builtins := append([]string{}, genericBuiltins...) // copy genericBuiltins
switch compileopts.CanonicalArchName(target) {
case "arm":
builtins = append(builtins, aeabiBuiltins...)
case "avr":
builtins = append(builtins, avrBuiltins...)
case "x86_64", "aarch64", "riscv64": // any 64-bit arch
builtins = append(builtins, genericBuiltins128...)
}
return builtins, nil
},
}
+318
View File
@@ -0,0 +1,318 @@
package builder
// This file implements a wrapper around the C compiler (Clang) which uses a
// build cache.
import (
"crypto/sha512"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"sort"
"strings"
"unicode"
"github.com/tinygo-org/tinygo/goenv"
"tinygo.org/x/go-llvm"
)
// compileAndCacheCFile compiles a C or assembly file using a build cache.
// Compiling the same file again (if nothing changed, including included header
// files) the output is loaded from the build cache instead.
//
// Its operation is a bit complex (more complex than Go package build caching)
// because the list of file dependencies is only known after the file is
// compiled. However, luckily compilers have a flag to write a list of file
// dependencies in Makefile syntax which can be used for caching.
//
// Because of this complexity, every file has in fact two cached build outputs:
// the file itself, and the list of dependencies. Its operation is as follows:
//
// depfile = hash(path, compiler, cflags, ...)
// if depfile exists:
// outfile = hash of all files and depfile name
// if outfile exists:
// # cache hit
// return outfile
// # cache miss
// tmpfile = compile file
// read dependencies (side effect of compile)
// write depfile
// outfile = hash of all files and depfile name
// rename tmpfile to outfile
//
// There are a few edge cases that are not handled:
// - If a file is added to an include path, that file may be included instead of
// some other file. This would be fixed by also including lookup failures in the
// dependencies file, but I'm not aware of a compiler which does that.
// - The Makefile syntax that compilers output has issues, see readDepFile for
// details.
// - A header file may be changed to add/remove an include. This invalidates the
// depfile but without invalidating its name. For this reason, the depfile is
// written on each new compilation (even when it seems unnecessary). However, it
// could in rare cases lead to a stale file fetched from the cache.
func compileAndCacheCFile(abspath, tmpdir string, cflags []string, printCommands func(string, ...string)) (string, error) {
// Hash input file.
fileHash, err := hashFile(abspath)
if err != nil {
return "", err
}
// Acquire a lock (if supported).
unlock := lock(filepath.Join(goenv.Get("GOCACHE"), fileHash+".c.lock"))
defer unlock()
// Create cache key for the dependencies file.
buf, err := json.Marshal(struct {
Path string
Hash string
Flags []string
LLVMVersion string
}{
Path: abspath,
Hash: fileHash,
Flags: cflags,
LLVMVersion: llvm.Version,
})
if err != nil {
panic(err) // shouldn't happen
}
depfileNameHashBuf := sha512.Sum512_224(buf)
depfileNameHash := hex.EncodeToString(depfileNameHashBuf[:])
// Load dependencies file, if possible.
depfileName := "dep-" + depfileNameHash + ".json"
depfileCachePath := filepath.Join(goenv.Get("GOCACHE"), depfileName)
depfileBuf, err := os.ReadFile(depfileCachePath)
var dependencies []string // sorted list of dependency paths
if err == nil {
// There is a dependency file, that's great!
// Parse it first.
err := json.Unmarshal(depfileBuf, &dependencies)
if err != nil {
return "", fmt.Errorf("could not parse dependencies JSON: %w", err)
}
// Obtain hashes of all the files listed as a dependency.
outpath, err := makeCFileCachePath(dependencies, depfileNameHash)
if err == nil {
if _, err := os.Stat(outpath); err == nil {
return outpath, nil
} else if !errors.Is(err, fs.ErrNotExist) {
return "", err
}
}
} else if !errors.Is(err, fs.ErrNotExist) {
// expected either nil or IsNotExist
return "", err
}
objTmpFile, err := os.CreateTemp(goenv.Get("GOCACHE"), "tmp-*.bc")
if err != nil {
return "", err
}
objTmpFile.Close()
depTmpFile, err := os.CreateTemp(tmpdir, "dep-*.d")
if err != nil {
return "", err
}
depTmpFile.Close()
flags := append([]string{}, cflags...) // copy cflags
flags = append(flags, "-MD", "-MV", "-MTdeps", "-MF", depTmpFile.Name(), "-flto=thin") // autogenerate dependencies
flags = append(flags, "-c", "-o", objTmpFile.Name(), abspath)
if strings.ToLower(filepath.Ext(abspath)) == ".s" {
// If this is an assembly file (.s or .S, lowercase or uppercase), then
// we'll need to add -Qunused-arguments because many parameters are
// relevant to C, not assembly. And with -Werror, having meaningless
// flags (for the assembler) is a compiler error.
flags = append(flags, "-Qunused-arguments")
}
if printCommands != nil {
printCommands("clang", flags...)
}
err = runCCompiler(flags...)
if err != nil {
return "", &commandError{"failed to build", abspath, err}
}
// Create sorted and uniqued slice of dependencies.
dependencyPaths, err := readDepFile(depTmpFile.Name())
if err != nil {
return "", err
}
dependencyPaths = append(dependencyPaths, abspath) // necessary for .s files
dependencySet := make(map[string]struct{}, len(dependencyPaths))
var dependencySlice []string
for _, path := range dependencyPaths {
if _, ok := dependencySet[path]; ok {
continue
}
dependencySet[path] = struct{}{}
dependencySlice = append(dependencySlice, path)
}
sort.Strings(dependencySlice)
// Write dependencies file.
f, err := os.CreateTemp(filepath.Dir(depfileCachePath), depfileName)
if err != nil {
return "", err
}
buf, err = json.MarshalIndent(dependencySlice, "", "\t")
if err != nil {
panic(err) // shouldn't happen
}
_, err = f.Write(buf)
if err != nil {
return "", err
}
err = f.Close()
if err != nil {
return "", err
}
err = os.Rename(f.Name(), depfileCachePath)
if err != nil {
return "", err
}
// Move temporary object file to final location.
outpath, err := makeCFileCachePath(dependencySlice, depfileNameHash)
if err != nil {
return "", err
}
err = os.Rename(objTmpFile.Name(), outpath)
if err != nil {
return "", err
}
return outpath, nil
}
// Create a cache path (a path in GOCACHE) to store the output of a compiler
// job. This path is based on the dep file name (which is a hash of metadata
// including compiler flags) and the hash of all input files in the paths slice.
func makeCFileCachePath(paths []string, depfileNameHash string) (string, error) {
// Hash all input files.
fileHashes := make(map[string]string, len(paths))
for _, path := range paths {
hash, err := hashFile(path)
if err != nil {
return "", err
}
fileHashes[path] = hash
}
// Calculate a cache key based on the above hashes.
buf, err := json.Marshal(struct {
DepfileHash string
FileHashes map[string]string
}{
DepfileHash: depfileNameHash,
FileHashes: fileHashes,
})
if err != nil {
panic(err) // shouldn't happen
}
outFileNameBuf := sha512.Sum512_224(buf)
cacheKey := hex.EncodeToString(outFileNameBuf[:])
outpath := filepath.Join(goenv.Get("GOCACHE"), "obj-"+cacheKey+".bc")
return outpath, nil
}
// hashFile hashes the given file path and returns the hash as a hex string.
func hashFile(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("failed to hash file: %w", err)
}
defer f.Close()
fileHasher := sha512.New512_224()
_, err = io.Copy(fileHasher, f)
if err != nil {
return "", fmt.Errorf("failed to hash file: %w", err)
}
return hex.EncodeToString(fileHasher.Sum(nil)), nil
}
// readDepFile reads a dependency file in NMake (Visual Studio make) format. The
// file is assumed to have a single target named deps.
//
// There are roughly three make syntax variants:
// - BSD make, which doesn't support any escaping. This means that many special
// characters are not supported in file names.
// - GNU make, which supports escaping using a backslash but when it fails to
// find a file it tries to fall back with the literal path name (to match BSD
// make).
// - NMake (Visual Studio) and Jom, which simply quote the string if there are
// any weird characters.
//
// Clang supports two variants: a format that's a compromise between BSD and GNU
// make (and is buggy to match GCC which is equally buggy), and NMake/Jom, which
// is at least somewhat sane. This last format isn't perfect either: it does not
// correctly handle filenames with quote marks in them. Those are generally not
// allowed on Windows, but of course can be used on POSIX like systems. Still,
// it's the most sane of any of the formats so readDepFile will use that format.
func readDepFile(filename string) ([]string, error) {
buf, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
if len(buf) == 0 {
return nil, nil
}
return parseDepFile(string(buf))
}
func parseDepFile(s string) ([]string, error) {
// This function makes no attempt at parsing anything other than Clang -MD
// -MV output.
// For Windows: replace CRLF with LF to make the logic below simpler.
s = strings.ReplaceAll(s, "\r\n", "\n")
// Collapse all lines ending in a backslash. These backslashes are really
// just a way to continue a line without making very long lines.
s = strings.ReplaceAll(s, "\\\n", " ")
// Only use the first line, which is expected to begin with "deps:".
line := strings.SplitN(s, "\n", 2)[0]
if !strings.HasPrefix(line, "deps:") {
return nil, errors.New("readDepFile: expected 'deps:' prefix")
}
line = strings.TrimSpace(line[len("deps:"):])
var deps []string
for line != "" {
if line[0] == '"' {
// File path is quoted. Path ends with double quote.
// This does not handle double quotes in path names, which is a
// problem on non-Windows systems.
line = line[1:]
end := strings.IndexByte(line, '"')
if end < 0 {
return nil, errors.New("readDepFile: path is incorrectly quoted")
}
dep := line[:end]
line = strings.TrimSpace(line[end+1:])
deps = append(deps, dep)
} else {
// File path is not quoted. Path ends in space or EOL.
end := strings.IndexFunc(line, unicode.IsSpace)
if end < 0 {
// last dependency
deps = append(deps, line)
break
}
dep := line[:end]
line = strings.TrimSpace(line[end:])
deps = append(deps, dep)
}
}
return deps, nil
}
+120 -72
View File
@@ -1,4 +1,11 @@
// +build byollvm
//go:build byollvm
// Source: https://github.com/llvm/llvm-project/blob/main/clang/tools/driver/cc1as_main.cpp
// This file needs to be updated each LLVM release.
// There are a few small modifications to make, like:
// * ExecuteAssembler is made non-static.
// * The struct AssemblerImplementation is moved to cc1as.h so it can be
// included elsewhere.
//===-- cc1as.cpp - Clang Assembler --------------------------------------===//
//
@@ -21,8 +28,8 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -38,6 +45,7 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
@@ -45,17 +53,18 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/Triple.h"
#include <memory>
#include <optional>
#include <system_error>
using namespace clang;
using namespace clang::driver;
@@ -73,10 +82,10 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Parse the arguments.
const OptTable &OptTbl = getDriverOptTable();
const unsigned IncludedFlagsBitmask = options::CC1AsOption;
llvm::opt::Visibility VisibilityMask(options::CC1AsOption);
unsigned MissingArgIndex, MissingArgCount;
InputArgList Args = OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount,
IncludedFlagsBitmask);
InputArgList Args =
OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount, VisibilityMask);
// Check for missing argument error.
if (MissingArgCount) {
@@ -89,7 +98,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
for (const Arg *A : Args.filtered(OPT_UNKNOWN)) {
auto ArgString = A->getAsString(Args);
std::string Nearest;
if (OptTbl.findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
if (OptTbl.findNearest(ArgString, Nearest, VisibilityMask) > 1)
Diags.Report(diag::err_drv_unknown_argument) << ArgString;
else
Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
@@ -101,6 +110,17 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Target Options
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple))
Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue());
if (Arg *A = Args.getLastArg(OPT_darwin_target_variant_sdk_version_EQ)) {
VersionTuple Version;
if (Version.tryParse(A->getValue()))
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
else
Opts.DarwinTargetVariantSDKVersion = Version;
}
Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu));
Opts.Features = Args.getAllArgValues(OPT_target_feature);
@@ -115,35 +135,32 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Any DebugInfoKind implies GenDwarfForAssembly.
Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ);
if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections,
OPT_compress_debug_sections_EQ)) {
if (A->getOption().getID() == OPT_compress_debug_sections) {
// TODO: be more clever about the compression type auto-detection
Opts.CompressDebugSections = llvm::DebugCompressionType::GNU;
} else {
Opts.CompressDebugSections =
llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
.Case("none", llvm::DebugCompressionType::None)
.Case("zlib", llvm::DebugCompressionType::Z)
.Case("zlib-gnu", llvm::DebugCompressionType::GNU)
.Default(llvm::DebugCompressionType::None);
}
if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections_EQ)) {
Opts.CompressDebugSections =
llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
.Case("none", llvm::DebugCompressionType::None)
.Case("zlib", llvm::DebugCompressionType::Zlib)
.Case("zstd", llvm::DebugCompressionType::Zstd)
.Default(llvm::DebugCompressionType::None);
}
Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
Opts.RelaxELFRelocations = !Args.hasArg(OPT_mrelax_relocations_no);
Opts.SSE2AVX = Args.hasArg(OPT_msse2avx);
if (auto *DwarfFormatArg = Args.getLastArg(OPT_gdwarf64, OPT_gdwarf32))
Opts.Dwarf64 = DwarfFormatArg->getOption().matches(OPT_gdwarf64);
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags);
Opts.DwarfDebugFlags =
std::string(Args.getLastArgValue(OPT_dwarf_debug_flags));
Opts.DwarfDebugProducer =
std::string(Args.getLastArgValue(OPT_dwarf_debug_producer));
Opts.DebugCompilationDir =
std::string(Args.getLastArgValue(OPT_fdebug_compilation_dir));
if (const Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
options::OPT_fdebug_compilation_dir_EQ))
Opts.DebugCompilationDir = A->getValue();
Opts.MainFileName = std::string(Args.getLastArgValue(OPT_main_file_name));
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
auto Split = StringRef(Arg).split('=');
Opts.DebugPrefixMap.insert(
{std::string(Split.first), std::string(Split.second)});
Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);
}
// Frontend Options
@@ -190,6 +207,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn);
Opts.NoTypeCheck = Args.hasArg(OPT_mno_type_check);
Opts.RelocationModel =
std::string(Args.getLastArgValue(OPT_mrelocation_model, "pic"));
Opts.TargetABI = std::string(Args.getLastArgValue(OPT_target_abi));
@@ -207,6 +225,20 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
.Default(0);
}
if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) {
Opts.EmitDwarfUnwind =
llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue())
.Case("always", EmitDwarfUnwindType::Always)
.Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind)
.Case("default", EmitDwarfUnwindType::Default);
}
Opts.EmitCompactUnwindNonCanonical =
Args.hasArg(OPT_femit_compact_unwind_non_canonical);
Opts.Crel = Args.hasArg(OPT_crel);
Opts.AsSecureLogFile = Args.getLastArgValue(OPT_as_secure_log_file);
return Success;
}
@@ -219,7 +251,7 @@ getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
std::error_code EC;
auto Out = std::make_unique<raw_fd_ostream>(
Path, EC, (Binary ? sys::fs::OF_None : sys::fs::OF_Text));
Path, EC, (Binary ? sys::fs::OF_None : sys::fs::OF_TextWithCRLF));
if (EC) {
Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();
return nullptr;
@@ -228,7 +260,8 @@ getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) {
return Out;
}
bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
DiagnosticsEngine &Diags) {
// Get the target specific parser.
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(Opts.Triple, Error);
@@ -236,11 +269,11 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
MemoryBuffer::getFileOrSTDIN(Opts.InputFile);
MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
if (std::error_code EC = Buffer.getError()) {
Error = EC.message();
return Diags.Report(diag::err_fe_error_reading) << Opts.InputFile;
return Diags.Report(diag::err_fe_error_reading)
<< Opts.InputFile << EC.message();
}
SourceMgr SrcMgr;
@@ -256,15 +289,23 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
assert(MRI && "Unable to create target register info!");
MCTargetOptions MCOptions;
MCOptions.MCRelaxAll = Opts.RelaxAll;
MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical;
MCOptions.MCSaveTempLabels = Opts.SaveTemporaryLabels;
MCOptions.Crel = Opts.Crel;
MCOptions.X86RelaxRelocations = Opts.RelaxELFRelocations;
MCOptions.X86Sse2Avx = Opts.SSE2AVX;
MCOptions.CompressDebugSections = Opts.CompressDebugSections;
MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
std::unique_ptr<MCAsmInfo> MAI(
TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions));
assert(MAI && "Unable to create target asm info!");
// Ensure MCAsmInfo initialization occurs before any use, otherwise sections
// may be created with a combination of default and explicit settings.
MAI->setCompressDebugSections(Opts.CompressDebugSections);
MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
if (Opts.OutputPath.empty())
@@ -277,11 +318,15 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
if (!Opts.SplitDwarfOutput.empty())
DwoOS = getOutputStream(Opts.SplitDwarfOutput, Diags, IsBinary);
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
// Build up the feature string from the target feature list.
std::string FS = llvm::join(Opts.Features, ",");
MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr, &MCOptions);
std::unique_ptr<MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
assert(STI && "Unable to create subtarget info!");
MCContext Ctx(Triple(Opts.Triple), MAI.get(), MRI.get(), STI.get(), &SrcMgr,
&MCOptions);
bool PIC = false;
if (Opts.RelocationModel == "static") {
@@ -294,9 +339,16 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
PIC = false;
}
MOFI->InitMCObjectFileInfo(Triple(Opts.Triple), PIC, Ctx);
if (Opts.SaveTemporaryLabels)
Ctx.setAllowTemporaryLabels(false);
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
std::unique_ptr<MCObjectFileInfo> MOFI(
TheTarget->createMCObjectFileInfo(Ctx, PIC));
if (Opts.DarwinTargetVariantTriple)
MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple);
if (!Opts.DarwinTargetVariantSDKVersion.empty())
MOFI->setDarwinTargetVariantSDKVersion(Opts.DarwinTargetVariantSDKVersion);
Ctx.setObjectFileInfo(MOFI.get());
if (Opts.GenDwarfForAssembly)
Ctx.setGenDwarfForAssembly(true);
if (!Opts.DwarfDebugFlags.empty())
@@ -316,25 +368,26 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
Ctx.addDebugPrefixMapEntry(KV.first, KV.second);
if (!Opts.MainFileName.empty())
Ctx.setMainFileName(StringRef(Opts.MainFileName));
Ctx.setDwarfFormat(Opts.Dwarf64 ? dwarf::DWARF64 : dwarf::DWARF32);
Ctx.setDwarfVersion(Opts.DwarfVersion);
if (Opts.GenDwarfForAssembly)
Ctx.setGenDwarfRootFile(Opts.InputFile,
SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer());
// Build up the feature string from the target feature list.
std::string FS = llvm::join(Opts.Features, ",");
std::unique_ptr<MCStreamer> Str;
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
std::unique_ptr<MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(Opts.Triple, Opts.CPU, FS));
assert(MCII && "Unable to create instruction info!");
raw_pwrite_stream *Out = FDOS.get();
std::unique_ptr<buffer_ostream> BOS;
MCOptions.MCNoWarn = Opts.NoWarn;
MCOptions.MCFatalWarnings = Opts.FatalWarnings;
MCOptions.MCNoTypeCheck = Opts.NoTypeCheck;
MCOptions.ShowMCInst = Opts.ShowInst;
MCOptions.AsmVerbose = true;
MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;
MCOptions.ABIName = Opts.TargetABI;
// FIXME: There is a bit of code duplication with addPassesToEmitFile.
@@ -344,15 +397,13 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
std::unique_ptr<MCCodeEmitter> CE;
if (Opts.ShowEncoding)
CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx));
std::unique_ptr<MCAsmBackend> MAB(
TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
auto FOut = std::make_unique<formatted_raw_ostream>(*Out);
Str.reset(TheTarget->createAsmStreamer(
Ctx, std::move(FOut), /*asmverbose*/ true,
/*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB),
Opts.ShowInst));
Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(FOut), IP,
std::move(CE), std::move(MAB)));
} else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
Str.reset(createNullStreamer(Ctx));
} else {
@@ -364,34 +415,30 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
}
std::unique_ptr<MCCodeEmitter> CE(
TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
TheTarget->createMCCodeEmitter(*MCII, Ctx));
std::unique_ptr<MCAsmBackend> MAB(
TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
assert(MAB && "Unable to create asm backend!");
std::unique_ptr<MCObjectWriter> OW =
DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS)
: MAB->createObjectWriter(*Out);
Triple T(Opts.Triple);
Str.reset(TheTarget->createMCObjectStreamer(
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI,
Opts.RelaxAll, Opts.IncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ true));
Str.get()->InitSections(Opts.NoExecStack);
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI));
Str.get()->initSections(Opts.NoExecStack, *STI);
}
// When -fembed-bitcode is passed to clang_as, a 1-byte marker
// is emitted in __LLVM,__asm section if the object file is MachO format.
if (Opts.EmbedBitcode && Ctx.getObjectFileInfo()->getObjectFileType() ==
MCObjectFileInfo::IsMachO) {
if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) {
MCSection *AsmLabel = Ctx.getMachOSection(
"__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly());
Str.get()->SwitchSection(AsmLabel);
Str.get()->switchSection(AsmLabel);
Str.get()->emitZeros(1);
}
// Assembly to object compilation should leverage assembly info.
Str->setUseAssemblerInfoForParsing(true);
bool Failed = false;
std::unique_ptr<MCAsmParser> Parser(
@@ -419,12 +466,12 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
Failed = Parser->Run(Opts.NoInitialTextSection);
}
// Close Streamer first.
// It might have a reference to the output stream.
Str.reset();
// Close the output stream early.
BOS.reset();
FDOS.reset();
return Failed;
}
bool ExecuteAssembler(AssemblerInvocation &Opts,
DiagnosticsEngine &Diags) {
bool Failed = ExecuteAssemblerImpl(Opts, Diags);
// Delete output file if there were errors.
if (Failed) {
@@ -437,7 +484,7 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) {
return Failed;
}
static void LLVMErrorHandler(void *UserData, const std::string &Message,
static void LLVMErrorHandler(void *UserData, const char *Message,
bool GenCrashDiag) {
DiagnosticsEngine &Diags = *static_cast<DiagnosticsEngine*>(UserData);
@@ -472,11 +519,12 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
return 1;
if (Asm.ShowHelp) {
getDriverOptTable().PrintHelp(
getDriverOptTable().printHelp(
llvm::outs(), "clang -cc1as [options] file...",
"Clang Integrated Assembler",
/*Include=*/driver::options::CC1AsOption, /*Exclude=*/0,
/*ShowAllAliases=*/false);
"Clang Integrated Assembler", /*ShowHidden=*/false,
/*ShowAllAliases=*/false,
llvm::opt::Visibility(driver::options::CC1AsOption));
return 0;
}
+51 -1
View File
@@ -1,3 +1,6 @@
// Source: https://github.com/llvm/llvm-project/blob/main/clang/tools/driver/cc1as_main.cpp
// See cc1as.cpp for details.
//===-- cc1as.h - Clang Assembler ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -35,15 +38,23 @@ struct AssemblerInvocation {
/// @{
std::vector<std::string> IncludePaths;
LLVM_PREFERRED_TYPE(bool)
unsigned NoInitialTextSection : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SaveTemporaryLabels : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned GenDwarfForAssembly : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned RelaxELFRelocations : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SSE2AVX : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned Dwarf64 : 1;
unsigned DwarfVersion;
std::string DwarfDebugFlags;
std::string DwarfDebugProducer;
std::string DebugCompilationDir;
std::map<const std::string, const std::string> DebugPrefixMap;
llvm::SmallVector<std::pair<std::string, std::string>, 0> DebugPrefixMap;
llvm::DebugCompressionType CompressDebugSections =
llvm::DebugCompressionType::None;
std::string MainFileName;
@@ -62,7 +73,9 @@ struct AssemblerInvocation {
FT_Obj ///< Object file output.
};
FileType OutputType;
LLVM_PREFERRED_TYPE(bool)
unsigned ShowHelp : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned ShowVersion : 1;
/// @}
@@ -70,20 +83,41 @@ struct AssemblerInvocation {
/// @{
unsigned OutputAsmVariant;
LLVM_PREFERRED_TYPE(bool)
unsigned ShowEncoding : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned ShowInst : 1;
/// @}
/// @name Assembler Options
/// @{
LLVM_PREFERRED_TYPE(bool)
unsigned RelaxAll : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned NoExecStack : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned FatalWarnings : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned NoWarn : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned NoTypeCheck : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned IncrementalLinkerCompatible : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned EmbedBitcode : 1;
/// Whether to emit DWARF unwind info.
EmitDwarfUnwindType EmitDwarfUnwind;
// Whether to emit compact-unwind for non-canonical entries.
// Note: maybe overriden by other constraints.
LLVM_PREFERRED_TYPE(bool)
unsigned EmitCompactUnwindNonCanonical : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned Crel : 1;
/// The name of the relocation model to use.
std::string RelocationModel;
@@ -91,6 +125,16 @@ struct AssemblerInvocation {
/// otherwise.
std::string TargetABI;
/// Darwin target variant triple, the variant of the deployment target
/// for which the code is being compiled.
std::optional<llvm::Triple> DarwinTargetVariantTriple;
/// The version of the darwin target variant SDK which was used during the
/// compilation
llvm::VersionTuple DarwinTargetVariantSDKVersion;
/// The name of a file to use with \c .secure_log_unique directives.
std::string AsSecureLogFile;
/// @}
public:
@@ -104,12 +148,18 @@ public:
ShowInst = 0;
ShowEncoding = 0;
RelaxAll = 0;
SSE2AVX = 0;
NoExecStack = 0;
FatalWarnings = 0;
NoWarn = 0;
NoTypeCheck = 0;
IncrementalLinkerCompatible = 0;
Dwarf64 = 0;
DwarfVersion = 0;
EmbedBitcode = 0;
EmitDwarfUnwind = EmitDwarfUnwindType::Default;
EmitCompactUnwindNonCanonical = false;
Crel = false;
}
static bool CreateFromArgs(AssemblerInvocation &Res,
+33
View File
@@ -0,0 +1,33 @@
package builder
import (
"reflect"
"testing"
)
func TestSplitDepFile(t *testing.T) {
for i, tc := range []struct {
in string
out []string
}{
{`deps: foo bar`, []string{"foo", "bar"}},
{`deps: foo "bar"`, []string{"foo", "bar"}},
{`deps: "foo" bar`, []string{"foo", "bar"}},
{`deps: "foo bar"`, []string{"foo bar"}},
{`deps: "foo bar" `, []string{"foo bar"}},
{"deps: foo\nbar", []string{"foo"}},
{"deps: foo \\\nbar", []string{"foo", "bar"}},
{"deps: foo\\bar \\\nbaz", []string{"foo\\bar", "baz"}},
{"deps: foo\\bar \\\r\n baz", []string{"foo\\bar", "baz"}}, // Windows uses CRLF line endings
} {
out, err := parseDepFile(tc.in)
if err != nil {
t.Errorf("test #%d failed: %v", i, err)
continue
}
if !reflect.DeepEqual(out, tc.out) {
t.Errorf("test #%d failed: expected %#v but got %#v", i, tc.out, out)
continue
}
}
}
+2 -2
View File
@@ -1,4 +1,4 @@
// +build byollvm
//go:build byollvm
#include <clang/Basic/DiagnosticOptions.h>
#include <clang/CodeGen/CodeGenAction.h>
@@ -11,7 +11,7 @@
#include <clang/FrontendTool/Utils.h>
#include <llvm/ADT/IntrusiveRefCntPtr.h>
#include <llvm/Option/Option.h>
#include <llvm/Support/Host.h>
#include <llvm/TargetParser/Host.h>
using namespace llvm;
using namespace clang;
+25 -13
View File
@@ -2,7 +2,7 @@ package builder
import (
"errors"
"os"
"fmt"
"os/exec"
"runtime"
"strings"
@@ -21,13 +21,24 @@ func init() {
commands["clang"] = []string{"clang-" + llvmMajor}
commands["ld.lld"] = []string{"ld.lld-" + llvmMajor, "ld.lld"}
commands["wasm-ld"] = []string{"wasm-ld-" + llvmMajor, "wasm-ld"}
commands["lldb"] = []string{"lldb-" + llvmMajor, "lldb"}
// Add the path to a Homebrew-installed LLVM for ease of use (no need to
// manually set $PATH).
if runtime.GOOS == "darwin" {
prefix := "/usr/local/opt/llvm@" + llvmMajor + "/bin/"
var prefix string
switch runtime.GOARCH {
case "amd64":
prefix = "/usr/local/opt/llvm@" + llvmMajor + "/bin/"
case "arm64":
prefix = "/opt/homebrew/opt/llvm@" + llvmMajor + "/bin/"
default:
// unknown GOARCH
panic(fmt.Sprintf("unknown GOARCH: %s on darwin", runtime.GOARCH))
}
commands["clang"] = append(commands["clang"], prefix+"clang-"+llvmMajor)
commands["ld.lld"] = append(commands["ld.lld"], prefix+"ld.lld")
commands["wasm-ld"] = append(commands["wasm-ld"], prefix+"wasm-ld")
commands["lldb"] = append(commands["lldb"], prefix+"lldb")
}
// Add the path for when LLVM was installed with the installer from
// llvm.org, which by default doesn't add LLVM to the $PATH environment
@@ -36,6 +47,7 @@ func init() {
commands["clang"] = append(commands["clang"], "clang", "C:\\Program Files\\LLVM\\bin\\clang.exe")
commands["ld.lld"] = append(commands["ld.lld"], "lld", "C:\\Program Files\\LLVM\\bin\\lld.exe")
commands["wasm-ld"] = append(commands["wasm-ld"], "C:\\Program Files\\LLVM\\bin\\wasm-ld.exe")
commands["lldb"] = append(commands["lldb"], "C:\\Program Files\\LLVM\\bin\\lldb.exe")
}
// Add the path to LLVM installed from ports.
if runtime.GOOS == "freebsd" {
@@ -43,23 +55,23 @@ func init() {
commands["clang"] = append(commands["clang"], prefix+"clang-"+llvmMajor)
commands["ld.lld"] = append(commands["ld.lld"], prefix+"ld.lld")
commands["wasm-ld"] = append(commands["wasm-ld"], prefix+"wasm-ld")
commands["lldb"] = append(commands["lldb"], prefix+"lldb")
}
}
func execCommand(cmdNames []string, args ...string) error {
for _, cmdName := range cmdNames {
cmd := exec.Command(cmdName, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
// LookupCommand looks up the executable name for a given LLVM tool such as
// clang or wasm-ld. It returns the (relative) command that can be used to
// invoke the tool or an error if it could not be found.
func LookupCommand(name string) (string, error) {
for _, cmdName := range commands[name] {
_, err := exec.LookPath(cmdName)
if err != nil {
if err, ok := err.(*exec.Error); ok && (err.Err == exec.ErrNotFound || err.Err.Error() == "file does not exist") {
// this command was not found, try the next
if errors.Unwrap(err) == exec.ErrNotFound {
continue
}
return err
return cmdName, err
}
return nil
return cmdName, nil
}
return errors.New("none of these commands were found in your $PATH: " + strings.Join(cmdNames, " "))
return "", errors.New("none of these commands were found in your $PATH: " + strings.Join(commands[name], " "))
}
+33 -12
View File
@@ -1,8 +1,8 @@
package builder
import (
"errors"
"fmt"
"runtime"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
@@ -13,27 +13,48 @@ import (
// uses the currently active GOPATH (from the goenv package) to determine the Go
// version to use.
func NewConfig(options *compileopts.Options) (*compileopts.Config, error) {
spec, err := compileopts.LoadTarget(options.Target)
spec, err := compileopts.LoadTarget(options)
if err != nil {
return nil, err
}
goroot := goenv.Get("GOROOT")
if goroot == "" {
return nil, errors.New("cannot locate $GOROOT, please set it manually")
if options.OpenOCDCommands != nil {
// Override the OpenOCDCommands from the target spec if specified on
// the command-line
spec.OpenOCDCommands = options.OpenOCDCommands
}
major, minor, err := goenv.GetGorootVersion(goroot)
// Version range supported by TinyGo.
const minorMin = 19
const minorMax = 24
// Check that we support this Go toolchain version.
gorootMajor, gorootMinor, err := goenv.GetGorootVersion()
if err != nil {
return nil, fmt.Errorf("could not read version from GOROOT (%v): %v", goroot, err)
return nil, err
}
if major != 1 || minor < 13 || minor > 16 {
return nil, fmt.Errorf("requires go version 1.13 through 1.16, got go%d.%d", major, minor)
if gorootMajor != 1 || gorootMinor < minorMin || gorootMinor > minorMax {
// Note: when this gets updated, also update the Go compatibility matrix:
// https://github.com/tinygo-org/tinygo-site/blob/dev/content/docs/reference/go-compat-matrix.md
return nil, fmt.Errorf("requires go version 1.%d through 1.%d, got go%d.%d", minorMin, minorMax, gorootMajor, gorootMinor)
}
clangHeaderPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
// Check that the Go toolchain version isn't too new, if we haven't been
// compiled with the latest Go version.
// This may be a bit too aggressive: if the newer version doesn't change the
// Go language we will most likely be able to compile it.
buildMajor, buildMinor, _, err := goenv.Parse(runtime.Version())
if err != nil {
return nil, err
}
if buildMajor != 1 || buildMinor < gorootMinor {
return nil, fmt.Errorf("cannot compile with Go toolchain version go%d.%d (TinyGo was built using toolchain version %s)", gorootMajor, gorootMinor, runtime.Version())
}
return &compileopts.Config{
Options: options,
Target: spec,
GoMinorVersion: minor,
ClangHeaders: clangHeaderPath,
GoMinorVersion: gorootMinor,
TestConfig: options.TestConfig,
}, nil
}
+58
View File
@@ -0,0 +1,58 @@
package builder
import (
"path/filepath"
"strings"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
)
// Create a job that builds a Darwin libSystem.dylib stub library. This library
// contains all the symbols needed so that we can link against it, but it
// doesn't contain any real symbol implementations.
func makeDarwinLibSystemJob(config *compileopts.Config, tmpdir string) *compileJob {
return &compileJob{
description: "compile Darwin libSystem.dylib",
run: func(job *compileJob) (err error) {
arch := strings.Split(config.Triple(), "-")[0]
job.result = filepath.Join(tmpdir, "libSystem.dylib")
objpath := filepath.Join(tmpdir, "libSystem.o")
inpath := filepath.Join(goenv.Get("TINYGOROOT"), "lib/macos-minimal-sdk/src", arch, "libSystem.s")
// Compile assembly file to object file.
flags := []string{
"-nostdlib",
"--target=" + config.Triple(),
"-c",
"-o", objpath,
inpath,
}
if config.Options.PrintCommands != nil {
config.Options.PrintCommands("clang", flags...)
}
err = runCCompiler(flags...)
if err != nil {
return err
}
// Link object file to dynamic library.
platformVersion := strings.TrimPrefix(strings.Split(config.Triple(), "-")[2], "macosx")
flags = []string{
"-flavor", "darwin",
"-demangle",
"-dynamic",
"-dylib",
"-arch", arch,
"-platform_version", "macos", platformVersion, platformVersion,
"-install_name", "/usr/lib/libSystem.B.dylib",
"-o", job.result,
objpath,
}
if config.Options.PrintCommands != nil {
config.Options.PrintCommands("ld.lld", flags...)
}
return link("ld.lld", flags...)
},
}
}
+57
View File
@@ -0,0 +1,57 @@
package builder
import (
"debug/elf"
"fmt"
"os"
)
func getElfSectionData(executable string, sectionName string) ([]byte, elf.FileHeader, error) {
elfFile, err := elf.Open(executable)
if err != nil {
return nil, elf.FileHeader{}, err
}
defer elfFile.Close()
section := elfFile.Section(sectionName)
if section == nil {
return nil, elf.FileHeader{}, fmt.Errorf("could not find %s section", sectionName)
}
data, err := section.Data()
return data, elfFile.FileHeader, err
}
func replaceElfSection(executable string, sectionName string, data []byte) error {
fp, err := os.OpenFile(executable, os.O_RDWR, 0)
if err != nil {
return err
}
defer fp.Close()
elfFile, err := elf.Open(executable)
if err != nil {
return err
}
defer elfFile.Close()
section := elfFile.Section(sectionName)
if section == nil {
return fmt.Errorf("could not find %s section", sectionName)
}
// Implicitly check for compressed sections
if section.Size != section.FileSize {
return fmt.Errorf("expected section %s to have identical size and file size, got %d and %d", sectionName, section.Size, section.FileSize)
}
// Only permit complete replacement of section
if section.Size != uint64(len(data)) {
return fmt.Errorf("expected section %s to have size %d, was actually %d", sectionName, len(data), section.Size)
}
// Write the replacement section data
_, err = fp.WriteAt(data, int64(section.Offset))
return err
}
-89
View File
@@ -1,89 +0,0 @@
package builder
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"tinygo.org/x/go-llvm"
)
// getClangHeaderPath returns the path to the built-in Clang headers. It tries
// multiple locations, which should make it find the directory when installed in
// various ways.
func getClangHeaderPath(TINYGOROOT string) string {
// Check whether we're running from the source directory.
path := filepath.Join(TINYGOROOT, "llvm-project", "clang", "lib", "Headers")
if _, err := os.Stat(path); !os.IsNotExist(err) {
return path
}
// Check whether we're running from the installation directory.
path = filepath.Join(TINYGOROOT, "lib", "clang", "include")
if _, err := os.Stat(path); !os.IsNotExist(err) {
return path
}
// It looks like we are built with a system-installed LLVM. Do a last
// attempt: try to use Clang headers relative to the clang binary.
llvmMajor := strings.Split(llvm.Version, ".")[0]
for _, cmdName := range commands["clang"] {
binpath, err := exec.LookPath(cmdName)
if err == nil {
// This should be the command that will also be used by
// execCommand. To avoid inconsistencies, make sure we use the
// headers relative to this command.
binpath, err = filepath.EvalSymlinks(binpath)
if err != nil {
// Unexpected.
return ""
}
// Example executable:
// /usr/lib/llvm-9/bin/clang
// Example include path:
// /usr/lib/llvm-9/lib64/clang/9.0.1/include/
llvmRoot := filepath.Dir(filepath.Dir(binpath))
clangVersionRoot := filepath.Join(llvmRoot, "lib64", "clang")
dirs64, err64 := ioutil.ReadDir(clangVersionRoot)
// Example include path:
// /usr/lib/llvm-9/lib/clang/9.0.1/include/
clangVersionRoot = filepath.Join(llvmRoot, "lib", "clang")
dirs32, err32 := ioutil.ReadDir(clangVersionRoot)
if err64 != nil && err32 != nil {
// Unexpected.
continue
}
dirnames := make([]string, len(dirs64)+len(dirs32))
dirCount := 0
for _, d := range dirs32 {
name := d.Name()
if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") {
dirnames[dirCount] = filepath.Join(llvmRoot, "lib", "clang", name)
dirCount++
}
}
for _, d := range dirs64 {
name := d.Name()
if name == llvmMajor || strings.HasPrefix(name, llvmMajor+".") {
dirnames[dirCount] = filepath.Join(llvmRoot, "lib64", "clang", name)
dirCount++
}
}
sort.Strings(dirnames)
// Check for the highest version first.
for i := dirCount - 1; i >= 0; i-- {
path := filepath.Join(dirnames[i], "include")
_, err := os.Stat(filepath.Join(path, "stdint.h"))
if err == nil {
return path
}
}
}
}
// Could not find it.
return ""
}
+7 -5
View File
@@ -3,7 +3,8 @@ package builder
// MultiError is a list of multiple errors (actually: diagnostics) returned
// during LLVM IR generation.
type MultiError struct {
Errs []error
ImportPath string
Errs []error
}
func (e *MultiError) Error() string {
@@ -14,15 +15,16 @@ func (e *MultiError) Error() string {
// newMultiError returns a *MultiError if there is more than one error, or
// returns that error directly when there is only one. Passing an empty slice
// will lead to a panic.
func newMultiError(errs []error) error {
// will return nil (because there is no error).
// The importPath may be passed if this error is for a single package.
func newMultiError(errs []error, importPath string) error {
switch len(errs) {
case 0:
panic("attempted to create empty MultiError")
return nil
case 1:
return errs[0]
default:
return &MultiError{errs}
return &MultiError{importPath, errs}
}
}
+50 -10
View File
@@ -13,8 +13,9 @@ import (
"debug/elf"
"encoding/binary"
"fmt"
"io/ioutil"
"os"
"sort"
"strings"
)
type espImageSegment struct {
@@ -22,7 +23,7 @@ type espImageSegment struct {
data []byte
}
// makeESPFirmare converts an input ELF file to an image file for an ESP32 or
// makeESPFirmareImage converts an input ELF file to an image file for an ESP32 or
// ESP8266 chip. This is a special purpose image format just for the ESP chip
// family, and is parsed by the on-chip mask ROM bootloader.
//
@@ -78,11 +79,37 @@ func makeESPFirmareImage(infile, outfile, format string) error {
// An added benefit is that we don't need to check for errors all the time.
outf := &bytes.Buffer{}
// Separate esp32 and esp32-img. The -img suffix indicates we should make an
// image, not just a binary to be flashed at 0x1000 for example.
chip := format
makeImage := false
if strings.HasSuffix(format, "-img") {
makeImage = true
chip = format[:len(format)-len("-img")]
}
if makeImage {
// The bootloader starts at 0x1000, or 4096.
// TinyGo doesn't use a separate bootloader and runs the entire
// application in the bootloader location.
outf.Write(make([]byte, 4096))
}
// Chip IDs. Source:
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L22
chip_id := map[string]uint16{
"esp32": 0x0000,
"esp32c3": 0x0005,
}[chip]
// Image header.
switch format {
case "esp32":
switch chip {
case "esp32", "esp32c3":
// Header format:
// https://github.com/espressif/esp-idf/blob/8fbb63c2/components/bootloader_support/include/esp_image_format.h#L58
// https://github.com/espressif/esp-idf/blob/v4.3/components/bootloader_support/include/esp_app_format.h#L71
// Note: not adding a SHA256 hash as the binary is modified by
// esptool.py while flashing and therefore the hash won't be valid
// anymore.
binary.Write(outf, binary.LittleEndian, struct {
magic uint8
segment_count uint8
@@ -91,15 +118,18 @@ func makeESPFirmareImage(infile, outfile, format string) error {
entry_addr uint32
wp_pin uint8
spi_pin_drv [3]uint8
reserved [11]uint8
chip_id uint16
min_chip_rev uint8
reserved [8]uint8
hash_appended bool
}{
magic: 0xE9,
segment_count: byte(len(segments)),
spi_mode: 0, // irrelevant, replaced by esptool when flashing
spi_speed_size: 0, // spi_speed, spi_size: replaced by esptool when flashing
spi_mode: 2, // ESP_IMAGE_SPI_MODE_DIO
spi_speed_size: 0x1f, // ESP_IMAGE_SPI_SPEED_80M, ESP_IMAGE_FLASH_SIZE_2MB
entry_addr: uint32(inf.Entry),
wp_pin: 0xEE, // disable WP pin
chip_id: chip_id,
hash_appended: true, // add a SHA256 hash
})
case "esp8266":
@@ -142,12 +172,22 @@ func makeESPFirmareImage(infile, outfile, format string) error {
outf.Write(make([]byte, 15-outf.Len()%16))
outf.WriteByte(checksum)
if format == "esp32" {
if chip != "esp8266" {
// SHA256 hash (to protect against image corruption, not for security).
hash := sha256.Sum256(outf.Bytes())
outf.Write(hash[:])
}
// QEMU (or more precisely, qemu-system-xtensa from Espressif) expects the
// image to be a certain size.
if makeImage {
// Use a default image size of 4MB.
grow := 4096*1024 - outf.Len()
if grow > 0 {
outf.Write(make([]byte, grow))
}
}
// Write the image to the output file.
return ioutil.WriteFile(outfile, outf.Bytes(), 0666)
return os.WriteFile(outfile, outf.Bytes(), 0666)
}
+149 -90
View File
@@ -4,8 +4,12 @@ package builder
// parallel while taking care of dependencies.
import (
"container/heap"
"errors"
"fmt"
"runtime"
"sort"
"strings"
"time"
)
@@ -13,111 +17,143 @@ import (
// concurrency or performance issues.
const jobRunnerDebug = false
type jobState uint8
const (
jobStateQueued jobState = iota // not yet running
jobStateRunning // running
jobStateFinished // finished running
)
// compileJob is a single compiler job, comparable to a single Makefile target.
// It is used to orchestrate various compiler tasks that can be run in parallel
// but that have dependencies and thus have limitations in how they can be run.
type compileJob struct {
description string // description, only used for logging
dependencies []*compileJob
run func() error
state jobState
result string // result (path)
run func(*compileJob) (err error)
err error // error if finished
duration time.Duration // how long it took to run this job (only set after finishing)
}
// readyToRun returns whether this job is ready to run: it is itself not yet
// started and all dependencies are finished.
func (job *compileJob) readyToRun() bool {
if job.state != jobStateQueued {
// Already running or finished, so shouldn't be run again.
return false
// dummyCompileJob returns a new *compileJob that produces an output without
// doing anything. This can be useful where a *compileJob producing an output is
// expected but nothing needs to be done, for example for a load from a cache.
func dummyCompileJob(result string) *compileJob {
return &compileJob{
description: "<dummy>",
result: result,
}
// Check dependencies.
for _, dep := range job.dependencies {
if dep.state != jobStateFinished {
// A dependency is not finished, so this job has to wait until it
// is.
return false
}
}
// All conditions are satisfied.
return true
}
// runJobs runs all the jobs indicated in the jobs slice and returns the error
// of the first job that fails to run.
// It runs all jobs in the order of the slice, as long as all dependencies have
// already run. Therefore, if some jobs are preferred to run before others, they
// should be ordered as such in this slice.
func runJobs(jobs []*compileJob) error {
// Create channels to communicate with the workers.
doneChan := make(chan *compileJob)
workerChan := make(chan *compileJob)
defer close(workerChan)
// Start a number of workers.
for i := 0; i < runtime.NumCPU(); i++ {
if jobRunnerDebug {
fmt.Println("## starting worker", i)
}
go jobWorker(workerChan, doneChan)
// runJobs runs the indicated job and all its dependencies. For every job, all
// the dependencies are run first. It returns the error of the first job that
// fails.
// It runs all jobs in the order of the dependencies slice, depth-first.
// Therefore, if some jobs are preferred to run before others, they should be
// ordered as such in the job dependencies.
func runJobs(job *compileJob, sema chan struct{}) error {
if sema == nil {
// Have a default, if the semaphore isn't set. This is useful for tests.
sema = make(chan struct{}, runtime.NumCPU())
}
if cap(sema) == 0 {
return errors.New("cannot run 0 jobs at a time")
}
// Send each job in the jobs slice to a worker, taking care of job
// dependencies.
// Create a slice of jobs to run, where all dependencies are run in order.
jobs := []*compileJob{}
addedJobs := map[*compileJob]struct{}{}
var addJobs func(*compileJob)
addJobs = func(job *compileJob) {
if _, ok := addedJobs[job]; ok {
return
}
for _, dep := range job.dependencies {
addJobs(dep)
}
jobs = append(jobs, job)
addedJobs[job] = struct{}{}
}
addJobs(job)
waiting := make(map[*compileJob]map[*compileJob]struct{}, len(jobs))
dependents := make(map[*compileJob][]*compileJob, len(jobs))
compileJobs := make(map[*compileJob]int)
var ready intHeap
for i, job := range jobs {
compileJobs[job] = i
if len(job.dependencies) == 0 {
// This job is ready to run.
ready.Push(i)
continue
}
// Construct a map for dependencies which the job is currently waiting on.
waitDeps := make(map[*compileJob]struct{})
waiting[job] = waitDeps
// Add the job to the dependents list of each dependency.
for _, dep := range job.dependencies {
dependents[dep] = append(dependents[dep], job)
waitDeps[dep] = struct{}{}
}
}
// Create a channel to accept notifications of completion.
doneChan := make(chan *compileJob)
// Send each job in the jobs slice to a worker, taking care of job dependencies.
numRunningJobs := 0
var totalTime time.Duration
start := time.Now()
for {
// If there are free workers, try starting a new job (if one is
// available). If it succeeds, try again to fill the entire worker pool.
if numRunningJobs < runtime.NumCPU() {
jobToRun := nextJob(jobs)
if jobToRun != nil {
// Start job.
for len(ready.IntSlice) > 0 || numRunningJobs != 0 {
var completed *compileJob
if len(ready.IntSlice) > 0 {
select {
case sema <- struct{}{}:
// Start a job.
job := jobs[heap.Pop(&ready).(int)]
if jobRunnerDebug {
fmt.Println("## start: ", jobToRun.description)
fmt.Println("## start: ", job.description)
}
jobToRun.state = jobStateRunning
workerChan <- jobToRun
go runJob(job, doneChan)
numRunningJobs++
continue
case completed = <-doneChan:
// A job completed.
}
} else {
// Wait for a job to complete.
completed = <-doneChan
}
// When there are no jobs running, all jobs in the jobs slice must have
// been finished. Therefore, the work is done.
if numRunningJobs == 0 {
break
}
// Wait until a job is finished.
job := <-doneChan
job.state = jobStateFinished
numRunningJobs--
totalTime += job.duration
<-sema
if jobRunnerDebug {
fmt.Println("## finished:", job.description, "(time "+job.duration.String()+")")
fmt.Println("## finished:", completed.description, "(time "+completed.duration.String()+")")
}
if job.err != nil {
// Wait for running jobs to finish.
if completed.err != nil {
// Wait for any current jobs to finish.
for numRunningJobs != 0 {
<-doneChan
numRunningJobs--
}
// Return error of first failing job.
return job.err
// The build failed.
return completed.err
}
// Update total run time.
totalTime += completed.duration
// Update dependent jobs.
for _, j := range dependents[completed] {
wait := waiting[j]
delete(wait, completed)
if len(wait) == 0 {
// This job is now ready to run.
ready.Push(compileJobs[j])
delete(waiting, j)
}
}
}
if len(waiting) != 0 {
// There is a dependency cycle preventing some jobs from running.
return errDependencyCycle{waiting}
}
// Some statistics, if debugging.
@@ -134,27 +170,50 @@ func runJobs(jobs []*compileJob) error {
return nil
}
// nextJob returns the first ready-to-run job.
// This is an implementation detail of runJobs.
func nextJob(jobs []*compileJob) *compileJob {
for _, job := range jobs {
if job.readyToRun() {
return job
}
}
return nil
type errDependencyCycle struct {
waiting map[*compileJob]map[*compileJob]struct{}
}
// jobWorker is the goroutine that runs received jobs.
// This is an implementation detail of runJobs.
func jobWorker(workerChan, doneChan chan *compileJob) {
for job := range workerChan {
start := time.Now()
err := job.run()
func (err errDependencyCycle) Error() string {
waits := make([]string, 0, len(err.waiting))
for j, wait := range err.waiting {
deps := make([]string, 0, len(wait))
for dep := range wait {
deps = append(deps, dep.description)
}
sort.Strings(deps)
waits = append(waits, fmt.Sprintf("\t%s is waiting for [%s]",
j.description, strings.Join(deps, ", "),
))
}
sort.Strings(waits)
return "deadlock:\n" + strings.Join(waits, "\n")
}
type intHeap struct {
sort.IntSlice
}
func (h *intHeap) Push(x interface{}) {
h.IntSlice = append(h.IntSlice, x.(int))
}
func (h *intHeap) Pop() interface{} {
x := h.IntSlice[len(h.IntSlice)-1]
h.IntSlice = h.IntSlice[:len(h.IntSlice)-1]
return x
}
// runJob runs a compile job and notifies doneChan of completion.
func runJob(job *compileJob, doneChan chan *compileJob) {
start := time.Now()
if job.run != nil {
err := job.run(job)
if err != nil {
job.err = err
}
job.duration = time.Since(start)
doneChan <- job
}
job.duration = time.Since(start)
doneChan <- job
}
+210 -73
View File
@@ -1,10 +1,15 @@
package builder
import (
"errors"
"io/fs"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
)
@@ -14,130 +19,230 @@ type Library struct {
// The library name, such as compiler-rt or picolibc.
name string
cflags func() []string
// makeHeaders creates a header include dir for the library
makeHeaders func(target, includeDir string) error
// The source directory, relative to TINYGOROOT.
sourceDir string
// cflags returns the C flags specific to this library
cflags func(target, headerPath string) []string
// The source directory.
sourceDir func() string
// The source files, relative to sourceDir.
sources func(target string) []string
librarySources func(target string) ([]string, error)
// The source code for the crt1.o file, relative to sourceDir.
crt1Source string
}
// fullPath returns the full path to the source directory.
func (l *Library) fullPath() string {
return filepath.Join(goenv.Get("TINYGOROOT"), l.sourceDir)
}
// sourcePaths returns a slice with the full paths to the source files.
func (l *Library) sourcePaths(target string) []string {
sources := l.sources(target)
paths := make([]string, len(sources))
for i, name := range sources {
paths[i] = filepath.Join(l.fullPath(), name)
}
return paths
}
// Load the library archive, possibly generating and caching it if needed.
// The resulting file is stored in the provided tmpdir, which is expected to be
// removed after the Load call.
func (l *Library) Load(target, tmpdir string) (path string, err error) {
path, job, err := l.load(target, "", tmpdir)
if err != nil {
return "", err
}
if job != nil {
jobs := append([]*compileJob{job}, job.dependencies...)
err = runJobs(jobs)
}
return path, err
}
// load returns a path to the library file for the given target, loading it from
// cache if possible. It will return a non-zero compiler job if the library
// wasn't cached, this job (and its dependencies) must be run before the library
// path is valid.
// load returns a compile job to build this library file for the given target
// and CPU. It may return a dummy compileJob if the library build is already
// cached. The path is stored as job.result but is only valid after the job has
// been run.
// The provided tmpdir will be used to store intermediary files and possibly the
// output archive file, it is expected to be removed after use.
func (l *Library) load(target, cpu, tmpdir string) (path string, job *compileJob, err error) {
// Try to load a precompiled library.
precompiledPath := filepath.Join(goenv.Get("TINYGOROOT"), "pkg", target, l.name+".a")
if _, err := os.Stat(precompiledPath); err == nil {
// As a side effect, this call creates the library header files if they didn't
// exist yet.
func (l *Library) load(config *compileopts.Config, tmpdir string) (job *compileJob, abortLock func(), err error) {
outdir, precompiled := config.LibcPath(l.name)
archiveFilePath := filepath.Join(outdir, "lib.a")
if precompiled {
// Found a precompiled library for this OS/architecture. Return the path
// directly.
return precompiledPath, nil, nil
return dummyCompileJob(archiveFilePath), func() {}, nil
}
var outfile string
if cpu != "" {
outfile = l.name + "-" + target + "-" + cpu + ".a"
} else {
outfile = l.name + "-" + target + ".a"
}
// Create a lock on the output (if supported).
// This is a bit messy, but avoids a deadlock because it is ordered consistently with other library loads within a build.
outname := filepath.Base(outdir)
unlock := lock(filepath.Join(goenv.Get("GOCACHE"), outname+".lock"))
var ok bool
defer func() {
if !ok {
unlock()
}
}()
// Try to fetch this library from the cache.
if path, err := cacheLoad(outfile, l.sourcePaths(target)); path != "" || err != nil {
// Cache hit.
return path, nil, err
if _, err := os.Stat(archiveFilePath); err == nil {
return dummyCompileJob(archiveFilePath), func() {}, nil
}
// Cache miss, build it now.
// Create the destination directory where the components of this library
// (lib.a file, include directory) are placed.
err = os.MkdirAll(filepath.Join(goenv.Get("GOCACHE"), outname), 0o777)
if err != nil {
// Could not create directory (and not because it already exists).
return nil, nil, err
}
// Make headers if needed.
headerPath := filepath.Join(outdir, "include")
target := config.Triple()
if l.makeHeaders != nil {
if _, err = os.Stat(headerPath); err != nil {
temporaryHeaderPath, err := os.MkdirTemp(outdir, "include.tmp*")
if err != nil {
return nil, nil, err
}
defer os.RemoveAll(temporaryHeaderPath)
err = l.makeHeaders(target, temporaryHeaderPath)
if err != nil {
return nil, nil, err
}
err = os.Chmod(temporaryHeaderPath, 0o755) // TempDir uses 0o700 by default
if err != nil {
return nil, nil, err
}
err = os.Rename(temporaryHeaderPath, headerPath)
if err != nil {
switch {
case errors.Is(err, fs.ErrExist):
// Another invocation of TinyGo also seems to have already created the headers.
case runtime.GOOS == "windows" && errors.Is(err, fs.ErrPermission):
// On Windows, a rename with a destination directory that already
// exists does not result in an IsExist error, but rather in an
// access denied error. To be sure, check for this case by checking
// whether the target directory exists.
if _, err := os.Stat(headerPath); err == nil {
break
}
fallthrough
default:
return nil, nil, err
}
}
}
}
remapDir := filepath.Join(os.TempDir(), "tinygo-"+l.name)
dir := filepath.Join(tmpdir, "build-lib-"+l.name)
err = os.Mkdir(dir, 0777)
if err != nil {
return "", nil, err
return nil, nil, err
}
// Precalculate the flags to the compiler invocation.
// Note: -fdebug-prefix-map is necessary to make the output archive
// reproducible. Otherwise the temporary directory is stored in the archive
// itself, which varies each run.
args := append(l.cflags(), "-c", "-Oz", "-g", "-ffunction-sections", "-fdata-sections", "-Wno-macro-redefined", "--target="+target, "-fdebug-prefix-map="+dir+"="+remapDir)
args := append(l.cflags(target, headerPath), "-c", "-Oz", "-gdwarf-4", "-ffunction-sections", "-fdata-sections", "-Wno-macro-redefined", "--target="+target, "-fdebug-prefix-map="+dir+"="+remapDir)
resourceDir := goenv.ClangResourceDir(false)
if resourceDir != "" {
args = append(args, "-resource-dir="+resourceDir)
}
cpu := config.CPU()
if cpu != "" {
args = append(args, "-mcpu="+cpu)
// X86 has deprecated the -mcpu flag, so we need to use -march instead.
// However, ARM has not done this.
if strings.HasPrefix(target, "i386") || strings.HasPrefix(target, "x86_64") {
args = append(args, "-march="+cpu)
} else if strings.HasPrefix(target, "avr") {
args = append(args, "-mmcu="+cpu)
} else {
args = append(args, "-mcpu="+cpu)
}
}
if strings.HasPrefix(target, "arm") || strings.HasPrefix(target, "thumb") {
args = append(args, "-fshort-enums", "-fomit-frame-pointer", "-mfloat-abi=soft")
if config.ABI() != "" {
args = append(args, "-mabi="+config.ABI())
}
if strings.HasPrefix(target, "riscv32-") {
args = append(args, "-march=rv32imac", "-mabi=ilp32", "-fforce-enable-int128")
switch compileopts.CanonicalArchName(target) {
case "arm":
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")
}
case "avr":
// AVR defaults to C float and double both being 32-bit. This deviates
// from what most code (and certainly compiler-rt) expects. So we need
// to force the compiler to use 64-bit floating point numbers for
// double.
args = append(args, "-mdouble=64")
case "riscv32":
args = append(args, "-march=rv32imac", "-fforce-enable-int128")
case "riscv64":
args = append(args, "-march=rv64gc")
case "mips":
args = append(args, "-fno-pic")
}
if strings.HasPrefix(target, "riscv64-") {
args = append(args, "-march=rv64gc", "-mabi=lp64")
if config.Target.SoftFloat {
// Use softfloat instead of floating point instructions. This is
// supported on many architectures.
args = append(args, "-msoft-float")
} else {
if strings.HasPrefix(target, "armv5") {
// On ARMv5 we need to explicitly enable hardware floating point
// instructions: Clang appears to assume the hardware doesn't have a
// FPU otherwise.
args = append(args, "-mfpu=vfpv2")
}
}
var once sync.Once
// Create job to put all the object files in a single archive. This archive
// file is the (static) library file.
var objs []string
arpath := filepath.Join(dir, l.name+".a")
job = &compileJob{
description: "ar " + l.name + ".a",
run: func() error {
description: "ar " + l.name + "/lib.a",
result: filepath.Join(goenv.Get("GOCACHE"), outname, "lib.a"),
run: func(*compileJob) error {
defer once.Do(unlock)
// Create an archive of all object files.
err := makeArchive(arpath, objs)
f, err := os.CreateTemp(outdir, "libc.a.tmp*")
if err != nil {
return err
}
err = makeArchive(f, objs)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
err = os.Chmod(f.Name(), 0o644) // TempFile uses 0o600 by default
if err != nil {
return err
}
// Store this archive in the cache.
_, err = cacheStore(arpath, outfile, l.sourcePaths(target))
return err
return os.Rename(f.Name(), archiveFilePath)
},
}
sourceDir := l.sourceDir()
// Create jobs to compile all sources. These jobs are depended upon by the
// archive job above, so must be run first.
for _, srcpath := range l.sourcePaths(target) {
srcpath := srcpath // avoid concurrency issues by redefining inside the loop
objpath := filepath.Join(dir, filepath.Base(srcpath)+".o")
paths, err := l.librarySources(target)
if err != nil {
return nil, nil, err
}
for _, path := range paths {
// Strip leading "../" parts off the path.
cleanpath := path
for strings.HasPrefix(cleanpath, "../") {
cleanpath = cleanpath[3:]
}
srcpath := filepath.Join(sourceDir, path)
objpath := filepath.Join(dir, cleanpath+".o")
os.MkdirAll(filepath.Dir(objpath), 0o777)
objs = append(objs, objpath)
job.dependencies = append(job.dependencies, &compileJob{
description: "compile " + srcpath,
run: func() error {
run: func(*compileJob) error {
var compileArgs []string
compileArgs = append(compileArgs, args...)
compileArgs = append(compileArgs, "-o", objpath, srcpath)
err := runCCompiler("clang", compileArgs...)
if config.Options.PrintCommands != nil {
config.Options.PrintCommands("clang", compileArgs...)
}
err := runCCompiler(compileArgs...)
if err != nil {
return &commandError{"failed to build", srcpath, err}
}
@@ -146,5 +251,37 @@ func (l *Library) load(target, cpu, tmpdir string) (path string, job *compileJob
})
}
return arpath, job, nil
// Create crt1.o job, if needed.
// Add this as a (fake) dependency to the ar file so it gets compiled.
// (It could be done in parallel with creating the ar file, but it probably
// won't make much of a difference in speed).
if l.crt1Source != "" {
srcpath := filepath.Join(sourceDir, l.crt1Source)
job.dependencies = append(job.dependencies, &compileJob{
description: "compile " + srcpath,
run: func(*compileJob) error {
var compileArgs []string
compileArgs = append(compileArgs, args...)
tmpfile, err := os.CreateTemp(outdir, "crt1.o.tmp*")
if err != nil {
return err
}
tmpfile.Close()
compileArgs = append(compileArgs, "-o", tmpfile.Name(), srcpath)
if config.Options.PrintCommands != nil {
config.Options.PrintCommands("clang", compileArgs...)
}
err = runCCompiler(compileArgs...)
if err != nil {
return &commandError{"failed to build", srcpath, err}
}
return os.Rename(tmpfile.Name(), filepath.Join(outdir, "crt1.o"))
},
})
}
ok = true
return job, func() {
once.Do(unlock)
}, nil
}
+21 -8
View File
@@ -1,19 +1,32 @@
// +build byollvm
//go:build byollvm
// This file provides C wrappers for liblld.
#include <lld/Common/Driver.h>
#include <llvm/Support/Parallel.h>
LLD_HAS_DRIVER(coff)
LLD_HAS_DRIVER(elf)
LLD_HAS_DRIVER(mingw)
LLD_HAS_DRIVER(macho)
LLD_HAS_DRIVER(wasm)
static void configure() {
#if _WIN64
// This is a hack to work around a hang in the LLD linker on Windows, with
// -DLLVM_ENABLE_THREADS=ON. It has a similar effect as the -threads=1
// linker flag, but with support for the COFF linker.
llvm::parallel::strategy = llvm::hardware_concurrency(1);
#endif
}
extern "C" {
bool tinygo_link_elf(int argc, char **argv) {
bool tinygo_link(int argc, char **argv) {
configure();
std::vector<const char*> args(argv, argv + argc);
return lld::elf::link(args, false, llvm::outs(), llvm::errs());
}
bool tinygo_link_wasm(int argc, char **argv) {
std::vector<const char*> args(argv, argv + argc);
return lld::wasm::link(args, false, llvm::outs(), llvm::errs());
lld::Result r = lld::lldMain(args, llvm::outs(), llvm::errs(), LLD_ALL_DRIVERS);
return !r.retCode;
}
} // external "C"
+120
View File
@@ -0,0 +1,120 @@
package builder
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/tinygo-org/tinygo/goenv"
)
var libMinGW = Library{
name: "mingw-w64",
makeHeaders: func(target, includeDir string) error {
// copy _mingw.h
srcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib", "mingw-w64")
outf, err := os.Create(includeDir + "/_mingw.h")
if err != nil {
return err
}
defer outf.Close()
inf, err := os.Open(srcDir + "/mingw-w64-headers/crt/_mingw.h.in")
if err != nil {
return err
}
_, err = io.Copy(outf, inf)
return err
},
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/mingw-w64") },
cflags: func(target, headerPath string) []string {
mingwDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/mingw-w64")
return []string{
"-nostdlibinc",
"-isystem", mingwDir + "/mingw-w64-headers/crt",
"-I", mingwDir + "/mingw-w64-headers/defaults/include",
"-I" + headerPath,
}
},
librarySources: func(target string) ([]string, error) {
// These files are needed so that printf and the like are supported.
sources := []string{
"mingw-w64-crt/stdio/ucrt_fprintf.c",
"mingw-w64-crt/stdio/ucrt_fwprintf.c",
"mingw-w64-crt/stdio/ucrt_printf.c",
"mingw-w64-crt/stdio/ucrt_snprintf.c",
"mingw-w64-crt/stdio/ucrt_sprintf.c",
"mingw-w64-crt/stdio/ucrt_vfprintf.c",
"mingw-w64-crt/stdio/ucrt_vprintf.c",
"mingw-w64-crt/stdio/ucrt_vsnprintf.c",
"mingw-w64-crt/stdio/ucrt_vsprintf.c",
}
return sources, nil
},
}
// makeMinGWExtraLibs returns a slice of jobs to import the correct .dll
// libraries. This is done by converting input .def files to .lib files which
// can then be linked as usual.
//
// TODO: cache the result. At the moment, it costs a few hundred milliseconds to
// compile these files.
func makeMinGWExtraLibs(tmpdir, goarch string) []*compileJob {
var jobs []*compileJob
root := goenv.Get("TINYGOROOT")
// Normally all the api-ms-win-crt-*.def files are all compiled to a single
// .lib file. But to simplify things, we're going to leave them as separate
// files.
for _, name := range []string{
"kernel32.def.in",
"api-ms-win-crt-conio-l1-1-0.def",
"api-ms-win-crt-convert-l1-1-0.def.in",
"api-ms-win-crt-environment-l1-1-0.def",
"api-ms-win-crt-filesystem-l1-1-0.def",
"api-ms-win-crt-heap-l1-1-0.def",
"api-ms-win-crt-locale-l1-1-0.def",
"api-ms-win-crt-math-l1-1-0.def.in",
"api-ms-win-crt-multibyte-l1-1-0.def",
"api-ms-win-crt-private-l1-1-0.def.in",
"api-ms-win-crt-process-l1-1-0.def",
"api-ms-win-crt-runtime-l1-1-0.def.in",
"api-ms-win-crt-stdio-l1-1-0.def",
"api-ms-win-crt-string-l1-1-0.def",
"api-ms-win-crt-time-l1-1-0.def",
"api-ms-win-crt-utility-l1-1-0.def",
} {
outpath := filepath.Join(tmpdir, filepath.Base(name)+".lib")
inpath := filepath.Join(root, "lib/mingw-w64/mingw-w64-crt/lib-common/"+name)
job := &compileJob{
description: "create lib file " + inpath,
result: outpath,
run: func(job *compileJob) error {
defpath := inpath
var archDef, emulation string
switch goarch {
case "amd64":
archDef = "-DDEF_X64"
emulation = "i386pep"
case "arm64":
archDef = "-DDEF_ARM64"
emulation = "arm64pe"
default:
return fmt.Errorf("unsupported architecture for mingw-w64: %s", goarch)
}
if strings.HasSuffix(inpath, ".in") {
// .in files need to be preprocessed by a preprocessor (-E)
// first.
defpath = outpath + ".def"
err := runCCompiler("-E", "-x", "c", "-Wp,-w", "-P", archDef, "-DDATA", "-o", defpath, inpath, "-I"+goenv.Get("TINYGOROOT")+"/lib/mingw-w64/mingw-w64-crt/def-include/")
if err != nil {
return err
}
}
return link("ld.lld", "-m", emulation, "-o", outpath, defpath)
},
}
jobs = append(jobs, job)
}
return jobs
}
+191
View File
@@ -0,0 +1,191 @@
package builder
import (
"bytes"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
)
var libMusl = Library{
name: "musl",
makeHeaders: func(target, includeDir string) error {
bits := filepath.Join(includeDir, "bits")
err := os.Mkdir(bits, 0777)
if err != nil {
return err
}
arch := compileopts.MuslArchitecture(target)
muslDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib", "musl")
// Create the file alltypes.h.
f, err := os.Create(filepath.Join(bits, "alltypes.h"))
if err != nil {
return err
}
infiles := []string{
filepath.Join(muslDir, "arch", arch, "bits", "alltypes.h.in"),
filepath.Join(muslDir, "include", "alltypes.h.in"),
}
for _, infile := range infiles {
data, err := os.ReadFile(infile)
if err != nil {
return err
}
lines := strings.Split(string(data), "\n")
for _, line := range lines {
if strings.HasPrefix(line, "TYPEDEF ") {
matches := regexp.MustCompile(`TYPEDEF (.*) ([^ ]*);`).FindStringSubmatch(line)
value := matches[1]
name := matches[2]
line = fmt.Sprintf("#if defined(__NEED_%s) && !defined(__DEFINED_%s)\ntypedef %s %s;\n#define __DEFINED_%s\n#endif\n", name, name, value, name, name)
}
if strings.HasPrefix(line, "STRUCT ") {
matches := regexp.MustCompile(`STRUCT * ([^ ]*) (.*);`).FindStringSubmatch(line)
name := matches[1]
value := matches[2]
line = fmt.Sprintf("#if defined(__NEED_struct_%s) && !defined(__DEFINED_struct_%s)\nstruct %s %s;\n#define __DEFINED_struct_%s\n#endif\n", name, name, name, value, name)
}
f.WriteString(line + "\n")
}
}
f.Close()
// Create the file syscall.h.
f, err = os.Create(filepath.Join(bits, "syscall.h"))
if err != nil {
return err
}
data, err := os.ReadFile(filepath.Join(muslDir, "arch", arch, "bits", "syscall.h.in"))
if err != nil {
return err
}
_, err = f.Write(bytes.ReplaceAll(data, []byte("__NR_"), []byte("SYS_")))
if err != nil {
return err
}
f.Close()
return nil
},
cflags: func(target, headerPath string) []string {
arch := compileopts.MuslArchitecture(target)
muslDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl")
cflags := []string{
"-std=c99", // same as in musl
"-D_XOPEN_SOURCE=700", // same as in musl
// Musl triggers some warnings and we don't want to show any
// warnings while compiling (only errors or silence), so disable
// specific warnings that are triggered in musl.
"-Werror",
"-Wno-logical-op-parentheses",
"-Wno-bitwise-op-parentheses",
"-Wno-shift-op-parentheses",
"-Wno-ignored-attributes",
"-Wno-string-plus-int",
"-Wno-ignored-pragmas",
"-Wno-tautological-constant-out-of-range-compare",
"-Wno-deprecated-non-prototype",
"-Wno-format",
"-Wno-parentheses",
"-Qunused-arguments",
// Select include dirs. Don't include standard library includes
// (that would introduce host dependencies and other complications),
// but do include all the include directories expected by musl.
"-nostdlibinc",
"-I" + muslDir + "/arch/" + arch,
"-I" + muslDir + "/arch/generic",
"-I" + muslDir + "/src/include",
"-I" + muslDir + "/src/internal",
"-I" + headerPath,
"-I" + muslDir + "/include",
"-fno-stack-protector",
}
return cflags
},
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/musl/src") },
librarySources: func(target string) ([]string, error) {
arch := compileopts.MuslArchitecture(target)
globs := []string{
"env/*.c",
"errno/*.c",
"exit/*.c",
"fcntl/*.c",
"internal/defsysinfo.c",
"internal/libc.c",
"internal/syscall_ret.c",
"internal/vdso.c",
"legacy/*.c",
"locale/*.c",
"linux/*.c",
"malloc/*.c",
"malloc/mallocng/*.c",
"mman/*.c",
"math/*.c",
"misc/*.c",
"multibyte/*.c",
"signal/" + arch + "/*.s",
"signal/*.c",
"stdio/*.c",
"string/*.c",
"thread/" + arch + "/*.s",
"thread/*.c",
"time/*.c",
"unistd/*.c",
"process/*.c",
}
if arch == "arm" {
// These files need to be added to the start for some reason.
globs = append([]string{"thread/arm/*.c"}, globs...)
}
if arch != "aarch64" && arch != "mips" {
//aarch64 and mips have no architecture specific code, either they
// are not supported or don't need any?
globs = append([]string{"process/" + arch + "/*.s"}, globs...)
}
var sources []string
seenSources := map[string]struct{}{}
basepath := goenv.Get("TINYGOROOT") + "/lib/musl/src/"
for _, pattern := range globs {
matches, err := filepath.Glob(basepath + pattern)
if err != nil {
// From the documentation:
// > Glob ignores file system errors such as I/O errors reading
// > directories. The only possible returned error is
// > ErrBadPattern, when pattern is malformed.
// So the only possible error is when the (statically defined)
// pattern is wrong. In other words, a programming bug.
return nil, fmt.Errorf("musl: could not glob source dirs: %w", err)
}
if len(matches) == 0 {
return nil, fmt.Errorf("musl: did not find any files for pattern %#v", pattern)
}
for _, match := range matches {
relpath, err := filepath.Rel(basepath, match)
if err != nil {
// Not sure if this is even possible.
return nil, err
}
// Make sure architecture specific files override generic files.
id := strings.ReplaceAll(relpath, "/"+arch+"/", "/")
if _, ok := seenSources[id]; ok {
// Already seen this file, skipping this (generic) file.
continue
}
seenSources[id] = struct{}{}
sources = append(sources, relpath)
}
}
return sources, nil
},
crt1Source: "../crt/crt1.c", // lib/musl/crt/crt1.c
}
+117
View File
@@ -0,0 +1,117 @@
package builder
import (
"archive/zip"
"bytes"
"encoding/binary"
"encoding/json"
"os"
"github.com/sigurn/crc16"
"github.com/tinygo-org/tinygo/compileopts"
)
// Structure of the manifest.json file.
type jsonManifest struct {
Manifest struct {
Application struct {
BinaryFile string `json:"bin_file"`
DataFile string `json:"dat_file"`
InitPacketData nrfInitPacket `json:"init_packet_data"`
} `json:"application"`
DFUVersion float64 `json:"dfu_version"` // yes, this is a JSON number, not a string
} `json:"manifest"`
}
// Structure of the init packet.
// Source:
// https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/master/lib/sdk11/components/libraries/bootloader_dfu/dfu_init.h#L47-L57
type nrfInitPacket struct {
ApplicationVersion uint32 `json:"application_version"`
DeviceRevision uint16 `json:"device_revision"`
DeviceType uint16 `json:"device_type"`
FirmwareCRC16 uint16 `json:"firmware_crc16"`
SoftDeviceRequired []uint16 `json:"softdevice_req"` // this is actually a variable length array
}
// Create the init packet (the contents of application.dat).
func (p nrfInitPacket) createInitPacket() []byte {
buf := &bytes.Buffer{}
binary.Write(buf, binary.LittleEndian, p.DeviceType) // uint16_t device_type;
binary.Write(buf, binary.LittleEndian, p.DeviceRevision) // uint16_t device_rev;
binary.Write(buf, binary.LittleEndian, p.ApplicationVersion) // uint32_t app_version;
binary.Write(buf, binary.LittleEndian, uint16(len(p.SoftDeviceRequired))) // uint16_t softdevice_len;
binary.Write(buf, binary.LittleEndian, p.SoftDeviceRequired) // uint16_t softdevice[1];
binary.Write(buf, binary.LittleEndian, p.FirmwareCRC16)
return buf.Bytes()
}
// Make a Nordic DFU firmware image from an ELF file.
func makeDFUFirmwareImage(options *compileopts.Options, infile, outfile string) error {
// Read ELF file as input and convert it to a binary image file.
_, data, err := extractROM(infile)
if err != nil {
return err
}
// Create the zip file in memory.
// It won't be very large anyway.
buf := &bytes.Buffer{}
w := zip.NewWriter(buf)
// Write the application binary to the zip file.
binw, err := w.Create("application.bin")
if err != nil {
return err
}
_, err = binw.Write(data)
if err != nil {
return err
}
// Create the init packet.
initPacket := nrfInitPacket{
ApplicationVersion: 0xffff_ffff, // appears to be unused by the Adafruit bootloader
DeviceRevision: 0xffff, // DFU_DEVICE_REVISION_EMPTY
DeviceType: 0x0052, // ADAFRUIT_DEVICE_TYPE
FirmwareCRC16: crc16.Checksum(data, crc16.MakeTable(crc16.CRC16_CCITT_FALSE)),
SoftDeviceRequired: []uint16{0xfffe}, // DFU_SOFTDEVICE_ANY
}
// Write the init packet to the zip file.
datw, err := w.Create("application.dat")
if err != nil {
return err
}
_, err = datw.Write(initPacket.createInitPacket())
if err != nil {
return err
}
// Create the JSON manifest.
manifest := &jsonManifest{}
manifest.Manifest.Application.BinaryFile = "application.bin"
manifest.Manifest.Application.DataFile = "application.dat"
manifest.Manifest.Application.InitPacketData = initPacket
manifest.Manifest.DFUVersion = 0.5
// Write the JSON manifest to the file.
jsonw, err := w.Create("manifest.json")
if err != nil {
return err
}
enc := json.NewEncoder(jsonw)
enc.SetIndent("", " ")
err = enc.Encode(manifest)
if err != nil {
return err
}
// Finish the zip file.
err = w.Close()
if err != nil {
return err
}
return os.WriteFile(outfile, buf.Bytes(), 0o666)
}
+2 -2
View File
@@ -2,7 +2,7 @@ package builder
import (
"debug/elf"
"io/ioutil"
"io"
"os"
"sort"
@@ -87,7 +87,7 @@ func extractROM(path string) (uint64, []byte, error) {
// Pad the difference
rom = append(rom, make([]byte, diff)...)
}
data, err := ioutil.ReadAll(prog.Open())
data, err := io.ReadAll(prog.Open())
if err != nil {
return 0, nil, objcopyError{"failed to extract segment from ELF file: " + path, err}
}
+428 -111
View File
@@ -1,127 +1,444 @@
package builder
import (
"os"
"path/filepath"
"strings"
"github.com/tinygo-org/tinygo/goenv"
)
// Picolibc is a C library for bare metal embedded devices. It was originally
// libPicolibc is a C library for bare metal embedded devices. It was originally
// based on newlib.
var Picolibc = Library{
var libPicolibc = Library{
name: "picolibc",
cflags: func() []string {
picolibcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib/libc")
return []string{"-Werror", "-Wall", "-std=gnu11", "-D_COMPILING_NEWLIB", "-nostdlibinc", "-Xclang", "-internal-isystem", "-Xclang", picolibcDir + "/include", "-I" + picolibcDir + "/tinystdio", "-I" + goenv.Get("TINYGOROOT") + "/lib/picolibc-include"}
makeHeaders: func(target, includeDir string) error {
f, err := os.Create(filepath.Join(includeDir, "picolibc.h"))
if err != nil {
return err
}
return f.Close()
},
sourceDir: "lib/picolibc/newlib/libc",
sources: func(target string) []string {
return picolibcSources
cflags: func(target, headerPath string) []string {
newlibDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib")
return []string{
"-Werror",
"-Wall",
"-std=gnu11",
"-D_COMPILING_NEWLIB",
"-D_HAVE_ALIAS_ATTRIBUTE",
"-DTINY_STDIO",
"-DPOSIX_IO",
"-DFORMAT_DEFAULT_INTEGER", // use __i_vfprintf and __i_vfscanf by default
"-D_IEEE_LIBM",
"-D__OBSOLETE_MATH_FLOAT=1", // use old math code that doesn't expect a FPU
"-D__OBSOLETE_MATH_DOUBLE=0",
"-D_WANT_IO_C99_FORMATS",
"-D__PICOLIBC_ERRNO_FUNCTION=__errno_location",
"-nostdlibinc",
"-isystem", newlibDir + "/libc/include",
"-I" + newlibDir + "/libc/tinystdio",
"-I" + newlibDir + "/libm/common",
"-I" + headerPath,
}
},
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/picolibc/newlib") },
librarySources: func(target string) ([]string, error) {
sources := append([]string(nil), picolibcSources...)
if !strings.HasPrefix(target, "avr") {
// Small chips without long jumps can't compile many files (printf,
// pow, etc). Therefore exclude those source files for those chips.
// Unfortunately it's difficult to exclude only some chips, so this
// excludes those files on all AVR chips for now.
// More information:
// https://github.com/llvm/llvm-project/issues/67042
sources = append(sources, picolibcSourcesLarge...)
}
return sources, nil
},
}
var picolibcSources = []string{
"string/bcmp.c",
"string/bcopy.c",
"string/bzero.c",
"string/explicit_bzero.c",
"string/ffsl.c",
"string/ffsll.c",
"string/fls.c",
"string/flsl.c",
"string/flsll.c",
"string/gnu_basename.c",
"string/index.c",
"string/memccpy.c",
"string/memchr.c",
"string/memcmp.c",
"string/memcpy.c",
"string/memmem.c",
"string/memmove.c",
"string/mempcpy.c",
"string/memrchr.c",
"string/memset.c",
"string/rawmemchr.c",
"string/rindex.c",
"string/stpcpy.c",
"string/stpncpy.c",
"string/strcasecmp.c",
"string/strcasecmp_l.c",
"string/strcasestr.c",
"string/strcat.c",
"string/strchr.c",
"string/strchrnul.c",
"string/strcmp.c",
"string/strcoll.c",
"string/strcoll_l.c",
"string/strcpy.c",
"string/strcspn.c",
"string/strdup.c",
"string/strerror.c",
"string/strerror_r.c",
"string/strlcat.c",
"string/strlcpy.c",
"string/strlen.c",
"string/strlwr.c",
"string/strncasecmp.c",
"string/strncasecmp_l.c",
"string/strncat.c",
"string/strncmp.c",
"string/strncpy.c",
"string/strndup.c",
"string/strnlen.c",
"string/strnstr.c",
"string/strpbrk.c",
"string/strrchr.c",
"string/strsep.c",
"string/strsignal.c",
"string/strspn.c",
"string/strstr.c",
"string/strtok.c",
"string/strtok_r.c",
"string/strupr.c",
"string/strverscmp.c",
"string/strxfrm.c",
"string/strxfrm_l.c",
"string/swab.c",
"string/timingsafe_bcmp.c",
"string/timingsafe_memcmp.c",
"string/u_strerr.c",
"string/wcpcpy.c",
"string/wcpncpy.c",
"string/wcscasecmp.c",
"string/wcscasecmp_l.c",
"string/wcscat.c",
"string/wcschr.c",
"string/wcscmp.c",
"string/wcscoll.c",
"string/wcscoll_l.c",
"string/wcscpy.c",
"string/wcscspn.c",
"string/wcsdup.c",
"string/wcslcat.c",
"string/wcslcpy.c",
"string/wcslen.c",
"string/wcsncasecmp.c",
"string/wcsncasecmp_l.c",
"string/wcsncat.c",
"string/wcsncmp.c",
"string/wcsncpy.c",
"string/wcsnlen.c",
"string/wcspbrk.c",
"string/wcsrchr.c",
"string/wcsspn.c",
"string/wcsstr.c",
"string/wcstok.c",
"string/wcswidth.c",
"string/wcsxfrm.c",
"string/wcsxfrm_l.c",
"string/wcwidth.c",
"string/wmemchr.c",
"string/wmemcmp.c",
"string/wmemcpy.c",
"string/wmemmove.c",
"string/wmempcpy.c",
"string/wmemset.c",
"string/xpg_strerror_r.c",
"../../picolibc-stdio.c",
"libc/string/bcmp.c",
"libc/string/bcopy.c",
"libc/string/bzero.c",
"libc/string/explicit_bzero.c",
"libc/string/ffsl.c",
"libc/string/ffsll.c",
"libc/string/fls.c",
"libc/string/flsl.c",
"libc/string/flsll.c",
"libc/string/gnu_basename.c",
"libc/string/index.c",
"libc/string/memccpy.c",
"libc/string/memchr.c",
"libc/string/memcmp.c",
"libc/string/memcpy.c",
"libc/string/memmem.c",
"libc/string/memmove.c",
"libc/string/mempcpy.c",
"libc/string/memrchr.c",
"libc/string/memset.c",
"libc/string/rawmemchr.c",
"libc/string/rindex.c",
"libc/string/stpcpy.c",
"libc/string/stpncpy.c",
"libc/string/strcasecmp.c",
"libc/string/strcasecmp_l.c",
"libc/string/strcasestr.c",
"libc/string/strcat.c",
"libc/string/strchr.c",
"libc/string/strchrnul.c",
"libc/string/strcmp.c",
"libc/string/strcoll.c",
"libc/string/strcoll_l.c",
"libc/string/strcpy.c",
"libc/string/strcspn.c",
"libc/string/strdup.c",
"libc/string/strerror.c",
"libc/string/strerror_r.c",
"libc/string/strlcat.c",
"libc/string/strlcpy.c",
"libc/string/strlen.c",
"libc/string/strlwr.c",
"libc/string/strncasecmp.c",
"libc/string/strncasecmp_l.c",
"libc/string/strncat.c",
"libc/string/strncmp.c",
"libc/string/strncpy.c",
"libc/string/strndup.c",
"libc/string/strnlen.c",
"libc/string/strnstr.c",
"libc/string/strpbrk.c",
"libc/string/strrchr.c",
"libc/string/strsep.c",
"libc/string/strsignal.c",
"libc/string/strspn.c",
"libc/string/strstr.c",
"libc/string/strtok.c",
"libc/string/strtok_r.c",
"libc/string/strupr.c",
"libc/string/strverscmp.c",
"libc/string/strxfrm.c",
"libc/string/strxfrm_l.c",
"libc/string/swab.c",
"libc/string/timingsafe_bcmp.c",
"libc/string/timingsafe_memcmp.c",
"libc/string/u_strerr.c",
"libc/string/wcpcpy.c",
"libc/string/wcpncpy.c",
"libc/string/wcscasecmp.c",
"libc/string/wcscasecmp_l.c",
"libc/string/wcscat.c",
"libc/string/wcschr.c",
"libc/string/wcscmp.c",
"libc/string/wcscoll.c",
"libc/string/wcscoll_l.c",
"libc/string/wcscpy.c",
"libc/string/wcscspn.c",
"libc/string/wcsdup.c",
"libc/string/wcslcat.c",
"libc/string/wcslcpy.c",
"libc/string/wcslen.c",
"libc/string/wcsncasecmp.c",
"libc/string/wcsncasecmp_l.c",
"libc/string/wcsncat.c",
"libc/string/wcsncmp.c",
"libc/string/wcsncpy.c",
"libc/string/wcsnlen.c",
"libc/string/wcspbrk.c",
"libc/string/wcsrchr.c",
"libc/string/wcsspn.c",
"libc/string/wcsstr.c",
"libc/string/wcstok.c",
"libc/string/wcswidth.c",
"libc/string/wcsxfrm.c",
"libc/string/wcsxfrm_l.c",
"libc/string/wcwidth.c",
"libc/string/wmemchr.c",
"libc/string/wmemcmp.c",
"libc/string/wmemcpy.c",
"libc/string/wmemmove.c",
"libc/string/wmempcpy.c",
"libc/string/wmemset.c",
"libc/string/xpg_strerror_r.c",
}
// Parts of picolibc that are too large for small AVRs.
var picolibcSourcesLarge = []string{
// srcs_tinystdio
"libc/tinystdio/asprintf.c",
"libc/tinystdio/bufio.c",
"libc/tinystdio/clearerr.c",
"libc/tinystdio/ecvt_r.c",
"libc/tinystdio/ecvt.c",
"libc/tinystdio/ecvtf_r.c",
"libc/tinystdio/ecvtf.c",
"libc/tinystdio/fcvt.c",
"libc/tinystdio/fcvt_r.c",
"libc/tinystdio/fcvtf.c",
"libc/tinystdio/fcvtf_r.c",
"libc/tinystdio/gcvt.c",
"libc/tinystdio/gcvtf.c",
"libc/tinystdio/fclose.c",
"libc/tinystdio/fdevopen.c",
"libc/tinystdio/feof.c",
"libc/tinystdio/ferror.c",
"libc/tinystdio/fflush.c",
"libc/tinystdio/fgetc.c",
"libc/tinystdio/fgets.c",
"libc/tinystdio/fileno.c",
"libc/tinystdio/filestrget.c",
"libc/tinystdio/filestrput.c",
"libc/tinystdio/filestrputalloc.c",
"libc/tinystdio/fmemopen.c",
"libc/tinystdio/fprintf.c",
"libc/tinystdio/fputc.c",
"libc/tinystdio/fputs.c",
"libc/tinystdio/fread.c",
//"libc/tinystdio/freopen.c", // crashes with AVR, see: https://github.com/picolibc/picolibc/pull/369
"libc/tinystdio/fscanf.c",
"libc/tinystdio/fseek.c",
"libc/tinystdio/fseeko.c",
"libc/tinystdio/ftell.c",
"libc/tinystdio/ftello.c",
"libc/tinystdio/fwrite.c",
"libc/tinystdio/getchar.c",
"libc/tinystdio/gets.c",
"libc/tinystdio/matchcaseprefix.c",
"libc/tinystdio/mktemp.c",
"libc/tinystdio/perror.c",
"libc/tinystdio/printf.c",
"libc/tinystdio/putchar.c",
"libc/tinystdio/puts.c",
"libc/tinystdio/rewind.c",
"libc/tinystdio/scanf.c",
"libc/tinystdio/setbuf.c",
"libc/tinystdio/setbuffer.c",
"libc/tinystdio/setlinebuf.c",
"libc/tinystdio/setvbuf.c",
"libc/tinystdio/snprintf.c",
"libc/tinystdio/sprintf.c",
"libc/tinystdio/snprintfd.c",
"libc/tinystdio/snprintff.c",
"libc/tinystdio/sprintff.c",
"libc/tinystdio/sprintfd.c",
"libc/tinystdio/sscanf.c",
"libc/tinystdio/strfromf.c",
"libc/tinystdio/strfromd.c",
"libc/tinystdio/strtof.c",
"libc/tinystdio/strtof_l.c",
"libc/tinystdio/strtod.c",
"libc/tinystdio/strtod_l.c",
"libc/tinystdio/ungetc.c",
"libc/tinystdio/vasprintf.c",
"libc/tinystdio/vfiprintf.c",
"libc/tinystdio/vfprintf.c",
"libc/tinystdio/vfprintff.c",
"libc/tinystdio/vfscanf.c",
"libc/tinystdio/vfiscanf.c",
"libc/tinystdio/vfscanff.c",
"libc/tinystdio/vprintf.c",
"libc/tinystdio/vscanf.c",
"libc/tinystdio/vsscanf.c",
"libc/tinystdio/vsnprintf.c",
"libc/tinystdio/vsprintf.c",
"libm/common/sf_finite.c",
"libm/common/sf_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_iseqsig.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_getpayload.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_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/math_errf_divzerof.c",
"libm/common/math_errf_invalidf.c",
"libm/common/math_errf_may_uflowf.c",
"libm/common/math_errf_oflowf.c",
"libm/common/math_errf_uflowf.c",
"libm/common/math_errf_with_errnof.c",
"libm/common/math_inexact.c",
"libm/common/math_inexactf.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/k_cos.c",
"libm/math/k_rem_pio2.c",
"libm/math/k_sin.c",
"libm/math/k_tan.c",
"libm/math/kf_cos.c",
"libm/math/kf_rem_pio2.c",
"libm/math/kf_sin.c",
"libm/math/kf_tan.c",
"libm/math/s_acos.c",
"libm/math/s_acosh.c",
"libm/math/s_asin.c",
"libm/math/s_asinh.c",
"libm/math/s_atan.c",
"libm/math/s_atan2.c",
"libm/math/s_atanh.c",
"libm/math/s_ceil.c",
"libm/math/s_cos.c",
"libm/math/s_cosh.c",
"libm/math/s_drem.c",
"libm/math/s_erf.c",
"libm/math/s_exp.c",
"libm/math/s_exp2.c",
"libm/math/s_fabs.c",
"libm/math/s_floor.c",
"libm/math/s_fmod.c",
"libm/math/s_frexp.c",
"libm/math/s_gamma.c",
"libm/math/s_hypot.c",
"libm/math/s_j0.c",
"libm/math/s_j1.c",
"libm/math/s_jn.c",
"libm/math/s_lgamma.c",
"libm/math/s_log.c",
"libm/math/s_log10.c",
"libm/math/s_pow.c",
"libm/math/s_rem_pio2.c",
"libm/math/s_remainder.c",
"libm/math/s_scalb.c",
"libm/math/s_signif.c",
"libm/math/s_sin.c",
"libm/math/s_sincos.c",
"libm/math/s_sinh.c",
"libm/math/s_sqrt.c",
"libm/math/s_tan.c",
"libm/math/s_tanh.c",
"libm/math/s_tgamma.c",
"libm/math/sf_acos.c",
"libm/math/sf_acosh.c",
"libm/math/sf_asin.c",
"libm/math/sf_asinh.c",
"libm/math/sf_atan.c",
"libm/math/sf_atan2.c",
"libm/math/sf_atanh.c",
"libm/math/sf_ceil.c",
"libm/math/sf_cos.c",
"libm/math/sf_cosh.c",
"libm/math/sf_drem.c",
"libm/math/sf_erf.c",
"libm/math/sf_exp.c",
"libm/math/sf_exp2.c",
"libm/math/sf_fabs.c",
"libm/math/sf_floor.c",
"libm/math/sf_fmod.c",
"libm/math/sf_frexp.c",
"libm/math/sf_gamma.c",
"libm/math/sf_hypot.c",
"libm/math/sf_j0.c",
"libm/math/sf_j1.c",
"libm/math/sf_jn.c",
"libm/math/sf_lgamma.c",
"libm/math/sf_log.c",
"libm/math/sf_log10.c",
"libm/math/sf_log2.c",
"libm/math/sf_pow.c",
"libm/math/sf_rem_pio2.c",
"libm/math/sf_remainder.c",
"libm/math/sf_scalb.c",
"libm/math/sf_signif.c",
"libm/math/sf_sin.c",
"libm/math/sf_sincos.c",
"libm/math/sf_sinh.c",
"libm/math/sf_sqrt.c",
"libm/math/sf_tan.c",
"libm/math/sf_tanh.c",
"libm/math/sf_tgamma.c",
"libm/math/sr_lgamma.c",
"libm/math/srf_lgamma.c",
}
+56
View File
@@ -0,0 +1,56 @@
package builder
import (
_ "embed"
"fmt"
"html/template"
"os"
)
//go:embed size-report.html
var sizeReportBase string
func writeSizeReport(sizes *programSize, filename, pkgName string) error {
tmpl, err := template.New("report").Parse(sizeReportBase)
if err != nil {
return err
}
f, err := os.Create(filename)
if err != nil {
return fmt.Errorf("could not open report file: %w", err)
}
defer f.Close()
// Prepare data for the report.
type sizeLine struct {
Name string
Size *packageSize
}
programData := []sizeLine{}
for _, name := range sizes.sortedPackageNames() {
pkgSize := sizes.Packages[name]
programData = append(programData, sizeLine{
Name: name,
Size: pkgSize,
})
}
sizeTotal := map[string]uint64{
"code": sizes.Code,
"rodata": sizes.ROData,
"data": sizes.Data,
"bss": sizes.BSS,
"flash": sizes.Flash(),
}
// Write the report.
err = tmpl.Execute(f, map[string]any{
"pkgName": pkgName,
"sizes": programData,
"sizeTotal": sizeTotal,
})
if err != nil {
return fmt.Errorf("could not create report file: %w", err)
}
return nil
}
+109
View File
@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Size Report for {{.pkgName}}</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<style>
.table-vertical-border {
border-left: calc(var(--bs-border-width) * 2) solid currentcolor;
}
/* Hover on only the rows that are clickable. */
.row-package:hover > * {
--bs-table-color-state: var(--bs-table-hover-color);
--bs-table-bg-state: var(--bs-table-hover-bg);
}
</style>
</head>
<body>
<div class="container-xxl">
<h1>Size Report for {{.pkgName}}</h1>
<p>How much space is used by Go packages, C libraries, and other bits to set up the program environment.</p>
<ul>
<li><strong>Code</strong> is the actual program code (machine code instructions).</li>
<li><strong>Read-only data</strong> are read-only global variables. On most microcontrollers, these are stored in flash and do not take up any RAM.</li>
<li><strong>Data</strong> are writable global variables with a non-zero initializer. On microcontrollers, they are copied from flash to RAM on reset.</li>
<li><strong>BSS</strong> are writable global variables that are zero initialized. They do not take up any space in the binary, but do take up RAM. On microcontrollers, this area is zeroed on reset.</li>
</ul>
<p>The binary size consists of code, read-only data, and data. On microcontrollers, this is exactly the size of the firmware image. On other systems, there is some extra overhead: binary metadata (headers of the ELF/MachO/COFF file), debug information, exception tables, symbol names, etc. Using <code>-no-debug</code> strips most of those.</p>
<h2>Program breakdown</h2>
<p>You can click on the rows below to see which files contribute to the binary size.</p>
<div class="table-responsive">
<table class="table w-auto">
<thead>
<tr>
<th>Package</th>
<th class="table-vertical-border">Code</th>
<th>Read-only data</th>
<th>Data</th>
<th title="zero-initialized data">BSS</th>
<th class="table-vertical-border" style="min-width: 16em">Binary size</th>
</tr>
</thead>
<tbody class="table-group-divider">
{{range $i, $pkg := .sizes}}
<tr class="row-package" data-collapse=".collapse-row-{{$i}}">
<td>{{.Name}}</td>
<td class="table-vertical-border">{{.Size.Code}}</td>
<td>{{.Size.ROData}}</td>
<td>{{.Size.Data}}</td>
<td>{{.Size.BSS}}</td>
<td class="table-vertical-border" style="background: linear-gradient(to right, var(--bs-info-bg-subtle) {{.Size.FlashPercent}}%, var(--bs-table-bg) {{.Size.FlashPercent}}%)">
{{.Size.Flash}}
</td>
</tr>
{{range $filename, $sizes := .Size.Sub}}
<tr class="table-secondary collapse collapse-row-{{$i}}">
<td class="ps-4">
{{if eq $filename ""}}
(unknown file)
{{else}}
{{$filename}}
{{end}}
</td>
<td class="table-vertical-border">{{$sizes.Code}}</td>
<td>{{$sizes.ROData}}</td>
<td>{{$sizes.Data}}</td>
<td>{{$sizes.BSS}}</td>
<td class="table-vertical-border" style="background: linear-gradient(to right, var(--bs-info-bg-subtle) {{$sizes.FlashPercent}}%, var(--bs-table-bg) {{$sizes.FlashPercent}}%)">
{{$sizes.Flash}}
</td>
</tr>
{{end}}
{{end}}
</tbody>
<tfoot class="table-group-divider">
<tr>
<th>Total</th>
<td class="table-vertical-border">{{.sizeTotal.code}}</td>
<td>{{.sizeTotal.rodata}}</td>
<td>{{.sizeTotal.data}}</td>
<td>{{.sizeTotal.bss}}</td>
<td class="table-vertical-border">{{.sizeTotal.flash}}</td>
</tr>
</tfoot>
</table>
</div>
</div>
<script>
// Make table rows toggleable to show filenames.
for (let clickable of document.querySelectorAll('.row-package')) {
clickable.addEventListener('click', e => {
for (let row of document.querySelectorAll(clickable.dataset.collapse)) {
row.classList.toggle('show');
}
});
}
</script>
</body>
</html>
+926 -109
View File
File diff suppressed because it is too large Load Diff
+140
View File
@@ -0,0 +1,140 @@
package builder
import (
"regexp"
"runtime"
"testing"
"time"
"github.com/tinygo-org/tinygo/compileopts"
)
var sema = make(chan struct{}, runtime.NumCPU())
type sizeTest struct {
target string
path string
codeSize uint64
rodataSize uint64
dataSize uint64
bssSize uint64
}
// Test whether code and data size is as expected for the given targets.
// This tests both the logic of loadProgramSize and checks that code size
// doesn't change unintentionally.
//
// If you find that code or data size is reduced, then great! You can reduce the
// number in this test.
// If you find that the code or data size is increased, take a look as to why
// this is. It could be due to an update (LLVM version, Go version, etc) which
// is fine, but it could also mean that a recent change introduced this size
// increase. If so, please consider whether this new feature is indeed worth the
// size increase for all users.
func TestBinarySize(t *testing.T) {
if runtime.GOOS == "linux" && !hasBuiltinTools {
// Debian LLVM packages are modified a bit and tend to produce
// different machine code. Ideally we'd fix this (with some attributes
// or something?), but for now skip it.
t.Skip("Skip: using external LLVM version so binary size might differ")
}
// This is a small number of very diverse targets that we want to test.
tests := []sizeTest{
// microcontrollers
{"hifive1b", "examples/echo", 4560, 280, 0, 2268},
{"microbit", "examples/serial", 2916, 388, 8, 2272},
{"wioterminal", "examples/pininterrupt", 7359, 1489, 116, 6912},
// TODO: also check wasm. Right now this is difficult, because
// wasm binaries are run through wasm-opt and therefore the
// output varies by binaryen version.
}
for _, tc := range tests {
tc := tc
t.Run(tc.target+"/"+tc.path, func(t *testing.T) {
t.Parallel()
// Build the binary.
result := buildBinary(t, tc.target, tc.path)
// Check whether the size of the binary matches the expected size.
sizes, err := loadProgramSize(result.Executable, nil)
if err != nil {
t.Fatal("could not read program size:", err)
}
if sizes.Code != tc.codeSize || sizes.ROData != tc.rodataSize || sizes.Data != tc.dataSize || sizes.BSS != tc.bssSize {
t.Errorf("Unexpected code size when compiling: -target=%s %s", tc.target, tc.path)
t.Errorf(" code rodata data bss")
t.Errorf("expected: %6d %6d %6d %6d", tc.codeSize, tc.rodataSize, tc.dataSize, tc.bssSize)
t.Errorf("actual: %6d %6d %6d %6d", sizes.Code, sizes.ROData, sizes.Data, sizes.BSS)
}
})
}
}
// Check that the -size=full flag attributes binary size to the correct package
// without filesystem paths and things like that.
func TestSizeFull(t *testing.T) {
tests := []string{
"microbit",
"wasip1",
}
libMatch := regexp.MustCompile(`^C [a-z -]+$`) // example: "C interrupt vector"
pkgMatch := regexp.MustCompile(`^[a-z/]+$`) // example: "internal/task"
for _, target := range tests {
target := target
t.Run(target, func(t *testing.T) {
t.Parallel()
// Build the binary.
result := buildBinary(t, target, "examples/serial")
// Check whether the binary doesn't contain any unexpected package
// names.
sizes, err := loadProgramSize(result.Executable, result.PackagePathMap)
if err != nil {
t.Fatal("could not read program size:", err)
}
for _, pkg := range sizes.sortedPackageNames() {
if pkg == "(padding)" || pkg == "(unknown)" {
// TODO: correctly attribute all unknown binary size.
continue
}
if libMatch.MatchString(pkg) {
continue
}
if pkgMatch.MatchString(pkg) {
continue
}
t.Error("unexpected package name in size output:", pkg)
}
})
}
}
func buildBinary(t *testing.T, targetString, pkgName string) BuildResult {
options := compileopts.Options{
Target: targetString,
Opt: "z",
Semaphore: sema,
InterpTimeout: 60 * time.Second,
Debug: true,
VerifyIR: true,
}
target, err := compileopts.LoadTarget(&options)
if err != nil {
t.Fatal("could not load target:", err)
}
config := &compileopts.Config{
Options: &options,
Target: target,
}
result, err := Build(pkgName, "", t.TempDir(), config)
if err != nil {
t.Fatal("could not build:", err)
}
return result
}
+5 -8
View File
@@ -1,4 +1,4 @@
// +build byollvm
//go:build byollvm
package builder
@@ -12,8 +12,7 @@ import (
#include <stdbool.h>
#include <stdlib.h>
bool tinygo_clang_driver(int argc, char **argv);
bool tinygo_link_elf(int argc, char **argv);
bool tinygo_link_wasm(int argc, char **argv);
bool tinygo_link(int argc, char **argv);
*/
import "C"
@@ -24,7 +23,7 @@ const hasBuiltinTools = true
// This version actually runs the tools because TinyGo was compiled while
// linking statically with LLVM (with the byollvm build tag).
func RunTool(tool string, args ...string) error {
args = append([]string{"tinygo:" + tool}, args...)
args = append([]string{tool}, args...)
var cflag *C.char
buf := C.calloc(C.size_t(len(args)), C.size_t(unsafe.Sizeof(cflag)))
@@ -40,10 +39,8 @@ func RunTool(tool string, args ...string) error {
switch tool {
case "clang":
ok = C.tinygo_clang_driver(C.int(len(args)), (**C.char)(buf))
case "ld.lld":
ok = C.tinygo_link_elf(C.int(len(args)), (**C.char)(buf))
case "wasm-ld":
ok = C.tinygo_link_wasm(C.int(len(args)), (**C.char)(buf))
case "ld.lld", "wasm-ld":
ok = C.tinygo_link(C.int(len(args)), (**C.char)(buf))
default:
return errors.New("unknown tool: " + tool)
}
+1 -1
View File
@@ -1,4 +1,4 @@
// +build !byollvm
//go:build !byollvm
package builder
+167 -35
View File
@@ -1,59 +1,191 @@
package builder
import (
"errors"
"bytes"
"fmt"
"go/scanner"
"go/token"
"os"
"os/exec"
"github.com/tinygo-org/tinygo/goenv"
"regexp"
"strconv"
"strings"
)
// runCCompiler invokes a C compiler with the given arguments.
func runCCompiler(command string, flags ...string) error {
if hasBuiltinTools && command == "clang" {
func runCCompiler(flags ...string) error {
// Find the right command to run Clang.
var cmd *exec.Cmd
if hasBuiltinTools {
// Compile this with the internal Clang compiler.
headerPath := getClangHeaderPath(goenv.Get("TINYGOROOT"))
if headerPath == "" {
return errors.New("could not locate Clang headers")
cmd = exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
} else {
// Compile this with an external invocation of the Clang compiler.
name, err := LookupCommand("clang")
if err != nil {
return err
}
flags = append(flags, "-I"+headerPath)
cmd := exec.Command(os.Args[0], append([]string{"clang"}, flags...)...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
cmd = exec.Command(name, flags...)
}
// Running some other compiler. Maybe it has been defined in the
// commands map (unlikely).
if cmdNames, ok := commands[command]; ok {
return execCommand(cmdNames, flags...)
}
// Alternatively, run the compiler directly.
cmd := exec.Command(command, flags...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
// Make sure the command doesn't use any environmental variables.
// Most importantly, it should not use C_INCLUDE_PATH and the like.
cmd.Env = []string{}
// Let some environment variables through. One important one is the
// temporary directory, especially on Windows it looks like Clang breaks if
// the temporary directory has not been set.
// See: https://github.com/tinygo-org/tinygo/issues/4557
// Also see: https://github.com/llvm/llvm-project/blob/release/18.x/llvm/lib/Support/Unix/Path.inc#L1435
for _, env := range os.Environ() {
// We could parse the key and look it up in a map, but since there are
// only a few keys iterating through them is easier and maybe even
// faster.
for _, prefix := range []string{"TMPDIR=", "TMP=", "TEMP=", "TEMPDIR="} {
if strings.HasPrefix(env, prefix) {
cmd.Env = append(cmd.Env, env)
break
}
}
}
return cmd.Run()
}
// link invokes a linker with the given name and flags.
func link(linker string, flags ...string) error {
if hasBuiltinTools && (linker == "ld.lld" || linker == "wasm-ld") {
// Run command with internal linker.
cmd := exec.Command(os.Args[0], append([]string{linker}, flags...)...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
// We only support LLD.
if linker != "ld.lld" && linker != "wasm-ld" {
return fmt.Errorf("unexpected: linker %s should be ld.lld or wasm-ld", linker)
}
// Fall back to external command.
if cmdNames, ok := commands[linker]; ok {
return execCommand(cmdNames, flags...)
var cmd *exec.Cmd
if hasBuiltinTools {
cmd = exec.Command(os.Args[0], append([]string{linker}, flags...)...)
} else {
name, err := LookupCommand(linker)
if err != nil {
return err
}
cmd = exec.Command(name, flags...)
}
cmd := exec.Command(linker, flags...)
var buf bytes.Buffer
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = goenv.Get("TINYGOROOT")
return cmd.Run()
cmd.Stderr = &buf
err := cmd.Run()
if err != nil {
if buf.Len() == 0 {
// The linker failed but there was no output.
// Therefore, show some output anyway.
return fmt.Errorf("failed to run linker: %w", err)
}
return parseLLDErrors(buf.String())
}
return nil
}
// Split LLD errors into individual erros (including errors that continue on the
// next line, using a ">>>" prefix). If possible, replace the raw errors with a
// more user-friendly version (and one that's more in a Go style).
func parseLLDErrors(text string) error {
// Split linker output in separate error messages.
lines := strings.Split(text, "\n")
var errorLines []string // one or more line (belonging to a single error) per line
for _, line := range lines {
line = strings.TrimRight(line, "\r") // needed for Windows
if len(errorLines) != 0 && strings.HasPrefix(line, ">>> ") {
errorLines[len(errorLines)-1] += "\n" + line
continue
}
if line == "" {
continue
}
errorLines = append(errorLines, line)
}
// Parse error messages.
var linkErrors []error
var flashOverflow, ramOverflow uint64
for _, message := range errorLines {
parsedError := false
// Check for undefined symbols.
// This can happen in some cases like with CGo and //go:linkname tricker.
if matches := regexp.MustCompile(`^ld.lld(-[0-9]+)?: error: undefined symbol: (.*)\n`).FindStringSubmatch(message); matches != nil {
symbolName := matches[2]
for _, line := range strings.Split(message, "\n") {
matches := regexp.MustCompile(`referenced by .* \(((.*):([0-9]+))\)`).FindStringSubmatch(line)
if matches != nil {
parsedError = true
line, _ := strconv.Atoi(matches[3])
// TODO: detect common mistakes like -gc=none?
linkErrors = append(linkErrors, scanner.Error{
Pos: token.Position{
Filename: matches[2],
Line: line,
},
Msg: "linker could not find symbol " + symbolName,
})
}
}
}
// Check for flash/RAM overflow.
if matches := regexp.MustCompile(`^ld.lld(-[0-9]+)?: error: section '(.*?)' will not fit in region '(.*?)': overflowed by ([0-9]+) bytes$`).FindStringSubmatch(message); matches != nil {
region := matches[3]
n, err := strconv.ParseUint(matches[4], 10, 64)
if err != nil {
// Should not happen at all (unless it overflows an uint64 for some reason).
continue
}
// Check which area overflowed.
// Some chips use differently named memory areas, but these are by
// far the most common.
switch region {
case "FLASH_TEXT":
if n > flashOverflow {
flashOverflow = n
}
parsedError = true
case "RAM":
if n > ramOverflow {
ramOverflow = n
}
parsedError = true
}
}
// If we couldn't parse the linker error: show the error as-is to
// the user.
if !parsedError {
linkErrors = append(linkErrors, LinkerError{message})
}
}
if flashOverflow > 0 {
linkErrors = append(linkErrors, LinkerError{
Msg: fmt.Sprintf("program too large for this chip (flash overflowed by %d bytes)\n\toptimization guide: https://tinygo.org/docs/guides/optimizing-binaries/", flashOverflow),
})
}
if ramOverflow > 0 {
linkErrors = append(linkErrors, LinkerError{
Msg: fmt.Sprintf("program uses too much static RAM on this chip (RAM overflowed by %d bytes)", ramOverflow),
})
}
return newMultiError(linkErrors, "")
}
// LLD linker error that could not be parsed or doesn't refer to a source
// location.
type LinkerError struct {
Msg string
}
func (e LinkerError) Error() string {
return e.Msg
}
+5 -3
View File
@@ -10,7 +10,7 @@ package builder
import (
"bytes"
"encoding/binary"
"io/ioutil"
"os"
"strconv"
)
@@ -26,7 +26,7 @@ func convertELFFileToUF2File(infile, outfile string, uf2FamilyID string) error {
if err != nil {
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.
@@ -141,11 +141,13 @@ func split(input []byte, limit int) [][]byte {
var block []byte
output := make([][]byte, 0, len(input)/limit+1)
for len(input) >= limit {
// add all blocks
block, input = input[:limit], input[limit:]
output = append(output, block)
}
if len(input) > 0 {
output = append(output, input[:len(input)])
// add remaining block (that isn't full sized)
output = append(output, input)
}
return output
}
+81
View File
@@ -0,0 +1,81 @@
package builder
import (
"os"
"path/filepath"
"github.com/tinygo-org/tinygo/goenv"
)
var libWasmBuiltins = Library{
name: "wasmbuiltins",
makeHeaders: func(target, includeDir string) error {
if err := os.Mkdir(includeDir+"/bits", 0o777); err != nil {
return err
}
f, err := os.Create(includeDir + "/bits/alltypes.h")
if err != nil {
return err
}
if _, err := f.Write([]byte(wasmAllTypes)); err != nil {
return err
}
return f.Close()
},
cflags: func(target, headerPath string) []string {
libcDir := filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc")
return []string{
"-Werror",
"-Wall",
"-std=gnu11",
"-nostdlibinc",
"-isystem", libcDir + "/libc-top-half/musl/arch/wasm32",
"-isystem", libcDir + "/libc-top-half/musl/arch/generic",
"-isystem", libcDir + "/libc-top-half/musl/src/internal",
"-isystem", libcDir + "/libc-top-half/musl/src/include",
"-isystem", libcDir + "/libc-top-half/musl/include",
"-isystem", libcDir + "/libc-bottom-half/headers/public",
"-I" + headerPath,
}
},
sourceDir: func() string { return filepath.Join(goenv.Get("TINYGOROOT"), "lib/wasi-libc") },
librarySources: func(target string) ([]string, error) {
return []string{
// memory builtins needed for llvm.memcpy.*, llvm.memmove.*, and
// llvm.memset.* LLVM intrinsics.
"libc-top-half/musl/src/string/memcpy.c",
"libc-top-half/musl/src/string/memmove.c",
"libc-top-half/musl/src/string/memset.c",
// exp, exp2, and log are needed for LLVM math builtin functions
// like llvm.exp.*.
"libc-top-half/musl/src/math/__math_divzero.c",
"libc-top-half/musl/src/math/__math_invalid.c",
"libc-top-half/musl/src/math/__math_oflow.c",
"libc-top-half/musl/src/math/__math_uflow.c",
"libc-top-half/musl/src/math/__math_xflow.c",
"libc-top-half/musl/src/math/exp.c",
"libc-top-half/musl/src/math/exp_data.c",
"libc-top-half/musl/src/math/exp2.c",
"libc-top-half/musl/src/math/log.c",
"libc-top-half/musl/src/math/log_data.c",
}, nil
},
}
// alltypes.h for wasm-libc, using the types as defined inside Clang.
const wasmAllTypes = `
typedef __SIZE_TYPE__ size_t;
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
typedef __UINTPTR_TYPE__ uintptr_t;
// This type is used internally in wasi-libc.
typedef double double_t;
`
+796 -707
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
//go:build go1.22
package cgo
// Code specifically for Go 1.22.
import (
"go/ast"
"go/token"
)
func init() {
setASTFileFields = func(f *ast.File, start, end token.Pos) {
f.FileStart = start
f.FileEnd = end
}
}
+132 -38
View File
@@ -5,12 +5,12 @@ import (
"flag"
"fmt"
"go/ast"
"go/build"
"go/format"
"go/parser"
"go/scanner"
"go/token"
"go/types"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"runtime"
@@ -23,39 +23,30 @@ var flagUpdate = flag.Bool("update", false, "Update images based on test output.
// normalizeResult normalizes Go source code that comes out of tests across
// platforms and Go versions.
func normalizeResult(result string) string {
actual := strings.ReplaceAll(result, "\r\n", "\n")
func normalizeResult(t *testing.T, result string) string {
result = strings.ReplaceAll(result, "\r\n", "\n")
// Make sure all functions are wrapped, even those that would otherwise be
// single-line functions. This is necessary because Go 1.14 changed the way
// such functions are wrapped and it's important to have consistent test
// results.
re := regexp.MustCompile(`func \((.+)\)( .*?) +{ (.+) }`)
actual = re.ReplaceAllString(actual, "func ($1)$2 {\n\t$3\n}")
// This changed to 'undefined:', in Go 1.20.
result = strings.ReplaceAll(result, ": undeclared name:", ": undefined:")
// Go 1.20 added a bit more detail
result = regexp.MustCompile(`(unknown field z in struct literal).*`).ReplaceAllString(result, "$1")
return actual
return result
}
func TestCGo(t *testing.T) {
var cflags = []string{"--target=armv6m-none-eabi"}
var cflags = []string{"--target=armv6m-unknown-unknown-eabi"}
for _, name := range []string{"basic", "errors", "types", "flags", "const"} {
for _, name := range []string{
"basic",
"errors",
"types",
"symbols",
"flags",
"const",
} {
name := name // avoid a race condition
t.Run(name, func(t *testing.T) {
// Skip tests that require specific Go version.
if name == "errors" {
ok := false
for _, version := range build.Default.ReleaseTags {
if version == "go1.16" {
ok = true
break
}
}
if !ok {
t.Skip("Results for errors test are only valid for Go 1.16+")
}
}
// Read the AST in memory.
path := filepath.Join("testdata", name+".go")
fset := token.NewFileSet()
@@ -65,7 +56,7 @@ func TestCGo(t *testing.T) {
}
// Process the AST with CGo.
cgoAST, _, cgoErrors := Process([]*ast.File{f}, "testdata", fset, cflags)
cgoFiles, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags, "linux")
// Check the AST for type errors.
var typecheckErrors []error
@@ -73,10 +64,10 @@ func TestCGo(t *testing.T) {
Error: func(err error) {
typecheckErrors = append(typecheckErrors, err)
},
Importer: simpleImporter{},
Importer: newSimpleImporter(),
Sizes: types.SizesFor("gccgo", "arm"),
}
_, err = config.Check("", fset, []*ast.File{f, cgoAST}, nil)
_, err = config.Check("", fset, append([]*ast.File{f}, cgoFiles...), nil)
if err != nil && len(typecheckErrors) == 0 {
// Only report errors when no type errors are found (an
// unexpected condition).
@@ -101,15 +92,15 @@ func TestCGo(t *testing.T) {
}
buf.WriteString("\n")
}
err = format.Node(buf, fset, cgoAST)
err = format.Node(buf, fset, cgoFiles[0])
if err != nil {
t.Errorf("could not write out CGo AST: %v", err)
}
actual := normalizeResult(string(buf.Bytes()))
actual := normalizeResult(t, buf.String())
// Read the file with the expected output, to compare against.
outfile := filepath.Join("testdata", name+".out.go")
expectedBytes, err := ioutil.ReadFile(outfile)
expectedBytes, err := os.ReadFile(outfile)
if err != nil {
t.Fatalf("could not read expected output: %v", err)
}
@@ -120,7 +111,7 @@ func TestCGo(t *testing.T) {
// It is not. Test failed.
if *flagUpdate {
// Update the file with the expected data.
err := ioutil.WriteFile(outfile, []byte(actual), 0666)
err := os.WriteFile(outfile, []byte(actual), 0666)
if err != nil {
t.Error("could not write updated output file:", err)
}
@@ -132,15 +123,112 @@ func TestCGo(t *testing.T) {
}
}
func Test_cgoPackage_isEquivalentAST(t *testing.T) {
fieldA := &ast.Field{Type: &ast.BasicLit{Kind: token.STRING, Value: "a"}}
fieldB := &ast.Field{Type: &ast.BasicLit{Kind: token.STRING, Value: "b"}}
listOfFieldA := &ast.FieldList{List: []*ast.Field{fieldA}}
listOfFieldB := &ast.FieldList{List: []*ast.Field{fieldB}}
funcDeclA := &ast.FuncDecl{Name: &ast.Ident{Name: "a"}, Type: &ast.FuncType{Params: &ast.FieldList{}, Results: listOfFieldA}}
funcDeclB := &ast.FuncDecl{Name: &ast.Ident{Name: "b"}, Type: &ast.FuncType{Params: &ast.FieldList{}, Results: listOfFieldB}}
funcDeclNoResults := &ast.FuncDecl{Name: &ast.Ident{Name: "C"}, Type: &ast.FuncType{Params: &ast.FieldList{}}}
testCases := []struct {
name string
a, b ast.Node
expected bool
}{
{
name: "both nil",
expected: true,
},
{
name: "not same type",
a: fieldA,
b: &ast.FuncDecl{},
expected: false,
},
{
name: "Field same",
a: fieldA,
b: fieldA,
expected: true,
},
{
name: "Field different",
a: fieldA,
b: fieldB,
expected: false,
},
{
name: "FuncDecl Type Results nil",
a: funcDeclNoResults,
b: funcDeclNoResults,
expected: true,
},
{
name: "FuncDecl Type Results same",
a: funcDeclA,
b: funcDeclA,
expected: true,
},
{
name: "FuncDecl Type Results different",
a: funcDeclA,
b: funcDeclB,
expected: false,
},
{
name: "FuncDecl Type Results a nil",
a: funcDeclNoResults,
b: funcDeclB,
expected: false,
},
{
name: "FuncDecl Type Results b nil",
a: funcDeclA,
b: funcDeclNoResults,
expected: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
p := &cgoPackage{}
if got := p.isEquivalentAST(tc.a, tc.b); tc.expected != got {
t.Errorf("expected %v, got %v", tc.expected, got)
}
})
}
}
// simpleImporter implements the types.Importer interface, but only allows
// importing the unsafe package.
// importing the syscall and unsafe packages.
type simpleImporter struct {
syscallPkg *types.Package
}
func newSimpleImporter() *simpleImporter {
i := &simpleImporter{}
// Implement a dummy syscall package with the Errno type.
i.syscallPkg = types.NewPackage("syscall", "syscall")
obj := types.NewTypeName(token.NoPos, i.syscallPkg, "Errno", nil)
named := types.NewNamed(obj, nil, nil)
i.syscallPkg.Scope().Insert(obj)
named.SetUnderlying(types.Typ[types.Uintptr])
sig := types.NewSignatureType(nil, nil, nil, types.NewTuple(), types.NewTuple(types.NewParam(token.NoPos, i.syscallPkg, "", types.Typ[types.String])), false)
named.AddMethod(types.NewFunc(token.NoPos, i.syscallPkg, "Error", sig))
i.syscallPkg.MarkComplete()
return i
}
// Import implements the Importer interface. For testing usage only: it only
// supports importing the unsafe package.
func (i simpleImporter) Import(path string) (*types.Package, error) {
func (i *simpleImporter) Import(path string) (*types.Package, error) {
switch path {
case "syscall":
return i.syscallPkg, nil
case "unsafe":
return types.Unsafe, nil
default:
@@ -148,10 +236,16 @@ func (i simpleImporter) Import(path string) (*types.Package, error) {
}
}
// formatDiagnostics formats the error message to be an indented comment. It
// formatDiagnostic formats the error message to be an indented comment. It
// also fixes Windows path name issues (backward slashes).
func formatDiagnostic(err error) string {
msg := err.Error()
var msg string
switch err := err.(type) {
case scanner.Error:
msg = err.Pos.String() + ": " + err.Msg
default:
msg = err.Error()
}
if runtime.GOOS == "windows" {
// Fix Windows path slashes.
msg = strings.ReplaceAll(msg, "testdata\\", "testdata/")
+336 -77
View File
@@ -11,105 +11,326 @@ import (
"strings"
)
var (
prefixParseFns map[token.Token]func(*tokenizer) (ast.Expr, *scanner.Error)
precedences = map[token.Token]int{
token.OR: precedenceOr,
token.XOR: precedenceXor,
token.AND: precedenceAnd,
token.SHL: precedenceShift,
token.SHR: precedenceShift,
token.ADD: precedenceAdd,
token.SUB: precedenceAdd,
token.MUL: precedenceMul,
token.QUO: precedenceMul,
token.REM: precedenceMul,
}
)
// See: https://en.cppreference.com/w/c/language/operator_precedence
const (
precedenceLowest = iota + 1
precedenceOr
precedenceXor
precedenceAnd
precedenceShift
precedenceAdd
precedenceMul
precedencePrefix
)
func init() {
// This must be done in an init function to avoid an initialization order
// failure.
prefixParseFns = map[token.Token]func(*tokenizer) (ast.Expr, *scanner.Error){
token.IDENT: parseIdent,
token.INT: parseBasicLit,
token.FLOAT: parseBasicLit,
token.STRING: parseBasicLit,
token.CHAR: parseBasicLit,
token.LPAREN: parseParenExpr,
token.SUB: parseUnaryExpr,
}
}
// parseConst parses the given string as a C constant.
func parseConst(pos token.Pos, fset *token.FileSet, value string) (ast.Expr, *scanner.Error) {
t := newTokenizer(pos, fset, value)
expr, err := parseConstExpr(t)
if t.token != token.EOF {
func parseConst(pos token.Pos, fset *token.FileSet, value string, params []ast.Expr, callerPos token.Pos, f *cgoFile) (ast.Expr, *scanner.Error) {
t := newTokenizer(pos, fset, value, f)
// If params is non-nil (could be a zero length slice), this const is
// actually a function-call like expression from another macro.
// This means we have to parse a string like "(a, b) (a+b)".
// We do this by parsing the parameters at the start and then treating the
// following like a normal constant expression.
if params != nil {
// Parse opening paren.
if t.curToken != token.LPAREN {
return nil, unexpectedToken(t, token.LPAREN)
}
t.Next()
// Parse parameters (identifiers) and closing paren.
var paramIdents []string
for i := 0; ; i++ {
if i == 0 && t.curToken == token.RPAREN {
// No parameters, break early.
t.Next()
break
}
// Read the parameter name.
if t.curToken != token.IDENT {
return nil, unexpectedToken(t, token.IDENT)
}
paramIdents = append(paramIdents, t.curValue)
t.Next()
// Read the next token: either a continuation (comma) or end of list
// (rparen).
if t.curToken == token.RPAREN {
// End of parameter list.
t.Next()
break
} else if t.curToken == token.COMMA {
// Comma, so there will be another parameter name.
t.Next()
} else {
return nil, &scanner.Error{
Pos: t.fset.Position(t.curPos),
Msg: "unexpected token " + t.curToken.String() + " inside macro parameters, expected ',' or ')'",
}
}
}
// Report an error if there is a mismatch in parameter length.
// The error is reported at the location of the closing paren from the
// caller location.
if len(params) != len(paramIdents) {
return nil, &scanner.Error{
Pos: t.fset.Position(callerPos),
Msg: fmt.Sprintf("unexpected number of parameters: expected %d, got %d", len(paramIdents), len(params)),
}
}
// Assign values to the parameters.
// These parameter names are closer in 'scope' than other identifiers so
// will be used first when parsing an identifier.
for i, name := range paramIdents {
t.params[name] = params[i]
}
}
expr, err := parseConstExpr(t, precedenceLowest)
t.Next()
if t.curToken != token.EOF {
return nil, &scanner.Error{
Pos: t.fset.Position(t.pos),
Msg: "unexpected token " + t.token.String(),
Pos: t.fset.Position(t.curPos),
Msg: "unexpected token " + t.curToken.String() + ", expected end of expression",
}
}
return expr, err
}
// parseConstExpr parses a stream of C tokens to a Go expression.
func parseConstExpr(t *tokenizer) (ast.Expr, *scanner.Error) {
switch t.token {
case token.LPAREN:
lparen := t.pos
t.Next()
x, err := parseConstExpr(t)
if err != nil {
return nil, err
}
if t.token != token.RPAREN {
return nil, unexpectedToken(t, token.RPAREN)
}
expr := &ast.ParenExpr{
Lparen: lparen,
X: x,
Rparen: t.pos,
}
t.Next()
return expr, nil
case token.INT, token.FLOAT, token.STRING, token.CHAR:
expr := &ast.BasicLit{
ValuePos: t.pos,
Kind: t.token,
Value: t.value,
}
t.Next()
return expr, nil
case token.IDENT:
expr := &ast.Ident{
NamePos: t.pos,
Name: "C." + t.value,
}
t.Next()
return expr, nil
case token.EOF:
func parseConstExpr(t *tokenizer, precedence int) (ast.Expr, *scanner.Error) {
if t.curToken == token.EOF {
return nil, &scanner.Error{
Pos: t.fset.Position(t.pos),
Pos: t.fset.Position(t.curPos),
Msg: "empty constant",
}
default:
}
prefix := prefixParseFns[t.curToken]
if prefix == nil {
return nil, &scanner.Error{
Pos: t.fset.Position(t.pos),
Msg: fmt.Sprintf("unexpected token %s", t.token),
Pos: t.fset.Position(t.curPos),
Msg: fmt.Sprintf("unexpected token %s", t.curToken),
}
}
leftExpr, err := prefix(t)
for t.peekToken != token.EOF && precedence < precedences[t.peekToken] {
switch t.peekToken {
case token.OR, token.XOR, token.AND, token.SHL, token.SHR, token.ADD, token.SUB, token.MUL, token.QUO, token.REM:
t.Next()
leftExpr, err = parseBinaryExpr(t, leftExpr)
}
}
return leftExpr, err
}
func parseIdent(t *tokenizer) (ast.Expr, *scanner.Error) {
// If the identifier is one of the parameters of this function-like macro,
// use the parameter value.
if val, ok := t.params[t.curValue]; ok {
return val, nil
}
if t.f != nil {
// Check whether this identifier is actually a macro "call" with
// parameters. In that case, we should parse the parameters and pass it
// on to a new invocation of parseConst.
if t.peekToken == token.LPAREN {
if cursor, ok := t.f.names[t.curValue]; ok && t.f.isFunctionLikeMacro(cursor) {
// We know the current and peek tokens (the peek one is the '('
// token). So skip ahead until the current token is the first
// unknown token.
t.Next()
t.Next()
// Parse the list of parameters until ')' (rparen) is found.
params := []ast.Expr{}
for i := 0; ; i++ {
if i == 0 && t.curToken == token.RPAREN {
break
}
x, err := parseConstExpr(t, precedenceLowest)
if err != nil {
return nil, err
}
params = append(params, x)
t.Next()
if t.curToken == token.COMMA {
t.Next()
} else if t.curToken == token.RPAREN {
break
} else {
return nil, &scanner.Error{
Pos: t.fset.Position(t.curPos),
Msg: "unexpected token " + t.curToken.String() + ", ',' or ')'",
}
}
}
// Evaluate the macro value and use it as the identifier value.
rparen := t.curPos
pos, text := t.f.getMacro(cursor)
return parseConst(pos, t.fset, text, params, rparen, t.f)
}
}
// Normally the name is something defined in the file (like another
// macro) which we get the declaration from using getASTDeclName.
// This ensures that names that are only referenced inside a macro are
// still getting defined.
if cursor, ok := t.f.names[t.curValue]; ok {
return &ast.Ident{
NamePos: t.curPos,
Name: t.f.getASTDeclName(t.curValue, cursor, false),
}, nil
}
}
// t.f is nil during testing. This is a fallback.
return &ast.Ident{
NamePos: t.curPos,
Name: "C." + t.curValue,
}, nil
}
func parseBasicLit(t *tokenizer) (ast.Expr, *scanner.Error) {
return &ast.BasicLit{
ValuePos: t.curPos,
Kind: t.curToken,
Value: t.curValue,
}, nil
}
func parseParenExpr(t *tokenizer) (ast.Expr, *scanner.Error) {
lparen := t.curPos
t.Next()
x, err := parseConstExpr(t, precedenceLowest)
if err != nil {
return nil, err
}
t.Next()
if t.curToken != token.RPAREN {
return nil, unexpectedToken(t, token.RPAREN)
}
expr := &ast.ParenExpr{
Lparen: lparen,
X: x,
Rparen: t.curPos,
}
return expr, nil
}
func parseBinaryExpr(t *tokenizer, left ast.Expr) (ast.Expr, *scanner.Error) {
expression := &ast.BinaryExpr{
X: left,
Op: t.curToken,
OpPos: t.curPos,
}
precedence := precedences[t.curToken]
t.Next()
right, err := parseConstExpr(t, precedence)
expression.Y = right
return expression, err
}
func parseUnaryExpr(t *tokenizer) (ast.Expr, *scanner.Error) {
expression := &ast.UnaryExpr{
OpPos: t.curPos,
Op: t.curToken,
}
t.Next()
x, err := parseConstExpr(t, precedencePrefix)
expression.X = x
return expression, err
}
// unexpectedToken returns an error of the form "unexpected token FOO, expected
// BAR".
func unexpectedToken(t *tokenizer, expected token.Token) *scanner.Error {
return &scanner.Error{
Pos: t.fset.Position(t.pos),
Msg: fmt.Sprintf("unexpected token %s, expected %s", t.token, expected),
Pos: t.fset.Position(t.curPos),
Msg: fmt.Sprintf("unexpected token %s, expected %s", t.curToken, expected),
}
}
// tokenizer reads C source code and converts it to Go tokens.
type tokenizer struct {
pos token.Pos
fset *token.FileSet
token token.Token
value string
buf string
f *cgoFile
curPos, peekPos token.Pos
fset *token.FileSet
curToken, peekToken token.Token
curValue, peekValue string
buf string
params map[string]ast.Expr
}
// newTokenizer initializes a new tokenizer, positioned at the first token in
// the string.
func newTokenizer(start token.Pos, fset *token.FileSet, buf string) *tokenizer {
func newTokenizer(start token.Pos, fset *token.FileSet, buf string, f *cgoFile) *tokenizer {
t := &tokenizer{
pos: start,
fset: fset,
buf: buf,
token: token.ILLEGAL,
f: f,
peekPos: start,
fset: fset,
buf: buf,
peekToken: token.ILLEGAL,
params: make(map[string]ast.Expr),
}
t.Next() // Parse the first token.
// Parse the first two tokens (cur and peek).
t.Next()
t.Next()
return t
}
// Next consumes the next token in the stream. There is no return value, read
// the next token from the pos, token and value properties.
func (t *tokenizer) Next() {
t.pos += token.Pos(len(t.value))
// The previous peek is now the current token.
t.curPos = t.peekPos
t.curToken = t.peekToken
t.curValue = t.peekValue
// Parse the next peek token.
if t.peekPos != token.NoPos {
t.peekPos += token.Pos(len(t.curValue))
}
for {
if len(t.buf) == 0 {
t.token = token.EOF
t.peekToken = token.EOF
return
}
c := t.buf[0]
@@ -118,17 +339,55 @@ func (t *tokenizer) Next() {
// Skip whitespace.
// Based on this source, not sure whether it represents C whitespace:
// https://en.cppreference.com/w/cpp/string/byte/isspace
t.pos++
if t.peekPos != token.NoPos {
t.peekPos++
}
t.buf = t.buf[1:]
case c == '(' || c == ')':
case len(t.buf) >= 2 && (string(t.buf[:2]) == "||" || string(t.buf[:2]) == "&&" || string(t.buf[:2]) == "<<" || string(t.buf[:2]) == ">>"):
// Two-character tokens.
switch c {
case '&':
t.peekToken = token.LAND
case '|':
t.peekToken = token.LOR
case '<':
t.peekToken = token.SHL
case '>':
t.peekToken = token.SHR
default:
panic("unreachable")
}
t.peekValue = t.buf[:2]
t.buf = t.buf[2:]
return
case c == '(' || c == ')' || c == ',' || c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '&' || c == '|' || c == '^':
// Single-character tokens.
// TODO: ++ (increment) and -- (decrement) operators.
switch c {
case '(':
t.token = token.LPAREN
t.peekToken = token.LPAREN
case ')':
t.token = token.RPAREN
t.peekToken = token.RPAREN
case ',':
t.peekToken = token.COMMA
case '+':
t.peekToken = token.ADD
case '-':
t.peekToken = token.SUB
case '*':
t.peekToken = token.MUL
case '/':
t.peekToken = token.QUO
case '%':
t.peekToken = token.REM
case '&':
t.peekToken = token.AND
case '|':
t.peekToken = token.OR
case '^':
t.peekToken = token.XOR
}
t.value = t.buf[:1]
t.peekValue = t.buf[:1]
t.buf = t.buf[1:]
return
case c >= '0' && c <= '9':
@@ -146,17 +405,17 @@ func (t *tokenizer) Next() {
break
}
}
t.value = t.buf[:tokenLen]
t.peekValue = t.buf[:tokenLen]
t.buf = t.buf[tokenLen:]
if hasDot {
// Integer constants are more complicated than this but this is
// a close approximation.
// https://en.cppreference.com/w/cpp/language/integer_literal
t.token = token.FLOAT
t.value = strings.TrimRight(t.value, "f")
t.peekToken = token.FLOAT
t.peekValue = strings.TrimRight(t.peekValue, "f")
} else {
t.token = token.INT
t.value = strings.TrimRight(t.value, "uUlL")
t.peekToken = token.INT
t.peekValue = strings.TrimRight(t.peekValue, "uUlL")
}
return
case c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c == '_':
@@ -170,9 +429,9 @@ func (t *tokenizer) Next() {
break
}
}
t.value = t.buf[:tokenLen]
t.peekValue = t.buf[:tokenLen]
t.buf = t.buf[tokenLen:]
t.token = token.IDENT
t.peekToken = token.IDENT
return
case c == '"':
// String constant. Find the first '"' character that is not
@@ -188,8 +447,8 @@ func (t *tokenizer) Next() {
escape = c == '\\'
}
}
t.token = token.STRING
t.value = t.buf[:tokenLen]
t.peekToken = token.STRING
t.peekValue = t.buf[:tokenLen]
t.buf = t.buf[tokenLen:]
return
case c == '\'':
@@ -206,12 +465,12 @@ func (t *tokenizer) Next() {
escape = c == '\\'
}
}
t.token = token.CHAR
t.value = t.buf[:tokenLen]
t.peekToken = token.CHAR
t.peekValue = t.buf[:tokenLen]
t.buf = t.buf[tokenLen:]
return
default:
t.token = token.ILLEGAL
t.peekToken = token.ILLEGAL
return
}
}
+28 -3
View File
@@ -18,7 +18,7 @@ func TestParseConst(t *testing.T) {
{`(5)`, `(5)`},
{`(((5)))`, `(5)`},
{`)`, `error: 1:1: unexpected token )`},
{`5)`, `error: 1:2: unexpected token )`},
{`5)`, `error: 1:2: unexpected token ), expected end of expression`},
{" \t)", `error: 1:4: unexpected token )`},
{`5.8f`, `5.8`},
{`foo`, `C.foo`},
@@ -30,11 +30,36 @@ func TestParseConst(t *testing.T) {
{`'a'`, `'a'`},
{`0b10`, `0b10`},
{`0x1234_5678`, `0x1234_5678`},
{`5 5`, `error: 1:3: unexpected token INT`}, // test for a bugfix
{`5 5`, `error: 1:3: unexpected token INT, expected end of expression`}, // test for a bugfix
// Binary operators.
{`5+5`, `5 + 5`},
{`5-5`, `5 - 5`},
{`5*5`, `5 * 5`},
{`5/5`, `5 / 5`},
{`5%5`, `5 % 5`},
{`5&5`, `5 & 5`},
{`5|5`, `5 | 5`},
{`5^5`, `5 ^ 5`},
{`5<<5`, `5 << 5`},
{`5>>5`, `5 >> 5`},
{`5>>5 + 3`, `5 >> (5 + 3)`},
{`5>>5 ^ 3`, `5>>5 ^ 3`},
{`5||5`, `error: 1:2: unexpected token ||, expected end of expression`}, // logical binops aren't supported yet
{`(5/5)`, `(5 / 5)`},
{`1 - 2`, `1 - 2`},
{`1 - 2 + 3`, `1 - 2 + 3`},
{`1 - 2 * 3`, `1 - 2*3`},
{`(1 - 2) * 3`, `(1 - 2) * 3`},
{`1 * 2 - 3`, `1*2 - 3`},
{`1 * (2 - 3)`, `1 * (2 - 3)`},
// Unary operators.
{`-5`, `-5`},
{`-5-2`, `-5 - 2`},
{`5 - - 2`, `5 - -2`},
} {
fset := token.NewFileSet()
startPos := fset.AddFile("", -1, 1000).Pos(0)
expr, err := parseConst(startPos, fset, tc.C)
expr, err := parseConst(startPos, fset, tc.C, nil, token.NoPos, nil)
s := "<invalid>"
if err != nil {
if !strings.HasPrefix(tc.Go, "error: ") {
+605 -240
View File
File diff suppressed because it is too large Load Diff
-14
View File
@@ -1,14 +0,0 @@
// +build !byollvm
// +build !llvm10
package cgo
/*
#cgo linux CFLAGS: -I/usr/lib/llvm-11/include
#cgo darwin CFLAGS: -I/usr/local/opt/llvm@11/include
#cgo freebsd CFLAGS: -I/usr/local/llvm11/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-11/lib -lclang
#cgo darwin LDFLAGS: -L/usr/local/opt/llvm@11/lib -lclang -lffi
#cgo freebsd LDFLAGS: -L/usr/local/llvm11/lib -lclang
*/
import "C"
-14
View File
@@ -1,14 +0,0 @@
// +build !byollvm
// +build llvm10
package cgo
/*
#cgo linux CFLAGS: -I/usr/lib/llvm-10/include
#cgo darwin CFLAGS: -I/usr/local/opt/llvm@10/include
#cgo freebsd CFLAGS: -I/usr/local/llvm10/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-10/lib -lclang
#cgo darwin LDFLAGS: -L/usr/local/opt/llvm@10/lib -lclang -lffi
#cgo freebsd LDFLAGS: -L/usr/local/llvm10/lib -lclang
*/
import "C"
+15
View File
@@ -0,0 +1,15 @@
//go:build !byollvm && llvm15
package cgo
/*
#cgo linux CFLAGS: -I/usr/lib/llvm-15/include
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@15/include
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@15/include
#cgo freebsd CFLAGS: -I/usr/local/llvm15/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-15/lib -lclang
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@15/lib -lclang
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@15/lib -lclang
#cgo freebsd LDFLAGS: -L/usr/local/llvm15/lib -lclang
*/
import "C"
+21
View File
@@ -0,0 +1,21 @@
//go:build !byollvm && llvm16
package cgo
// As of 2023-05-05, there is a packaging issue with LLVM 16 on Debian:
// https://github.com/llvm/llvm-project/issues/62199
// A workaround is to fix this locally, using something like this:
//
// ln -sf ../../x86_64-linux-gnu/libclang-16.so.1 /usr/lib/llvm-16/lib/libclang.so
/*
#cgo linux CFLAGS: -I/usr/lib/llvm-16/include
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@16/include
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@16/include
#cgo freebsd CFLAGS: -I/usr/local/llvm16/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-16/lib -lclang
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@16/lib -lclang
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@16/lib -lclang
#cgo freebsd LDFLAGS: -L/usr/local/llvm16/lib -lclang
*/
import "C"
+15
View File
@@ -0,0 +1,15 @@
//go:build !byollvm && llvm17
package cgo
/*
#cgo linux CFLAGS: -I/usr/include/llvm-17 -I/usr/include/llvm-c-17 -I/usr/lib/llvm-17/include
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@17/include
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@17/include
#cgo freebsd CFLAGS: -I/usr/local/llvm17/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-17/lib -lclang
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@17/lib -lclang
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@17/lib -lclang
#cgo freebsd LDFLAGS: -L/usr/local/llvm17/lib -lclang
*/
import "C"
+15
View File
@@ -0,0 +1,15 @@
//go:build !byollvm && llvm18
package cgo
/*
#cgo linux CFLAGS: -I/usr/include/llvm-18 -I/usr/include/llvm-c-18 -I/usr/lib/llvm-18/include
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@18/include
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@18/include
#cgo freebsd CFLAGS: -I/usr/local/llvm18/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-18/lib -lclang
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@18/lib -lclang
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@18/lib -lclang
#cgo freebsd LDFLAGS: -L/usr/local/llvm18/lib -lclang
*/
import "C"
+15
View File
@@ -0,0 +1,15 @@
//go:build !byollvm && !llvm15 && !llvm16 && !llvm17 && !llvm18
package cgo
/*
#cgo linux CFLAGS: -I/usr/include/llvm-19 -I/usr/include/llvm-c-19 -I/usr/lib/llvm-19/include
#cgo darwin,amd64 CFLAGS: -I/usr/local/opt/llvm@19/include
#cgo darwin,arm64 CFLAGS: -I/opt/homebrew/opt/llvm@19/include
#cgo freebsd CFLAGS: -I/usr/local/llvm19/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-19/lib -lclang
#cgo darwin,amd64 LDFLAGS: -L/usr/local/opt/llvm@19/lib -lclang
#cgo darwin,arm64 LDFLAGS: -L/opt/homebrew/opt/llvm@19/lib -lclang
#cgo freebsd LDFLAGS: -L/usr/local/llvm19/lib -lclang
*/
import "C"
+22 -2
View File
@@ -3,7 +3,7 @@
// are slightly different from the ones defined in libclang.go, but they
// should be ABI compatible.
#include <clang-c/Index.h> // if this fails, install libclang-10-dev
#include <clang-c/Index.h> // If this fails, libclang headers aren't available. Please take a look here: https://tinygo.org/docs/guides/build/
CXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu) {
return clang_getTranslationUnitCursor(tu);
@@ -17,6 +17,14 @@ CXString tinygo_clang_getCursorSpelling(CXCursor c) {
return clang_getCursorSpelling(c);
}
CXString tinygo_clang_getCursorPrettyPrinted(CXCursor c, CXPrintingPolicy policy) {
return clang_getCursorPrettyPrinted(c, policy);
}
CXPrintingPolicy tinygo_clang_getCursorPrintingPolicy(CXCursor c) {
return clang_getCursorPrintingPolicy(c);
}
enum CXCursorKind tinygo_clang_getCursorKind(CXCursor c) {
return clang_getCursorKind(c);
}
@@ -45,6 +53,10 @@ CXCursor tinygo_clang_Cursor_getArgument(CXCursor c, unsigned i) {
return clang_Cursor_getArgument(c, i);
}
enum CX_StorageClass tinygo_clang_Cursor_getStorageClass(CXCursor c) {
return clang_Cursor_getStorageClass(c);
}
CXSourceLocation tinygo_clang_getCursorLocation(CXCursor c) {
return clang_getCursorLocation(c);
}
@@ -65,6 +77,14 @@ CXType tinygo_clang_getEnumDeclIntegerType(CXCursor c) {
return clang_getEnumDeclIntegerType(c);
}
unsigned tinygo_clang_Cursor_isAnonymous(CXCursor c) {
return clang_Cursor_isAnonymous(c);
}
unsigned tinygo_clang_Cursor_isBitField(CXCursor c) {
return clang_Cursor_isBitField(c);
}
}
unsigned tinygo_clang_Cursor_isMacroFunctionLike(CXCursor c) {
return clang_Cursor_isMacroFunctionLike(c);
}
+1
View File
@@ -142,6 +142,7 @@ var validLinkerFlags = []*regexp.Regexp{
re(`-L([^@\-].*)`),
re(`-O`),
re(`-O([^@\-].*)`),
re(`--export=([^@\-].*)`),
re(`-f(no-)?(pic|PIC|pie|PIE)`),
re(`-f(no-)?openmp(-simd)?`),
re(`-fsanitize=([^@\-].*)`),
+1
View File
@@ -108,6 +108,7 @@ var goodLinkerFlags = [][]string{
{"-Fbar"},
{"-lbar"},
{"-Lbar"},
{"--export=my_symbol"},
{"-fpic"},
{"-fno-pic"},
{"-fPIC"},
+48 -20
View File
@@ -1,26 +1,54 @@
package main
import "syscall"
import "unsafe"
var _ unsafe.Pointer
type C.int16_t = int16
type C.int32_t = int32
type C.int64_t = int64
type C.int8_t = int8
type C.uint16_t = uint16
type C.uint32_t = uint32
type C.uint64_t = uint64
type C.uint8_t = uint8
type C.uintptr_t = uintptr
type C.char uint8
type C.int int32
type C.long int32
type C.longlong int64
type C.schar int8
type C.short int16
type C.uchar uint8
type C.uint uint32
type C.ulong uint32
type C.ulonglong uint64
type C.ushort uint16
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
+16
View File
@@ -3,10 +3,26 @@ package main
/*
#define foo 3
#define bar foo
#define unreferenced 4
#define referenced unreferenced
#define fnlike() 5
#define fnlike_val fnlike()
#define square(n) (n*n)
#define square_val square(20)
#define add(a, b) (a + b)
#define add_val add(3, 5)
*/
import "C"
const (
Foo = C.foo
Bar = C.bar
Baz = C.referenced
fnlike = C.fnlike_val
square = C.square_val
add = C.add_val
)
+55 -22
View File
@@ -1,29 +1,62 @@
package main
import "syscall"
import "unsafe"
var _ unsafe.Pointer
const C.bar = C.foo
const C.foo = 3
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
type C.int16_t = int16
type C.int32_t = int32
type C.int64_t = int64
type C.int8_t = int8
type C.uint16_t = uint16
type C.uint32_t = uint32
type C.uint64_t = uint64
type C.uint8_t = uint8
type C.uintptr_t = uintptr
type C.char uint8
type C.int int32
type C.long int32
type C.longlong int64
type C.schar int8
type C.short int16
type C.uchar uint8
type C.uint uint32
type C.ulong uint32
type C.ulonglong uint64
type C.ushort uint16
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
const _Cgo_foo = 3
const _Cgo_bar = _Cgo_foo
const _Cgo_unreferenced = 4
const _Cgo_referenced = _Cgo_unreferenced
const _Cgo_fnlike_val = 5
const _Cgo_square_val = (20 * 20)
const _Cgo_add_val = (3 + 5)
+35 -1
View File
@@ -10,18 +10,39 @@ typedef struct {
typedef someType noType; // undefined type
// Some invalid noescape lines
#cgo noescape
#cgo noescape foo bar
#cgo noescape unusedFunction
#define SOME_CONST_1 5) // invalid const syntax
#define SOME_CONST_2 6) // const not used (so no error)
#define SOME_CONST_3 1234 // const too large for byte
#define SOME_CONST_b 3 ) // const with lots of weird whitespace (to test error locations)
# define SOME_CONST_startspace 3)
*/
//
//
// #define SOME_CONST_4 8) // after some empty lines
// #cgo CFLAGS: -DSOME_PARAM_CONST_invalid=3/+3
// #cgo CFLAGS: -DSOME_PARAM_CONST_valid=3+4
import "C"
// #warning another warning
import "C"
// #define add(a, b) (a+b)
// #define add_toomuch add(1, 2, 3)
// #define add_toolittle add(1)
import "C"
// Make sure that errors for the following lines won't change with future
// additions to the CGo preamble.
//
//line errors.go:100
var (
// constant too large
_ C.uint8_t = 2 << 10
_ C.char = 2 << 10
// z member does not exist
_ C.point_t = C.point_t{z: 3}
@@ -30,4 +51,17 @@ var (
_ = C.SOME_CONST_1
_ byte = C.SOME_CONST_3
_ = C.SOME_CONST_4
_ = C.SOME_CONST_b
_ = C.SOME_CONST_startspace
// constants passed by a command line parameter
_ = C.SOME_PARAM_CONST_invalid
_ = C.SOME_PARAM_CONST_valid
_ = C.add_toomuch
_ = C.add_toolittle
)
+74 -28
View File
@@ -1,43 +1,89 @@
// CGo errors:
// testdata/errors.go:14:1: missing function name in #cgo noescape line
// testdata/errors.go:15:1: multiple function names in #cgo noescape line
// testdata/errors.go:4:2: warning: some warning
// testdata/errors.go:11:9: error: unknown type name 'someType'
// testdata/errors.go:13:23: unexpected token )
// testdata/errors.go:31:5: warning: another warning
// testdata/errors.go:18:23: unexpected token ), expected end of expression
// testdata/errors.go:26:26: unexpected token ), expected end of expression
// testdata/errors.go:21:33: unexpected token ), expected end of expression
// testdata/errors.go:22:34: unexpected token ), expected end of expression
// -: unexpected token INT, expected end of expression
// testdata/errors.go:35:35: unexpected number of parameters: expected 2, got 3
// testdata/errors.go:36:31: unexpected number of parameters: expected 2, got 1
// testdata/errors.go:3:1: function "unusedFunction" in #cgo noescape line is not used
// Type checking errors after CGo processing:
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as uint8 value in variable declaration (overflows)
// testdata/errors.go:102: cannot use 2 << 10 (untyped int constant 2048) as _Cgo_char value in variable declaration (overflows)
// testdata/errors.go:105: unknown field z in struct literal
// testdata/errors.go:108: undeclared name: C.SOME_CONST_1
// testdata/errors.go:110: cannot use C.SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)
// testdata/errors.go:108: undefined: _Cgo_SOME_CONST_1
// testdata/errors.go:110: cannot use _Cgo_SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)
// testdata/errors.go:112: undefined: _Cgo_SOME_CONST_4
// testdata/errors.go:114: undefined: _Cgo_SOME_CONST_b
// testdata/errors.go:116: undefined: _Cgo_SOME_CONST_startspace
// testdata/errors.go:119: undefined: _Cgo_SOME_PARAM_CONST_invalid
// testdata/errors.go:122: undefined: _Cgo_add_toomuch
// testdata/errors.go:123: undefined: _Cgo_add_toolittle
package main
import "syscall"
import "unsafe"
var _ unsafe.Pointer
const C.SOME_CONST_3 = 1234
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
type C.int16_t = int16
type C.int32_t = int32
type C.int64_t = int64
type C.int8_t = int8
type C.uint16_t = uint16
type C.uint32_t = uint32
type C.uint64_t = uint64
type C.uint8_t = uint8
type C.uintptr_t = uintptr
type C.char uint8
type C.int int32
type C.long int32
type C.longlong int64
type C.schar int8
type C.short int16
type C.uchar uint8
type C.uint uint32
type C.ulong uint32
type C.ulonglong uint64
type C.ushort uint16
type C.point_t = struct {
x C.int
y C.int
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
type _Cgo_struct_point_t struct {
x _Cgo_int
y _Cgo_int
}
type _Cgo_point_t = _Cgo_struct_point_t
const _Cgo_SOME_CONST_3 = 1234
const _Cgo_SOME_PARAM_CONST_valid = 3 + 4
+50 -22
View File
@@ -5,30 +5,58 @@
package main
import "syscall"
import "unsafe"
var _ unsafe.Pointer
const C.BAR = 3
const C.FOO_H = 1
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
type C.int16_t = int16
type C.int32_t = int32
type C.int64_t = int64
type C.int8_t = int8
type C.uint16_t = uint16
type C.uint32_t = uint32
type C.uint64_t = uint64
type C.uint8_t = uint8
type C.uintptr_t = uintptr
type C.char uint8
type C.int int32
type C.long int32
type C.longlong int64
type C.schar int8
type C.short int16
type C.uchar uint8
type C.uint uint32
type C.ulong uint32
type C.ulonglong uint64
type C.ushort uint16
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
const _Cgo_BAR = 3
const _Cgo_FOO_H = 1
+30
View File
@@ -0,0 +1,30 @@
package main
/*
// Function signatures.
int foo(int a, int b);
void variadic0();
void variadic2(int x, int y, ...);
static void staticfunc(int x);
// Global variable signatures.
extern int someValue;
void notEscapingFunction(int *a);
#cgo noescape notEscapingFunction
*/
import "C"
// Test function signatures.
func accessFunctions() {
C.foo(3, 4)
C.variadic0()
C.variadic2(3, 5)
C.staticfunc(3)
C.notEscapingFunction(nil)
}
func accessGlobals() {
_ = C.someValue
}
+84
View File
@@ -0,0 +1,84 @@
package main
import "syscall"
import "unsafe"
var _ unsafe.Pointer
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
type (
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
//export foo
func _Cgo_foo(a _Cgo_int, b _Cgo_int) _Cgo_int
var _Cgo_foo$funcaddr unsafe.Pointer
//export variadic0
//go:variadic
func _Cgo_variadic0()
var _Cgo_variadic0$funcaddr unsafe.Pointer
//export variadic2
//go:variadic
func _Cgo_variadic2(x _Cgo_int, y _Cgo_int)
var _Cgo_variadic2$funcaddr unsafe.Pointer
//export _Cgo_static_173c95a79b6df1980521_staticfunc
func _Cgo_staticfunc!symbols.go(x _Cgo_int)
var _Cgo_staticfunc!symbols.go$funcaddr unsafe.Pointer
//export notEscapingFunction
//go:noescape
func _Cgo_notEscapingFunction(a *_Cgo_int)
var _Cgo_notEscapingFunction$funcaddr unsafe.Pointer
//go:extern someValue
var _Cgo_someValue _Cgo_int
+8 -10
View File
@@ -104,14 +104,18 @@ typedef struct {
unsigned char e : 3;
// Note that C++ allows bitfields bigger than the underlying type.
} bitfield_t;
// Function signatures.
void variadic0();
void variadic2(int x, int y, ...);
*/
import "C"
// // Test that we can refer from this CGo fragment to the fragment above.
// typedef myint myint2;
import "C"
var (
// aliases
_ C.float
_ C.double
// Simple typedefs.
_ C.myint
@@ -167,9 +171,3 @@ func accessUnion() {
var _ *C.int = union2d.unionfield_i()
var _ *[2]float64 = union2d.unionfield_d()
}
// Test function signatures.
func accessFunctions() {
C.variadic0()
C.variadic2(3, 5)
}
+140 -124
View File
@@ -1,150 +1,166 @@
package main
import "syscall"
import "unsafe"
var _ unsafe.Pointer
func C.variadic0() //go:variadic
func C.variadic2(x C.int, y C.int) //go:variadic
var C.variadic0$funcaddr unsafe.Pointer
var C.variadic2$funcaddr unsafe.Pointer
//go:linkname _Cgo_CString runtime.cgo_CString
func _Cgo_CString(string) *_Cgo_char
const C.option2A = 20
const C.optionA = 0
const C.optionB = 1
const C.optionC = -5
const C.optionD = -4
const C.optionE = 10
const C.optionF = 11
const C.optionG = 12
const C.unused1 = 5
//go:linkname _Cgo_GoString runtime.cgo_GoString
func _Cgo_GoString(*_Cgo_char) string
type C.int16_t = int16
type C.int32_t = int32
type C.int64_t = int64
type C.int8_t = int8
type C.uint16_t = uint16
type C.uint32_t = uint32
type C.uint64_t = uint64
type C.uint8_t = uint8
type C.uintptr_t = uintptr
type C.char uint8
type C.int int32
type C.long int32
type C.longlong int64
type C.schar int8
type C.short int16
type C.uchar uint8
type C.uint uint32
type C.ulong uint32
type C.ulonglong uint64
type C.ushort uint16
type C.bitfield_t = C.struct_4
type C.myIntArray = [10]C.int
type C.myint = C.int
type C.option2_t = C.uint
type C.option_t = C.enum_option
type C.point2d_t = struct {
x C.int
y C.int
}
type C.point3d_t = C.struct_point3d
type C.struct_nested_t = struct {
begin C.point2d_t
end C.point2d_t
tag C.int
//go:linkname _Cgo___GoStringN runtime.cgo_GoStringN
func _Cgo___GoStringN(*_Cgo_char, uintptr) string
coord C.union_2
func _Cgo_GoStringN(cstr *_Cgo_char, length _Cgo_int) string {
return _Cgo___GoStringN(cstr, uintptr(length))
}
type C.types_t = struct {
f float32
d float64
ptr *C.int
}
type C.union1_t = struct{ i C.int }
type C.union2d_t = C.union_union2d
type C.union3_t = C.union_1
type C.union_nested_t = C.union_3
type C.unionarray_t = struct{ arr [10]C.uchar }
func (s *C.struct_4) bitfield_a() C.uchar {
return s.__bitfield_1 & 0x1f
}
func (s *C.struct_4) set_bitfield_a(value C.uchar) {
s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0
}
func (s *C.struct_4) bitfield_b() C.uchar {
return s.__bitfield_1 >> 5 & 0x1
}
func (s *C.struct_4) set_bitfield_b(value C.uchar) {
s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5
}
func (s *C.struct_4) bitfield_c() C.uchar {
return s.__bitfield_1 >> 6
}
func (s *C.struct_4) set_bitfield_c(value C.uchar,
//go:linkname _Cgo___GoBytes runtime.cgo_GoBytes
func _Cgo___GoBytes(unsafe.Pointer, uintptr) []byte
) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 }
func _Cgo_GoBytes(ptr unsafe.Pointer, length _Cgo_int) []byte {
return _Cgo___GoBytes(ptr, uintptr(length))
}
type C.struct_4 struct {
start C.uchar
__bitfield_1 C.uchar
//go:linkname _Cgo___CBytes runtime.cgo_CBytes
func _Cgo___CBytes([]byte) unsafe.Pointer
d C.uchar
e C.uchar
func _Cgo_CBytes(b []byte) unsafe.Pointer {
return _Cgo___CBytes(b)
}
type C.struct_point3d struct {
x C.int
y C.int
z C.int
}
type C.struct_type1 struct {
_type C.int
__type C.int
___type C.int
}
type C.struct_type2 struct{ _type C.int }
func (union *C.union_1) unionfield_i() *C.int {
return (*C.int)(unsafe.Pointer(&union.$union))
//go:linkname _Cgo___get_errno_num runtime.cgo_errno
func _Cgo___get_errno_num() uintptr
func _Cgo___get_errno() error {
return syscall.Errno(_Cgo___get_errno_num())
}
func (union *C.union_1) unionfield_d() *float64 {
type (
_Cgo_char uint8
_Cgo_schar int8
_Cgo_uchar uint8
_Cgo_short int16
_Cgo_ushort uint16
_Cgo_int int32
_Cgo_uint uint32
_Cgo_long int32
_Cgo_ulong uint32
_Cgo_longlong int64
_Cgo_ulonglong uint64
)
type _Cgo_myint = _Cgo_int
type _Cgo_struct_point2d_t struct {
x _Cgo_int
y _Cgo_int
}
type _Cgo_point2d_t = _Cgo_struct_point2d_t
type _Cgo_struct_point3d struct {
x _Cgo_int
y _Cgo_int
z _Cgo_int
}
type _Cgo_point3d_t = _Cgo_struct_point3d
type _Cgo_struct_type1 struct {
_type _Cgo_int
__type _Cgo_int
___type _Cgo_int
}
type _Cgo_struct_type2 struct{ _type _Cgo_int }
type _Cgo_union_union1_t struct{ i _Cgo_int }
type _Cgo_union1_t = _Cgo_union_union1_t
type _Cgo_union_union3_t struct{ $union uint64 }
func (union *_Cgo_union_union3_t) unionfield_i() *_Cgo_int {
return (*_Cgo_int)(unsafe.Pointer(&union.$union))
}
func (union *_Cgo_union_union3_t) unionfield_d() *float64 {
return (*float64)(unsafe.Pointer(&union.$union))
}
func (union *C.union_1) unionfield_s() *C.short {
return (*C.short)(unsafe.Pointer(&union.$union))
func (union *_Cgo_union_union3_t) unionfield_s() *_Cgo_short {
return (*_Cgo_short)(unsafe.Pointer(&union.$union))
}
type C.union_1 struct{ $union uint64 }
type _Cgo_union3_t = _Cgo_union_union3_t
type _Cgo_union_union2d struct{ $union [2]uint64 }
func (union *C.union_2) unionfield_area() *C.point2d_t {
return (*C.point2d_t)(unsafe.Pointer(&union.$union))
func (union *_Cgo_union_union2d) unionfield_i() *_Cgo_int {
return (*_Cgo_int)(unsafe.Pointer(&union.$union))
}
func (union *C.union_2) unionfield_solid() *C.point3d_t {
return (*C.point3d_t)(unsafe.Pointer(&union.$union))
}
type C.union_2 struct{ $union [3]uint32 }
func (union *C.union_3) unionfield_point() *C.point3d_t {
return (*C.point3d_t)(unsafe.Pointer(&union.$union))
}
func (union *C.union_3) unionfield_array() *C.unionarray_t {
return (*C.unionarray_t)(unsafe.Pointer(&union.$union))
}
func (union *C.union_3) unionfield_thing() *C.union3_t {
return (*C.union3_t)(unsafe.Pointer(&union.$union))
}
type C.union_3 struct{ $union [2]uint64 }
func (union *C.union_union2d) unionfield_i() *C.int {
return (*C.int)(unsafe.Pointer(&union.$union))
}
func (union *C.union_union2d) unionfield_d() *[2]float64 {
func (union *_Cgo_union_union2d) unionfield_d() *[2]float64 {
return (*[2]float64)(unsafe.Pointer(&union.$union))
}
type C.union_union2d struct{ $union [2]uint64 }
type C.enum_option C.int
type C.enum_unused C.uint
type _Cgo_union2d_t = _Cgo_union_union2d
type _Cgo_union_unionarray_t struct{ arr [10]_Cgo_uchar }
type _Cgo_unionarray_t = _Cgo_union_unionarray_t
type _Cgo__Ctype_union___0 struct{ $union [3]uint32 }
func (union *_Cgo__Ctype_union___0) unionfield_area() *_Cgo_point2d_t {
return (*_Cgo_point2d_t)(unsafe.Pointer(&union.$union))
}
func (union *_Cgo__Ctype_union___0) unionfield_solid() *_Cgo_point3d_t {
return (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union))
}
type _Cgo_struct_struct_nested_t struct {
begin _Cgo_point2d_t
end _Cgo_point2d_t
tag _Cgo_int
coord _Cgo__Ctype_union___0
}
type _Cgo_struct_nested_t = _Cgo_struct_struct_nested_t
type _Cgo_union_union_nested_t struct{ $union [2]uint64 }
func (union *_Cgo_union_union_nested_t) unionfield_point() *_Cgo_point3d_t {
return (*_Cgo_point3d_t)(unsafe.Pointer(&union.$union))
}
func (union *_Cgo_union_union_nested_t) unionfield_array() *_Cgo_unionarray_t {
return (*_Cgo_unionarray_t)(unsafe.Pointer(&union.$union))
}
func (union *_Cgo_union_union_nested_t) unionfield_thing() *_Cgo_union3_t {
return (*_Cgo_union3_t)(unsafe.Pointer(&union.$union))
}
type _Cgo_union_nested_t = _Cgo_union_union_nested_t
type _Cgo_enum_option = _Cgo_int
type _Cgo_option_t = _Cgo_enum_option
type _Cgo_enum_option2_t = _Cgo_uint
type _Cgo_option2_t = _Cgo_enum_option2_t
type _Cgo_struct_types_t struct {
f float32
d float64
ptr *_Cgo_int
}
type _Cgo_types_t = _Cgo_struct_types_t
type _Cgo_myIntArray = [10]_Cgo_int
type _Cgo_struct_bitfield_t struct {
start _Cgo_uchar
__bitfield_1 _Cgo_uchar
d _Cgo_uchar
e _Cgo_uchar
}
func (s *_Cgo_struct_bitfield_t) bitfield_a() _Cgo_uchar { return s.__bitfield_1 & 0x1f }
func (s *_Cgo_struct_bitfield_t) set_bitfield_a(value _Cgo_uchar) {
s.__bitfield_1 = s.__bitfield_1&^0x1f | value&0x1f<<0
}
func (s *_Cgo_struct_bitfield_t) bitfield_b() _Cgo_uchar {
return s.__bitfield_1 >> 5 & 0x1
}
func (s *_Cgo_struct_bitfield_t) set_bitfield_b(value _Cgo_uchar) {
s.__bitfield_1 = s.__bitfield_1&^0x20 | value&0x1<<5
}
func (s *_Cgo_struct_bitfield_t) bitfield_c() _Cgo_uchar {
return s.__bitfield_1 >> 6
}
func (s *_Cgo_struct_bitfield_t) set_bitfield_c(value _Cgo_uchar,
) { s.__bitfield_1 = s.__bitfield_1&0x3f | value<<6 }
type _Cgo_bitfield_t = _Cgo_struct_bitfield_t
+357 -75
View File
@@ -5,10 +5,12 @@ package compileopts
import (
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/google/shlex"
"github.com/tinygo-org/tinygo/goenv"
)
@@ -17,11 +19,10 @@ type Config struct {
Options *Options
Target *TargetSpec
GoMinorVersion int
ClangHeaders string // Clang built-in header include path
TestConfig TestConfig
}
// Triple returns the LLVM target triple, like armv6m-none-eabi.
// Triple returns the LLVM target triple, like armv6m-unknown-unknown-eabi.
func (c *Config) Triple() string {
return c.Target.Triple
}
@@ -32,11 +33,34 @@ func (c *Config) CPU() string {
return c.Target.CPU
}
// The current build mode (like the `-buildmode` command line flag).
func (c *Config) BuildMode() string {
if c.Options.BuildMode != "" {
return c.Options.BuildMode
}
if c.Target.BuildMode != "" {
return c.Target.BuildMode
}
return "default"
}
// Features returns a list of features this CPU supports. For example, for a
// RISC-V processor, that could be ["+a", "+c", "+m"]. For many targets, an
// empty list will be returned.
func (c *Config) Features() []string {
return c.Target.Features
// RISC-V processor, that could be "+a,+c,+m". For many targets, an empty list
// will be returned.
func (c *Config) Features() string {
if c.Target.Features == "" {
return c.Options.LLVMFeatures
}
if c.Options.LLVMFeatures == "" {
return c.Target.Features
}
return c.Target.Features + "," + c.Options.LLVMFeatures
}
// ABI returns the -mabi= flag for this target (like -mabi=lp64). A zero-length
// string is returned if the target doesn't specify an ABI.
func (c *Config) ABI() string {
return c.Target.ABI
}
// GOOS returns the GOOS of the target. This might not always be the actual OS:
@@ -47,32 +71,43 @@ func (c *Config) GOOS() string {
}
// GOARCH returns the GOARCH of the target. This might not always be the actual
// archtecture: for example, the AVR target is not supported by the Go standard
// architecture: for example, the AVR target is not supported by the Go standard
// library so such targets will usually pretend to be linux/arm.
func (c *Config) GOARCH() string {
return c.Target.GOARCH
}
// GOARM will return the GOARM environment variable given to the compiler when
// building a program.
func (c *Config) GOARM() string {
return c.Options.GOARM
}
// GOMIPS will return the GOMIPS environment variable given to the compiler when
// building a program.
func (c *Config) GOMIPS() string {
return c.Options.GOMIPS
}
// BuildTags returns the complete list of build tags used during this build.
func (c *Config) BuildTags() []string {
tags := append(c.Target.BuildTags, []string{"tinygo", "gc." + c.GC(), "scheduler." + c.Scheduler()}...)
tags := append([]string(nil), c.Target.BuildTags...) // copy slice (avoid a race)
tags = append(tags, []string{
"tinygo", // that's the compiler
"purego", // to get various crypto packages to work
"osusergo", // to get os/user to work
"math_big_pure_go", // to get math/big to work
"gc." + c.GC(), "scheduler." + c.Scheduler(), // used inside the runtime package
"serial." + c.Serial()}...) // used inside the machine package
for i := 1; i <= c.GoMinorVersion; i++ {
tags = append(tags, fmt.Sprintf("go1.%d", i))
}
if extraTags := strings.Fields(c.Options.Tags); len(extraTags) != 0 {
tags = append(tags, extraTags...)
}
tags = append(tags, c.Options.Tags...)
return tags
}
// CgoEnabled returns true if (and only if) CGo is enabled. It is true by
// default and false if CGO_ENABLED is set to "0".
func (c *Config) CgoEnabled() bool {
return goenv.Get("CGO_ENABLED") == "1"
}
// GC returns the garbage collection strategy in use on this platform. Valid
// values are "none", "leaking", "extalloc", and "conservative".
// values are "none", "leaking", "conservative" and "precise".
func (c *Config) GC() string {
if c.Options.GC != "" {
return c.Options.GC
@@ -80,21 +115,16 @@ func (c *Config) GC() string {
if c.Target.GC != "" {
return c.Target.GC
}
for _, tag := range c.Target.BuildTags {
if tag == "baremetal" || tag == "wasm" {
return "conservative"
}
}
return "extalloc"
return "conservative"
}
// NeedsStackObjects returns true if the compiler should insert stack objects
// that can be traced by the garbage collector.
func (c *Config) NeedsStackObjects() bool {
switch c.GC() {
case "conservative", "extalloc":
case "conservative", "custom", "precise":
for _, tag := range c.BuildTags() {
if tag == "wasm" {
if tag == "tinygo.wasm" {
return true
}
}
@@ -106,7 +136,7 @@ func (c *Config) NeedsStackObjects() bool {
}
// Scheduler returns the scheduler implementation. Valid values are "none",
//"coroutines" and "tasks".
// "asyncify" and "tasks".
func (c *Config) Scheduler() string {
if c.Options.Scheduler != "" {
return c.Options.Scheduler
@@ -114,32 +144,40 @@ func (c *Config) Scheduler() string {
if c.Target.Scheduler != "" {
return c.Target.Scheduler
}
// Fall back to coroutines, which are supported everywhere.
return "coroutines"
// Fall back to none.
return "none"
}
// FuncImplementation picks an appropriate func value implementation for the
// target.
func (c *Config) FuncImplementation() string {
switch c.Scheduler() {
case "tasks":
// A func value is implemented as a pair of pointers:
// {context, function pointer}
// where the context may be a pointer to a heap-allocated struct
// containing the free variables, or it may be undef if the function
// being pointed to doesn't need a context. The function pointer is a
// regular function pointer.
return "doubleword"
case "none", "coroutines":
// As "doubleword", but with the function pointer replaced by a unique
// ID per function signature. Function values are called by using a
// switch statement and choosing which function to call.
// Pick the switch implementation with the coroutines scheduler, as it
// allows the use of blocking inside a function that is used as a func
// value.
return "switch"
// Serial returns the serial implementation for this build configuration: uart,
// usb (meaning USB-CDC), or none.
func (c *Config) Serial() string {
if c.Options.Serial != "" {
return c.Options.Serial
}
if c.Target.Serial != "" {
return c.Target.Serial
}
return "none"
}
// OptLevels returns the optimization level (0-2), size level (0-2), and inliner
// threshold as used in the LLVM optimization pipeline.
func (c *Config) OptLevel() (level string, speedLevel, sizeLevel int) {
switch c.Options.Opt {
case "none", "0":
return "O0", 0, 0
case "1":
return "O1", 1, 0
case "2":
return "O2", 2, 0
case "s":
return "Os", 2, 1
case "z":
return "Oz", 2, 2 // default
default:
panic("unknown scheduler type")
// This is not shown to the user: valid choices are already checked as
// part of Options.Verify(). It is here as a sanity check.
panic("unknown optimization level: -opt=" + c.Options.Opt)
}
}
@@ -160,20 +198,198 @@ func (c *Config) AutomaticStackSize() bool {
return false
}
// StackSize returns the default stack size to be used for goroutines, if the
// stack size could not be determined automatically at compile time.
func (c *Config) StackSize() uint64 {
if c.Options.StackSize != 0 {
return c.Options.StackSize
}
return c.Target.DefaultStackSize
}
// MaxStackAlloc returns the size of the maximum allocation to put on the stack vs heap.
func (c *Config) MaxStackAlloc() uint64 {
if c.StackSize() > 32*1024 {
return 1024
}
return 256
}
// RP2040BootPatch returns whether the RP2040 boot patch should be applied that
// calculates and patches in the checksum for the 2nd stage bootloader.
func (c *Config) RP2040BootPatch() bool {
if c.Target.RP2040BootPatch != nil {
return *c.Target.RP2040BootPatch
}
return false
}
// Return a canonicalized architecture name, so we don't have to deal with arm*
// vs thumb* vs arm64.
func CanonicalArchName(triple string) string {
arch := strings.Split(triple, "-")[0]
if arch == "arm64" {
return "aarch64"
}
if strings.HasPrefix(arch, "arm") || strings.HasPrefix(arch, "thumb") {
return "arm"
}
if arch == "mipsel" {
return "mips"
}
return arch
}
// MuslArchitecture returns the architecture name as used in musl libc. It is
// usually the same as the first part of the LLVM triple, but not always.
func MuslArchitecture(triple string) string {
return CanonicalArchName(triple)
}
// LibcPath returns the path to the libc directory. The libc path will be either
// a precompiled libc shipped with a TinyGo build, or a libc path in the cache
// directory (which might not yet be built).
func (c *Config) LibcPath(name string) (path string, precompiled bool) {
archname := c.Triple()
if c.CPU() != "" {
archname += "-" + c.CPU()
}
if c.ABI() != "" {
archname += "-" + c.ABI()
}
if c.Target.SoftFloat {
archname += "-softfloat"
}
// Try to load a precompiled library.
precompiledDir := filepath.Join(goenv.Get("TINYGOROOT"), "pkg", archname, name)
if _, err := os.Stat(precompiledDir); err == nil {
// Found a precompiled library for this OS/architecture. Return the path
// directly.
return precompiledDir, true
}
// No precompiled library found. Determine the path name that will be used
// in the build cache.
return filepath.Join(goenv.Get("GOCACHE"), name+"-"+archname), false
}
// DefaultBinaryExtension returns the default extension for binaries, such as
// .exe, .wasm, or no extension (depending on the target).
func (c *Config) DefaultBinaryExtension() string {
parts := strings.Split(c.Triple(), "-")
if parts[0] == "wasm32" {
// WebAssembly files always have the .wasm file extension.
return ".wasm"
}
if len(parts) >= 3 && parts[2] == "windows" {
// Windows uses .exe.
return ".exe"
}
if len(parts) >= 3 && parts[2] == "unknown" {
// There appears to be a convention to use the .elf file extension for
// ELF files intended for microcontrollers. I'm not aware of the origin
// of this, it's just something that is used by many projects.
// I think it's a good tradition, so let's keep it.
return ".elf"
}
// Linux, MacOS, etc, don't use a file extension. Use it as a fallback.
return ""
}
// CFlags returns the flags to pass to the C compiler. This is necessary for CGo
// preprocessing.
func (c *Config) CFlags() []string {
cflags := append([]string{}, c.Options.CFlags...)
func (c *Config) CFlags(libclang bool) []string {
var cflags []string
for _, flag := range c.Target.CFlags {
cflags = append(cflags, strings.ReplaceAll(flag, "{root}", goenv.Get("TINYGOROOT")))
}
if c.Target.Libc == "picolibc" {
root := goenv.Get("TINYGOROOT")
cflags = append(cflags, "-nostdlibinc", "-Xclang", "-internal-isystem", "-Xclang", filepath.Join(root, "lib", "picolibc", "newlib", "libc", "include"))
cflags = append(cflags, "-I"+filepath.Join(root, "lib/picolibc-include"))
resourceDir := goenv.ClangResourceDir(libclang)
if resourceDir != "" {
// The resource directory contains the built-in clang headers like
// stdbool.h, stdint.h, float.h, etc.
// It is left empty if we're using an external compiler (that already
// knows these headers).
cflags = append(cflags,
"-resource-dir="+resourceDir,
)
}
if c.Debug() {
cflags = append(cflags, "-g")
switch c.Target.Libc {
case "darwin-libSystem":
root := goenv.Get("TINYGOROOT")
cflags = append(cflags,
"-nostdlibinc",
"-isystem", filepath.Join(root, "lib/macos-minimal-sdk/src/usr/include"),
)
case "picolibc":
root := goenv.Get("TINYGOROOT")
picolibcDir := filepath.Join(root, "lib", "picolibc", "newlib", "libc")
path, _ := c.LibcPath("picolibc")
cflags = append(cflags,
"-nostdlibinc",
"-isystem", filepath.Join(path, "include"),
"-isystem", filepath.Join(picolibcDir, "include"),
"-isystem", filepath.Join(picolibcDir, "tinystdio"),
"-D__PICOLIBC_ERRNO_FUNCTION=__errno_location",
)
case "musl":
root := goenv.Get("TINYGOROOT")
path, _ := c.LibcPath("musl")
arch := MuslArchitecture(c.Triple())
cflags = append(cflags,
"-nostdlibinc",
"-isystem", filepath.Join(path, "include"),
"-isystem", filepath.Join(root, "lib", "musl", "arch", arch),
"-isystem", filepath.Join(root, "lib", "musl", "arch", "generic"),
"-isystem", filepath.Join(root, "lib", "musl", "include"),
)
case "wasi-libc":
root := goenv.Get("TINYGOROOT")
cflags = append(cflags,
"-nostdlibinc",
"-isystem", root+"/lib/wasi-libc/sysroot/include")
case "wasmbuiltins":
// nothing to add (library is purely for builtins)
case "mingw-w64":
root := goenv.Get("TINYGOROOT")
path, _ := c.LibcPath("mingw-w64")
cflags = append(cflags,
"-nostdlibinc",
"-isystem", filepath.Join(path, "include"),
"-isystem", filepath.Join(root, "lib", "mingw-w64", "mingw-w64-headers", "crt"),
"-isystem", filepath.Join(root, "lib", "mingw-w64", "mingw-w64-headers", "defaults", "include"),
"-D_UCRT",
)
case "":
// No libc specified, nothing to add.
default:
// Incorrect configuration. This could be handled in a better way, but
// usually this will be found by developers (not by TinyGo users).
panic("unknown libc: " + c.Target.Libc)
}
// Always emit debug information. It is optionally stripped at link time.
cflags = append(cflags, "-gdwarf-4")
// Use the same optimization level as TinyGo.
cflags = append(cflags, "-O"+c.Options.Opt)
// Set the LLVM target triple.
cflags = append(cflags, "--target="+c.Triple())
// Set the -mcpu (or similar) flag.
if c.Target.CPU != "" {
if c.GOARCH() == "amd64" || c.GOARCH() == "386" {
// x86 prefers the -march flag (-mcpu is deprecated there).
cflags = append(cflags, "-march="+c.Target.CPU)
} else if strings.HasPrefix(c.Triple(), "avr") {
// AVR MCUs use -mmcu instead of -mcpu.
cflags = append(cflags, "-mmcu="+c.Target.CPU)
} else {
// The rest just uses -mcpu.
cflags = append(cflags, "-mcpu="+c.Target.CPU)
}
}
// Set the -mabi flag, if needed.
if c.ABI() != "" {
cflags = append(cflags, "-mabi="+c.ABI())
}
return cflags
}
@@ -184,7 +400,7 @@ func (c *Config) CFlags() []string {
func (c *Config) LDFlags() []string {
root := goenv.Get("TINYGOROOT")
// Merge and adjust LDFlags.
ldflags := append([]string{}, c.Options.LDFlags...)
var ldflags []string
for _, flag := range c.Target.LDFlags {
ldflags = append(ldflags, strings.ReplaceAll(flag, "{root}", root))
}
@@ -192,6 +408,8 @@ func (c *Config) LDFlags() []string {
if c.Target.LinkerScript != "" {
ldflags = append(ldflags, "-T", c.Target.LinkerScript)
}
ldflags = append(ldflags, c.Options.ExtLDFlags...)
return ldflags
}
@@ -213,8 +431,9 @@ func (c *Config) VerifyIR() bool {
return c.Options.VerifyIR
}
// Debug returns whether to add debug symbols to the IR, for debugging with GDB
// and similar.
// Debug returns whether debug (DWARF) information should be retained by the
// linker. By default, debug information is retained, but it can be removed
// with the -no-debug flag.
func (c *Config) Debug() bool {
return c.Options.Debug
}
@@ -229,6 +448,13 @@ func (c *Config) BinaryFormat(ext string) string {
return c.Target.BinaryFormat
}
return "bin"
case ".img":
// Image file. Only defined for the ESP32 at the moment, where it is a
// full (runnable) image that can be used in the Espressif QEMU fork.
if c.Target.BinaryFormat != "" {
return c.Target.BinaryFormat + "-img"
}
return "bin"
case ".hex":
// Similar to bin, but includes the start address and is thus usually a
// better format.
@@ -238,6 +464,11 @@ func (c *Config) BinaryFormat(ext string) string {
// More information:
// https://github.com/Microsoft/uf2
return "uf2"
case ".zip":
if c.Target.BinaryFormat != "" {
return c.Target.BinaryFormat
}
return "zip"
default:
// Use the ELF format for unrecognized file formats.
return "elf"
@@ -246,7 +477,7 @@ func (c *Config) BinaryFormat(ext string) string {
// Programmer returns the flash method and OpenOCD interface name given a
// particular configuration. It may either be all configured in the target JSON
// file or be modified using the -programmmer command-line option.
// file or be modified using the -programmer command-line option.
func (c *Config) Programmer() (method, openocdInterface string) {
switch c.Options.Programmer {
case "":
@@ -255,6 +486,9 @@ func (c *Config) Programmer() (method, openocdInterface string) {
case "openocd", "msd", "command":
// The -programmer flag only specifies the flash method.
return c.Options.Programmer, c.Target.OpenOCDInterface
case "bmp":
// The -programmer flag only specifies the flash method.
return c.Options.Programmer, ""
default:
// The -programmer flag specifies something else, assume it specifies
// the OpenOCD interface name.
@@ -270,26 +504,33 @@ func (c *Config) OpenOCDConfiguration() (args []string, err error) {
if openocdInterface == "" {
return nil, errors.New("OpenOCD programmer not set")
}
if !regexp.MustCompile("^[\\p{L}0-9_-]+$").MatchString(openocdInterface) {
if !regexp.MustCompile(`^[\p{L}0-9_-]+$`).MatchString(openocdInterface) {
return nil, fmt.Errorf("OpenOCD programmer has an invalid name: %#v", openocdInterface)
}
if c.Target.OpenOCDTarget == "" {
return nil, errors.New("OpenOCD chip not set")
}
if !regexp.MustCompile("^[\\p{L}0-9_-]+$").MatchString(c.Target.OpenOCDTarget) {
if !regexp.MustCompile(`^[\p{L}0-9_-]+$`).MatchString(c.Target.OpenOCDTarget) {
return nil, fmt.Errorf("OpenOCD target has an invalid name: %#v", c.Target.OpenOCDTarget)
}
if c.Target.OpenOCDTransport != "" && c.Target.OpenOCDTransport != "swd" {
return nil, fmt.Errorf("unknown OpenOCD transport: %#v", c.Target.OpenOCDTransport)
}
args = []string{"-f", "interface/" + openocdInterface + ".cfg"}
if c.Target.OpenOCDTransport != "" {
transport := c.Target.OpenOCDTransport
if transport == "swd" {
switch openocdInterface {
case "stlink-dap":
transport = "dapdirect_swd"
}
}
args = append(args, "-c", "transport select "+transport)
}
args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
for _, cmd := range c.Target.OpenOCDCommands {
args = append(args, "-c", cmd)
}
if c.Target.OpenOCDTransport != "" {
args = append(args, "-c", "transport select "+c.Target.OpenOCDTransport)
}
args = append(args, "-f", "target/"+c.Target.OpenOCDTarget+".cfg")
return args, nil
}
@@ -312,16 +553,57 @@ func (c *Config) RelocationModel() string {
return "static"
}
// WasmAbi returns the WASM ABI which is specified in the target JSON file, and
// the value is overridden by `-wasm-abi` flag if it is provided
func (c *Config) WasmAbi() string {
if c.Options.WasmAbi != "" {
return c.Options.WasmAbi
// EmulatorName is a shorthand to get the command for this emulator, something
// like qemu-system-arm or simavr.
func (c *Config) EmulatorName() string {
parts := strings.SplitN(c.Target.Emulator, " ", 2)
if len(parts) > 1 {
return parts[0]
}
return c.Target.WasmAbi
return ""
}
// EmulatorFormat returns the binary format for the emulator and the associated
// file extension. An empty string means to pass directly whatever the linker
// produces directly without conversion (usually ELF format).
func (c *Config) EmulatorFormat() (format, fileExt string) {
switch {
case strings.Contains(c.Target.Emulator, "{img}"):
return "img", ".img"
default:
return "", ""
}
}
// Emulator returns a ready-to-run command to run the given binary in an
// emulator. Give it the format (returned by EmulatorFormat()) and the path to
// the compiled binary.
func (c *Config) Emulator(format, binary string) ([]string, error) {
parts, err := shlex.Split(c.Target.Emulator)
if err != nil {
return nil, fmt.Errorf("could not parse emulator command: %w", err)
}
var emulator []string
for _, s := range parts {
s = strings.ReplaceAll(s, "{root}", goenv.Get("TINYGOROOT"))
// Allow replacement of what's usually /tmp except notably Windows.
s = strings.ReplaceAll(s, "{tmpDir}", os.TempDir())
s = strings.ReplaceAll(s, "{"+format+"}", binary)
emulator = append(emulator, s)
}
return emulator, nil
}
type TestConfig struct {
CompileTestBinary bool
// TODO: Filter the test functions to run, include verbose flag, etc
CompileOnly bool
Verbose bool
Short bool
RunRegexp string
SkipRegexp string
Count *int
BenchRegexp string
BenchTime string
BenchMem bool
Shuffle string
}
+71 -22
View File
@@ -2,41 +2,75 @@ package compileopts
import (
"fmt"
"regexp"
"strings"
"time"
)
var (
validGCOptions = []string{"none", "leaking", "extalloc", "conservative"}
validSchedulerOptions = []string{"none", "tasks", "coroutines"}
validPrintSizeOptions = []string{"none", "short", "full"}
validBuildModeOptions = []string{"default", "c-shared", "wasi-legacy"}
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
validSerialOptions = []string{"none", "uart", "usb", "rtt"}
validPrintSizeOptions = []string{"none", "short", "full", "html"}
validPanicStrategyOptions = []string{"print", "trap"}
validOptOptions = []string{"none", "0", "1", "2", "s", "z"}
)
// Options contains extra options to give to the compiler. These options are
// usually passed from the command line.
// usually passed from the command line, but can also be passed in environment
// variables for example.
type Options struct {
Target string
Opt string
GC string
PanicStrategy string
Scheduler string
PrintIR bool
DumpSSA bool
VerifyIR bool
PrintCommands bool
Debug bool
PrintSizes string
PrintStacks bool
CFlags []string
LDFlags []string
Tags string
WasmAbi string
TestConfig TestConfig
Programmer string
GOOS string // environment variable
GOARCH string // environment variable
GOARM string // environment variable (only used with GOARCH=arm)
GOMIPS string // environment variable (only used with GOARCH=mips and GOARCH=mipsle)
Directory string // working dir, leave it unset to use the current working dir
Target string
BuildMode string // -buildmode flag
Opt string
GC string
PanicStrategy string
Scheduler string
StackSize uint64 // goroutine stack size (if none could be automatically determined)
Serial string
Work bool // -work flag to print temporary build directory
InterpTimeout time.Duration
PrintIR bool
DumpSSA bool
VerifyIR bool
SkipDWARF bool
PrintCommands func(cmd string, args ...string) `json:"-"`
Semaphore chan struct{} `json:"-"` // -p flag controls cap
Debug bool
PrintSizes string
PrintAllocs *regexp.Regexp // regexp string
PrintStacks bool
Tags []string
GlobalValues map[string]map[string]string // map[pkgpath]map[varname]value
TestConfig TestConfig
Programmer string
OpenOCDCommands []string
LLVMFeatures string
PrintJSON bool
Monitor bool
BaudRate int
Timeout time.Duration
WITPackage string // pass through to wasm-tools component embed invocation
WITWorld string // pass through to wasm-tools component embed -w option
ExtLDFlags []string
}
// Verify performs a validation on the given options, raising an error if options are not valid.
func (o *Options) Verify() error {
if o.BuildMode != "" {
valid := isInArray(validBuildModeOptions, o.BuildMode)
if !valid {
return fmt.Errorf(`invalid buildmode option '%s': valid values are %s`,
o.BuildMode,
strings.Join(validBuildModeOptions, ", "))
}
}
if o.GC != "" {
valid := isInArray(validGCOptions, o.GC)
if !valid {
@@ -55,6 +89,15 @@ func (o *Options) Verify() error {
}
}
if o.Serial != "" {
valid := isInArray(validSerialOptions, o.Serial)
if !valid {
return fmt.Errorf(`invalid serial option '%s': valid values are %s`,
o.Serial,
strings.Join(validSerialOptions, ", "))
}
}
if o.PrintSizes != "" {
valid := isInArray(validPrintSizeOptions, o.PrintSizes)
if !valid {
@@ -73,6 +116,12 @@ func (o *Options) Verify() error {
}
}
if o.Opt != "" {
if !isInArray(validOptOptions, o.Opt) {
return fmt.Errorf("invalid -opt=%s: valid values are %s", o.Opt, strings.Join(validOptOptions, ", "))
}
}
return nil
}
+9 -15
View File
@@ -9,9 +9,9 @@ import (
func TestVerifyOptions(t *testing.T) {
expectedGCError := errors.New(`invalid gc option 'incorrect': valid values are none, leaking, extalloc, conservative`)
expectedSchedulerError := errors.New(`invalid scheduler option 'incorrect': valid values are none, tasks, coroutines`)
expectedPrintSizeError := errors.New(`invalid size option 'incorrect': valid values are none, short, full`)
expectedGCError := errors.New(`invalid gc option 'incorrect': valid values are none, leaking, conservative, custom, precise`)
expectedSchedulerError := errors.New(`invalid scheduler option 'incorrect': valid values are none, tasks, asyncify`)
expectedPrintSizeError := errors.New(`invalid size option 'incorrect': valid values are none, short, full, html`)
expectedPanicStrategyError := errors.New(`invalid panic option 'incorrect': valid values are print, trap`)
testCases := []struct {
@@ -42,18 +42,18 @@ func TestVerifyOptions(t *testing.T) {
GC: "leaking",
},
},
{
name: "GCOptionExtalloc",
opts: compileopts.Options{
GC: "extalloc",
},
},
{
name: "GCOptionConservative",
opts: compileopts.Options{
GC: "conservative",
},
},
{
name: "GCOptionCustom",
opts: compileopts.Options{
GC: "custom",
},
},
{
name: "InvalidSchedulerOption",
opts: compileopts.Options{
@@ -73,12 +73,6 @@ func TestVerifyOptions(t *testing.T) {
Scheduler: "tasks",
},
},
{
name: "SchedulerOptionCoroutines",
opts: compileopts.Options{
Scheduler: "coroutines",
},
},
{
name: "InvalidPrintSizeOption",
opts: compileopts.Options{
+400 -150
View File
@@ -5,8 +5,10 @@ package compileopts
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"reflect"
"runtime"
@@ -21,46 +23,54 @@ import (
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/struct.TargetOptions.html
// https://github.com/shepmaster/rust-arduino-blink-led-no-core-with-cargo/blob/master/blink/arduino.json
type TargetSpec struct {
Inherits []string `json:"inherits"`
Triple string `json:"llvm-target"`
CPU string `json:"cpu"`
Features []string `json:"features"`
GOOS string `json:"goos"`
GOARCH string `json:"goarch"`
BuildTags []string `json:"build-tags"`
GC string `json:"gc"`
Scheduler string `json:"scheduler"`
Compiler string `json:"compiler"`
Linker string `json:"linker"`
RTLib string `json:"rtlib"` // compiler runtime library (libgcc, compiler-rt)
Libc string `json:"libc"`
AutoStackSize *bool `json:"automatic-stack-size"` // Determine stack size automatically at compile time.
DefaultStackSize uint64 `json:"default-stack-size"` // Default stack size if the size couldn't be determined at compile time.
CFlags []string `json:"cflags"`
LDFlags []string `json:"ldflags"`
LinkerScript string `json:"linkerscript"`
ExtraFiles []string `json:"extra-files"`
Emulator []string `json:"emulator" override:"copy"` // inherited Emulator must not be append
FlashCommand string `json:"flash-command"`
GDB string `json:"gdb"`
PortReset string `json:"flash-1200-bps-reset"`
FlashMethod string `json:"flash-method"`
FlashVolume string `json:"msd-volume-name"`
FlashFilename string `json:"msd-firmware-name"`
UF2FamilyID string `json:"uf2-family-id"`
BinaryFormat string `json:"binary-format"`
OpenOCDInterface string `json:"openocd-interface"`
OpenOCDTarget string `json:"openocd-target"`
OpenOCDTransport string `json:"openocd-transport"`
OpenOCDCommands []string `json:"openocd-commands"`
JLinkDevice string `json:"jlink-device"`
CodeModel string `json:"code-model"`
RelocationModel string `json:"relocation-model"`
WasmAbi string `json:"wasm-abi"`
Inherits []string `json:"inherits,omitempty"`
Triple string `json:"llvm-target,omitempty"`
CPU string `json:"cpu,omitempty"`
ABI string `json:"target-abi,omitempty"` // roughly equivalent to -mabi= flag
Features string `json:"features,omitempty"`
GOOS string `json:"goos,omitempty"`
GOARCH string `json:"goarch,omitempty"`
SoftFloat bool // used for non-baremetal systems (GOMIPS=softfloat etc)
BuildTags []string `json:"build-tags,omitempty"`
BuildMode string `json:"buildmode,omitempty"` // default build mode (if nothing specified)
GC string `json:"gc,omitempty"`
Scheduler string `json:"scheduler,omitempty"`
Serial string `json:"serial,omitempty"` // which serial output to use (uart, usb, none)
Linker string `json:"linker,omitempty"`
RTLib string `json:"rtlib,omitempty"` // compiler runtime library (libgcc, compiler-rt)
Libc string `json:"libc,omitempty"`
AutoStackSize *bool `json:"automatic-stack-size,omitempty"` // Determine stack size automatically at compile time.
DefaultStackSize uint64 `json:"default-stack-size,omitempty"` // Default stack size if the size couldn't be determined at compile time.
CFlags []string `json:"cflags,omitempty"`
LDFlags []string `json:"ldflags,omitempty"`
LinkerScript string `json:"linkerscript,omitempty"`
ExtraFiles []string `json:"extra-files,omitempty"`
RP2040BootPatch *bool `json:"rp2040-boot-patch,omitempty"` // Patch RP2040 2nd stage bootloader checksum
BootPatches []string `json:"boot-patches,omitempty"` // Bootloader patches to be applied in the order they appear.
Emulator string `json:"emulator,omitempty"`
FlashCommand string `json:"flash-command,omitempty"`
GDB []string `json:"gdb,omitempty"`
PortReset string `json:"flash-1200-bps-reset,omitempty"`
SerialPort []string `json:"serial-port,omitempty"` // serial port IDs in the form "vid:pid"
FlashMethod string `json:"flash-method,omitempty"`
FlashVolume []string `json:"msd-volume-name,omitempty"`
FlashFilename string `json:"msd-firmware-name,omitempty"`
UF2FamilyID string `json:"uf2-family-id,omitempty"`
BinaryFormat string `json:"binary-format,omitempty"`
OpenOCDInterface string `json:"openocd-interface,omitempty"`
OpenOCDTarget string `json:"openocd-target,omitempty"`
OpenOCDTransport string `json:"openocd-transport,omitempty"`
OpenOCDCommands []string `json:"openocd-commands,omitempty"`
OpenOCDVerify *bool `json:"openocd-verify,omitempty"` // enable verify when flashing with openocd
JLinkDevice string `json:"jlink-device,omitempty"`
CodeModel string `json:"code-model,omitempty"`
RelocationModel string `json:"relocation-model,omitempty"`
WITPackage string `json:"wit-package,omitempty"`
WITWorld string `json:"wit-world,omitempty"`
}
// overrideProperties overrides all properties that are set in child into itself using reflection.
func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
func (spec *TargetSpec) overrideProperties(child *TargetSpec) error {
specType := reflect.TypeOf(spec).Elem()
specValue := reflect.ValueOf(spec).Elem()
childValue := reflect.ValueOf(child).Elem()
@@ -79,27 +89,30 @@ func (spec *TargetSpec) overrideProperties(child *TargetSpec) {
if src.Uint() != 0 {
dst.Set(src)
}
case reflect.Bool:
if src.Bool() {
dst.Set(src)
}
case reflect.Ptr: // for pointers, copy if not nil
if !src.IsNil() {
dst.Set(src)
}
case reflect.Slice: // for slices...
if src.Len() > 0 { // ... if not empty ...
switch tag := field.Tag.Get("override"); tag {
case "copy":
// copy the field of child to spec
dst.Set(src)
case "append", "":
// or append the field of child to spec
dst.Set(reflect.AppendSlice(src, dst))
default:
panic("override mode must be 'copy' or 'append' (default). I don't know how to '" + tag + "'.")
case reflect.Slice: // for slices, append the field and check for duplicates
dst.Set(reflect.AppendSlice(dst, src))
for i := 0; i < dst.Len(); i++ {
v := dst.Index(i).String()
for j := i + 1; j < dst.Len(); j++ {
w := dst.Index(j).String()
if v == w {
return fmt.Errorf("duplicate value '%s' in field %s", v, field.Name)
}
}
}
default:
panic("unknown field type : " + kind.String())
return fmt.Errorf("unknown field type: %s", kind)
}
}
return nil
}
// load reads a target specification from the JSON in the given io.Reader. It
@@ -114,10 +127,10 @@ func (spec *TargetSpec) load(r io.Reader) error {
}
// loadFromGivenStr loads the TargetSpec from the given string that could be:
// - targets/ directory inside the compiler sources
// - a relative or absolute path to custom (project specific) target specification .json file;
// the Inherits[] could contain the files from target folder (ex. stm32f4disco)
// as well as path to custom files (ex. myAwesomeProject.json)
// - targets/ directory inside the compiler sources
// - a relative or absolute path to custom (project specific) target specification .json file;
// the Inherits[] could contain the files from target folder (ex. stm32f4disco)
// as well as path to custom files (ex. myAwesomeProject.json)
func (spec *TargetSpec) loadFromGivenStr(str string) error {
path := ""
if strings.HasSuffix(str, ".json") {
@@ -147,127 +160,364 @@ func (spec *TargetSpec) resolveInherits() error {
if err != nil {
return err
}
newSpec.overrideProperties(subtarget)
err = newSpec.overrideProperties(subtarget)
if err != nil {
return err
}
}
// When all properties are loaded, make sure they are properly inherited.
newSpec.overrideProperties(spec)
err := newSpec.overrideProperties(spec)
if err != nil {
return err
}
*spec = *newSpec
return nil
}
// Load a target specification.
func LoadTarget(target string) (*TargetSpec, error) {
if target == "" {
// Configure based on GOOS/GOARCH environment variables (falling back to
// runtime.GOOS/runtime.GOARCH), and generate a LLVM target based on it.
goos := goenv.Get("GOOS")
goarch := goenv.Get("GOARCH")
llvmos := goos
llvmarch := map[string]string{
"386": "i386",
"amd64": "x86_64",
"arm64": "aarch64",
}[goarch]
if llvmarch == "" {
llvmarch = goarch
}
target = llvmarch + "--" + llvmos
if goarch == "arm" {
target += "-gnueabihf"
}
return defaultTarget(goos, goarch, target)
func LoadTarget(options *Options) (*TargetSpec, error) {
if options.Target == "" {
return defaultTarget(options)
}
// See whether there is a target specification for this target (e.g.
// Arduino).
spec := &TargetSpec{}
err := spec.loadFromGivenStr(target)
if err == nil {
// Successfully loaded this target from a built-in .json file. Make sure
// it includes all parents as specified in the "inherits" key.
err = spec.resolveInherits()
if err != nil {
return nil, err
}
return spec, nil
} else if !os.IsNotExist(err) {
// Expected a 'file not found' error, got something else. Report it as
// an error.
err := spec.loadFromGivenStr(options.Target)
if err != nil {
return nil, err
} else {
// Load target from given triple, ignore GOOS/GOARCH environment
// variables.
tripleSplit := strings.Split(target, "-")
if len(tripleSplit) < 3 {
return nil, errors.New("expected a full LLVM target or a custom target in -target flag")
}
if tripleSplit[0] == "arm" {
// LLVM and Clang have a different idea of what "arm" means, so
// upgrade to a slightly more modern ARM. In fact, when you pass
// --target=arm--linux-gnueabihf to Clang, it will convert that
// internally to armv7-unknown-linux-gnueabihf. Changing the
// architecture to armv7 will keep things consistent.
tripleSplit[0] = "armv7"
}
goos := tripleSplit[2]
if strings.HasPrefix(goos, "darwin") {
goos = "darwin"
}
goarch := map[string]string{ // map from LLVM arch to Go arch
"i386": "386",
"i686": "386",
"x86_64": "amd64",
"aarch64": "arm64",
"armv7": "arm",
}[tripleSplit[0]]
if goarch == "" {
goarch = tripleSplit[0]
}
return defaultTarget(goos, goarch, strings.Join(tripleSplit, "-"))
}
// Successfully loaded this target from a built-in .json file. Make sure
// it includes all parents as specified in the "inherits" key.
err = spec.resolveInherits()
if err != nil {
return nil, fmt.Errorf("%s : %w", options.Target, err)
}
if spec.Scheduler == "asyncify" {
spec.ExtraFiles = append(spec.ExtraFiles, "src/internal/task/task_asyncify_wasm.S")
}
return spec, nil
}
func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
// No target spec available. Use the default one, useful on most systems
// with a regular OS.
// GetTargetSpecs retrieves target specifications from the TINYGOROOT targets
// directory. Only valid target JSON files are considered, and the function
// returns a map of target names to their respective TargetSpec.
func GetTargetSpecs() (map[string]*TargetSpec, error) {
dir := filepath.Join(goenv.Get("TINYGOROOT"), "targets")
entries, err := os.ReadDir(dir)
if err != nil {
return nil, fmt.Errorf("could not list targets: %w", err)
}
maps := map[string]*TargetSpec{}
for _, entry := range entries {
entryInfo, err := entry.Info()
if err != nil {
return nil, fmt.Errorf("could not get entry info: %w", err)
}
if !entryInfo.Mode().IsRegular() || !strings.HasSuffix(entry.Name(), ".json") {
// Only inspect JSON files.
continue
}
path := filepath.Join(dir, entry.Name())
spec, err := LoadTarget(&Options{Target: path})
if err != nil {
return nil, fmt.Errorf("could not list target: %w", err)
}
if spec.FlashMethod == "" && spec.FlashCommand == "" && spec.Emulator == "" {
// This doesn't look like a regular target file, but rather like
// a parent target (such as targets/cortex-m.json).
continue
}
name := entry.Name()
name = name[:len(name)-5]
maps[name] = spec
}
return maps, nil
}
// Load a target from environment variables (which default to
// runtime.GOOS/runtime.GOARCH).
func defaultTarget(options *Options) (*TargetSpec, error) {
spec := TargetSpec{
Triple: triple,
GOOS: goos,
GOARCH: goarch,
BuildTags: []string{goos, goarch},
Compiler: "clang",
Linker: "cc",
CFlags: []string{"--target=" + triple},
GDB: "gdb",
PortReset: "false",
GOOS: options.GOOS,
GOARCH: options.GOARCH,
BuildTags: []string{options.GOOS, options.GOARCH},
GC: "precise",
Scheduler: "tasks",
Linker: "cc",
DefaultStackSize: 1024 * 64, // 64kB
GDB: []string{"gdb"},
PortReset: "false",
}
if goos == "darwin" {
spec.LDFlags = append(spec.LDFlags, "-Wl,-dead_strip")
} else {
spec.LDFlags = append(spec.LDFlags, "-no-pie", "-Wl,--gc-sections") // WARNING: clang < 5.0 requires -nopie
// Configure target based on GOARCH.
var llvmarch string
switch options.GOARCH {
case "386":
llvmarch = "i386"
spec.CPU = "pentium4"
spec.Features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
case "amd64":
llvmarch = "x86_64"
spec.CPU = "x86-64"
spec.Features = "+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87"
case "arm":
spec.CPU = "generic"
spec.CFlags = append(spec.CFlags, "-fno-unwind-tables", "-fno-asynchronous-unwind-tables")
subarch := strings.Split(options.GOARM, ",")
if len(subarch) > 2 {
return nil, fmt.Errorf("invalid GOARM=%s, must be of form <num>,[hardfloat|softfloat]", options.GOARM)
}
archLevel := subarch[0]
var fpu string
if len(subarch) >= 2 {
fpu = subarch[1]
} else {
// Pick the default fpu value: softfloat for armv5 and hardfloat
// above that.
if archLevel == "5" {
fpu = "softfloat"
} else {
fpu = "hardfloat"
}
}
switch fpu {
case "softfloat":
spec.CFlags = append(spec.CFlags, "-msoft-float")
spec.SoftFloat = true
case "hardfloat":
// Hardware floating point support is the default everywhere except
// on ARMv5 where it needs to be enabled explicitly.
if archLevel == "5" {
spec.CFlags = append(spec.CFlags, "-mfpu=vfpv2")
}
default:
return nil, fmt.Errorf("invalid extension GOARM=%s, must be softfloat or hardfloat", options.GOARM)
}
switch archLevel {
case "5":
llvmarch = "armv5"
if spec.SoftFloat {
spec.Features = "+armv5t,+soft-float,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
} else {
spec.Features = "+armv5t,+fp64,+strict-align,+vfp2,+vfp2sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-neon,-sha2,-thumb-mode,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
case "6":
llvmarch = "armv6"
if spec.SoftFloat {
spec.Features = "+armv6,+dsp,+soft-float,+strict-align,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
} else {
spec.Features = "+armv6,+dsp,+fp64,+strict-align,+vfp2,+vfp2sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-neon,-sha2,-thumb-mode,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
case "7":
llvmarch = "armv7"
if spec.SoftFloat {
spec.Features = "+armv7-a,+dsp,+soft-float,-aes,-bf16,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-mve,-mve.fp,-neon,-sha2,-thumb-mode,-vfp2,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
} else {
spec.Features = "+armv7-a,+d32,+dsp,+fp64,+neon,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,-aes,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-sha2,-thumb-mode,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"
}
default:
return nil, fmt.Errorf("invalid GOARM=%s, must be of form <num>,[hardfloat|softfloat] where num is 5, 6, or 7", options.GOARM)
}
case "arm64":
spec.CPU = "generic"
llvmarch = "aarch64"
if options.GOOS == "darwin" {
spec.Features = "+ete,+fp-armv8,+neon,+trbe,+v8a"
// Looks like Apple prefers to call this architecture ARM64
// instead of AArch64.
llvmarch = "arm64"
} else if options.GOOS == "windows" {
spec.Features = "+ete,+fp-armv8,+neon,+trbe,+v8a,-fmv"
} else { // linux
spec.Features = "+ete,+fp-armv8,+neon,+trbe,+v8a,-fmv,-outline-atomics"
}
case "mips", "mipsle":
spec.CPU = "mips32"
spec.CFlags = append(spec.CFlags, "-fno-pic")
if options.GOARCH == "mips" {
llvmarch = "mips" // big endian
} else {
llvmarch = "mipsel" // little endian
}
switch options.GOMIPS {
case "hardfloat":
spec.Features = "+fpxx,+mips32,+nooddspreg,-noabicalls"
case "softfloat":
spec.SoftFloat = true
spec.Features = "+mips32,+soft-float,-noabicalls"
spec.CFlags = append(spec.CFlags, "-msoft-float")
default:
return nil, fmt.Errorf("invalid GOMIPS=%s: must be hardfloat or softfloat", options.GOMIPS)
}
case "wasm":
return nil, fmt.Errorf("GOARCH=wasm but GOOS is unset. Please set GOOS to wasm, wasip1, or wasip2.")
default:
return nil, fmt.Errorf("unknown GOARCH=%s", options.GOARCH)
}
if goarch != "wasm" {
spec.ExtraFiles = append(spec.ExtraFiles, "src/runtime/gc_"+goarch+".S")
// Configure target based on GOOS.
llvmos := options.GOOS
llvmvendor := "unknown"
switch options.GOOS {
case "darwin":
platformVersion := "10.12.0"
if options.GOARCH == "arm64" {
platformVersion = "11.0.0" // first macosx platform with arm64 support
}
llvmvendor = "apple"
spec.Linker = "ld.lld"
spec.Libc = "darwin-libSystem"
// Use macosx* instead of darwin, otherwise darwin/arm64 will refer to
// iOS!
llvmos = "macosx" + platformVersion
spec.LDFlags = append(spec.LDFlags,
"-flavor", "darwin",
"-dead_strip",
"-arch", llvmarch,
"-platform_version", "macos", platformVersion, platformVersion,
)
spec.ExtraFiles = append(spec.ExtraFiles,
"src/internal/futex/futex_darwin.c",
"src/runtime/os_darwin.c",
"src/runtime/runtime_unix.c",
"src/runtime/signal.c")
case "linux":
spec.Linker = "ld.lld"
spec.RTLib = "compiler-rt"
spec.Libc = "musl"
spec.LDFlags = append(spec.LDFlags, "--gc-sections")
if options.GOARCH == "arm64" {
// Disable outline atomics. For details, see:
// https://cpufun.substack.com/p/atomics-in-aarch64
// A better way would be to fully support outline atomics, which
// makes atomics slightly more efficient on systems with many cores.
// But the instructions are only supported on newer aarch64 CPUs, so
// this feature is normally put in a system library which does
// feature detection for you.
// We take the lazy way out and simply disable this feature, instead
// of enabling it in compiler-rt (which is a bit more complicated).
// We don't really need this feature anyway as we don't even support
// proper threading.
spec.CFlags = append(spec.CFlags, "-mno-outline-atomics")
}
spec.ExtraFiles = append(spec.ExtraFiles,
"src/internal/futex/futex_linux.c",
"src/runtime/runtime_unix.c",
"src/runtime/signal.c")
case "windows":
spec.Linker = "ld.lld"
spec.Libc = "mingw-w64"
// Note: using a medium code model, low image base and no ASLR
// because Go doesn't really need those features. ASLR patches
// around issues for unsafe languages like C/C++ that are not
// normally present in Go (without explicitly opting in).
// For more discussion:
// https://groups.google.com/g/Golang-nuts/c/Jd9tlNc6jUE/m/Zo-7zIP_m3MJ?pli=1
switch options.GOARCH {
case "amd64":
spec.LDFlags = append(spec.LDFlags,
"-m", "i386pep",
"--image-base", "0x400000",
)
case "arm64":
spec.LDFlags = append(spec.LDFlags,
"-m", "arm64pe",
)
}
spec.LDFlags = append(spec.LDFlags,
"-Bdynamic",
"--gc-sections",
"--no-insert-timestamp",
"--no-dynamicbase",
)
case "wasm", "wasip1", "wasip2":
return nil, fmt.Errorf("GOOS=%s but GOARCH is unset. Please set GOARCH to wasm", options.GOOS)
default:
return nil, fmt.Errorf("unknown GOOS=%s", options.GOOS)
}
if goarch != runtime.GOARCH {
// Target triples (which actually have four components, but are called
// triples for historical reasons) have the form:
// arch-vendor-os-environment
spec.Triple = llvmarch + "-" + llvmvendor + "-" + llvmos
if options.GOOS == "windows" {
spec.Triple += "-gnu"
} else if options.GOOS == "linux" {
// We use musl on Linux (not glibc) so we should use -musleabi* instead
// of -gnueabi*.
// The *hf suffix selects between soft/hard floating point ABI.
if spec.SoftFloat {
spec.Triple += "-musleabi"
} else {
spec.Triple += "-musleabihf"
}
}
// Add extra assembly files (needed for the scheduler etc).
if options.GOARCH != "wasm" {
suffix := ""
if options.GOOS == "windows" && options.GOARCH == "amd64" {
// Windows uses a different calling convention on amd64 from other
// operating systems so we need separate assembly files.
suffix = "_windows"
}
asmGoarch := options.GOARCH
if options.GOARCH == "mips" || options.GOARCH == "mipsle" {
asmGoarch = "mipsx"
}
spec.ExtraFiles = append(spec.ExtraFiles, "src/runtime/asm_"+asmGoarch+suffix+".S")
spec.ExtraFiles = append(spec.ExtraFiles, "src/internal/task/task_stack_"+asmGoarch+suffix+".S")
}
// Configure the emulator.
if options.GOARCH != runtime.GOARCH {
// Some educated guesses as to how to invoke helper programs.
spec.GDB = "gdb-multiarch"
if goarch == "arm" && goos == "linux" {
spec.CFlags = append(spec.CFlags, "--sysroot=/usr/arm-linux-gnueabihf")
spec.Linker = "arm-linux-gnueabihf-gcc"
spec.Emulator = []string{"qemu-arm", "-L", "/usr/arm-linux-gnueabihf"}
}
if goarch == "arm64" && goos == "linux" {
spec.CFlags = append(spec.CFlags, "--sysroot=/usr/aarch64-linux-gnu")
spec.Linker = "aarch64-linux-gnu-gcc"
spec.Emulator = []string{"qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"}
}
if goarch == "386" && runtime.GOARCH == "amd64" {
spec.CFlags = append(spec.CFlags, "-m32")
spec.LDFlags = append(spec.LDFlags, "-m32")
spec.GDB = []string{"gdb-multiarch"}
if options.GOOS == "linux" {
switch options.GOARCH {
case "386":
// amd64 can _usually_ run 32-bit programs, so skip the emulator in that case.
if runtime.GOARCH != "amd64" {
spec.Emulator = "qemu-i386 {}"
}
case "amd64":
spec.Emulator = "qemu-x86_64 {}"
case "arm":
spec.Emulator = "qemu-arm {}"
case "arm64":
spec.Emulator = "qemu-aarch64 {}"
case "mips":
spec.Emulator = "qemu-mips {}"
case "mipsle":
spec.Emulator = "qemu-mipsel {}"
}
}
}
if options.GOOS != runtime.GOOS {
if options.GOOS == "windows" {
spec.Emulator = "wine {}"
}
}
return &spec, nil
}
// LookupGDB looks up a gdb executable.
func (spec *TargetSpec) LookupGDB() (string, error) {
if len(spec.GDB) == 0 {
return "", errors.New("gdb not configured in the target specification")
}
for _, d := range spec.GDB {
_, err := exec.LookPath(d)
if err == nil {
return d, nil
}
}
return "", errors.New("no gdb found configured in the target specification (" + strings.Join(spec.GDB, ", ") + ")")
}
+9 -12
View File
@@ -1,22 +1,24 @@
package compileopts
import (
"errors"
"io/fs"
"reflect"
"testing"
)
func TestLoadTarget(t *testing.T) {
_, err := LoadTarget("arduino")
_, err := LoadTarget(&Options{Target: "arduino"})
if err != nil {
t.Error("LoadTarget test failed:", err)
}
_, err = LoadTarget("notexist")
_, err = LoadTarget(&Options{Target: "notexist"})
if err == nil {
t.Error("LoadTarget should have failed with non existing target")
}
if err.Error() != "expected a full LLVM target or a custom target in -target flag" {
if !errors.Is(err, fs.ErrNotExist) {
t.Error("LoadTarget failed for wrong reason:", err)
}
}
@@ -26,9 +28,8 @@ func TestOverrideProperties(t *testing.T) {
base := &TargetSpec{
GOOS: "baseGoos",
CPU: "baseCpu",
Features: []string{"bf1", "bf2"},
CFlags: []string{"-base-foo", "-base-bar"},
BuildTags: []string{"bt1", "bt2"},
Emulator: []string{"be1", "be2"},
DefaultStackSize: 42,
AutoStackSize: &baseAutoStackSize,
}
@@ -36,8 +37,7 @@ func TestOverrideProperties(t *testing.T) {
child := &TargetSpec{
GOOS: "",
CPU: "chlidCpu",
Features: []string{"cf1", "cf2"},
Emulator: []string{"ce1", "ce2"},
CFlags: []string{"-child-foo", "-child-bar"},
AutoStackSize: &childAutoStackSize,
DefaultStackSize: 64,
}
@@ -50,15 +50,12 @@ func TestOverrideProperties(t *testing.T) {
if base.CPU != "chlidCpu" {
t.Errorf("Overriding failed : got %v", base.CPU)
}
if !reflect.DeepEqual(base.Features, []string{"cf1", "cf2", "bf1", "bf2"}) {
t.Errorf("Overriding failed : got %v", base.Features)
if !reflect.DeepEqual(base.CFlags, []string{"-base-foo", "-base-bar", "-child-foo", "-child-bar"}) {
t.Errorf("Overriding failed : got %v", base.CFlags)
}
if !reflect.DeepEqual(base.BuildTags, []string{"bt1", "bt2"}) {
t.Errorf("Overriding failed : got %v", base.BuildTags)
}
if !reflect.DeepEqual(base.Emulator, []string{"ce1", "ce2"}) {
t.Errorf("Overriding failed : got %v", base.Emulator)
}
if *base.AutoStackSize != false {
t.Errorf("Overriding failed : got %v", base.AutoStackSize)
}
+66
View File
@@ -0,0 +1,66 @@
package compiler
// This file defines alias functions for functions that are normally defined in
// Go assembly.
//
// The Go toolchain defines many performance critical functions in assembly
// instead of plain Go. This is a problem for TinyGo as it currently (as of
// august 2021) is not able to compile these assembly files and even if it
// could, it would not be able to make use of them for many targets that are
// supported by TinyGo (baremetal RISC-V, AVR, etc). Therefore, many of these
// functions are aliased to their generic Go implementation.
// This results in slower than possible implementations, but at least they are
// usable.
import "tinygo.org/x/go-llvm"
var stdlibAliases = map[string]string{
// crypto packages
"crypto/ed25519/internal/edwards25519/field.feMul": "crypto/ed25519/internal/edwards25519/field.feMulGeneric",
"crypto/internal/edwards25519/field.feSquare": "crypto/ed25519/internal/edwards25519/field.feSquareGeneric",
"crypto/md5.block": "crypto/md5.blockGeneric",
"crypto/sha1.block": "crypto/sha1.blockGeneric",
"crypto/sha1.blockAMD64": "crypto/sha1.blockGeneric",
"crypto/sha256.block": "crypto/sha256.blockGeneric",
"crypto/sha512.blockAMD64": "crypto/sha512.blockGeneric",
"internal/chacha8rand.block": "internal/chacha8rand.block_generic",
// AES
"crypto/aes.decryptBlockAsm": "crypto/aes.decryptBlock",
"crypto/aes.encryptBlockAsm": "crypto/aes.encryptBlock",
// math package
"math.archHypot": "math.hypot",
"math.archMax": "math.max",
"math.archMin": "math.min",
"math.archModf": "math.modf",
}
// createAlias implements the function (in the builder) as a call to the alias
// function.
func (b *builder) createAlias(alias llvm.Value) {
b.llvmFn.SetVisibility(llvm.HiddenVisibility)
b.llvmFn.SetUnnamedAddr(true)
if b.Debug {
if b.fn.Syntax() != nil {
// Create debug info file if present.
b.difunc = b.attachDebugInfo(b.fn)
}
pos := b.program.Fset.Position(b.fn.Pos())
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
}
entryBlock := b.ctx.AddBasicBlock(b.llvmFn, "entry")
b.SetInsertPointAtEnd(entryBlock)
if b.llvmFn.Type() != alias.Type() {
b.addError(b.fn.Pos(), "alias function should have the same type as aliasee "+alias.Name())
b.CreateUnreachable()
return
}
result := b.CreateCall(alias.GlobalValueType(), alias, b.llvmFn.Params(), "")
if result.Type().TypeKind() == llvm.VoidTypeKind {
b.CreateRetVoid()
} else {
b.CreateRet(result)
}
}
+95 -48
View File
@@ -15,22 +15,16 @@ import (
// createLookupBoundsCheck emits a bounds check before doing a lookup into a
// slice. This is required by the Go language spec: an index out of bounds must
// cause a panic.
func (b *builder) createLookupBoundsCheck(arrayLen, index llvm.Value, indexType types.Type) {
// The caller should make sure that index is at least as big as arrayLen.
func (b *builder) createLookupBoundsCheck(arrayLen, index llvm.Value) {
if b.info.nobounds {
// The //go:nobounds pragma was added to the function to avoid bounds
// checking.
return
}
if index.Type().IntTypeWidth() < arrayLen.Type().IntTypeWidth() {
// Sometimes, the index can be e.g. an uint8 or int8, and we have to
// correctly extend that type.
if indexType.Underlying().(*types.Basic).Info()&types.IsUnsigned == 0 {
index = b.CreateZExt(index, arrayLen.Type(), "")
} else {
index = b.CreateSExt(index, arrayLen.Type(), "")
}
} else if index.Type().IntTypeWidth() > arrayLen.Type().IntTypeWidth() {
// Extend arrayLen if it's too small.
if index.Type().IntTypeWidth() > arrayLen.Type().IntTypeWidth() {
// The index is bigger than the array length type, so extend it.
arrayLen = b.CreateZExt(arrayLen, index.Type(), "")
}
@@ -70,27 +64,9 @@ func (b *builder) createSliceBoundsCheck(capacity, low, high, max llvm.Value, lo
}
// Extend low and high to be the same size as capacity.
if low.Type().IntTypeWidth() < capacityType.IntTypeWidth() {
if lowType.Info()&types.IsUnsigned != 0 {
low = b.CreateZExt(low, capacityType, "")
} else {
low = b.CreateSExt(low, capacityType, "")
}
}
if high.Type().IntTypeWidth() < capacityType.IntTypeWidth() {
if highType.Info()&types.IsUnsigned != 0 {
high = b.CreateZExt(high, capacityType, "")
} else {
high = b.CreateSExt(high, capacityType, "")
}
}
if max.Type().IntTypeWidth() < capacityType.IntTypeWidth() {
if maxType.Info()&types.IsUnsigned != 0 {
max = b.CreateZExt(max, capacityType, "")
} else {
max = b.CreateSExt(max, capacityType, "")
}
}
low = b.extendInteger(low, lowType, capacityType)
high = b.extendInteger(high, highType, capacityType)
max = b.extendInteger(max, maxType, capacityType)
// Now do the bounds check: low > high || high > capacity
outOfBounds1 := b.CreateICmp(llvm.IntUGT, low, high, "slice.lowhigh")
@@ -101,6 +77,50 @@ func (b *builder) createSliceBoundsCheck(capacity, low, high, max llvm.Value, lo
b.createRuntimeAssert(outOfBounds, "slice", "slicePanic")
}
// createSliceToArrayPointerCheck adds a check for slice-to-array pointer
// conversions. This conversion was added in Go 1.17. For details, see:
// https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer
func (b *builder) createSliceToArrayPointerCheck(sliceLen llvm.Value, arrayLen int64) {
// From the spec:
// > If the length of the slice is less than the length of the array, a
// > run-time panic occurs.
arrayLenValue := llvm.ConstInt(b.uintptrType, uint64(arrayLen), false)
isLess := b.CreateICmp(llvm.IntULT, sliceLen, arrayLenValue, "")
b.createRuntimeAssert(isLess, "slicetoarray", "sliceToArrayPointerPanic")
}
// createUnsafeSliceStringCheck inserts a runtime check used for unsafe.Slice
// and unsafe.String. This function must panic if the ptr/len parameters are
// invalid.
func (b *builder) createUnsafeSliceStringCheck(name string, ptr, len llvm.Value, elementType llvm.Type, lenType *types.Basic) {
// From the documentation of unsafe.Slice and unsafe.String:
// > At run time, if len is negative, or if ptr is nil and len is not
// > zero, a run-time panic occurs.
// However, in practice, it is also necessary to check that the length is
// not too big that a GEP wouldn't be possible without wrapping the pointer.
// These two checks (non-negative and not too big) can be merged into one
// using an unsigned greater than.
// Make sure the len value is at least as big as a uintptr.
len = b.extendInteger(len, lenType, b.uintptrType)
// Determine the maximum slice size, and therefore the maximum value of the
// len parameter.
maxSize := b.maxSliceSize(elementType)
maxSizeValue := llvm.ConstInt(len.Type(), maxSize, false)
// Do the check. By using unsigned greater than for the length check, signed
// negative values are also checked (which are very large numbers when
// interpreted as signed values).
zero := llvm.ConstInt(len.Type(), 0, false)
lenOutOfBounds := b.CreateICmp(llvm.IntUGT, len, maxSizeValue, "")
ptrIsNil := b.CreateICmp(llvm.IntEQ, ptr, llvm.ConstNull(ptr.Type()), "")
lenIsNotZero := b.CreateICmp(llvm.IntNE, len, zero, "")
assert := b.CreateAnd(ptrIsNil, lenIsNotZero, "")
assert = b.CreateOr(assert, lenOutOfBounds, "")
b.createRuntimeAssert(assert, name, "unsafeSlicePanic")
}
// createChanBoundsCheck creates a bounds check before creating a new channel to
// check that the value is not too big for runtime.chanMake.
func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value, bufSizeType *types.Basic, pos token.Pos) {
@@ -110,23 +130,12 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value,
return
}
// Check whether the bufSize parameter must be cast to a wider integer for
// comparison.
if bufSize.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {
if bufSizeType.Info()&types.IsUnsigned != 0 {
// Unsigned, so zero-extend to uint type.
bufSizeType = types.Typ[types.Uint]
bufSize = b.CreateZExt(bufSize, b.intType, "")
} else {
// Signed, so sign-extend to int type.
bufSizeType = types.Typ[types.Int]
bufSize = b.CreateSExt(bufSize, b.intType, "")
}
}
// Make sure bufSize is at least as big as maxBufSize (an uintptr).
bufSize = b.extendInteger(bufSize, bufSizeType, b.uintptrType)
// Calculate (^uintptr(0)) >> 1, which is the max value that fits in an
// uintptr if uintptrs were signed.
maxBufSize := llvm.ConstLShr(llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)), llvm.ConstInt(b.uintptrType, 1, false))
maxBufSize := b.CreateLShr(llvm.ConstNot(llvm.ConstInt(b.uintptrType, 0, false)), llvm.ConstInt(b.uintptrType, 1, false), "")
if elementSize > maxBufSize.ZExtValue() {
b.addError(pos, fmt.Sprintf("channel element type is too big (%v bytes)", elementSize))
return
@@ -137,11 +146,11 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value,
}
// Make the maxBufSize actually the maximum allowed value (in number of
// elements in the channel buffer).
maxBufSize = llvm.ConstUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize, false))
maxBufSize = b.CreateUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize, false), "")
// Make sure maxBufSize has the same type as bufSize.
if maxBufSize.Type() != bufSize.Type() {
maxBufSize = llvm.ConstZExt(maxBufSize, bufSize.Type())
maxBufSize = b.CreateZExt(maxBufSize, bufSize.Type(), "")
}
// Do the check for a too large (or negative) buffer size.
@@ -159,6 +168,13 @@ func (b *builder) createNilCheck(inst ssa.Value, ptr llvm.Value, blockPrefix str
}
switch inst := inst.(type) {
case *ssa.Alloc:
// An alloc is never nil.
return
case *ssa.FreeVar:
// A free variable is allocated in a parent function and is thus never
// nil.
return
case *ssa.IndexAddr:
// This pointer is the result of an index operation into a slice or
// array. Such slices/arrays are already bounds checked so the pointer
@@ -199,6 +215,19 @@ func (b *builder) createNegativeShiftCheck(shift llvm.Value) {
b.createRuntimeAssert(isNegative, "shift", "negativeShiftPanic")
}
// createDivideByZeroCheck asserts that y is not zero. If it is, a runtime panic
// will be emitted. This follows the Go specification which says that a divide
// by zero must cause a run time panic.
func (b *builder) createDivideByZeroCheck(y llvm.Value) {
if b.info.nobounds {
return
}
// isZero = y == 0
isZero := b.CreateICmp(llvm.IntEQ, y, llvm.ConstInt(y.Type(), 0, false), "")
b.createRuntimeAssert(isZero, "divbyzero", "divideByZeroPanic")
}
// createRuntimeAssert is a common function to create a new branch on an assert
// bool, calling an assert func if the assert value is true (1).
func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc string) {
@@ -212,8 +241,10 @@ func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc
}
}
// Put the fault block at the end of the function and the next block at the
// current insert position.
faultBlock := b.ctx.AddBasicBlock(b.llvmFn, blockPrefix+".throw")
nextBlock := b.ctx.AddBasicBlock(b.llvmFn, blockPrefix+".next")
nextBlock := b.insertBasicBlock(blockPrefix + ".next")
b.blockExits[b.currentBlock] = nextBlock // adjust outgoing block for phi nodes
// Now branch to the out-of-bounds or the regular block.
@@ -227,3 +258,19 @@ func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc
// Ok: assert didn't trigger so continue normally.
b.SetInsertPointAtEnd(nextBlock)
}
// extendInteger extends the value to at least targetType using a zero or sign
// extend. The resulting value is not truncated: it may still be bigger than
// targetType.
func (b *builder) extendInteger(value llvm.Value, valueType types.Type, targetType llvm.Type) llvm.Value {
if value.Type().IntTypeWidth() < targetType.IntTypeWidth() {
if valueType.Underlying().(*types.Basic).Info()&types.IsUnsigned != 0 {
// Unsigned, so zero-extend to the target type.
value = b.CreateZExt(value, targetType, "")
} else {
// Signed, so sign-extend to the target type.
value = b.CreateSExt(value, targetType, "")
}
}
return value
}
+32 -59
View File
@@ -1,84 +1,57 @@
package compiler
import (
"strings"
"golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm"
)
// createAtomicOp lowers an atomic library call by lowering it as an LLVM atomic
// operation. It returns the result of the operation and true if the call could
// be lowered inline, and false otherwise.
func (b *builder) createAtomicOp(call *ssa.CallCommon) (llvm.Value, bool) {
name := call.Value.(*ssa.Function).Name()
// createAtomicOp lowers a sync/atomic function by lowering it as an LLVM atomic
// operation. It returns the result of the operation, or a zero llvm.Value if
// the result is void.
func (b *builder) createAtomicOp(name string) llvm.Value {
switch name {
case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
ptr := b.getValue(call.Args[0])
val := b.getValue(call.Args[1])
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1], getPos(b.fn))
oldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpAdd, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)
// Return the new value, not the original value returned by atomicrmw.
return b.CreateAdd(oldVal, val, ""), true
return b.CreateAdd(oldVal, val, "")
case "AndInt32", "AndInt64", "AndUint32", "AndUint64", "AndUintptr":
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1], getPos(b.fn))
oldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpAnd, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)
return oldVal
case "OrInt32", "OrInt64", "OrUint32", "OrUint64", "OrUintptr":
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1], getPos(b.fn))
oldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpOr, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)
return oldVal
case "SwapInt32", "SwapInt64", "SwapUint32", "SwapUint64", "SwapUintptr", "SwapPointer":
ptr := b.getValue(call.Args[0])
val := b.getValue(call.Args[1])
isPointer := val.Type().TypeKind() == llvm.PointerTypeKind
if isPointer {
// atomicrmw only supports integers, so cast to an integer.
val = b.CreatePtrToInt(val, b.uintptrType, "")
ptr = b.CreateBitCast(ptr, llvm.PointerType(val.Type(), 0), "")
}
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1], getPos(b.fn))
oldVal := b.CreateAtomicRMW(llvm.AtomicRMWBinOpXchg, ptr, val, llvm.AtomicOrderingSequentiallyConsistent, true)
if isPointer {
oldVal = b.CreateIntToPtr(oldVal, b.i8ptrType, "")
}
return oldVal, true
return oldVal
case "CompareAndSwapInt32", "CompareAndSwapInt64", "CompareAndSwapUint32", "CompareAndSwapUint64", "CompareAndSwapUintptr", "CompareAndSwapPointer":
ptr := b.getValue(call.Args[0])
old := b.getValue(call.Args[1])
newVal := b.getValue(call.Args[2])
if strings.HasSuffix(name, "64") {
arch := strings.Split(b.Triple, "-")[0]
if strings.HasPrefix(arch, "arm") && strings.HasSuffix(arch, "m") {
// Work around a bug in LLVM, at least LLVM 11:
// https://reviews.llvm.org/D95891
// Check for armv6m, armv7, armv7em, and perhaps others.
// See also: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
compareAndSwap := b.mod.NamedFunction("__sync_val_compare_and_swap_8")
if compareAndSwap.IsNil() {
// Declare the function if it isn't already declared.
i64Type := b.ctx.Int64Type()
fnType := llvm.FunctionType(i64Type, []llvm.Type{llvm.PointerType(i64Type, 0), i64Type, i64Type}, false)
compareAndSwap = llvm.AddFunction(b.mod, "__sync_val_compare_and_swap_8", fnType)
}
actualOldValue := b.CreateCall(compareAndSwap, []llvm.Value{ptr, old, newVal}, "")
// The __sync_val_compare_and_swap_8 function returns the old
// value. However, we shouldn't return the old value, we should
// return whether the compare/exchange was successful. This is
// easily done by comparing the returned (actual) old value with
// the expected old value passed to
// __sync_val_compare_and_swap_8.
swapped := b.CreateICmp(llvm.IntEQ, old, actualOldValue, "")
return swapped, true
}
}
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
old := b.getValue(b.fn.Params[1], getPos(b.fn))
newVal := b.getValue(b.fn.Params[2], getPos(b.fn))
tuple := b.CreateAtomicCmpXchg(ptr, old, newVal, llvm.AtomicOrderingSequentiallyConsistent, llvm.AtomicOrderingSequentiallyConsistent, true)
swapped := b.CreateExtractValue(tuple, 1, "")
return swapped, true
return swapped
case "LoadInt32", "LoadInt64", "LoadUint32", "LoadUint64", "LoadUintptr", "LoadPointer":
ptr := b.getValue(call.Args[0])
val := b.CreateLoad(ptr, "")
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.CreateLoad(b.getLLVMType(b.fn.Signature.Results().At(0).Type()), ptr, "")
val.SetOrdering(llvm.AtomicOrderingSequentiallyConsistent)
val.SetAlignment(b.targetData.PrefTypeAlignment(val.Type())) // required
return val, true
return val
case "StoreInt32", "StoreInt64", "StoreUint32", "StoreUint64", "StoreUintptr", "StorePointer":
ptr := b.getValue(call.Args[0])
val := b.getValue(call.Args[1])
ptr := b.getValue(b.fn.Params[0], getPos(b.fn))
val := b.getValue(b.fn.Params[1], getPos(b.fn))
store := b.CreateStore(val, ptr)
store.SetOrdering(llvm.AtomicOrderingSequentiallyConsistent)
store.SetAlignment(b.targetData.PrefTypeAlignment(val.Type())) // required
return store, true
return llvm.Value{}
default:
return llvm.Value{}, false
b.addError(b.fn.Pos(), "unknown atomic operation: "+b.fn.Name())
return llvm.Value{}
}
}
+95 -60
View File
@@ -19,8 +19,9 @@ const maxFieldsPerParam = 3
// useful while declaring or defining a function.
type paramInfo struct {
llvmType llvm.Type
name string // name, possibly with suffixes for e.g. struct fields
flags paramFlags
name string // name, possibly with suffixes for e.g. struct fields
elemSize uint64 // size of pointer element type, or 0 if this isn't a pointer
flags paramFlags // extra flags for this parameter
}
// paramFlags identifies parameter attributes for flags. Most importantly, it
@@ -28,54 +29,79 @@ type paramInfo struct {
type paramFlags uint8
const (
// Parameter may have the deferenceable_or_null attribute. This attribute
// cannot be applied to unsafe.Pointer and to the data pointer of slices.
paramIsDeferenceableOrNull = 1 << iota
// Whether this is a full or partial Go parameter (int, slice, etc).
// The extra context parameter is not a Go parameter.
paramIsGoParam = 1 << iota
)
// createCall creates a new call to runtime.<fnName> with the given arguments.
func (b *builder) createRuntimeCall(fnName string, args []llvm.Value, name string) llvm.Value {
fn := b.program.ImportedPackage("runtime").Members[fnName].(*ssa.Function)
llvmFn := b.getFunction(fn)
// createRuntimeCallCommon creates a runtime call. Use createRuntimeCall or
// createRuntimeInvoke instead.
func (b *builder) createRuntimeCallCommon(fnName string, args []llvm.Value, name string, isInvoke bool) llvm.Value {
member := b.program.ImportedPackage("runtime").Members[fnName]
if member == nil {
panic("unknown runtime call: " + fnName)
}
fn := member.(*ssa.Function)
fnType, llvmFn := b.getFunction(fn)
if llvmFn.IsNil() {
panic("trying to call non-existent function: " + fn.RelString(nil))
}
args = append(args, llvm.Undef(b.i8ptrType)) // unused context parameter
args = append(args, llvm.ConstPointerNull(b.i8ptrType)) // coroutine handle
return b.createCall(llvmFn, args, name)
args = append(args, llvm.Undef(b.dataPtrType)) // unused context parameter
if isInvoke {
return b.createInvoke(fnType, llvmFn, args, name)
}
return b.createCall(fnType, llvmFn, args, name)
}
// createRuntimeCall creates a new call to runtime.<fnName> with the given
// arguments.
func (b *builder) createRuntimeCall(fnName string, args []llvm.Value, name string) llvm.Value {
return b.createRuntimeCallCommon(fnName, args, name, false)
}
// createRuntimeInvoke creates a new call to runtime.<fnName> with the given
// arguments. If the runtime call panics, control flow is diverted to the
// landing pad block.
// Note that "invoke" here is meant in the LLVM sense (a call that can
// panic/throw), not in the Go sense (an interface method call).
func (b *builder) createRuntimeInvoke(fnName string, args []llvm.Value, name string) llvm.Value {
return b.createRuntimeCallCommon(fnName, args, name, true)
}
// createCall creates a call to the given function with the arguments possibly
// expanded.
func (b *builder) createCall(fn llvm.Value, args []llvm.Value, name string) llvm.Value {
func (b *builder) createCall(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
expanded := make([]llvm.Value, 0, len(args))
for _, arg := range args {
fragments := b.expandFormalParam(arg)
expanded = append(expanded, fragments...)
}
return b.CreateCall(fn, expanded, name)
return b.CreateCall(fnType, fn, expanded, name)
}
// createInvoke is like createCall but continues execution at the landing pad if
// the call resulted in a panic.
func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
if b.hasDeferFrame() {
b.createInvokeCheckpoint()
}
return b.createCall(fnType, fn, args, name)
}
// Expand an argument type to a list that can be used in a function call
// parameter list.
func expandFormalParamType(t llvm.Type, name string, goType types.Type) []paramInfo {
func (c *compilerContext) expandFormalParamType(t llvm.Type, name string, goType types.Type) []paramInfo {
switch t.TypeKind() {
case llvm.StructTypeKind:
fieldInfos := flattenAggregateType(t, name, goType)
fieldInfos := c.flattenAggregateType(t, name, goType)
if len(fieldInfos) <= maxFieldsPerParam {
// managed to expand this parameter
return fieldInfos
} else {
// failed to lower
}
// failed to expand this parameter: too many fields
}
// TODO: split small arrays
return []paramInfo{
{
llvmType: t,
name: name,
flags: getTypeFlags(goType),
},
}
return []paramInfo{c.getParamInfo(t, name, goType)}
}
// expandFormalParamOffsets returns a list of offsets from the start of an
@@ -105,7 +131,7 @@ func (b *builder) expandFormalParamOffsets(t llvm.Type) []uint64 {
func (b *builder) expandFormalParam(v llvm.Value) []llvm.Value {
switch v.Type().TypeKind() {
case llvm.StructTypeKind:
fieldInfos := flattenAggregateType(v.Type(), "", nil)
fieldInfos := b.flattenAggregateType(v.Type(), "", nil)
if len(fieldInfos) <= maxFieldsPerParam {
fields := b.flattenAggregate(v)
if len(fields) != len(fieldInfos) {
@@ -124,12 +150,14 @@ func (b *builder) expandFormalParam(v llvm.Value) []llvm.Value {
// Try to flatten a struct type to a list of types. Returns a 1-element slice
// with the passed in type if this is not possible.
func flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramInfo {
typeFlags := getTypeFlags(goType)
func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramInfo {
switch t.TypeKind() {
case llvm.StructTypeKind:
paramInfos := make([]paramInfo, 0, t.StructElementTypesCount())
var paramInfos []paramInfo
for i, subfield := range t.StructElementTypes() {
if c.targetData.TypeAllocSize(subfield) == 0 {
continue
}
suffix := strconv.Itoa(i)
if goType != nil {
// Try to come up with a good suffix for this struct field,
@@ -152,41 +180,39 @@ func flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramIn
suffix = []string{"context", "funcptr"}[i]
}
}
subInfos := flattenAggregateType(subfield, name+"."+suffix, extractSubfield(goType, i))
for i := range subInfos {
subInfos[i].flags |= typeFlags
}
subInfos := c.flattenAggregateType(subfield, name+"."+suffix, extractSubfield(goType, i))
paramInfos = append(paramInfos, subInfos...)
}
return paramInfos
default:
return []paramInfo{
{
llvmType: t,
name: name,
flags: typeFlags,
},
}
return []paramInfo{c.getParamInfo(t, name, goType)}
}
}
// getTypeFlags returns the type flags for a given type. It will not recurse
// into sub-types (such as in structs).
func getTypeFlags(t types.Type) paramFlags {
if t == nil {
return 0
// getParamInfo collects information about a parameter. For example, if this
// parameter is pointer-like, it will also store the element type for the
// dereferenceable_or_null attribute.
func (c *compilerContext) getParamInfo(t llvm.Type, name string, goType types.Type) paramInfo {
info := paramInfo{
llvmType: t,
name: name,
flags: paramIsGoParam,
}
switch t.Underlying().(type) {
case *types.Pointer:
// Pointers in Go must either point to an object or be nil.
return paramIsDeferenceableOrNull
case *types.Chan, *types.Map:
// Channels and maps are implemented as pointers pointing to some
// object, and follow the same rules as *types.Pointer.
return paramIsDeferenceableOrNull
default:
return 0
if goType != nil {
switch underlying := goType.Underlying().(type) {
case *types.Pointer:
// Pointers in Go must either point to an object or be nil.
info.elemSize = c.targetData.TypeAllocSize(c.getLLVMType(underlying.Elem()))
case *types.Chan:
// Channels are implemented simply as a *runtime.channel.
info.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType("channel"))
case *types.Map:
// Maps are similar to channels: they are implemented as a
// *runtime.hashmap.
info.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType("hashmap"))
}
}
return info
}
// extractSubfield extracts a field from a struct, or returns null if this is
@@ -209,7 +235,7 @@ func extractSubfield(t types.Type, field int) types.Type {
}
}
// flattenAggregateTypeOffset returns the offsets from the start of an object of
// flattenAggregateTypeOffsets returns the offsets from the start of an object of
// type t if this object were flattened like in flattenAggregate. Used together
// with flattenAggregate to know the start indices of each value in the
// non-flattened object.
@@ -218,8 +244,11 @@ func extractSubfield(t types.Type, field int) types.Type {
func (c *compilerContext) flattenAggregateTypeOffsets(t llvm.Type) []uint64 {
switch t.TypeKind() {
case llvm.StructTypeKind:
fields := make([]uint64, 0, t.StructElementTypesCount())
var fields []uint64
for fieldIndex, field := range t.StructElementTypes() {
if c.targetData.TypeAllocSize(field) == 0 {
continue
}
suboffsets := c.flattenAggregateTypeOffsets(field)
offset := c.targetData.ElementOffset(t, fieldIndex)
for i := range suboffsets {
@@ -238,8 +267,11 @@ func (c *compilerContext) flattenAggregateTypeOffsets(t llvm.Type) []uint64 {
func (b *builder) flattenAggregate(v llvm.Value) []llvm.Value {
switch v.Type().TypeKind() {
case llvm.StructTypeKind:
fields := make([]llvm.Value, 0, v.Type().StructElementTypesCount())
for i := range v.Type().StructElementTypes() {
var fields []llvm.Value
for i, field := range v.Type().StructElementTypes() {
if b.targetData.TypeAllocSize(field) == 0 {
continue
}
subfield := b.CreateExtractValue(v, i, "")
subfields := b.flattenAggregate(subfield)
fields = append(fields, subfields...)
@@ -266,10 +298,13 @@ func (b *builder) collapseFormalParam(t llvm.Type, fields []llvm.Value) llvm.Val
func (b *builder) collapseFormalParamInternal(t llvm.Type, fields []llvm.Value) (llvm.Value, []llvm.Value) {
switch t.TypeKind() {
case llvm.StructTypeKind:
flattened := flattenAggregateType(t, "", nil)
flattened := b.flattenAggregateType(t, "", nil)
if len(flattened) <= maxFieldsPerParam {
value := llvm.ConstNull(t)
for i, subtyp := range t.StructElementTypes() {
if b.targetData.TypeAllocSize(subtyp) == 0 {
continue
}
structField, remaining := b.collapseFormalParamInternal(subtyp, fields)
fields = remaining
value = b.CreateInsertValue(value, structField, i, "")
+80 -46
View File
@@ -4,7 +4,9 @@ package compiler
// or pseudo-operations that are lowered during goroutine lowering.
import (
"fmt"
"go/types"
"math"
"github.com/tinygo-org/tinygo/compiler/llvmutil"
"golang.org/x/tools/go/ssa"
@@ -14,7 +16,7 @@ import (
func (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value {
elementSize := b.targetData.TypeAllocSize(b.getLLVMType(expr.Type().Underlying().(*types.Chan).Elem()))
elementSizeValue := llvm.ConstInt(b.uintptrType, elementSize, false)
bufSize := b.getValue(expr.Size)
bufSize := b.getValue(expr.Size, getPos(expr))
b.createChanBoundsCheck(elementSize, bufSize, expr.Size.Type().Underlying().(*types.Basic), expr.Pos())
if bufSize.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {
bufSize = b.CreateZExt(bufSize, b.uintptrType, "")
@@ -27,46 +29,65 @@ func (b *builder) createMakeChan(expr *ssa.MakeChan) llvm.Value {
// createChanSend emits a pseudo chan send operation. It is lowered to the
// actual channel send operation during goroutine lowering.
func (b *builder) createChanSend(instr *ssa.Send) {
ch := b.getValue(instr.Chan)
chanValue := b.getValue(instr.X)
ch := b.getValue(instr.Chan, getPos(instr))
chanValue := b.getValue(instr.X, getPos(instr))
// store value-to-send
valueType := b.getLLVMType(instr.X.Type())
valueAlloca, valueAllocaCast, valueAllocaSize := b.createTemporaryAlloca(valueType, "chan.value")
b.CreateStore(chanValue, valueAlloca)
isZeroSize := b.targetData.TypeAllocSize(valueType) == 0
var valueAlloca, valueAllocaSize llvm.Value
if isZeroSize {
valueAlloca = llvm.ConstNull(b.dataPtrType)
} else {
valueAlloca, valueAllocaSize = b.createTemporaryAlloca(valueType, "chan.value")
b.CreateStore(chanValue, valueAlloca)
}
// Allocate blockedlist buffer.
channelBlockedList := b.mod.GetTypeByName("runtime.channelBlockedList")
channelBlockedListAlloca, channelBlockedListAllocaCast, channelBlockedListAllocaSize := b.createTemporaryAlloca(channelBlockedList, "chan.blockedList")
// Allocate buffer for the channel operation.
channelOp := b.getLLVMRuntimeType("channelOp")
channelOpAlloca, channelOpAllocaSize := b.createTemporaryAlloca(channelOp, "chan.op")
// Do the send.
b.createRuntimeCall("chanSend", []llvm.Value{ch, valueAllocaCast, channelBlockedListAlloca}, "")
b.createRuntimeCall("chanSend", []llvm.Value{ch, valueAlloca, channelOpAlloca}, "")
// End the lifetime of the allocas.
// This also works around a bug in CoroSplit, at least in LLVM 8:
// https://bugs.llvm.org/show_bug.cgi?id=41742
b.emitLifetimeEnd(channelBlockedListAllocaCast, channelBlockedListAllocaSize)
b.emitLifetimeEnd(valueAllocaCast, valueAllocaSize)
b.emitLifetimeEnd(channelOpAlloca, channelOpAllocaSize)
if !isZeroSize {
b.emitLifetimeEnd(valueAlloca, valueAllocaSize)
}
}
// createChanRecv emits a pseudo chan receive operation. It is lowered to the
// actual channel receive operation during goroutine lowering.
func (b *builder) createChanRecv(unop *ssa.UnOp) llvm.Value {
valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Chan).Elem())
ch := b.getValue(unop.X)
ch := b.getValue(unop.X, getPos(unop))
// Allocate memory to receive into.
valueAlloca, valueAllocaCast, valueAllocaSize := b.createTemporaryAlloca(valueType, "chan.value")
isZeroSize := b.targetData.TypeAllocSize(valueType) == 0
var valueAlloca, valueAllocaSize llvm.Value
if isZeroSize {
valueAlloca = llvm.ConstNull(b.dataPtrType)
} else {
valueAlloca, valueAllocaSize = b.createTemporaryAlloca(valueType, "chan.value")
}
// Allocate blockedlist buffer.
channelBlockedList := b.mod.GetTypeByName("runtime.channelBlockedList")
channelBlockedListAlloca, channelBlockedListAllocaCast, channelBlockedListAllocaSize := b.createTemporaryAlloca(channelBlockedList, "chan.blockedList")
// Allocate buffer for the channel operation.
channelOp := b.getLLVMRuntimeType("channelOp")
channelOpAlloca, channelOpAllocaSize := b.createTemporaryAlloca(channelOp, "chan.op")
// Do the receive.
commaOk := b.createRuntimeCall("chanRecv", []llvm.Value{ch, valueAllocaCast, channelBlockedListAlloca}, "")
received := b.CreateLoad(valueAlloca, "chan.received")
b.emitLifetimeEnd(channelBlockedListAllocaCast, channelBlockedListAllocaSize)
b.emitLifetimeEnd(valueAllocaCast, valueAllocaSize)
commaOk := b.createRuntimeCall("chanRecv", []llvm.Value{ch, valueAlloca, channelOpAlloca}, "")
var received llvm.Value
if isZeroSize {
received = llvm.ConstNull(valueType)
} else {
received = b.CreateLoad(valueType, valueAlloca, "chan.received")
b.emitLifetimeEnd(valueAlloca, valueAllocaSize)
}
b.emitLifetimeEnd(channelOpAlloca, channelOpAllocaSize)
if unop.CommaOk {
tuple := llvm.Undef(b.ctx.StructType([]llvm.Type{valueType, b.ctx.Int1Type()}, false))
@@ -105,6 +126,20 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
}
}
const maxSelectStates = math.MaxUint32 >> 2
if len(expr.States) > maxSelectStates {
// The runtime code assumes that the number of state must fit in 30 bits
// (so the select index can be stored in a uint32 with two bits reserved
// for other purposes). It seems unlikely that a real program would have
// that many states, but we check for this case anyway to be sure.
// We use a uint32 (and not a uintptr or uint64) to avoid 64-bit atomic
// operations which aren't available everywhere.
b.addError(expr.Pos(), fmt.Sprintf("too many select states: got %d but the maximum supported number is %d", len(expr.States), maxSelectStates))
// Continue as usual (we'll generate broken code but the error will
// prevent the compilation to complete).
}
// This code create a (stack-allocated) slice containing all the select
// cases and then calls runtime.chanSelect to perform the actual select
// statement.
@@ -116,11 +151,10 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
// determine the receive buffer size and alignment.
recvbufSize := uint64(0)
recvbufAlign := 0
hasReceives := false
var selectStates []llvm.Value
chanSelectStateType := b.getLLVMRuntimeType("chanSelectState")
for _, state := range expr.States {
ch := b.getValue(state.Chan)
ch := b.getValue(state.Chan, state.Pos)
selectState := llvm.ConstNull(chanSelectStateType)
selectState = b.CreateInsertValue(selectState, ch, 0, "")
switch state.Dir {
@@ -133,15 +167,13 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
if align := b.targetData.ABITypeAlignment(llvmType); align > recvbufAlign {
recvbufAlign = align
}
hasReceives = true
case types.SendOnly:
// Store this value in an alloca and put a pointer to this alloca
// in the send state.
sendValue := b.getValue(state.Send)
sendValue := b.getValue(state.Send, state.Pos)
alloca := llvmutil.CreateEntryBlockAlloca(b.Builder, sendValue.Type(), "select.send.value")
b.CreateStore(sendValue, alloca)
ptr := b.CreateBitCast(alloca, b.i8ptrType, "")
selectState = b.CreateInsertValue(selectState, ptr, 1, "")
selectState = b.CreateInsertValue(selectState, alloca, 1, "")
default:
panic("unreachable")
}
@@ -149,12 +181,12 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
}
// Create a receive buffer, where the received value will be stored.
recvbuf := llvm.Undef(b.i8ptrType)
if hasReceives {
recvbuf := llvm.Undef(b.dataPtrType)
if recvbufSize != 0 {
allocaType := llvm.ArrayType(b.ctx.Int8Type(), int(recvbufSize))
recvbufAlloca, _, _ := b.createTemporaryAlloca(allocaType, "select.recvbuf.alloca")
recvbufAlloca, _ := b.createTemporaryAlloca(allocaType, "select.recvbuf.alloca")
recvbufAlloca.SetAlignment(recvbufAlign)
recvbuf = b.CreateGEP(recvbufAlloca, []llvm.Value{
recvbuf = b.CreateGEP(allocaType, recvbufAlloca, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
}, "select.recvbuf")
@@ -162,16 +194,16 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
// Create the states slice (allocated on the stack).
statesAllocaType := llvm.ArrayType(chanSelectStateType, len(selectStates))
statesAlloca, statesI8, statesSize := b.createTemporaryAlloca(statesAllocaType, "select.states.alloca")
statesAlloca, statesSize := b.createTemporaryAlloca(statesAllocaType, "select.states.alloca")
for i, state := range selectStates {
// Set each slice element to the appropriate channel.
gep := b.CreateGEP(statesAlloca, []llvm.Value{
gep := b.CreateGEP(statesAllocaType, statesAlloca, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false),
}, "")
b.CreateStore(state, gep)
}
statesPtr := b.CreateGEP(statesAlloca, []llvm.Value{
statesPtr := b.CreateGEP(statesAllocaType, statesAlloca, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
}, "select.states")
@@ -182,10 +214,10 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
if expr.Blocking {
// Stack-allocate operation structures.
// If these were simply created as a slice, they would heap-allocate.
chBlockAllocaType := llvm.ArrayType(b.getLLVMRuntimeType("channelBlockedList"), len(selectStates))
chBlockAlloca, chBlockAllocaPtr, chBlockSize := b.createTemporaryAlloca(chBlockAllocaType, "select.block.alloca")
chBlockLen := llvm.ConstInt(b.uintptrType, uint64(len(selectStates)), false)
chBlockPtr := b.CreateGEP(chBlockAlloca, []llvm.Value{
opsAllocaType := llvm.ArrayType(b.getLLVMRuntimeType("channelOp"), len(selectStates))
opsAlloca, opsSize := b.createTemporaryAlloca(opsAllocaType, "select.block.alloca")
opsLen := llvm.ConstInt(b.uintptrType, uint64(len(selectStates)), false)
opsPtr := b.CreateGEP(opsAllocaType, opsAlloca, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
}, "select.block")
@@ -193,20 +225,23 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
results = b.createRuntimeCall("chanSelect", []llvm.Value{
recvbuf,
statesPtr, statesLen, statesLen, // []chanSelectState
chBlockPtr, chBlockLen, chBlockLen, // []channelBlockList
opsPtr, opsLen, opsLen, // []channelOp
}, "select.result")
// Terminate the lifetime of the operation structures.
b.emitLifetimeEnd(chBlockAllocaPtr, chBlockSize)
b.emitLifetimeEnd(opsAlloca, opsSize)
} else {
results = b.createRuntimeCall("tryChanSelect", []llvm.Value{
opsPtr := llvm.ConstNull(b.dataPtrType)
opsLen := llvm.ConstInt(b.uintptrType, 0, false)
results = b.createRuntimeCall("chanSelect", []llvm.Value{
recvbuf,
statesPtr, statesLen, statesLen, // []chanSelectState
opsPtr, opsLen, opsLen, // []channelOp (nil slice)
}, "select.result")
}
// Terminate the lifetime of the states alloca.
b.emitLifetimeEnd(statesI8, statesSize)
b.emitLifetimeEnd(statesAlloca, statesSize)
// The result value does not include all the possible received values,
// because we can't load them in advance. Instead, the *ssa.Extract
@@ -228,7 +263,7 @@ func (b *builder) createSelect(expr *ssa.Select) llvm.Value {
func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value {
if expr.Index == 0 {
// index
value := b.getValue(expr.Tuple)
value := b.getValue(expr.Tuple, getPos(expr))
index := b.CreateExtractValue(value, expr.Index, "")
if index.Type().IntTypeWidth() < b.intType.IntTypeWidth() {
index = b.CreateSExt(index, b.intType, "")
@@ -236,7 +271,7 @@ func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value {
return index
} else if expr.Index == 1 {
// comma-ok
value := b.getValue(expr.Tuple)
value := b.getValue(expr.Tuple, getPos(expr))
return b.CreateExtractValue(value, expr.Index, "")
} else {
// Select statements are (index, ok, ...) where ... is a number of
@@ -245,8 +280,7 @@ func (b *builder) getChanSelectResult(expr *ssa.Extract) llvm.Value {
// receive can proceed at a time) so we'll get that alloca, bitcast
// it to the correct type, and dereference it.
recvbuf := b.selectRecvBuf[expr.Tuple.(*ssa.Select)]
typ := llvm.PointerType(b.getLLVMType(expr.Type()), 0)
ptr := b.CreateBitCast(recvbuf, typ, "")
return b.CreateLoad(ptr, "")
typ := b.getLLVMType(expr.Type())
return b.CreateLoad(typ, recvbuf, "")
}
}
+1187 -503
View File
File diff suppressed because it is too large Load Diff
+160 -71
View File
@@ -3,13 +3,13 @@ package compiler
import (
"flag"
"go/types"
"io/ioutil"
"regexp"
"os"
"strconv"
"strings"
"testing"
"github.com/tinygo-org/tinygo/compileopts"
"github.com/tinygo-org/tinygo/goenv"
"github.com/tinygo-org/tinygo/loader"
"tinygo.org/x/go-llvm"
)
@@ -17,85 +17,106 @@ import (
// Pass -update to go test to update the output of the test files.
var flagUpdate = flag.Bool("update", false, "update tests based on test output")
type testCase struct {
file string
target string
scheduler string
}
// Basic tests for the compiler. Build some Go files and compare the output with
// the expected LLVM IR for regression testing.
func TestCompiler(t *testing.T) {
target, err := compileopts.LoadTarget("i686--linux")
t.Parallel()
// Determine Go minor version (e.g. 16 in go1.16.3).
_, goMinor, err := goenv.GetGorootVersion()
if err != nil {
t.Fatal("failed to load target:", err)
}
config := &compileopts.Config{
Options: &compileopts.Options{},
Target: target,
}
compilerConfig := &Config{
Triple: config.Triple(),
GOOS: config.GOOS(),
GOARCH: config.GOARCH(),
CodeModel: config.CodeModel(),
RelocationModel: config.RelocationModel(),
Scheduler: config.Scheduler(),
FuncImplementation: config.FuncImplementation(),
AutomaticStackSize: config.AutomaticStackSize(),
}
machine, err := NewTargetMachine(compilerConfig)
if err != nil {
t.Fatal("failed to create target machine:", err)
t.Fatal("could not read Go version:", err)
}
tests := []string{
"basic.go",
"pointer.go",
"slice.go",
"float.go",
// Determine which tests to run, depending on the Go and LLVM versions.
tests := []testCase{
{"basic.go", "", ""},
{"pointer.go", "", ""},
{"slice.go", "", ""},
{"string.go", "", ""},
{"float.go", "", ""},
{"interface.go", "", ""},
{"func.go", "", ""},
{"defer.go", "cortex-m-qemu", ""},
{"pragma.go", "", ""},
{"goroutine.go", "wasm", "asyncify"},
{"goroutine.go", "cortex-m-qemu", "tasks"},
{"channel.go", "", ""},
{"gc.go", "", ""},
{"zeromap.go", "", ""},
}
if goMinor >= 20 {
tests = append(tests, testCase{"go1.20.go", "", ""})
}
if goMinor >= 21 {
tests = append(tests, testCase{"go1.21.go", "", ""})
}
for _, testCase := range tests {
t.Run(testCase, func(t *testing.T) {
// Load entire program AST into memory.
lprogram, err := loader.Load(config, []string{"./testdata/" + testCase}, config.ClangHeaders, types.Config{
Sizes: Sizes(machine),
})
if err != nil {
t.Fatal("failed to create target machine:", err)
for _, tc := range tests {
name := tc.file
targetString := "wasm"
if tc.target != "" {
targetString = tc.target
name += "-" + tc.target
}
if tc.scheduler != "" {
name += "-" + tc.scheduler
}
t.Run(name, func(t *testing.T) {
options := &compileopts.Options{
Target: targetString,
}
err = lprogram.Parse()
if err != nil {
t.Fatalf("could not parse test case %s: %s", testCase, err)
if tc.scheduler != "" {
options.Scheduler = tc.scheduler
}
// Compile AST to IR.
pkg := lprogram.MainPkg()
mod, errs := CompilePackage(testCase, pkg, machine, compilerConfig, false)
mod, errs := testCompilePackage(t, options, tc.file)
if errs != nil {
for _, err := range errs {
t.Log("error:", err)
t.Error(err)
}
return
}
// Optimize IR a little.
funcPasses := llvm.NewFunctionPassManagerForModule(mod)
defer funcPasses.Dispose()
funcPasses.AddInstructionCombiningPass()
funcPasses.InitializeFunc()
for fn := mod.FirstFunction(); !fn.IsNil(); fn = llvm.NextFunction(fn) {
funcPasses.RunFunc(fn)
err := llvm.VerifyModule(mod, llvm.PrintMessageAction)
if err != nil {
t.Error(err)
}
funcPasses.FinalizeFunc()
outfile := "./testdata/" + testCase[:len(testCase)-3] + ".ll"
// Optimize IR a little.
passOptions := llvm.NewPassBuilderOptions()
defer passOptions.Dispose()
err = mod.RunPasses("instcombine", llvm.TargetMachine{}, passOptions)
if err != nil {
t.Error(err)
}
outFilePrefix := tc.file[:len(tc.file)-3]
if tc.target != "" {
outFilePrefix += "-" + tc.target
}
if tc.scheduler != "" {
outFilePrefix += "-" + tc.scheduler
}
outPath := "./testdata/" + outFilePrefix + ".ll"
// Update test if needed. Do not check the result.
if *flagUpdate {
err := ioutil.WriteFile(outfile, []byte(mod.String()), 0666)
err := os.WriteFile(outPath, []byte(mod.String()), 0666)
if err != nil {
t.Error("failed to write updated output file:", err)
}
return
}
expected, err := ioutil.ReadFile(outfile)
expected, err := os.ReadFile(outPath)
if err != nil {
t.Fatal("failed to read golden file:", err)
}
@@ -107,8 +128,6 @@ func TestCompiler(t *testing.T) {
}
}
var alignRegexp = regexp.MustCompile(", align [0-9]+$")
// fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly
// equal. That means, only relevant lines are compared (excluding comments
// etc.).
@@ -120,15 +139,6 @@ func fuzzyEqualIR(s1, s2 string) bool {
}
for i, line1 := range lines1 {
line2 := lines2[i]
match1 := alignRegexp.MatchString(line1)
match2 := alignRegexp.MatchString(line2)
if match1 != match2 {
// Only one of the lines has the align keyword. Remove it.
// This is a change to make the test work in both LLVM 10 and LLVM
// 11 (LLVM 11 appears to automatically add alignment everywhere).
line1 = alignRegexp.ReplaceAllString(line1, "")
line2 = alignRegexp.ReplaceAllString(line2, "")
}
if line1 != line2 {
return false
}
@@ -157,16 +167,95 @@ func filterIrrelevantIRLines(lines []string) []string {
if strings.HasPrefix(line, "source_filename = ") {
continue
}
if llvmVersion < 10 && strings.HasPrefix(line, "attributes ") {
// Ignore attribute groups. These may change between LLVM versions.
// Right now test outputs are for LLVM 10.
continue
}
if llvmVersion < 10 && strings.HasPrefix(line, "target datalayout ") {
// Ignore the target layout. This may change between LLVM versions.
if llvmVersion < 15 && strings.HasPrefix(line, "target datalayout = ") {
// The datalayout string may vary betewen LLVM versions.
// Right now test outputs are for LLVM 15 and higher.
continue
}
out = append(out, line)
}
return out
}
func TestCompilerErrors(t *testing.T) {
t.Parallel()
// Read expected errors from the test file.
var expectedErrors []string
errorsFile, err := os.ReadFile("testdata/errors.go")
if err != nil {
t.Error(err)
}
errorsFileString := strings.ReplaceAll(string(errorsFile), "\r\n", "\n")
for _, line := range strings.Split(errorsFileString, "\n") {
if strings.HasPrefix(line, "// ERROR: ") {
expectedErrors = append(expectedErrors, strings.TrimPrefix(line, "// ERROR: "))
}
}
// Compile the Go file with errors.
options := &compileopts.Options{
Target: "wasm",
}
_, errs := testCompilePackage(t, options, "errors.go")
// Check whether the actual errors match the expected errors.
expectedErrorsIdx := 0
for _, err := range errs {
err := err.(types.Error)
position := err.Fset.Position(err.Pos)
position.Filename = "errors.go" // don't use a full path
if expectedErrorsIdx >= len(expectedErrors) || expectedErrors[expectedErrorsIdx] != err.Msg {
t.Errorf("unexpected compiler error: %s: %s", position.String(), err.Msg)
continue
}
expectedErrorsIdx++
}
}
// Build a package given a number of compiler options and a file.
func testCompilePackage(t *testing.T, options *compileopts.Options, file string) (llvm.Module, []error) {
target, err := compileopts.LoadTarget(options)
if err != nil {
t.Fatal("failed to load target:", err)
}
config := &compileopts.Config{
Options: options,
Target: target,
}
compilerConfig := &Config{
Triple: config.Triple(),
Features: config.Features(),
ABI: config.ABI(),
GOOS: config.GOOS(),
GOARCH: config.GOARCH(),
CodeModel: config.CodeModel(),
RelocationModel: config.RelocationModel(),
Scheduler: config.Scheduler(),
AutomaticStackSize: config.AutomaticStackSize(),
DefaultStackSize: config.StackSize(),
NeedsStackObjects: config.NeedsStackObjects(),
}
machine, err := NewTargetMachine(compilerConfig)
if err != nil {
t.Fatal("failed to create target machine:", err)
}
defer machine.Dispose()
// Load entire program AST into memory.
lprogram, err := loader.Load(config, "./testdata/"+file, types.Config{
Sizes: Sizes(machine),
})
if err != nil {
t.Fatal("failed to create target machine:", err)
}
err = lprogram.Parse()
if err != nil {
t.Fatalf("could not parse test case %s: %s", file, err)
}
// Compile AST to IR.
program := lprogram.LoadSSA()
pkg := lprogram.MainPkg()
return CompilePackage(file, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false)
}
+265 -82
View File
@@ -15,12 +15,40 @@ package compiler
import (
"go/types"
"strconv"
"strings"
"github.com/tinygo-org/tinygo/compiler/llvmutil"
"golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm"
)
// supportsRecover returns whether the compiler supports the recover() builtin
// for the current architecture.
func (b *builder) supportsRecover() bool {
switch b.archFamily() {
case "wasm32":
// Probably needs to be implemented using the exception handling
// proposal of WebAssembly:
// https://github.com/WebAssembly/exception-handling
return false
case "riscv64", "xtensa":
// TODO: add support for these architectures
return false
default:
return true
}
}
// hasDeferFrame returns whether the current function needs to catch panics and
// run defers.
func (b *builder) hasDeferFrame() bool {
if b.fn.Recover == nil {
return false
}
return b.supportsRecover()
}
// deferInitFunc sets up this function for future deferred calls. It must be
// called from within the entry block when this function contains deferred
// calls.
@@ -33,9 +61,171 @@ func (b *builder) deferInitFunc() {
b.deferBuiltinFuncs = make(map[ssa.Value]deferBuiltin)
// Create defer list pointer.
deferType := llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)
b.deferPtr = b.CreateAlloca(deferType, "deferPtr")
b.CreateStore(llvm.ConstPointerNull(deferType), b.deferPtr)
b.deferPtr = b.CreateAlloca(b.dataPtrType, "deferPtr")
b.CreateStore(llvm.ConstPointerNull(b.dataPtrType), b.deferPtr)
if b.hasDeferFrame() {
// Set up the defer frame with the current stack pointer.
// This assumes that the stack pointer doesn't move outside of the
// function prologue/epilogue (an invariant maintained by TinyGo but
// possibly broken by the C alloca function).
// The frame pointer is _not_ saved, because it is marked as clobbered
// in the setjmp-like inline assembly.
deferFrameType := b.getLLVMRuntimeType("deferFrame")
b.deferFrame = b.CreateAlloca(deferFrameType, "deferframe.buf")
stackPointer := b.readStackPointer()
b.createRuntimeCall("setupDeferFrame", []llvm.Value{b.deferFrame, stackPointer}, "")
// Create the landing pad block, which is where control transfers after
// a panic.
b.landingpad = b.ctx.AddBasicBlock(b.llvmFn, "lpad")
}
}
// createLandingPad fills in the landing pad block. This block runs the deferred
// functions and returns (by jumping to the recover block). If the function is
// still panicking after the defers are run, the panic will be re-raised in
// destroyDeferFrame.
func (b *builder) createLandingPad() {
b.SetInsertPointAtEnd(b.landingpad)
// Add debug info, if needed.
// The location used is the closing bracket of the function.
if b.Debug {
pos := b.program.Fset.Position(b.fn.Syntax().End())
b.SetCurrentDebugLocation(uint(pos.Line), uint(pos.Column), b.difunc, llvm.Metadata{})
}
b.createRunDefers()
// Continue at the 'recover' block, which returns to the parent in an
// appropriate way.
b.CreateBr(b.blockEntries[b.fn.Recover])
}
// createInvokeCheckpoint saves the function state at the given point, to
// continue at the landing pad if a panic happened. This is implemented using a
// setjmp-like construct.
func (b *builder) createInvokeCheckpoint() {
// Construct inline assembly equivalents of setjmp.
// The assembly works as follows:
// * All registers (both callee-saved and caller saved) are clobbered
// after the inline assembly returns.
// * The assembly stores the address just past the end of the assembly
// into the jump buffer.
// * The return value (eax, rax, r0, etc) is set to zero in the inline
// assembly but set to an unspecified non-zero value when jumping using
// a longjmp.
var asmString, constraints string
resultType := b.uintptrType
switch b.archFamily() {
case "i386":
asmString = `
xorl %eax, %eax
movl $$1f, 4(%ebx)
1:`
constraints = "={eax},{ebx},~{ebx},~{ecx},~{edx},~{esi},~{edi},~{ebp},~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{fpsr},~{fpcr},~{flags},~{dirflag},~{memory}"
// This doesn't include the floating point stack because TinyGo uses
// newer floating point instructions.
case "x86_64":
asmString = `
leaq 1f(%rip), %rax
movq %rax, 8(%rbx)
xorq %rax, %rax
1:`
constraints = "={rax},{rbx},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{fpsr},~{fpcr},~{flags},~{dirflag},~{memory}"
// This list doesn't include AVX/AVX512 registers because TinyGo
// doesn't currently enable support for AVX instructions.
case "arm":
// Note: the following assembly takes into account that the PC is
// always 4 bytes ahead on ARM. The PC that is stored always points
// to the instruction just after the assembly fragment so that
// tinygo_longjmp lands at the correct instruction.
if b.isThumb() {
// Instructions are 2 bytes in size.
asmString = `
movs r0, #0
mov r2, pc
str r2, [r1, #4]`
} else {
// Instructions are 4 bytes in size.
asmString = `
str pc, [r1, #4]
movs r0, #0`
}
constraints = "={r0},{r1},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{cpsr},~{memory}"
case "aarch64":
asmString = `
adr x2, 1f
str x2, [x1, #8]
mov x0, #0
1:
`
constraints = "={x0},{x1},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28},~{lr},~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{q8},~{q9},~{q10},~{q11},~{q12},~{q13},~{q14},~{q15},~{q16},~{q17},~{q18},~{q19},~{q20},~{q21},~{q22},~{q23},~{q24},~{q25},~{q26},~{q27},~{q28},~{q29},~{q30},~{nzcv},~{ffr},~{memory}"
if b.GOOS != "darwin" && b.GOOS != "windows" {
// These registers cause the following warning when compiling for
// MacOS and Windows:
// warning: inline asm clobber list contains reserved registers:
// X18, FP
// Reserved registers on the clobber list may not be preserved
// across the asm statement, and clobbering them may lead to
// undefined behaviour.
constraints += ",~{x18},~{fp}"
}
// TODO: SVE registers, which we don't use in TinyGo at the moment.
case "avr":
// Note: the Y register (R28:R29) is a fixed register and therefore
// needs to be saved manually. TODO: do this only once per function with
// a defer frame, not for every call.
resultType = b.ctx.Int8Type()
asmString = `
ldi r24, pm_lo8(1f)
ldi r25, pm_hi8(1f)
std z+2, r24
std z+3, r25
std z+4, r28
std z+5, r29
ldi r24, 0
1:`
constraints = "={r24},z,~{r0},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r25},~{r26},~{r27}"
case "mips":
// $4 flag (zero or non-zero)
// $5 defer frame
asmString = `
.set noat
move $$4, $$zero
jal 1f
1:
addiu $$ra, 8
sw $$ra, 4($$5)
.set at`
constraints = "={$4},{$5},~{$1},~{$2},~{$3},~{$5},~{$6},~{$7},~{$8},~{$9},~{$10},~{$11},~{$12},~{$13},~{$14},~{$15},~{$16},~{$17},~{$18},~{$19},~{$20},~{$21},~{$22},~{$23},~{$24},~{$25},~{$26},~{$27},~{$28},~{$29},~{$30},~{$31},~{memory}"
if !strings.Contains(b.Features, "+soft-float") {
// Using floating point registers together with GOMIPS=softfloat
// results in a crash: "This value type is not natively supported!"
// So only add them when using hardfloat.
constraints += ",~{$f0},~{$f1},~{$f2},~{$f3},~{$f4},~{$f5},~{$f6},~{$f7},~{$f8},~{$f9},~{$f10},~{$f11},~{$f12},~{$f13},~{$f14},~{$f15},~{$f16},~{$f17},~{$f18},~{$f19},~{$f20},~{$f21},~{$f22},~{$f23},~{$f24},~{$f25},~{$f26},~{$f27},~{$f28},~{$f29},~{$f30},~{$f31}"
}
case "riscv32":
asmString = `
la a2, 1f
sw a2, 4(a1)
li a0, 0
1:`
constraints = "={a0},{a1},~{a1},~{a2},~{a3},~{a4},~{a5},~{a6},~{a7},~{s0},~{s1},~{s2},~{s3},~{s4},~{s5},~{s6},~{s7},~{s8},~{s9},~{s10},~{s11},~{t0},~{t1},~{t2},~{t3},~{t4},~{t5},~{t6},~{ra},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f18},~{f19},~{f20},~{f21},~{f22},~{f23},~{f24},~{f25},~{f26},~{f27},~{f28},~{f29},~{f30},~{f31},~{memory}"
default:
// This case should have been handled by b.supportsRecover().
b.addError(b.fn.Pos(), "unknown architecture for defer: "+b.archFamily())
}
asmType := llvm.FunctionType(resultType, []llvm.Type{b.deferFrame.Type()}, false)
asm := llvm.InlineAsm(asmType, asmString, constraints, false, false, 0, false)
result := b.CreateCall(asmType, asm, []llvm.Value{b.deferFrame}, "setjmp")
result.AddCallSiteAttribute(-1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("returns_twice"), 0))
isZero := b.CreateICmp(llvm.IntEQ, result, llvm.ConstInt(resultType, 0, false), "setjmp.result")
continueBB := b.insertBasicBlock("")
b.CreateCondBr(isZero, continueBB, b.landingpad)
b.SetInsertPointAtEnd(continueBB)
b.blockExits[b.currentBlock] = continueBB
}
// isInLoop checks if there is a path from a basic block to itself.
@@ -77,7 +267,7 @@ func isInLoop(start *ssa.BasicBlock) bool {
func (b *builder) createDefer(instr *ssa.Defer) {
// The pointer to the previous defer struct, which we will replace to
// make a linked list.
next := b.CreateLoad(b.deferPtr, "defer.next")
next := b.CreateLoad(b.dataPtrType, b.deferPtr, "defer.next")
var values []llvm.Value
valueTypes := []llvm.Type{b.uintptrType, next.Type()}
@@ -94,13 +284,13 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// Collect all values to be put in the struct (starting with
// runtime._defer fields, followed by the call parameters).
itf := b.getValue(instr.Call.Value) // interface
itf := b.getValue(instr.Call.Value, getPos(instr)) // interface
typecode := b.CreateExtractValue(itf, 0, "invoke.func.typecode")
receiverValue := b.CreateExtractValue(itf, 1, "invoke.func.receiver")
values = []llvm.Value{callback, next, typecode, receiverValue}
valueTypes = append(valueTypes, b.uintptrType, b.i8ptrType)
valueTypes = append(valueTypes, b.dataPtrType, b.dataPtrType)
for _, arg := range instr.Call.Args {
val := b.getValue(arg)
val := b.getValue(arg, getPos(instr))
values = append(values, val)
valueTypes = append(valueTypes, val.Type())
}
@@ -117,7 +307,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// runtime._defer fields).
values = []llvm.Value{callback, next}
for _, param := range instr.Call.Args {
llvmParam := b.getValue(param)
llvmParam := b.getValue(param, getPos(instr))
values = append(values, llvmParam)
valueTypes = append(valueTypes, llvmParam.Type())
}
@@ -129,7 +319,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// pointer.
// TODO: ignore this closure entirely and put pointers to the free
// variables directly in the defer struct, avoiding a memory allocation.
closure := b.getValue(instr.Call.Value)
closure := b.getValue(instr.Call.Value, getPos(instr))
context := b.CreateExtractValue(closure, 0, "")
// Get the callback number.
@@ -145,7 +335,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// context pointer).
values = []llvm.Value{callback, next}
for _, param := range instr.Call.Args {
llvmParam := b.getValue(param)
llvmParam := b.getValue(param, getPos(instr))
values = append(values, llvmParam)
valueTypes = append(valueTypes, llvmParam.Type())
}
@@ -157,7 +347,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
var argValues []llvm.Value
for _, arg := range instr.Call.Args {
argTypes = append(argTypes, arg.Type())
argValues = append(argValues, b.getValue(arg))
argValues = append(argValues, b.getValue(arg, getPos(instr)))
}
if _, ok := b.deferBuiltinFuncs[instr.Call.Value]; !ok {
@@ -180,7 +370,7 @@ func (b *builder) createDefer(instr *ssa.Defer) {
}
} else {
funcValue := b.getValue(instr.Call.Value)
funcValue := b.getValue(instr.Call.Value, getPos(instr))
if _, ok := b.deferExprFuncs[instr.Call.Value]; !ok {
b.deferExprFuncs[instr.Call.Value] = len(b.allDeferFuncs)
@@ -195,43 +385,45 @@ func (b *builder) createDefer(instr *ssa.Defer) {
values = []llvm.Value{callback, next, funcValue}
valueTypes = append(valueTypes, funcValue.Type())
for _, param := range instr.Call.Args {
llvmParam := b.getValue(param)
llvmParam := b.getValue(param, getPos(instr))
values = append(values, llvmParam)
valueTypes = append(valueTypes, llvmParam.Type())
}
}
// Make a struct out of the collected values to put in the defer frame.
deferFrameType := b.ctx.StructType(valueTypes, false)
deferFrame := llvm.ConstNull(deferFrameType)
// Make a struct out of the collected values to put in the deferred call
// struct.
deferredCallType := b.ctx.StructType(valueTypes, false)
deferredCall := llvm.ConstNull(deferredCallType)
for i, value := range values {
deferFrame = b.CreateInsertValue(deferFrame, value, i, "")
deferredCall = b.CreateInsertValue(deferredCall, value, i, "")
}
// Put this struct in an allocation.
var alloca llvm.Value
if !isInLoop(instr.Block()) {
// This can safely use a stack allocation.
alloca = llvmutil.CreateEntryBlockAlloca(b.Builder, deferFrameType, "defer.alloca")
alloca = llvmutil.CreateEntryBlockAlloca(b.Builder, deferredCallType, "defer.alloca")
} else {
// This may be hit a variable number of times, so use a heap allocation.
size := b.targetData.TypeAllocSize(deferFrameType)
size := b.targetData.TypeAllocSize(deferredCallType)
sizeValue := llvm.ConstInt(b.uintptrType, size, false)
allocCall := b.createRuntimeCall("alloc", []llvm.Value{sizeValue}, "defer.alloc.call")
alloca = b.CreateBitCast(allocCall, llvm.PointerType(deferFrameType, 0), "defer.alloc")
nilPtr := llvm.ConstNull(b.dataPtrType)
alloca = b.createRuntimeCall("alloc", []llvm.Value{sizeValue, nilPtr}, "defer.alloc.call")
}
if b.NeedsStackObjects {
b.trackPointer(alloca)
}
b.CreateStore(deferFrame, alloca)
b.CreateStore(deferredCall, alloca)
// Push it on top of the linked list by replacing deferPtr.
allocaCast := b.CreateBitCast(alloca, next.Type(), "defer.alloca.cast")
b.CreateStore(allocaCast, b.deferPtr)
b.CreateStore(alloca, b.deferPtr)
}
// createRunDefers emits code to run all deferred functions.
func (b *builder) createRunDefers() {
deferType := b.getLLVMRuntimeType("_defer")
// Add a loop like the following:
// for stack != nil {
// _stack := stack
@@ -247,17 +439,17 @@ func (b *builder) createRunDefers() {
// }
// }
// Create loop.
loophead := b.ctx.AddBasicBlock(b.llvmFn, "rundefers.loophead")
loop := b.ctx.AddBasicBlock(b.llvmFn, "rundefers.loop")
unreachable := b.ctx.AddBasicBlock(b.llvmFn, "rundefers.default")
end := b.ctx.AddBasicBlock(b.llvmFn, "rundefers.end")
// Create loop, in the order: loophead, loop, callback0, callback1, ..., unreachable, end.
end := b.insertBasicBlock("rundefers.end")
unreachable := b.ctx.InsertBasicBlock(end, "rundefers.default")
loop := b.ctx.InsertBasicBlock(unreachable, "rundefers.loop")
loophead := b.ctx.InsertBasicBlock(loop, "rundefers.loophead")
b.CreateBr(loophead)
// Create loop head:
// for stack != nil {
b.SetInsertPointAtEnd(loophead)
deferData := b.CreateLoad(b.deferPtr, "")
deferData := b.CreateLoad(b.dataPtrType, b.deferPtr, "")
stackIsNil := b.CreateICmp(llvm.IntEQ, deferData, llvm.ConstPointerNull(deferData.Type()), "stackIsNil")
b.CreateCondBr(stackIsNil, end, loop)
@@ -266,24 +458,24 @@ func (b *builder) createRunDefers() {
// stack = stack.next
// switch stack.callback {
b.SetInsertPointAtEnd(loop)
nextStackGEP := b.CreateInBoundsGEP(deferData, []llvm.Value{
nextStackGEP := b.CreateInBoundsGEP(deferType, deferData, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), 1, false), // .next field
}, "stack.next.gep")
nextStack := b.CreateLoad(nextStackGEP, "stack.next")
nextStack := b.CreateLoad(b.dataPtrType, nextStackGEP, "stack.next")
b.CreateStore(nextStack, b.deferPtr)
gep := b.CreateInBoundsGEP(deferData, []llvm.Value{
gep := b.CreateInBoundsGEP(deferType, deferData, []llvm.Value{
llvm.ConstInt(b.ctx.Int32Type(), 0, false),
llvm.ConstInt(b.ctx.Int32Type(), 0, false), // .callback field
}, "callback.gep")
callback := b.CreateLoad(gep, "callback")
callback := b.CreateLoad(b.uintptrType, gep, "callback")
sw := b.CreateSwitch(callback, unreachable, len(b.allDeferFuncs))
for i, callback := range b.allDeferFuncs {
// Create switch case, for example:
// case 0:
// // run first deferred call
block := b.ctx.AddBasicBlock(b.llvmFn, "rundefers.callback")
block := b.insertBasicBlock("rundefers.callback" + strconv.Itoa(i))
sw.AddCase(llvm.ConstInt(b.uintptrType, uint64(i), false), block)
b.SetInsertPointAtEnd(block)
switch callback := callback.(type) {
@@ -291,33 +483,32 @@ func (b *builder) createRunDefers() {
// Call on an value or interface value.
// Get the real defer struct type and cast to it.
valueTypes := []llvm.Type{b.uintptrType, llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)}
valueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}
if !callback.IsInvoke() {
//Expect funcValue to be passed through the defer frame.
//Expect funcValue to be passed through the deferred call.
valueTypes = append(valueTypes, b.getFuncType(callback.Signature()))
} else {
//Expect typecode
valueTypes = append(valueTypes, b.uintptrType, b.i8ptrType)
valueTypes = append(valueTypes, b.dataPtrType, b.dataPtrType)
}
for _, arg := range callback.Args {
valueTypes = append(valueTypes, b.getLLVMType(arg.Type()))
}
deferFrameType := b.ctx.StructType(valueTypes, false)
deferFramePtr := b.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame")
// Extract the params from the struct (including receiver).
forwardParams := []llvm.Value{}
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
deferredCallType := b.ctx.StructType(valueTypes, false)
for i := 2; i < len(valueTypes); i++ {
gep := b.CreateInBoundsGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "gep")
forwardParam := b.CreateLoad(gep, "param")
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "gep")
forwardParam := b.CreateLoad(valueTypes[i], gep, "param")
forwardParams = append(forwardParams, forwardParam)
}
var fnPtr llvm.Value
var fnType llvm.Type
if !callback.IsInvoke() {
// Isolate the func value.
@@ -325,93 +516,86 @@ func (b *builder) createRunDefers() {
forwardParams = forwardParams[1:]
//Get function pointer and context
fp, context := b.decodeFuncValue(funcValue, callback.Signature())
fnPtr = fp
var context llvm.Value
fnPtr, context = b.decodeFuncValue(funcValue)
fnType = b.getLLVMFunctionType(callback.Signature())
//Pass context
forwardParams = append(forwardParams, context)
} else {
// Isolate the typecode.
typecode := forwardParams[0]
forwardParams = forwardParams[1:]
fnPtr = b.getInvokePtr(callback, typecode)
// Move typecode from the start to the end of the list of
// parameters.
forwardParams = append(forwardParams[1:], forwardParams[0])
fnPtr = b.getInvokeFunction(callback)
fnType = fnPtr.GlobalValueType()
// Add the context parameter. An interface call cannot also be a
// closure but we have to supply the parameter anyway for platforms
// with a strict calling convention.
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))
}
// Parent coroutine handle.
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
b.createCall(fnPtr, forwardParams, "")
b.createCall(fnType, fnPtr, forwardParams, "")
case *ssa.Function:
// Direct call.
// Get the real defer struct type and cast to it.
valueTypes := []llvm.Type{b.uintptrType, llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)}
for _, param := range callback.Params {
valueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}
for _, param := range getParams(callback.Signature) {
valueTypes = append(valueTypes, b.getLLVMType(param.Type()))
}
deferFrameType := b.ctx.StructType(valueTypes, false)
deferFramePtr := b.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame")
deferredCallType := b.ctx.StructType(valueTypes, false)
// Extract the params from the struct.
forwardParams := []llvm.Value{}
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
for i := range callback.Params {
gep := b.CreateInBoundsGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
forwardParam := b.CreateLoad(gep, "param")
for i := range getParams(callback.Signature) {
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
forwardParam := b.CreateLoad(valueTypes[i+2], gep, "param")
forwardParams = append(forwardParams, forwardParam)
}
// Plain TinyGo functions add some extra parameters to implement async functionality and function recievers.
// Plain TinyGo functions add some extra parameters to implement async functionality and function receivers.
// These parameters should not be supplied when calling into an external C/ASM function.
if !b.getFunctionInfo(callback).exported {
// Add the context parameter. We know it is ignored by the receiving
// function, but we have to pass one anyway.
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
// Parent coroutine handle.
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
forwardParams = append(forwardParams, llvm.Undef(b.dataPtrType))
}
// Call real function.
b.createCall(b.getFunction(callback), forwardParams, "")
fnType, fn := b.getFunction(callback)
b.createInvoke(fnType, fn, forwardParams, "")
case *ssa.MakeClosure:
// Get the real defer struct type and cast to it.
fn := callback.Fn.(*ssa.Function)
valueTypes := []llvm.Type{b.uintptrType, llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)}
valueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}
params := fn.Signature.Params()
for i := 0; i < params.Len(); i++ {
valueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))
}
valueTypes = append(valueTypes, b.i8ptrType) // closure
deferFrameType := b.ctx.StructType(valueTypes, false)
deferFramePtr := b.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame")
valueTypes = append(valueTypes, b.dataPtrType) // closure
deferredCallType := b.ctx.StructType(valueTypes, false)
// Extract the params from the struct.
forwardParams := []llvm.Value{}
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
for i := 2; i < len(valueTypes); i++ {
gep := b.CreateInBoundsGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "")
forwardParam := b.CreateLoad(gep, "param")
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i), false)}, "")
forwardParam := b.CreateLoad(valueTypes[i], gep, "param")
forwardParams = append(forwardParams, forwardParam)
}
// Parent coroutine handle.
forwardParams = append(forwardParams, llvm.Undef(b.i8ptrType))
// Call deferred function.
b.createCall(b.getFunction(fn), forwardParams, "")
fnType, llvmFn := b.getFunction(fn)
b.createCall(fnType, llvmFn, forwardParams, "")
case *ssa.Builtin:
db := b.deferBuiltinFuncs[callback]
//Get parameter types
valueTypes := []llvm.Type{b.uintptrType, llvm.PointerType(b.getLLVMRuntimeType("_defer"), 0)}
valueTypes := []llvm.Type{b.uintptrType, b.dataPtrType}
//Get signature from call results
params := callback.Type().Underlying().(*types.Signature).Params()
@@ -419,15 +603,14 @@ func (b *builder) createRunDefers() {
valueTypes = append(valueTypes, b.getLLVMType(params.At(i).Type()))
}
deferFrameType := b.ctx.StructType(valueTypes, false)
deferFramePtr := b.CreateBitCast(deferData, llvm.PointerType(deferFrameType, 0), "deferFrame")
deferredCallType := b.ctx.StructType(valueTypes, false)
// Extract the params from the struct.
var argValues []llvm.Value
zero := llvm.ConstInt(b.ctx.Int32Type(), 0, false)
for i := 0; i < params.Len(); i++ {
gep := b.CreateInBoundsGEP(deferFramePtr, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
forwardParam := b.CreateLoad(gep, "param")
gep := b.CreateInBoundsGEP(deferredCallType, deferData, []llvm.Value{zero, llvm.ConstInt(b.ctx.Int32Type(), uint64(i+2), false)}, "gep")
forwardParam := b.CreateLoad(valueTypes[i+2], gep, "param")
argValues = append(argValues, forwardParam)
}
+1 -11
View File
@@ -3,7 +3,6 @@ package compiler
// This file contains some utility functions related to error handling.
import (
"go/scanner"
"go/token"
"go/types"
"path/filepath"
@@ -20,20 +19,11 @@ func (c *compilerContext) makeError(pos token.Pos, msg string) types.Error {
}
}
// addError adds a new compiler diagnostic with the given location and message.
func (c *compilerContext) addError(pos token.Pos, msg string) {
c.diagnostics = append(c.diagnostics, c.makeError(pos, msg))
}
// errorAt returns an error value at the location of the instruction.
// The location information may not be complete as it depends on debug
// information in the IR.
func errorAt(inst llvm.Value, msg string) scanner.Error {
return scanner.Error{
Pos: getPosition(inst),
Msg: msg,
}
}
// getPosition returns the position information for the given value, as far as
// it is available.
func getPosition(val llvm.Value) token.Position {
+18 -65
View File
@@ -13,40 +13,11 @@ import (
// createFuncValue creates a function value from a raw function pointer with no
// context.
func (b *builder) createFuncValue(funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
return b.compilerContext.createFuncValue(b.Builder, funcPtr, context, sig)
}
// createFuncValue creates a function value from a raw function pointer with no
// context.
func (c *compilerContext) createFuncValue(builder llvm.Builder, funcPtr, context llvm.Value, sig *types.Signature) llvm.Value {
var funcValueScalar llvm.Value
switch c.FuncImplementation {
case "doubleword":
// Closure is: {context, function pointer}
funcValueScalar = funcPtr
case "switch":
sigGlobal := c.getTypeCode(sig)
funcValueWithSignatureGlobalName := funcPtr.Name() + "$withSignature"
funcValueWithSignatureGlobal := c.mod.NamedGlobal(funcValueWithSignatureGlobalName)
if funcValueWithSignatureGlobal.IsNil() {
funcValueWithSignatureType := c.getLLVMRuntimeType("funcValueWithSignature")
funcValueWithSignature := llvm.ConstNamedStruct(funcValueWithSignatureType, []llvm.Value{
llvm.ConstPtrToInt(funcPtr, c.uintptrType),
sigGlobal,
})
funcValueWithSignatureGlobal = llvm.AddGlobal(c.mod, funcValueWithSignatureType, funcValueWithSignatureGlobalName)
funcValueWithSignatureGlobal.SetInitializer(funcValueWithSignature)
funcValueWithSignatureGlobal.SetGlobalConstant(true)
funcValueWithSignatureGlobal.SetLinkage(llvm.InternalLinkage)
}
funcValueScalar = llvm.ConstPtrToInt(funcValueWithSignatureGlobal, c.uintptrType)
default:
panic("unimplemented func value variant")
}
funcValueType := c.getFuncType(sig)
// Closure is: {context, function pointer}
funcValueType := b.getFuncType(sig)
funcValue := llvm.Undef(funcValueType)
funcValue = builder.CreateInsertValue(funcValue, context, 0, "")
funcValue = builder.CreateInsertValue(funcValue, funcValueScalar, 1, "")
funcValue = b.CreateInsertValue(funcValue, context, 0, "")
funcValue = b.CreateInsertValue(funcValue, funcPtr, 1, "")
return funcValue
}
@@ -63,38 +34,20 @@ func (b *builder) extractFuncContext(funcValue llvm.Value) llvm.Value {
}
// decodeFuncValue extracts the context and the function pointer from this func
// value. This may be an expensive operation.
func (b *builder) decodeFuncValue(funcValue llvm.Value, sig *types.Signature) (funcPtr, context llvm.Value) {
// value.
func (b *builder) decodeFuncValue(funcValue llvm.Value) (funcPtr, context llvm.Value) {
context = b.CreateExtractValue(funcValue, 0, "")
switch b.FuncImplementation {
case "doubleword":
funcPtr = b.CreateExtractValue(funcValue, 1, "")
case "switch":
llvmSig := b.getRawFuncType(sig)
sigGlobal := b.getTypeCode(sig)
funcPtr = b.createRuntimeCall("getFuncPtr", []llvm.Value{funcValue, sigGlobal}, "")
funcPtr = b.CreateIntToPtr(funcPtr, llvmSig, "")
default:
panic("unimplemented func value variant")
}
funcPtr = b.CreateExtractValue(funcValue, 1, "")
return
}
// getFuncType returns the type of a func value given a signature.
func (c *compilerContext) getFuncType(typ *types.Signature) llvm.Type {
switch c.FuncImplementation {
case "doubleword":
rawPtr := c.getRawFuncType(typ)
return c.ctx.StructType([]llvm.Type{c.i8ptrType, rawPtr}, false)
case "switch":
return c.getLLVMRuntimeType("funcValue")
default:
panic("unimplemented func value variant")
}
return c.ctx.StructType([]llvm.Type{c.dataPtrType, c.funcPtrType}, false)
}
// getRawFuncType returns a LLVM function pointer type for a given signature.
func (c *compilerContext) getRawFuncType(typ *types.Signature) llvm.Type {
// getLLVMFunctionType returns a LLVM function type for a given signature.
func (c *compilerContext) getLLVMFunctionType(typ *types.Signature) llvm.Type {
// Get the return type.
var returnType llvm.Type
switch typ.Results().Len() {
@@ -122,24 +75,23 @@ func (c *compilerContext) getRawFuncType(typ *types.Signature) llvm.Type {
if recv.StructName() == "runtime._interface" {
// This is a call on an interface, not a concrete type.
// The receiver is not an interface, but a i8* type.
recv = c.i8ptrType
recv = c.dataPtrType
}
for _, info := range expandFormalParamType(recv, "", nil) {
for _, info := range c.expandFormalParamType(recv, "", nil) {
paramTypes = append(paramTypes, info.llvmType)
}
}
for i := 0; i < typ.Params().Len(); i++ {
subType := c.getLLVMType(typ.Params().At(i).Type())
for _, info := range expandFormalParamType(subType, "", nil) {
for _, info := range c.expandFormalParamType(subType, "", nil) {
paramTypes = append(paramTypes, info.llvmType)
}
}
// All functions take these parameters at the end.
paramTypes = append(paramTypes, c.i8ptrType) // context
paramTypes = append(paramTypes, c.i8ptrType) // parent coroutine
paramTypes = append(paramTypes, c.dataPtrType) // context
// Make a func type out of the signature.
return llvm.PointerType(llvm.FunctionType(returnType, paramTypes, false), c.funcPtrAddrSpace)
return llvm.FunctionType(returnType, paramTypes, false)
}
// parseMakeClosure makes a function value (with context) from the given
@@ -154,7 +106,7 @@ func (b *builder) parseMakeClosure(expr *ssa.MakeClosure) (llvm.Value, error) {
boundVars := make([]llvm.Value, len(expr.Bindings))
for i, binding := range expr.Bindings {
// The context stores the bound variables.
llvmBoundVar := b.getValue(binding)
llvmBoundVar := b.getValue(binding, getPos(expr))
boundVars[i] = llvmBoundVar
}
@@ -163,5 +115,6 @@ func (b *builder) parseMakeClosure(expr *ssa.MakeClosure) (llvm.Value, error) {
context := b.emitPointerPack(boundVars)
// Create the closure.
return b.createFuncValue(b.getFunction(f), context, f.Signature), nil
_, fn := b.getFunction(f)
return b.createFuncValue(fn, context, f.Signature), nil
}

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