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

382 коммитов

Автор SHA1 Сообщение Дата
Ayke van Laethem
b61751e429 compiler: check for errors
Some errors were generated but never returned or never checked in the
test function. That's a problem. Therefore this commit fixes this
oversight (by me).
2021-04-09 14:05:44 +02:00
Ayke van Laethem
0b7957d612 compiler: optimize string literals and globals
This commit optimizes string literals and globals by setting the
appropriate alignment and using a nil pointer in zero-length strings.

  - Setting the alignment for string values has a surprisingly large
    effect, up to around 2% in binary size. I suspect that LLVM will
    pick some default alignment for larger byte arrays if no alignment
    has been specified and forcing an alignment of 1 will pack all
    strings closer together.
  - Using nil for zero-length strings also has a positive effect, but
    I'm not sure why. Perhaps it makes some optimizations more trivial.
  - Always setting the alignment on globals improves code size slightly,
    probably for the same reasons setting the alignment of string
    literals improves code size. The effect is much smaller, however.

This commit might have an effect on performance, but if it does this
should be tested separately and such a large win in binary size should
definitely not be ignored for small embedded systems.
2021-04-08 11:40:59 +02:00
Ayke van Laethem
61243f6c57 transform: don't rely on struct name of runtime.typecodeID
Sometimes, LLVM may rename named structs when merging modules.
Therefore, we can't rely on typecodeID structs to retain their struct
names.

This commit changes the interface lowering pass to not rely on these
names. The interp package does however still rely on this name, but I
hope to fix that in the future.
2021-04-08 11:40:59 +02:00
Ayke van Laethem
b44d41d9ec compiler: fix "fragment covers entire variable" bug
This bug could sometimes be triggered by syscall/js code it seems. But
it's a generic bug, not specific to WebAssembly.
2021-03-29 10:16:59 +02:00
Ayke van Laethem
bcce296ca3 transform: optimize reflect.Type Implements() method
This commit adds a new transform that converts reflect Implements()
calls to runtime.interfaceImplements. At the moment, the Implements()
method is not yet implemented (how ironic) but if the value passed to
Implements is known at compile time the method call can be optimized to
runtime.interfaceImplements to make it a regular interface assert.

This commit is the last change necessary to add basic support for the
encoding/json package. The json package is certainly not yet fully
supported, but some trivial objects can be converted to JSON.
2021-03-28 14:00:37 +02:00
Ayke van Laethem
19dec048b0 compiler: do not check for impossible type asserts
Previously there was code to avoid impossible type asserts but it wasn't
great and in fact was too aggressive when combined with reflection.

This commit improves this by checking all types that exist in the
program that may appear in an interface (even struct fields and the
like) but without creating runtime.typecodeID objects with the type
assert. This has two advantages:

  * As mentioned, it optimizes impossible type asserts away.
  * It allows methods on types that were only asserted on (in
    runtime.typeAssert) but never used in an interface to be optimized
    away using GlobalDCE. This may have a cascading effect so that other
    parts of the code can be further optimized.

This sometimes massively improves code size and mostly negates the code
size regression of the previous commit.
2021-03-23 14:32:33 +01:00
Ayke van Laethem
bbb2909283 compiler: merge runtime.typecodeID and runtime.typeInInterface
This distinction was useful before when reflect wasn't properly
supported. Back then it made sense to only include method sets that were
actually used in an interface. But now that it is possible to get to
other values (for example, by extracting fields from structs) and it is
possible to turn them back into interfaces, it is necessary to preserve
all method sets that can possibly be used in the program in a type
assert, interface assert or interface method call.

In the future, this logic will need to be revisited again when
reflect.New or reflect.Zero gets implemented.

Code size increases a bit in some cases, but usually in a very limited
way (except for one outlier in the drivers smoke tests). The next commit
will improve the situation significantly.
2021-03-23 14:32:33 +01:00
Ayke van Laethem
c522569378 wasm: only export explicitly exported functions
Previously we used the --export-all linker flag to export most
functions. However, this is not needed and possibly increases binary
size. Instead, we should be exporting the specific functions to be
exported.
2021-03-22 13:48:12 +01:00
Ayke van Laethem
e2f532709f builder, compiler: compile and cache packages in parallel
This commit switches from the previous behavior of compiling the whole
program at once, to compiling every package in parallel and linking the
LLVM bitcode files together for further whole-program optimization.
This is a small performance win, but it has several advantages in the
future:

  - There are many more things that can be done per package in parallel,
    avoiding the bottleneck at the end of the compiler phase. This
    should speed up the compiler futher.
  - This change is a necessary step towards a non-LTO build mode for
    fast incremental builds that only rebuild the changed package, when
    compiler speed is more important than binary size.
  - This change refactors the compiler in such a way that it will be
    easier to inspect the IR for one package only. Inspecting this IR
    will be very helpful for compiler developers.
2021-03-21 11:51:35 +01:00
Ayke van Laethem
dc1ff80e10 compiler: remove SimpleDCE pass
The SimpleDCE pass was previously used to only compile the parts of the
program that were in use. However, lately the only real purpose has been
to speed up the compiler a bit by only compiling the necessary
functions.

This pass however is a problem for compiling (and caching) packages in
parallel. Therefore, this commit removes it as a preparatory step
towards that goal.
2021-03-21 11:51:35 +01:00
Ayke van Laethem
13db2c13e5 compiler: do not use llvm.GlobalContext()
This is a leftover from a long time ago, when everything was still in
the global context. The fact that this uses the global context is most
certainly a bug.

I have seen occasional crashes in the build-packages-indepedently branch
(and PRs based on it) which I suspect are caused by this bug. I think
this is a long-dormant bug that only surfaced when doing the compilation
steps in parallel.
2021-03-18 16:49:33 +01:00
Ayke van Laethem
9612af466b compiler: move settings to a separate Config struct
Moving settings to a separate config struct has two benefits:
  - It decouples the compiler a bit from other packages, most
    importantly the compileopts package. Decoupling is generally a good
    thing.
  - Perhaps more importantly, it precisely specifies which settings are
    used while compiling and affect the resulting LLVM module. This will
    be necessary for caching the LLVM module.
    While it would have been possible to cache without this refactor, it
    would have been very easy to miss a setting and thus let the
    compiler work with invalid/stale data.
2021-01-29 14:49:58 +01:00
Ayke van Laethem
5bae55d755 compiler: create runtime types lazily when needed
This fixes a longstanding TODO comment and similar to
https://github.com/tinygo-org/tinygo/pull/1593 it removes some code out
of the compiler.CompileProgram function that doesn't need to be there.
2021-01-25 17:14:02 +01:00
Ayke van Laethem
0bad2c9ff2 compiler: move the setting of attributes to getFunction
This is a small refactor to move code away from compiler.CompilePackage,
with the goal that compiler.CompilePackage will eventually be removed
entirely in favor of compiler.CompilePackage.
2021-01-25 16:28:30 +01:00
Ayke van Laethem
92ed645a11 compiler: remove unnecessary main.main call workaround
Since https://github.com/tinygo-org/tinygo/pull/1571 (in particular, the first
commit that sets the main package path), the main package is always named
"main". This makes the callMain() workaround in the runtime unnecessary and
allows directly calling the main.main function with a //go:linkname pragma.
2021-01-24 22:53:40 +01:00
Ayke van Laethem
d8cc48b09b compiler: remove ir package
This package was long making the design of the compiler more complicated
than it needs to be. Previously this package implemented several
optimization passes, but those passes have since moved to work directly
with LLVM IR instead of Go SSA. The only remaining pass is the SimpleDCE
pass.

This commit removes the *ir.Function type that permeated the whole
compiler and instead switches to use *ssa.Function directly. The
SimpleDCE pass is kept but is far less tightly coupled to the rest of
the compiler so that it can easily be removed once the switch to
building and caching packages individually happens.
2021-01-24 15:39:15 +01:00
Ayke van Laethem
9bd36597d6 compiler: support all kinds of deferred builtins
This change extends defer support to all supported builitin functions.
Not all of them make sense (such as len, cap, real, imag, etc) but this
change for example adds support for `defer(delete(m, key))` which is
used in the Go 1.15 encoding/json package.
2021-01-24 09:28:09 +01:00
Nia Weiss
a5cf704d83 compiler: test float to int conversions and fix upper-bound calculation 2021-01-19 14:02:32 +01:00
Nia Weiss
a867b56e5f compiler: saturate float-to-int conversions
This works around some UB in LLVM, where an out-of-bounds conversion would produce a poison value.
The selected behavior is saturating, except that NaN is mapped to the minimum value.
2021-01-16 19:12:36 +01:00
Nia Weiss
f159429152 compiler: emit a nil check when slicing an array pointer 2021-01-15 21:35:49 +01:00
Ayke van Laethem
a848d720db compiler: refactor and add tests
This commit finally introduces unit tests for the compiler, to check
whether input Go code is converted to the expected output IR.

To make this necessary, a few refactors were needed. Hopefully these
refactors (to compile a program package by package instead of all at
once) will eventually become standard, so that packages can all be
compiled separate from each other and be cached between compiles.
2021-01-15 14:43:43 +01:00
Ayke van Laethem
fb0bb69f62 compiler: fix non-int integer constants
Before this change, the compiler could panic with the following message:

    panic: 20 not an Int

That of course doesn't make much sense. But it apparently is expected
behavior, see https://github.com/golang/go/issues/43165 for details.

This commit fixes this issue by converting the constant to an integer if
needed.
2020-12-27 16:13:36 +01:00
Ayke van Laethem
3e40b08ba0 compiler: implement negate for complex numbers 2020-10-28 07:38:51 +01:00
Lucas Teske
c2bfe6bc8d arm64: Add support for system calls (SVC) 2020-10-03 20:07:51 +02:00
Ayke van Laethem
1096596b69 compiler: fix floating point bugs
There were a few bugs related to floating point. After fixing these, the
math package started passing all tests.
2020-09-21 10:43:46 +02:00
Ayke van Laethem
88fd2823df all: run test binaries in the correct directory
Test binaries must be run in the source directory of the package to be
tested. This wasn't done, leading to a few "file not found" errors.

This commit implements this. Unfortunately, it does not allow more
packages to be tested as both affected packages (debug/macho and
debug/plan9obj) will still fail with this patch even though the "file
not found" errors are gone.
2020-09-04 12:21:19 +02:00
Ayke van Laethem
c810628a20 loader: rewrite/refactor much of the code to use go list directly
There were a few problems with the go/packages package. While it is more
or less designed for our purpose, it didn't work quite well as it didn't
provide access to indirectly imported packages (most importantly the
runtime package). This led to a workaround that sometimes broke
`tinygo test`.

This PR contains a number of related changes:

  * It uses `go list` directly to retrieve the list of packages/files to
    compile, instead of relying on the go/packages package.
  * It replaces our custom TestMain replace code with the standard code
    for running tests (generated by `go list`).
  * It adds a dummy runtime/pprof package and modifies the testing
    package, to get tests to run again with the code generated by
    `go list`.
2020-09-03 22:10:14 +02:00
Ayke van Laethem
f05b378b89 compiler: add proper parameter names to runtime.initAll
This is required by the coroutines pass, otherwise it will panic. It
checks for the proper parameter names to make sure the function is not
exported. In this case, the runtime.initAll function wasn't exported but
simply didn't have the correct parameter names so the check triggered
even though it shouldn't.
2020-07-31 17:34:44 +02:00
waj334
848c3e55a9
compiler: implement func value and builtin defers
Co-authored-by: Justin A. Wilson <maker.pro.game@gmail.com>
2020-07-31 01:48:57 +02:00
Lucas Teske
3650c2c739 nintendoswitch: Add experimental Nintendo Switch support without CRT
Bare minimal nintendo switch support using LLD
2020-07-31 00:58:09 +02:00
Ayke van Laethem
d4e04e4e49 compiler: fix named string to []byte slice conversion
This was missing a `.Underlying()` call to avoid testing the named type
(but instead test for the underlying type).
2020-07-29 12:13:37 +02:00
Ayke van Laethem
e2bf7bbb49 device: add new cross-arch Asm and AsmFull functions
This is necessary to avoid a circular dependency between the device/avr
and runtime/interrupts package in the next commit.

It may be worth replacing existing calls like device/arm.Asm to
device.Asm, to have a single place where these are defined.
2020-06-14 14:44:22 -04:00
Yannis Huber
d3f5b51cd8
compiler: add support for custom code model 2020-06-08 16:50:39 +02:00
Ayke van Laethem
fed433c046 compiler: add support for atomic operations
This also implements DisableInterrupts/EnableInterrupts for RISC-V, as
those operations were needed to implement a few libcalls.
2020-05-28 15:11:46 +02:00
Ayke van Laethem
c248418dbe compiler: fix a few crashes due to named types
There were a few cases left where a named type would cause a crash in
the compiler. While going through enough code would have found them
eventually, I specifically looked for the `Type().(` pattern: a Type()
call that is then used in a type assert. Most of those were indeed bugs,
although for some I couldn't come up with a reproducer so I left them
as-is.
2020-05-27 16:14:41 +02:00
Ayke van Laethem
4ca2d3f0cf loader: load packages using Go modules
This commit replaces the existing ad-hoc package loader with a package
loader that uses the x/tools/go/packages package to find all
to-be-loaded packages.
2020-05-27 13:08:17 +02:00
Ayke van Laethem
35015a7918 loader: merge roots from both Go and TinyGo in a cached directory
This commit changes the way that packages are looked up. Instead of
working around the loader package by modifying the GOROOT variable for
specific packages, create a new GOROOT using symlinks. This GOROOT is
cached for the specified configuration (Go version, underlying GOROOT
path, TinyGo path, whether to override the syscall package).

This will also enable go module support in the future.

Windows is a bit harder to support, because it only allows the creation
of symlinks when developer mode is enabled. This is worked around by
using symlinks and if that fails, using directory junctions or hardlinks
instead. This should work in the vast majority of cases. The only case
it doesn't work, is if developer mode is disabled and TinyGo, the Go
toolchain, and the cache directory are not all on the same filesystem.
If this is a problem, it is still possible to improve the code by using
file copies instead.

As a side effect, this also makes diagnostics use a relative file path
only when the file is not in GOROOT or in TINYGOROOT.
2020-05-27 13:08:17 +02:00
Lucas Teske
726d735ad3 cgo: Add LDFlags support 2020-05-21 00:57:19 +02:00
Jaden Weiss
473644d918 internal/bytealg: reimplement bytealg in pure Go
Previously, we implemented individual bytealg functions via linknaming, and had to update them every once in a while when we hit linker errors.
Instead, this change reimplements the bytealg package in pure Go.
If something is missing, it will cause a compiler error rather than a linker error.
This is easier to test and maintain.
2020-05-16 14:56:05 +02:00
cornelk
7e64bc8f77 runtime: add cap and len support for chans 2020-05-12 01:17:27 +02:00
Ayke van Laethem
6389e45d99 all: replace ReadRegister with AsmFull inline assembly
This makes AsmFull more powerful (by supporting return values) and
avoids a compiler builtin.
2020-04-29 18:25:16 +02:00
Ayke van Laethem
16c2d84c49 compiler: add parameter names to IR
This makes viewing the IR easier because parameters have readable names.

This also makes it easier to write compiler tests (still a work in
progress), that work in LLVM 9 and LLVM 10, as LLVM 10 started printing
value names for unnamed parameters.
2020-04-21 08:54:39 +02:00
Ayke van Laethem
7b2377586f compiler: unexport some exported symbols
Some symbols (constants/types/methods) were exported while they are an
implementation detail. To keep the public API clean, unexport them.
2020-04-13 09:24:57 +02:00
Ayke van Laethem
46345aade6 compiler: optimize comparing interface values against nil
This is a very common case. Avoiding a runtime.interfaceEqual call leads
to a very big reduction in code size in some cases (while it doesn't
affect many other examples). A number of driver smoke tests are reduced
by about 4kB just with this optimization.

I found this issue while looking into automatically calculating the
required amount of stack space for goroutines. The
runtime.interfaceEqual function is recursive, so it is best avoided.
2020-04-04 22:47:21 +02:00
Ayke van Laethem
407149e323 compiler: add debug info to goroutine start wrappers 2020-04-03 08:12:18 +02:00
Jaden Weiss
ccf8b378b3 compiler: track PHI nodes 2020-04-02 15:06:58 +02:00
Ayke van Laethem
cc4a4c755f interp: show backtrace with error
This should make it much easier to figure out why and where an error
happens at package initialization time.
2020-03-28 21:55:12 +01:00
Jaden Weiss
2501602b4f ir: add descriptive error messages to SimpleDCE pass
This commit modifies the SimpleDCE pass to emit errors similar to those emitted by gc when the main function is missing.
2020-03-28 20:52:53 +01:00
Jaden Weiss
5cc130bb6e
compiler: implement spec-compliant shifts
Previously, the compiler used LLVM's shift instructions directly, which have UB whenever the shifts are large or negative.
This commit adds runtime checks for negative shifts, and handles oversized shifts.
2020-03-28 17:35:19 +01:00
Ayke van Laethem
91d1a23b14 compiler,runtime: translate memzero calls to LLVM memset intrinsics
This gives the optimizer a bit more information about what the calls do.
This should result in slightly better generated code.

Code size sometimes goes up and sometimes goes down. I blame the code
size going up on the inliner which inlines more functions, because
compiling the smoke tests in the drivers repository with -opt=1 results
in a slight code size reduction in all cases.
2020-03-27 21:01:59 +01:00