It should only be added at the point that it is needed, for example when
using libclang or using the built-in Clang. It isn't needed when running
an external tool.
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.
This commit improves accuracy of the -size=full flag in a big way.
Instead of relying on symbol names to figure out by which package
symbols belong, it will instead mostly use DWARF debug information
(specifically, debug line tables and debug information for global
variables) relying on symbols only for some specific things. This is
much more accurate: it also accounts for inlined functions.
For example, here is how it looked previously when compiling a personal
project:
code rodata data bss | flash ram | package
1902 333 0 0 | 2235 0 | (bootstrap)
46 256 0 0 | 302 0 | github
0 454 0 0 | 454 0 | handleHardFault$string
154 24 4 4 | 182 8 | internal/task
2498 83 5 2054 | 2586 2059 | machine
0 16 24 130 | 40 154 | machine$alloc
1664 32 12 8 | 1708 20 | main
0 0 0 200 | 0 200 | main$alloc
2476 79 0 36 | 2555 36 | runtime
576 0 0 0 | 576 0 | tinygo
9316 1277 45 2432 | 10638 2477 | (sum)
11208 - 48 6548 | 11256 6596 | (all)
And here is how it looks now:
code rodata data bss | flash ram | package
------------------------------- | --------------- | -------
1509 0 12 23 | 1521 35 | (unknown)
660 0 0 0 | 660 0 | C compiler-rt
58 0 0 0 | 58 0 | C picolibc
0 0 0 4096 | 0 4096 | C stack
174 0 0 0 | 174 0 | device/arm
6 0 0 0 | 6 0 | device/sam
598 256 0 0 | 854 0 | github.com/aykevl/ledsgo
320 24 0 4 | 344 4 | internal/task
1414 99 24 2181 | 1537 2205 | machine
726 352 12 208 | 1090 220 | main
3002 542 0 36 | 3544 36 | runtime
848 0 0 0 | 848 0 | runtime/volatile
70 0 0 0 | 70 0 | time
550 0 0 0 | 550 0 | tinygo.org/x/drivers/ws2812
------------------------------- | --------------- | -------
9935 1273 48 6548 | 11256 6596 | total
There are some notable differences:
* Odd packages like main$alloc and handleHardFault$string are gone,
instead their code is put in the correct package.
* C libraries and the stack are now included in the list, they were
previously part of the (bootstrap) pseudo-package.
* Unknown bytes are slightly reduced. It should be possible to reduce
it significantly more in the future: most of it is now caused by
interface invoke wrappers.
* Inlined functions are now correctly attributed. For example, the
runtime/volatile package is normally entirely inlined.
* There is no difference between (sum) and (all) anymore. A better
code size algorithm now counts the code/data sizes correctly.
* And last (but not least) there is a stylistic change: the table now
looks more like a table. Especially the summary should be clearer
now.
Future goals:
* Improve debug information so that the (unknown) pseudo-package is
reduced in size or even eliminated altogether.
* Add support for other file formats, most importantly WebAssembly.
* Perhaps provide a way to expand this report per file, or in a
machine-readable format like JSON or CSV.
This is necessary to display error messages on Windows. For example,
this command invocation is not correct (esp32 doesn't define
machine.LED, you need esp32-coreboard-v2 for example):
tinygo run -target=esp32 examples/blinky1
It results in the following hard-to-read error message:
# examples/blinky1
..\..\..\..\..\AppData\Local\tinygo\goroot-go1.16-24cb853b66a5367bf6d65bc08b2cb665c75bd9971f0be8f8b73f69d1a33e04a1-syscall\src\examples\blinky1\blinky1.go:11:17: LED not declared by package machine
With this commit, this error message becomes much easier to read:
# examples/blinky1
C:\Users\Ayke\go\src\github.com\tinygo-org\tinygo\src\examples\blinky1\blinky1.go:11:17: LED not declared by package machine
For example, the following did not work before but does work with this
change:
// int add(int a, int b) {
// return a + b;
// }
import "C"
func main() {
println("add:", C.add(3, 5))
}
Even better, the functions in the header are compiled together with the
rest of the Go code and so they can be optimized together! Currently,
inlining is not yet allowed but const-propagation across functions
works. This should be improved in the future.
If all of the Go files presented to the compiler have syntax errors,
cgo.Process gets an empty files slice and will panic:
panic: runtime error: index out of range [0] with length 0
goroutine 1 [running]:
github.com/tinygo-org/tinygo/cgo.Process({0x0, 0x4e8e36, 0x0}, {0xc000024104, 0x18}, 0xc000090fc0, {0xc000899780, 0x7, 0xc00018ce68})
/home/ayke/src/github.com/tinygo-org/tinygo/cgo/cgo.go:186 +0x22ee
github.com/tinygo-org/tinygo/loader.(*Package).parseFiles(0xc0001ccf00)
/home/ayke/src/github.com/tinygo-org/tinygo/loader/loader.go:400 +0x51e
This is simple to work around: just don't try to run CGo when there are
no files to process. It just means there are bugs to fix before CGo can
properly run.
(This is perhaps not the nicest solution but certainly the simplest).
This was broken because multiple packages in the program were named
'main', even one that was imported (by the generated main package).
This fixes tests for main packages.
This commit makes the output of `tinygo test` similar to that of `go
test`. It changes the following things in the process:
* Running multiple tests in a single command is now possible. They
aren't paralellized yet.
* Packages with no test files won't crash TinyGo, instead it logs it
in the same way the Go toolchain does.
This patch adds support for passing CFLAGS added in #cgo lines of the
CGo preprocessing phase to the compiler when compiling C files inside
packages. This is expected and convenient but didn't work before.
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.
This is an addition that landed in Go 1.12 but we couldn't use before
because we were supporting Go back until Go 1.11. It simplifies the code
around processes a bit.
This should make exported names a bit more consistent.
I believe there was a bug report for this issue, but I can't easily find
it. In any case, I think it's an important improvement to match the
behavior of the Go toolchain.
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`.
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.
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.
This commit also adds a bit of version independence, in particular for
external commands. It also adds the LLVM version to the `tinygo version`
command, which might help while debugging.
Add location information (whenever possible) to failed imports. This
helps in debugging where an incorrect import came from.
For example, show the following error message:
/home/ayke/src/github.com/tinygo-org/tinygo/src/machine/machine.go:5:8: cannot find package "foobar" in any of:
/usr/local/go/src/foobar (from $GOROOT)
/home/ayke/src/foobar (from $GOPATH)
Instead of the following:
error: cannot find package "foobar" in any of:
/usr/local/go/src/foobar (from $GOROOT)
/home/ayke/src/foobar (from $GOPATH)
This allows importing (for example) both
"github.com/tinygo-org/tinygo/src/machine" and "machine" without issues.
The former is renamed to just "machine".
This is a big commit that does a few things:
* It moves CGo processing into a separate package. It never really
belonged in the loader package, and certainly not now that the
loader package may be refactored into a driver package.
* It adds support for multiple CGo files (files that import package
"C") in a single package. Previously, this led to multiple
definition errors in the Go typecheck phase because certain C
symbols were defined multiple times in all the files. Now it
generates a new fake AST that defines these, to avoid multiple
definition errors.
* It improves debug info in a few edge cases that are probably not
relevant outside of bugs in cgo itself.
Check various locations that $GOROOT may live, including the location of
the go binary. But make it possible to override this autodetection by
setting GOROOT manually as an environment variable.
This makes CGo-emitted diagnostics very similar to regular errors
emitted while parsing/typechecking a package.
It's not complete, but after introducing some errors in testdata/cgo,
this is the resulting output:
# ./testdata/cgo/
testdata/cgo/main.h:18:11: error: a parameter list without types is only allowed in a function definition
testdata/cgo/main.go:5:10: note: in file included from testdata/cgo/main.go!cgo.c:2:
testdata/cgo/main.go:6:19: error: expected identifier or '('
Previously, this was the output:
/home/ayke/src/github.com/tinygo-org/tinygo/testdata/cgo/main.h:18:11: error: a parameter list without types is only allowed in a function definition
cgo-fake.c:3:19: error: expected identifier or '('
# ./testdata/cgo/
cgo: libclang cannot parse fragment
So far, we've pretended to be js/wasm in baremetal targets to make the
stdlib happy. Unfortunately, this has various problems because
syscall/js (a dependency of many stdlib packages) thinks it can do JS
calls, and emulating them gets quite hard with all changes to the
syscall/js packages in Go 1.12.
This commit does a few things:
* It lets baremetal targets pretend to be linux/arm instead of
js/wasm.
* It lets the loader only select particular packages from the src
overlay, instead of inserting them just before GOROOT. This makes it
possible to pick which packages to overlay for a given target.
* It adds a baremetal-only syscall package that stubs out almost all
syscalls.