420 Commits

Author SHA1 Message Date
Jake Bailey 9e9be09e9a testing: avoid Goexit without unwind support
Goexit cannot run deferred functions on architectures without panic
unwinding. Query runtime.supportsRecover before calling it so unsupported
targets report an error instead of leaving the test runner blocked forever.
2026-07-22 11:27:51 -07:00
Jake Bailey 9e7d89d4d5 compiler: pass large aggregates by pointer
LLVM ComputeValueVTs recursively expands arrays and structs into one
value type per scalar leaf. SelectionDAG call lowering allocates data
structures proportional to this count, which makes very large values
exhaust memory or crash LLVM.

Count scalar leaves and use pointers for internal parameters and results
when the count exceeds 1024. A result pointer is the first parameter,
and aggregate parameters point to read-only memory. Exported function
types are unchanged.

Keep these SSA values in memory and copy them with memcpy when needed.
Handle calls, interfaces, maps, channels, selects, defers, goroutines,
phis, and multiple results. Update the expected compiler IR and re-enable
the native compress/flate tests.
2026-07-22 11:22:03 -07:00
Jake Bailey bc35d087c2 compiler: move SSA result handling into helpers
createInstruction records each LLVM value in locals, emits stack object
tracking, and constructs function returns inline.

Move these operations to setValue and createReturn. This keeps the
instruction switch from having to know how an SSA value or function
result is emitted.
2026-07-22 11:22:03 -07:00
Jake Bailey deaf532d61 compiler: resolve callees before lowering arguments
createFunctionCall and createGo currently lower arguments before they
determine whether the call is direct, an interface invoke, or through a
function value.

Resolve the callee, function type, and context first, then append the
arguments in the same order as before. This does not change the
generated LLVM IR.
2026-07-22 11:22:03 -07:00
Jake Bailey 39a105dab9 compiler: centralize loads and stores of SSA values
Map, channel, index, and goroutine lowering each create allocas, store
SSA values into them, load results, and emit lifetime intrinsics.

Add helpers for these operations and use runtimeValueResult for runtime
calls that write a value and an optional comma-ok result. The generated
LLVM IR is unchanged.
2026-07-22 11:22:03 -07:00
Pat Whittingslow b536dd6f79 compiler: handle nested unsigned shift being untyped after type resolution (#5497)
* apply compiler patch for fix of #5496

* add compiler/testdata smoketest

* make diff error more explicit on difference

* apply golden fix
2026-07-22 07:35:18 +02:00
Nia Waldvogel cd4e479dd5 compiler: consistently pass layout and alignment to createAlloc 2026-07-21 07:15:43 +02:00
Evan Wies 35a61ac8c5 compiler: support file-level //go:linkname directives
Modern golang.org/x/sys/unix (v0.36+) declares its linknames
detached from function declarations, e.g.:

    func syscall_syscall(...)
    //go:linkname syscall_syscall syscall.syscall

TinyGo's pragma parser only inspected function doc comments and
therefore missed these, producing link errors like:

    undefined symbol: _golang.org/x/sys/unix.syscall_syscall

Extend parsePragmas to also walk the enclosing *ast.File's
free-standing comments for //go:linkname directives matching the
function's name. Function-attached directives still take
precedence. The existing 'unsafe' import gate is preserved.

Fixes #4395, #5365
2026-07-12 11:54:38 +02:00
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
Ayke van Laethem 7ffbcbc666 compiler: refactor runtime.alloc call
This refactor makes no other changes.
2026-06-25 21:09:43 +02:00
Ayke van Laethem ba95eb3e1b compiler: use LLVM intrinsics for math trig operations
I think this failed in the past, but presumably those failures have been
fixed by now. So these intrinsics can now be used.

Using these intrinsics instead of the native Go implementations helps
LLVM to reason about them: it can for example evaluate the value at
compile time or do optimizations like convert
`float32(math.Sin(float64(x)))` into a 32-bit sin operation. If the math
operation is not available on the target platform the C library
implementation will be used instead.
2026-06-25 18:31:58 +02:00
Jake Bailey 1b9bb143bf compiler: disambiguate function-local named types (#5336)
* compiler: make getTypeCodeName a method on compilerContext

* testdata: add regression tests for function-local named types

* compiler: disambiguate function-local named types

* Some PR feedback
2026-06-05 11:04:44 +02:00
Jake Bailey 278aa09819 compiler: share recoverable fault blocks 2026-06-04 19:25:47 +02:00
Jake Bailey eed4afda63 compiler, runtime: make runtime panics recoverable
Emit fault checkpoints around compiler-generated runtime assertions so
runtimePanicAt can unwind through the existing defer/recover machinery
instead of aborting. This lets panics from bounds checks, type checks,
and other compiler-inserted runtime checks be recovered by deferred
functions.

Mark functions that call recover as noinline. Inlining such a function
into a deferred closure can make recover observe the wrong call context
and report success when it should return nil.

Addresses tinygo-org/tinygo issues 2759 and 3510.
2026-06-04 19:25:47 +02:00
Ayke van Laethem 85d223c5e2 compiler: add //go:noheap pragma 2026-05-25 16:58:01 +02:00
Ayke van Laethem 7b486e398a compiler: clean up pointer pack code
This means runtime.alloc isn't allocated every time but instead only
when it is actually needed. It also just cleans up the compiler code a
little bit, and makes the next commit a bit nicer.
2026-05-25 16:58:01 +02:00
deadprogram ddacdfacd5 compiler, runtime: fix SyscallN handling for Windows on Go 1.26+
Go 1.26 changed all Windows syscall wrappers in zsyscall_windows.go
to use SyscallN instead of fixed-argument Syscall/Syscall6/etc. The
SyscallN function now has a body that calls an unexported syscalln
function (provided by runtime via //go:linkname).

TinyGo's existing createSyscall compiler builtin used call.Args[2:]
to extract syscall arguments, but for variadic SyscallN the SSA
representation passes args as a slice value (not individual args),
causing call.Args[2:] to be empty -- resulting in zero arguments
being passed to Windows API calls and 0xc0000005 access violations.

Fix this by:
1. Excluding syscall.SyscallN from builtin interception, letting
   Go 1.26's function body compile normally (it calls syscalln)
2. Adding a new createSyscalln compiler builtin that intercepts
   syscall.syscalln and correctly handles the variadic slice:
   - Generates a switch on the arg count n (0-18 cases)
   - Each case loads args from the slice via GEP/Load
   - Wraps calls with SetLastError(0)/GetLastError() as before
   - Handles i386 stdcall conventions
3. Adding runtime stubs for both Go versions:
   - go1.26: syscall.syscalln stub (body intercepted by compiler)
   - pre-go1.26: syscall.SyscallN stub (linker satisfaction)
2026-04-11 12:38:36 +01:00
Damian Gryski f496571747 compiler: add instrinsic for crypto/internal/constanttime.boolToUint8 2026-04-11 12:38:36 +01:00
Nia Waldvogel a40586d092 compiler: implement copy directly
The compiler now implements the copy builtin directly instead of calling sliceCopy.
The length is calculated with the llvm.umax.* intrinsics, and the move is performed by llvm.memmove.*.
Both of these operations are easily understood by LLVM's optimization passes.
The type's alignment is also provided to llvm.memmove.*, which is useful when rewriting the move.

Interp no longer needs to reimplement sliceCopy.
Some edge case handling was implemented by sliceCopy but not llvm.memmove.*/llvm.memcpy.*.
I copied this over, so copies of external slices should work now.
Volatile moves/copies are now run at runtime by interp.

There is a 4-byte size increase due to some confusing length logic in sendUSBPacket.
I will look at sendUSBPacket in a future PR.
2026-01-05 15:10:31 -05:00
Nia Waldvogel bc9708f51a compiler: fix min/max on floats by using intrinsics
This fixes two edge cases for min/max:
min/max(+0.0, -0.0) = -0.0, +0.0
min/max(number, NaN) = NaN, NaN

The compare and select method does not work here.
I switched to the llvm.minimum/llvm.maximum intrinsics which match the intended behavior.

The integer min/max were also swapped over to using intrinsics.
The compare and select path is now only used by strings.
2026-01-05 19:46:06 +00:00
Nia Waldvogel 266d70816f compiler/runtime: add element layout to sliceAppend
Attach the memory layout of the element type to newly created slices via append when using the precise collector.
2025-12-26 21:27:24 -05:00
Nia Waldvogel 852dde671e compiler: use Tarjan's SCC algorithm to detect loops for defer
The compiler needs to know whether a defer is in a loop to determine whether to allocate stack or heap memory.
Previously, this performed a DFS of the CFG every time a defer was found.
This resulted in time complexity jointly proportional to the number of defers and the number of blocks in the function.

Now, the compiler will instead use Tarjan's strongly connected components algorithm to find cycles in linear time.
The search is performed lazily, so this has minimal performance impact on functions without defers.

In order to implement Tarjan's SCC algorithm, additional state needed to be attached to the blocks.
I chose to merge all of the per-block state into a single slice to simplify memory management.
2025-11-10 07:27:40 +01:00
Ayke van Laethem 3a2188fc7b runtime/interrupt: add Checkpoint type
This type can be used to jump back to a previous position in a program
from inside an interrupt. This is useful for baremetal systems that
implement wfi but not wfe, and therefore have no easy (race-free) way to
wait until a flag gets changed inside an interrupt. This is an issue on
RISC-V, where this is racy (the interrupt might happen after the check
but before the wfi instruction):

    configureInterrupt()
    for flag.Load() != 0 {
        riscv.Asm("wfi")
    }
2025-06-12 21:04:36 +02:00
Ayke van Laethem 64a30424da runtime: add exportedFuncPtr
This function isn't used yet, but will be used for the "cores" scheduler
for RISC-V.
2025-06-12 21:04:36 +02:00
Ayke van Laethem 2e043c7fbc compiler: add support for GODEBUG=gotypesalias=1
Since we now require Go 1.22, this became a lot simpler (since we can
now refer to `types.Alias` and `types.Unalias`).
2025-05-24 19:49:49 +02:00
Damian Gryski 0fdf08d14f add -nobounds (similar to -gcflags=-B) 2025-04-15 12:55:44 +02: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 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
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 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
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
Ayke van Laethem 8b626e6ea7 compiler: add support for Go 1.23 range-over-func 2024-08-17 11:49:14 +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
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
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
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
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
Damian Gryski 2867da164d Allow larger systems to have a larger max stack alloc
Fixes #3331
2024-01-31 17:51:55 +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
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
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
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 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
Damian Gryski 4326c8f10e compiler: ensure all defers have been seen before creating rundefers
Fixes #3643
2023-04-11 18:54:05 -07: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 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
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