Move these asserts into compiler/asserts.go, to keep them together.
The make([]T) asserts aren't moved yet because that code is (still!)
quite ugly and in need of some clean up.
This commit implements nil checks for all platforms. These nil checks
can be optimized on systems with a MMU, but since a major target is
systems without MMU, keep it this way for now.
It implements three checks:
* Nil checks before dereferencing a pointer.
* Nil checks before calculating an address (*ssa.FieldAddr and
*ssa.IndexAddr)
* Nil checks before calling a function pointer.
The first check has by far the biggest impact, with around 5% increase
in code size. The other checks only trigger in only some test cases and
have a minimal impact on code size.
This first nil check is also the one that is easiest to avoid on systems
with MMU, if necessary.
In LLVM 8, the AVR backend has moved all function pointers to address
space 1 by default. Much of the code still assumes function pointers
live in address space 0, leading to assertion failures.
This commit fixes this problem by autodetecting function pointers and
avoiding them in interface pseudo-calls.
Without this, the following code would not panic:
func getInt(i int) { return i }
make([][1<<18], getInt(1<<18))
Or this code would be allowed to compile for 32-bit systems:
make([][1<<18], 1<<18)
Previously, this would have resulted in a LLVM verification error
because runtime.sliceBoundsCheckMake would not accept 64-bit integers on
these platforms.
The interp package does a much better job at interpretation, and is
implemented as a pass on the IR which makes it much easier to compose.
Also, the implementation works much better as it is based on LLVM IR
instead of Go SSA.
Match data layout of complex numbers to that of Clang, for better
interoperability. This makes alignment of complex numbes the same as the
individual elements (real and imaginary), as is required by the C spec
and implemented in Clang, but unlike the gc compler. The Go language
specification is silent on this matter.
> Each complex type has the same object representation and alignment
> requirements as an array of two elements of the corresponding real
> type (float for float complex, double for double complex, long double
> for long double complex). The first element of the array holds the
> real part, and the second element of the array holds the imaginary
> component.
Source: https://en.cppreference.com/w/c/language/arithmetic_types
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.
This commit makes sure all Go types can be encoded in the interface type
code, so that Type.Kind() always returns a proper type kind for any
non-nil interface.
This makes sure the most commonly used types have the lowest type codes.
This was intended to be the case, but apparently I forgot to sort them
the right way.
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%).
By running these interprocedural optimizations after interface lowering,
in particular the heap-to-stack transformation pass, interfaces can be
zero cost in some more cases.
For example, say you have the following interface:
type Writer interface {
Write([]byte) (int, error)
}
and you do something with it:
func foo(w io.Writer) {
w.Write([]byte("foo"))
}
this commit enables escape analysis across interface boundaries, which
means that the Write call does not cause an allocation if all
implementations of io.Writer do not let the slice escape. This enables
broader uses of interfaces, as they are now a zero-cost abstraction in
more cases.
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