LLVM supports both "ordered" and "unordered" floating point comparisons.
The difference is that unordered comparisons ignore NaN and produce
incorrect results when presented with a NaN value.
This commit switches these comparisons from ordered to unordered.
Extract directly from the string instead of calling the len() builtin.
This is both cleaner and avoids a zero-extension to an integer on AVR,
which led to a LLVM verification error.
Support for channels is not complete. The following pieces are missing:
* Channels with values bigger than int. An int in TinyGo can always
contain at least a pointer, so pointers are okay to send.
* Buffered channels.
* The select statement.
Before this commit, goroutine support was spread through the compiler.
This commit changes this support, so that the compiler itself only
generates simple intrinsics and leaves the real support to a compiler
pass that runs as one of the TinyGo-specific optimization passes.
The biggest change, that was done together with the rewrite, was support
for goroutines in WebAssembly for JavaScript. The challenge in
JavaScript is that in general no blocking operations are allowed, which
means that programs that call time.Sleep() but do not start goroutines
also have to be scheduled by the scheduler.
This commit does two things:
* It adds support for the GOOS and GOARCH environment variables. They
fall back to runtime.GO* only when not available.
* It adds support for 3 new architectures: 386, arm, and arm64. For
now, this is Linux-only.
* all: add support for specifying target CPU in target config
* avr: specify the chip name in the target CPU
This reduces code size by a large margin. For examples/blinky, it
reduces code size from 1360 to 1266 when compiling for the Arduino Uno
(94 bytes, or ~7%).
This reduces complexity in the compiler without affecting binary sizes
too much.
Cortex-M0: no changes
Linux x64: no changes
WebAssembly: some testcases (calls, coroutines, map) are slightly bigger
Implement defer in a different way, which results in smaller binaries.
The binary produced from testdata/calls.go (the only test case with
defer) is reduced a bit in size, but the savings in bytes greatly vary
by architecture:
Cortex-M0: -96 .text / flash
WebAssembly: -215 entire file
Linux x64: -32 .text
Deferred functions in TinyGo were implemented by creating a linked list
of struct objects that contain a function pointer to a thunk, a pointer
to the next object, and a list of parameters. When it was time to run
deferred functions, a helper runtime function called each function
pointer (the thunk) with the struct pointer as a parameter. This thunk
would then in turn extract the saved function parameter from the struct
and call the real function.
What this commit changes, is that the loop to call deferred functions is
moved into the end of the function (practically inlining it) and
replacing the thunks with direct calls inside this loop. This makes it
much easier for LLVM to perform all kinds of optimizations like inlining
and dead argument elimination.
This simplifies the ABI a lot and makes future changes easier.
In the future, determining which functions need a context parameter
should be moved from IR generation into an optimization pass, avoiding
the need for recursively scanning the Go SSA.
This commit changes many things:
* Most interface-related operations are moved into an optimization
pass for more modularity. IR construction creates pseudo-calls which
are lowered in this pass.
* Type codes are assigned in this interface lowering pass, after DCE.
* Type codes are sorted by usage: types more often used in type
asserts are assigned lower numbers to ease jump table construction
during machine code generation.
* Interface assertions are optimized: they are replaced by constant
false, comparison against a constant, or a typeswitch with only
concrete types in the general case.
* Interface calls are replaced with unreachable, direct calls, or a
concrete type switch with direct calls depending on the number of
implementing types. This hopefully makes some interface patterns
zero-cost.
These changes lead to a ~0.5K reduction in code size on Cortex-M for
testdata/interface.go. It appears that a major cause for this is the
replacement of function pointers with direct calls, which are far more
susceptible to optimization. Also, not having a fixed global array of
function pointers greatly helps dead code elimination.
This change also makes future optimizations easier, like optimizations
on interface value comparisons.
Move attaching debug info to where the function is defined. As LLVM does
not allow setting debug info on declarations, this makes more sense and
is less error-prone.
This commit fixes debug info when using CGo.
* Use 64-bit integers on 64-bit platforms, just like gc and gccgo:
https://golang.org/doc/go1.1#int
* Do not use a separate length type. Instead, use uintptr everywhere a
length is expected.
To support the WebAssembly<->JS barrier, return values also have to be
passed in memory. i64 return values are used by syscall/js, so must be
supported across this ABI barrier.
This makes it easier to get an overview of everything interface related,
because interfaces are quite complicated and were scattered through the
(huge!) compiler.go file.
This interpreter currently complements the Go SSA level interpreter. It
may stay complementary or may be the only interpreter in the future.
This interpreter is experimental and not yet finished (there are known
bugs!) so it is disabled by default. It can be enabled by passing the
-initinterp flag.
The goal is to be able to run all initializations at compile time except
for the ones having side effects. This mostly works except perhaps for a
few edge cases.
In the future, this interpeter may be used to actually run regular Go
code, perhaps in a shell.
I don't know why they sometimes have them, but apparently some packages
do. Don't panic in that case, the interpreter will stop anyway on the
first branch.
In Go, function pointers are not comparable. This means that the address
itself is not significant and functions can therefore be merged.
Add the unnamed_addr attribute to all functions to learn LLVM about this
fact. At the moment the mergefunc pass hasn't been enabled, but it
should be in the future to reduce code size.