Граф коммитов

35 коммитов

Автор SHA1 Сообщение Дата
Ayke van Laethem
5510dec846 compiler: add location information to the IR checker 2019-12-21 20:49:51 +01:00
Ayke van Laethem
374349cfa5 compiler: refactor func lowering to the transform package
This commit makes a number of changes:

  * It avoids a dependency on Compiler.emitStartGoroutine.
  * It moves the func-lowering pass to the transform package.
  * It adds testing to func lowering.

No functionality should have changed with this commit.
2019-12-04 22:19:49 +01:00
Ayke van Laethem
f0bb3c092d compiler: move GC passes to the transform package 2019-11-25 09:14:31 +01:00
Ayke van Laethem
172efc26a7 compiler: move ReplacePanicsWithTrap pass to transforms
This moves the transformation pass to the right location, and adds tests
to see that it actually works correctly.
2019-11-16 18:41:28 +01:00
Ayke van Laethem
e20af665fa compiler,transform: move interface lowering to transform package 2019-11-15 23:37:17 +01:00
Ayke van Laethem
3b0ed63c29 all: refactor compile options
Move most of the logic of determining which compiler configuration to
use (such as GOOS/GOARCH, build tags, whether to include debug symbols,
panic strategy, etc.) into the compileopts package. This makes it a
single source of truth for anything related to compiler configuration.

It has a few advantages:

  * The compile configuration is independent of the compiler package.
    This makes it possible to move optimization passes out of the
    compiler, as they don't rely on compiler.Config anymore.
  * There is only one place to look if an incorrect compile option is
    used.
  * The compileopts provides some resistance against unintentionally
    picking the wrong option, such as with c.selectGC() vs c.GC() in the
    compiler.
  * It is now a lot easier to change compile options, as most options
    are getters now.
2019-11-04 11:45:35 +01:00
Jaden Weiss
388d11eecf use error returns to generate detailed error messages in the IR checker 2019-10-25 15:50:03 +02:00
Jaden Weiss
d843ebfe40 Improved blocking (#513)
core: major improvements to blocking, including support for buffered channels.
2019-09-22 17:58:00 +02:00
Ayke van Laethem
65beddafe8 compiler: move OptimizeStringToBytes to transform package
Unfortunately, while doing this I found that it doesn't actually apply
in any real-world programs (tested with `make smoketest`), apparently
because nil pointer checking messes with the functionattrs pass. I hope
to fix that after moving to LLVM 9, which has an optimization that makes
nil pointer checking easier to implement.
2019-09-22 08:25:50 +02:00
Jaden Weiss
abca3132a9 fix bugs found by LLVM assertions 2019-09-16 18:31:33 +02:00
Ayke van Laethem
8cd2c7502e all: move OptimizeMaps to transforms and add tests 2019-09-15 21:26:27 +02:00
Ayke van Laethem
d905476231 all: refactor heap-to-stack transform into the transform package
Also add unit tests.

This is the first of several transformation (optimization/lowering)
passes that I'd like to move to the new transform package. This
separates the compiler from the optimizer.

Also, it finally adds unit tests for the compiler, not just end-to-end
compilation tests. This should improve robustness and should make it
easier to change these transformation passes in the future.
While the heap-to-stack transform is relatively simple, other passes are
much more complex. Adding unit tests not only helps robustness over
time, but also doubles as documentation as to what these transformation
passes do exactly.
2019-09-15 21:26:27 +02:00
Ayke van Laethem
10ed3decb0 compiler: rename getZeroValue to llvm.ConstNull
It does the same thing but should be more complete, and it probably is
faster as well (just one CGo call instead of several).
2019-09-15 19:09:10 +02:00
Ayke van Laethem
542135c357 compiler,runtime: implement stack-based scheduler
This scheduler is intended to live along the (stackless) coroutine based
scheduler which is needed for WebAssembly and unsupported platforms. The
stack based scheduler is somewhat simpler in implementation as it does
not require full program transform passes and supports things like
function pointers and interface methods out of the box with no changes.

Code size is reduced in most cases, even in the case where no scheduler
scheduler is used at all. I'm not exactly sure why but these changes
likely allowed some further optimizations somewhere. Even RAM is
slightly reduced, perhaps some global was elminated in the process as
well.
2019-08-15 17:31:54 +02:00
Ayke van Laethem
385d1d0a5d
compiler,runtime: implement a portable conservative GC 2019-07-01 16:30:33 +02:00
Ayke van Laethem
a79edf416c cgo: do not allow capturing of external/exported functions
Instead of assuming all declared (but not defined) functions are CGo
functions, mark all pointer params of externally visible symbols
'nocapture'. This means you may not store pointers between function
calls.

This is already the case when calling CGo functions upstream:
https://golang.org/cmd/cgo/#hdr-Passing_pointers
2019-05-05 20:56:35 +02:00
Ayke van Laethem
6d23809218 compiler: simplify code around getZeroValue
The LLVM library we use does not (yet) provide a llvm.Zero (like it
provides a llvm.Undef) so we have implemented our own. However, in
theory it might return an error in some cases.

No real-world errors have been seen in a while and errors would likely
indicate a serious compiler bug anyway (not an external error), so make
it panic instead of returning an error.
2019-04-26 08:52:10 +02:00
Ayke van Laethem
0fd90c49cc compiler: make panic configurable
Currently defined: abort and trap. -panic=unwind should be implemented
in the future.
2019-04-25 13:56:19 +02:00
Ayke van Laethem
2a0a7722f9 compiler: lower func values to switch + direct call
This has several advantages, among them:
  - Many passes (heap-to-stack, dead arg elimination, inlining) do not
    work with function pointer calls. Making them normal function calls
    improves their effectiveness.
  - Goroutine lowering to LLVM coroutines does not currently support
    function pointers. By eliminating function pointers, coroutine
    lowering gets support for them for free.
    This is especially useful for WebAssembly.
Because of the second point, this work is currently only enabled for the
WebAssembly target.
2019-04-17 23:12:59 +02:00
Ayke van Laethem
d653088cbe compiler: fix escapes due to nil checks
Some tests get bigger, most get smaller. However, all tested driver
examples get smaller in size showing that this is a good change in the
real world.
2019-04-04 09:32:30 +02:00
Ayke van Laethem
38f8cf7bee compiler: imporove escape analysis to allow icmp
The icmp instruction is often used in nil checks, so this instruction
happens very frequently now that TinyGo automatically inserts nil checks
everywhere. Escape analysis would conservatively mark such pointers as
escaping, which they obviously don't.
This commit improves escape analysis to allow icmp instructions.
2019-04-03 16:38:08 +02:00
Ayke van Laethem
9092dbcc53
all: rename go-llvm to new import path
the new import path is:

    tinygo.org/x/go-llvm
2019-01-27 19:26:16 +01:00
Ayke van Laethem
602c264749
all: rewrite goroutine lowering
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.
2019-01-21 22:09:33 +01:00
Ayke van Laethem
18b16fc151
compiler: run some optimizations after interface lowering
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.
2018-12-22 19:06:01 +01:00
Ayke van Laethem
5a15d4162d
compiler: add optsize function attr to reduce binary size
This is also added by Clang at -Oz and results in slightly smaller
binaries.
2018-12-22 18:58:43 +01:00
Ayke van Laethem
b4c90f3677
compiler: lower interfaces in a separate pass
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.
2018-12-01 13:26:06 +01:00
Ayke van Laethem
100901574b
compiler: let escape analysis look across bitcasts
This is necessary to avoid memory allocation in the math packages in
some functions.
2018-11-16 23:03:38 +01:00
Ayke van Laethem
317b12b8c0
compiler: remove println statement
I forgot to remove this debug print after I wrote the code...
2018-10-29 18:18:23 +01:00
Ayke van Laethem
2a5c331516
compiler: assume external functions don't let pointers escape
Assume any external function won't let pointers live longer than the
call itself. This is true in the vast majority of cases (apparently
everywhere currently) but might not always be true.

TODO: add a //go:noescape (or maybe //go:escape) to handle this, instead
of this assumption.
2018-10-29 14:04:55 +01:00
Ayke van Laethem
cb0a148cd7
compiler: fix map optimization
Not all uses of a map are call instructions. Don't assume they are.
TODO: investigate these uses and see whether they might be eliminated?
2018-10-24 12:37:47 +02:00
Ayke van Laethem
52199f4a14
compiler: eliminate created but never used maps 2018-10-12 17:00:39 +02:00
Ayke van Laethem
25e73a5439
compiler: align and zero-initialize stack allocated values 2018-10-12 16:57:17 +02:00
Ayke van Laethem
ec73bd6a26
compiler: optimize runtime.stringToBytes calls
This optimization makes sure the following pattern doesn't do a heap
allocation (assuming Write doesn't modify the slice):

    var w *machine.UART = ...
    w.Write([]byte("foo"))

As long as Write doesn't modify the slice and LLVM can detect this, a
call to runtime.stringToBytes with the necessary allocation + copy is
avoided.
2018-10-09 14:18:12 +02:00
Ayke van Laethem
4219652535
compiler: add basic heap-to-stack optimization 2018-10-09 14:14:52 +02:00
Ayke van Laethem
5db43e8d04
compiler: move Optimize() function to a separate file
In the future, there will be more optimizations. Let's keep them in a
separate file for separation of concerns.
2018-10-06 19:57:41 +02:00