54 Commits

Author SHA1 Message Date
Jake Bailey 7c3dc05117 all: modernize (#5498)
* modernize string cut usage

* modernize string cut prefix usage

* modernize slices helper usage

* modernize min and max usage

* modernize loop variable copies

* modernize integer range loops

* modernize map copy loops

* modernize go types iterator usage

* modernize empty interface usage

* modernize atomic type usage

* modernize string builders

* modernize string split iteration

* modernize remaining loop variable copies

* modernize usb cdc min usage

* modernize src integer range loops

* modernize example empty interface usage

* modernize src min and max usage

* modernize src integer range loops

* modernize src empty interface usage

* modernize src atomic type usage

* modernize reflect type lookups

* modernize review nits
2026-07-06 21:58:48 +02:00
Piotr Bocheński 4465360f3d transform: add -print-allocs-cover and restore -print-allocs reason output
PR #5220 changed -print-allocs output to the go coverage tool format, which
replaced the original human-readable explanation of why each object had to be
heap allocated. That explanation is useful on its own, so this restores it as
the default behavior of -print-allocs and moves the coverage format behind a
-print-allocs-cover flag.

Signed-off-by: Piotr Bocheński <piotr@bochen.ski>
2026-06-12 19:57:08 +02:00
Jake Bailey 89d9e33bca interp: bail out of loops that iterate too many times (#5395)
* interp: bail out of loops that iterate too many times

The existing loop guard (errLoopUnrolled) only fires when a loop body
emits runtime instructions. Loops that are fully evaluable at compile
time, such as inserting thousands of entries into a map, were not
caught and could hang the compiler.

Add a per-basic-block iteration counter that triggers a recoverable
error (errLoopTooLong) when any block is entered more than 1000 times
in a single function call. This defers the init function to runtime,
which is the same behavior as other interp bailouts.

Profiling showed that 83% of CPU time was spent in GC, caused by
allocation pressure from the interp memory cloning on each map
mutation. The iteration limit avoids this entirely by bailing out
before the quadratic cost becomes significant.

Performance on the reproducer from #2090 (map init with strconv.Itoa):

    entries  before       after
    5,000    7.4s         2.1s
    10,000   17.5s        2.1s
    20,000   48.0s        2.8s
    65,536   >180s (OOM)  3.2s

* Add -interp-loop-limit
2026-05-17 20:42:27 +02:00
sivchari 4d62cca267 feature: Add flag to ignore go compatibility matrix (#5078)
* add go-compatibility feature

Signed-off-by: sivchari <shibuuuu5@gmail.com>

* rename env

Signed-off-by: sivchari <shibuuuu5@gmail.com>

* fix description

Signed-off-by: sivchari <shibuuuu5@gmail.com>

---------

Signed-off-by: sivchari <shibuuuu5@gmail.com>
2025-11-06 21:28:06 +01:00
Ayke van Laethem 60f8a62978 all: add support for multicore scheduler
This commit adds support for a scheduler that runs a scheduler on all
available cores. It is meant to be used on baremetal systems with a
fixed number of cores, such as the RP2040.

The initial implementation adds support for multicore scheduling to the
riscv-qemu target as a convenient testing target. This means that this
new multicore scheduler is tested in CI, including a bunch of standard
library tests (`make tinygo-test-baremetal`). This should ensure the new
scheduler is reasonably well tested before trying to use it on
harder-to-debug targets like the RP2040.
2025-06-12 21:04:36 +02:00
Ayke van Laethem c2765e9eca main: change -json flag to match upstream Go
This changes the -json flag for build/run/flash/gdb etc commands to not
print `compileopts.Config` but instead match upstream Go and print build
errors in a structured way.

For more details, see the proposal:
https://github.com/golang/go/issues/62067
2025-04-23 12:39:23 +02:00
Damian Gryski 0fdf08d14f add -nobounds (similar to -gcflags=-B) 2025-04-15 12:55:44 +02:00
Ayke van Laethem 120d17c124 runtime: map every goroutine to a new OS thread
This is not a scheduler in the runtime, instead every goroutine is
mapped to a single OS thread - meaning 1:1 scheduling.

While this may not perform well (or at all) for large numbers of
threads, it greatly simplifies many things in the runtime. For example,
blocking syscalls can be called directly instead of having to use epoll
or similar. Also, we don't need to do anything special to call C code -
the default stack is all we need.
2025-04-11 15:18:41 +02:00
Ayke van Laethem 3a7c25f987 all: add the Boehm-Demers-Weiser GC on Linux
This adds support for the well-known Boehm GC. It's significantly faster
than our own naive GC and could be used as an alternative on bigger
systems.

In the future, this GC might also be supported on WebAssembly with some
extra work. Right now it's Linux only (though Windows/MacOS shouldn't be
too difficult to add).
2025-03-18 10:31:38 +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 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
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 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 892efaec97 support -extldflags
Fixes #4320
2024-09-18 08:05:25 +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
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 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 8d2a07b927 main: add -serial=rtt support 2023-12-23 08:14:35 -05: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
Anuraag Agrawal eebd2f648b Add -gc=custom option (#3302)
* Add -gc=custom option
2023-01-28 20:24:56 +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
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
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 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
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
sago35 80f38e8449 main: add serial port monitoring functionality
Co-authored-by: Ayke <aykevanlaethem@gmail.com>
2022-09-16 09:28:03 +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
Damian Gryski 0b77e92c50 make interp timeout configurable from command line 2022-08-20 07:40:39 +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 234234af15 build: add JSON output to build command 2022-03-24 05:51:38 +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
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
Nia Waldvogel ea2a6b70b2 internal/task: remove coroutines 2022-01-19 14:42:02 -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 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
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
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
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 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 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 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
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 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 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 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 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
Fauchon c4d642007e New tinygo -x option to print commands (#1572)
main: add '-x' runtime flag that displays the executed external commands when performing operations like flashing.
2021-01-14 21:35:01 +01:00
Ayke van Laethem da0161d6ab wasm: implement a growable heap
On WebAssembly it is possible to grow the heap with the memory.grow
instruction. This commit implements this feature and with that also
removes the -heap-size flag that was reportedly broken (I haven't
verified that). This should make it easier to use TinyGo for
WebAssembly, where there was no good reason to use a fixed heap size.

This commit has no effect on baremetal targets with optimizations
enabled.
2021-01-10 21:08:52 +01:00
Ayke van Laethem d606315515 builder: try to determine stack size information at compile time
For now, this is just an extra flag that can be used to print stack
frame information, but this is intended to provide a way to determine
stack sizes for goroutines at compile time in many cases.

Stack sizes are often somewhere around 350 bytes so are in fact not all
that big usually. Once this can be determined at compile time in many
cases, it is possible to use this information when available and as a
result increase the fallback stack size if the size cannot be determined
at compile time. This should reduce stack overflows while at the same
time reducing RAM consumption in many cases.

Interesting output for testdata/channel.go:

    function                                 stack usage (in bytes)
    Reset_Handler                            332
    .Lcommand-line-arguments.fastreceiver    220
    .Lcommand-line-arguments.fastsender      192
    .Lcommand-line-arguments.iterator        192
    .Lcommand-line-arguments.main$1          184
    .Lcommand-line-arguments.main$2          200
    .Lcommand-line-arguments.main$3          200
    .Lcommand-line-arguments.main$4          328
    .Lcommand-line-arguments.receive         176
    .Lcommand-line-arguments.selectDeadlock  72
    .Lcommand-line-arguments.selectNoOp      72
    .Lcommand-line-arguments.send            184
    .Lcommand-line-arguments.sendComplex     192
    .Lcommand-line-arguments.sender          192
    .Lruntime.run$1                          548

This shows that the stack size (if these numbers are correct) can in
fact be determined automatically in many cases, especially for small
goroutines. One of the great things about Go is lightweight goroutines,
and reducing stack sizes is very important to make goroutines
lightweight on microcontrollers.
2020-07-11 14:47:43 +02:00