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

80 коммитов

Автор SHA1 Сообщение Дата
Damian Gryski
2de64d3f4e compiler, reflect: add Type.PkgPath 2023-03-08 09:38:49 -08:00
Damian Gryski
7654d86d2c compiler, reflect: add support for named types 2023-03-08 09:38:49 -08:00
Ayke van Laethem
ca823f9a0d compiler: remove unsafe.Pointer(uintptr(v) + idx) optimization
I have checked this conversion is not needed anymore after the previous
commit, by running various smoke tests of which none triggered this
optimization. The only case where the optimization would have kicked in
is in syscall/syscall_windows.go:76 of the Go standard library.
Therefore, I prefer to remove it to reduce code complexity.
2023-03-03 16:55:13 +01:00
Damian Gryski
476621736c
compiler: zero struct padding during map operations
Fixes #3358
2023-02-25 22:40:08 +01:00
Ayke van Laethem
4e8453167f all: refactor reflect package
This is a big commit that changes the way runtime type information is stored in
the binary. Instead of compressing it and storing it in a number of sidetables,
it is stored similar to how the Go compiler toolchain stores it (but still more
compactly).

This has a number of advantages:

  * It is much easier to add new features to reflect support. They can simply
    be added to these structs without requiring massive changes (especially in
    the reflect lowering pass).
  * It removes the reflect lowering pass, which was a large amount of hard to
    understand and debug code.
  * The reflect lowering pass also required merging all LLVM IR into one
    module, which is terrible for performance especially when compiling large
    amounts of code. See issue 2870 for details.
  * It is (probably!) easier to reason about for the compiler.

The downside is that it increases code size a bit, especially when reflect is
involved. I hope to fix some of that in later patches.
2023-02-17 22:54:34 +01:00
Ayke van Laethem
da362b8a24 wasm: support ThinLTO
Using ThinLTO manages to optimize binaries quite significantly. The
exact amount varies a lot by program but it's about 10-15% usually.

Don't remove non-ThinLTO support yet. It would not surprise me if this
triggered some unintended side effect. Eventually, non-ThinLTO support
should be removed though.
2023-01-25 18:43:00 +01:00
Ayke van Laethem
c41a212712 wasm: avoid miscompile with ThinLTO
I found that when I enable ThinLTO, a miscompilation triggers that had
been hidden all the time previously. The bug appears to happen as
follows:

 1. TinyGo generates a function with a runtime.trackPointer call, but
    without an alloca (or the alloca gets optimized away).
 2. LLVM sees that no alloca needs to be kept alive across the
    runtime.trackPointer call, and therefore it adds the 'tail' flag.
    One of the effects of this flag is that it makes it undefined
    behavior to keep allocas alive across the call (which is still safe
    at that point).
 3. The GC lowering pass adds a stack slot alloca and converts
    runtime.trackPointer calls into alloca stores.

The last step triggers the bug: the compiler inserts an alloca where
there was none before but that's not valid as long as the 'tail' flag is
present.

This patch fixes the bug in a somewhat dirty way, by always creating a
dummy alloca so that LLVM won't do the optimization in step 2 (and
possibly other optimizations that rely on there being no alloca
instruction).
2023-01-18 08:24:42 +01:00
Ayke van Laethem
f9d0ff3bec all: store data layout as little endian value
This makes it much easier to read the value at runtime, as pointer
indices are naturally little endian. It should not affect anything else
in the program.
2023-01-17 19:32:18 +01:00
Ayke van Laethem
c43958972c compiler: add support for new unsafe slice/string functions
This adds support for unsafe.SliceData, unsafe.String, and
unsafe.SringData that were introduced in Go 1.20.
2023-01-17 08:38:54 +01:00
Ayke van Laethem
9fd0567fb5 compiler: fix stack overflow when creating recursive pointer types
There were two types that could result in a compiler stack overflow.
This is difficult to fix in LLVM 14, so I won't even bother. However,
this is trivial to fix with opaque pointers in LLVM 15. Therefore, this
fix is for LLVM 15 only.

Fixes: https://github.com/tinygo-org/tinygo/issues/3341
2022-12-22 17:45:05 +01:00
Ayke van Laethem
2b7f562202 ci: add support for LLVM 15
This commit switches to LLVM 15 everywhere by default, while still
keeping LLVM 14 support.
2022-10-19 22:23:19 +02:00
Ayke van Laethem
8bbfb1ee68 wasm: do not allow undefined symbols
--allow-undefined can be a problem: it allows compiling code that will
fail when loaded. This change makes sure that if some symbols are
undefined, they are reported as an error by the linker.

Previously, people could get away with importing a function that was not
defined, like this:

    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

This was always unintended but mostly worked. With this change, it isn't
possible anymore. Now every function needs to be marked with //export
explicitly:

    //export add
    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

As before, functions will be placed in the `env` module with the name
set from the `//export` tag. This can be overridden with
`//go:import-module`:

    //go:import-module math
    //export add
    func add(int a, int b) int

    func test() {
        println(add(3, 5))
    }

For the syscall/js package, I needed to give a list of symbols that are
undefined. This list is based on the JavaScript functions defined in
targets/wasm_exec.js.
2022-09-08 08:25:27 +02:00
Ayke van Laethem
20a7a6fd54 compiler: replace some math operation bodies with fast intrinsics
Instead of changing the calls, replace the function bodies themselves.
This is useful for a number of reasons, see
https://github.com/tinygo-org/tinygo/pull/2920 for more information.

I have removed the math intrinsics tests because they are no longer
useful. Instead, I think `tinygo test math` should suffice.
2022-08-30 17:33:16 +02:00
Ayke van Laethem
4695da83b7 all: drop support for Go 1.16 and Go 1.17 2022-08-30 12:38:06 +02:00
Ayke van Laethem
b8a6a1f62b compiler: use the LLVM builtins everywhere
This gives some more optimization opportunities to LLVM, because it
understands these intrinsics. For example, it might convert
llvm.sqrt.f64 to llvm.sqrt.f32 if possible.
2022-08-28 23:37:56 +02:00
Ayke van Laethem
c7a23183e8 all: format code according to Go 1.19 rules
Go 1.19 started reformatting code in a way that makes it more obvious
how it will be rendered on pkg.go.dev. It gets it almost right, but not
entirely. Therefore, I had to modify some of the comments so that they
are formatted correctly.
2022-08-04 12:18:32 +02:00
Phil Kedy
05cdde162c Set internal linkage and keeping default visibility for anonymous functions 2022-08-01 10:53:48 +02:00
Ayke van Laethem
7b1e5f6f99 compiler: implement unsafe.Alignof and unsafe.Sizeof for generic code
For some reason, these aren't lowered when a generic function is
instantiated by the SSA package.

I've left unsafe.Offsetof to be implemented later, it's a bit difficult
to do correctly the way the code is currently structured.
2022-07-28 15:43:51 +02:00
Ayke van Laethem
70c52ef1b4 compiler: fix type names for generic named structs
Without this change, the compiler would probably have worked just fine
but the generated types would look odd.

You can see in the test case that it now doesn't use `main.Point` but
rather the correct `main.Poin[float32]` etc.
2022-07-28 15:43:51 +02:00
Ayke van Laethem
5078ce382d compiler: do not try to build generic functions
There is no reason to: we should only build instantiated generic
functions.
2022-07-28 15:43:51 +02:00
Ayke van Laethem
408855da14 compiler: add generics test case
This test case shows a few bugs, that I will fix in subsequent patches.
2022-07-28 15:43:51 +02:00
Ayke van Laethem
2825b4fe74 compiler: update tests after adding new wasm features
I don't understand why this wasn't caught in CI. It should have. In any
case, because the llvm-features string was updated, these IR outputs
were updated.
2022-06-22 07:50:40 +02:00
Ayke van Laethem
9af535bf98 avr: add support for recover()
You can see that it works with the following command:

    tinygo run -target=simavr ./testdata/recover.go

This also gets the following tests to pass again:

    go test -run=Build -target=simavr -v

Adding support for AVR was a bit more compliated because it's also
necessary to save and restore the Y register.
2022-06-19 11:51:12 +02:00
Ayke van Laethem
159f0051bb runtime: move *task.DeferFrame here
This is a refactor that makes the next commit simpler. Perhaps it should
have been like this from the beginning but I didn't like all the casts.
2022-06-19 11:51:12 +02:00
Ayke van Laethem
8d6b210c09 compiler: implement recover() built-in function 2022-06-16 07:59:21 +02:00
Ayke van Laethem
79ba6a50c3 compiler: insert basic blocks at an appropriate location
For example, this commit moves the 'throw' branch of an assertion (nil
check, slice index check, etc) to the end of the function while
inserting the "continue" branch right after the insert location. This
makes the resulting IR easier to follow.

For some reason, this also reduces code size a bit on average. The
TinyGo smoke tests saw a reduction of 0.22%, mainly from WebAssembly.
The drivers repo saw little average change in code size (-0.01%).

This commit also adds a few compiler tests for the defer keyword.
2022-06-16 07:59:21 +02:00
Ayke van Laethem
6b31ee1e93 all: update to LLVM 14
Switch over to LLVM 14 for static builds. Keep using LLVM 13 for regular
builds for now.

This uses a branch of the upstream Espressif branch to fix an issue,
see: https://github.com/espressif/llvm-project/pull/59
2022-04-23 08:45:46 +02:00
Ayke van Laethem
c0d257d682 compiler: fix difference in aliases in interface methods
There used to be a difference between `byte` and `uint8` in interface
methods. These are aliases, so they should be treated the same.
This patch introduces a custom serialization format for types,
circumventing the `Type.String()` method that is slightly wrong for our
purposes.

This also fixes an issue with the `any` keyword in Go 1.18, which
suffers from the same problem (but this time actually leads to a crash).
2022-04-07 12:54:17 +02:00
Nia Waldvogel
c6ae1c58fc compiler: remove parentHandle from calling convention
This removes the parentHandle argument from the internal calling convention.
It was formerly used to implment coroutines.
Now that coroutines have been removed, it is no longer necessary.
2022-01-19 14:42:02 -05:00
Nia Waldvogel
0c2fefa09b transform: remove switched func lowering
The switched func lowering was mainly necessary for coroutines.
With coroutines removed, this is no longer necessary.
2022-01-19 14:42:02 -05:00
Nia Waldvogel
ea2a6b70b2 internal/task: remove coroutines 2022-01-19 14:42:02 -05:00
Nia Waldvogel
57ff3a5ca0 compiler: predeclare runtime.trackPointer
When a package only uses runtime.trackPointer to create interface packs, the compiler fails to find runtime.trackPointer.
This change predeclares it alongside runtime.alloc and updates the tests to use runtime.trackPointer when the test's target uses it.
2022-01-18 16:27:12 -05:00
Ayke van Laethem
ebd4969cde all: switch to LLVM 13
This adds support for building with `-tags=llvm13` and switches to LLVM
13 for tinygo binaries that are statically linked against LLVM.

Some notes on this commit:

  * Added `-mfloat-abi=soft` to all Cortex-M targets because otherwise
    nrfx would complain that floating point was enabled on Cortex-M0.
    That's not the case, but with `-mfloat-abi=soft` the `__SOFTFP__`
    macro is defined which silences this warning.
    See: https://reviews.llvm.org/D100372
  * Changed from `--sysroot=<root>` to `-nostdlib -isystem <root>` for
    musl because with Clang 13, even with `--sysroot` some system
    libraries are used which we don't want.
  * Changed all `-Xclang -internal-isystem -Xclang` to simply
    `-isystem`, for consistency with the above change. It appears to
    have the same effect.
  * Moved WebAssembly function declarations to the top of the file in
    task_asyncify_wasm.S because (apparently) the assembler has become
    more strict.
2022-01-09 11:04:10 +01:00
Ayke van Laethem
21b89ef327 compiler: fix emission of large object layouts
Large object layouts don't fit in a pointer-sized integer and therefore
need to be stored in a global instead. However, the way the data was
stored in these globals was not correct for buffers that don't have
pointers near the end. This commit fixes this issue by using math/big
FillBytes() instead of Bytes().

This gets the unicode package to compile on AVR.
2022-01-03 21:22:49 +01:00
Nia Waldvogel
a4f9e5e552 targets (wasi/wasm): raise default stack size to 16 KiB
In some cases, 8 KiB is not enough for both the C stack and the asyncify stack.
This gets the compress/zlib tests to fail without crashing.
2021-12-30 12:20:04 -05:00
Nia Waldvogel
e4de7b4957 internal/task: swap stack chain when switching goroutines
This change swaps the stack chain when switching goroutines, ensuring that the chain is maintained consistently.
This is only really currently necessary with asyncify on wasm.
2021-12-17 10:01:11 +01:00
Ayke van Laethem
5127b9d65b all: add LLVM 12 support
Originally based on a PR by @QuLogic, but extended a lot to get all
tests to pass.
2021-11-30 21:53:16 +01:00
Damian Gryski
0e7a129de7 compiler: update testdata/string.ll
$ go test ./compiler -update
2021-11-18 11:07:45 +01:00
Nia Waldvogel
641dcd7c16 internal/task: use asyncify on webassembly
This change implements a new "scheduler" for WebAssembly using binaryen's asyncify transform.
This is more reliable than the current "coroutines" transform, and works with non-Go code in the call stack.

runtime (js/wasm): handle scheduler nesting

If WASM calls into JS which calls back into WASM, it is possible for the scheduler to nest.
The event from the callback must be handled immediately, so the task cannot simply be deferred to the outer scheduler.
This creates a minimal scheduler loop which is used to handle such nesting.
2021-11-14 10:49:28 +01:00
Ayke van Laethem
c1d697f868 compiler: fix indices into strings and arrays
This PR fixes two bugs at once:

 1. Indices were incorrectly extended to a bigger type. Specifically,
    unsigned integers were sign extended and signed integers were zero
    extended. This commit swaps them around.
 2. The getelementptr instruction was given the raw index, even if it
    was a uint8 for example. However, getelementptr assumes the indices
    are signed, and therefore an index of uint8(200) was interpreted as
    an index of int8(-56).
2021-11-13 11:04:24 +01:00
Ayke van Laethem
fce403b7a0 targets: match LLVM triple to the one Clang uses
The target triples have to match mostly to be able to link LLVM modules.
Linking LLVM modules is already possible (the triples already match),
but testing becomes much easier when they match exactly.

For macOS, I picked "macosx10.12.0". That's an old and unsupported
version, but I had to pick _something_. Clang by default uses
"macos10.4.0", which is much older.
2021-11-05 09:42:00 +01:00
Ayke van Laethem
f63c389f1a compiler: change symbol name for string and packed data constants
This new symbol name format (package name + "$string" or "$pack" suffix)
is easier to parse for analysis.
2021-11-03 16:28:04 +01:00
Ayke van Laethem
0704794def compiler: add object layout information to heap allocations
This commit adds object layout information to new heap allocations. It
is not yet used anywhere: the next commit will make use of it.

Object layout information will eventually be used for a (mostly) precise
garbage collector. This is what the data is made for. However, it is
also useful in the interp package which can work better if it knows the
memory layout and thus the approximate LLVM type of heap-allocated
objects.
2021-11-02 22:16:15 +01:00
Ayke van Laethem
f24a93c51d compiler, runtime: add layout parameter to runtime.alloc
This layout parameter is currently always nil and ignored, but will
eventually contain a pointer to a memory layout.

This commit also adds module verification to the transform tests, as I
found out that it didn't (and therefore didn't initially catch all
bugs).
2021-11-02 22:16:15 +01:00
Ayke van Laethem
9e1b4de999 compiler: add support for the go keyword on interface methods
This is a feature that was long missing, but because of the previous
refactor, it is now trivial to implement.
2021-10-31 14:17:25 +01:00
Ayke van Laethem
a4afc3b4b0 compiler: simplify interface lowering
This commit simplifies the IR a little bit: instead of calling
pseudo-functions runtime.interfaceImplements and
runtime.interfaceMethod, real declared functions are being called that
are then defined in the interface lowering pass. This should simplify
the interaction between various transformation passes. It also reduces
the number of lines of code, which is generally a good thing.
2021-10-31 14:17:25 +01:00
Ayke van Laethem
afd49e7cdd compiler: add support for recursive function types
This adds support for a construct like this:

    type foo func(fn foo)

Unfortunately, LLVM cannot create function pointers that look like this.
LLVM only supports named types for structs (not for pointers) and thus
can't add a pointer to a function type of the same type to a parameter
of that function type.

The fix is simple: cast all function pointers to a void function, in
LLVM IR:

    void ()*

Raw function pointers are cast to this type before storing, and cast
back to the regular function type before calling. This means that
function parameters will never refer to its own type because raw
function types are fixed at that one type.

Somehow, this does have an effect on binary size in some cases. The
effect is small and goes both ways. On top of that, there is work
underway in LLVM which would make all pointer types opaque (without a
pointee type). This would make this whole commit useless and therefore
should fix any size increases that might happen.
https://llvm.org/docs/OpaquePointers.html
2021-10-30 15:55:20 +02:00
Ayke van Laethem
86f1e6aec4 compiler: properly implement div and rem operations
The division and remainder operations were lowered directly to LLVM IR.
This is wrong however because the Go specification defines exactly what
happens on a divide by zero or signed integer overflow and LLVM IR
itself treats those cases as undefined behavior. Therefore, this commit
implements divide by zero and signed integer overflow according to the
Go specification.

This does have an impact on the generated code, but it is surprisingly
small. I've used the drivers repo to test the code before and after, and
to my surprise most driver smoke tests are not changed at all. Those
that are, have only a small increase in code size. At the same time,
this change makes TinyGo more compliant to the Go specification.
2021-10-28 15:55:02 +02:00
Ayke van Laethem
478dd3a28d compiler: add nounwind attribute
This attribute is also set by Clang when it compiles C source files
(unless -fexceptions is set). The advantage is that no unwind tables are
emitted on Linux (and perhaps other systems). It also avoids
__aeabi_unwind_cpp_pr0 on ARM when using the musl libc.
2021-10-25 13:39:54 +02:00
Ayke van Laethem
bf9dab36f7 build: normalize target triples to match Clang
This commit changes a target triple like "armv6m-none-eabi" to
"armv6m-unknown-unknow-eabi". The reason is that while the former is
correctly parsed in Clang (due to normalization), it wasn't parsed
correctly in LLVM meaning that the environment wasn't set to EABI.

This change normalizes all target triples and uses the EABI environment
(-eabi in the triple) for Cortex-M targets.

This change also drops the `--target=` flag in the target JSON files,
the flag is now added implicitly in `(*compileopts.Config).CFlags()`.
This removes some duplication in target JSON files.

Unfortunately, this change also increases code size for Cortex-M
targets. It looks like LLVM now emits calls like __aeabi_memmove instead
of memmove, which pull in slightly more code (they basically just call
the regular C functions) and the calls themself don't seem to be as
efficient as they could be. Perhaps this is a LLVM bug that will be
fixed in the future, as this is a very common occurrence.
2021-09-28 18:44:11 +02:00