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.
In the early days of TinyGo, the idea of `postinit` was to enable
interrupts only after initializers have run. Which kind of makes
sense... except that `time.Sleep` is allowed in init code and
`time.Sleep` requires interrupts to be enabled. Therefore, interrupts
must be enabled while initializers are being run.
This commit simply moves the enabling of interrupts to a point right
before running package initializers. It also removes `runtime.postinit`,
which is not necessary anymore (and was only used on AVR).
The extalloc collector has been broken for a while, and it doesn't seem reasonable to fix right now.
In addition, after a recent change it no longer compiles.
In the future similar functionality can hopefully be reintroduced, but for now this seems to be the most reasonable option.
FreeBSD support has been broken for a long time, probably since
https://github.com/tinygo-org/tinygo/pull/1860 (merged in May). Nobody
has complained yet, so I am going to assume nobody uses it.
This doesn't remove support for FreeBSD entirely: the code necessary to
build TinyGo on FreeBSD is still there. It just removes the code
necessary to build binaries targetting FreeBSD. But again, it could very
well be broken as we don't test it.
If anybody wants to re-enable support for FreeBSD, they would be welcome
to do that. But I think it would at the very least need a smoke test of
some sort.
This generally means that code size is reduced, especially when the os
package is not imported.
Specifically:
- On Linux (which currently statically links musl), it avoids calling
malloc, which avoids including the musl C heap for small programs
saving around 1.6kB.
- On WASI, it avoids initializing the args slice when the os package
is not used. This reduces binary size by around 1kB.
This commit adds support for musl-libc and uses it by default on Linux.
The main benefit of it is that binaries are always statically linked
instead of depending on the host libc, even when using CGo.
Advantages:
- The resulting binaries are always statically linked.
- No need for any tools on the host OS, like a compiler, linker, or
libc in a release build of TinyGo.
- This also simplifies cross compilation as no cross compiler is
needed (it's all built into the TinyGo release build).
Disadvantages:
- Binary size increases by 5-6 kilobytes if -no-debug is used. Binary
size increases by a much larger margin when debugging symbols are
included (the default behavior) because musl is built with debugging
symbols enabled.
- Musl does things a bit differently than glibc, and some CGo code
might rely on the glibc behavior.
- The first build takes a bit longer because musl needs to be built.
As an additional bonus, time is now obtained from the system in a way
that fixes the Y2038 problem because musl has been a bit more agressive
in switching to 64-bit time_t.
At startup, a large chunk of virtual memory is used up by the heap. This
works fine in emulation (qemu-arm), but doesn't work so well on an
actual Raspberry Pi. Therefore, this commit reduces the requested amount
until a heap size is found that works on the system.
This can certainly be improved, but for now it's an important fix
because it allows TinyGo built binaries to actually run on a Raspberry
Pi with just 1GB RAM.
This function previously returned the atomic time, that isn't affected
by system time changes but also has a time base at some arbitrary time
in the past. This makes sense for baremetal platforms (which typically
don't know the wall time) but it gives surprising results on Linux and
macOS: time.Now() usually returns a time somewhere near the start of
1970.
This commit fixes this by obtaining both time values: the monotonic time
and the wall clock time. This is also how the Go runtime implements the
time.now function.
There is no reason to specialize this per chip as it is only ever used
for JavaScript. Not only that, it is causing confusion and is yet
another quirk to learn when porting the runtime to a new
microcontroller.
This commit does two things:
1. It makes it possible to grow the heap on Linux and MacOS by
allocating 1GB of virtual memory on startup and then slowly using it
as necessary, when running out of available heap space.
2. It switches the default GC to be the conservative GC (previously
extalloc). This is good for consistency with other platforms that
all use this same GC.
This makes the extalloc GC unused by default.
This heap allocation would normally be optimized away, but with -opt=0
perhaps not. This is a problem if the conservative GC is used, because
the conservative GC needs to be initialized before use.
The only architecture that actually needs special support for scanning
the stack is WebAssembly. All others allow raw access to the stack with
a small bit of assembly. Therefore, don't manually keep track of all
these objects on the stack manually and instead just use conservative
stack scanning.
This results in a massive code size decrease in the affected targets
(only tested linux/amd64 for code size) - sometimes around 33%. It also
allows for future improvements such as using proper stackful goroutines.
* initial commit for WASI support
* merge "time" package with wasi build tag
* override syscall package with wasi build tag
* create runtime_wasm_{js,wasi}.go files
* create syscall_wasi.go file
* create time/zoneinfo_wasi.go file as the replacement of zoneinfo_js.go
* add targets/wasi.json target
* set visbility hidden for runtime extern variables
Accodring to the WASI docs (https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md#current-unstable-abi),
none of exports of WASI executable(Command) should no be accessed.
v0.19.0 of bytecodealliance/wasmetime, which is often refered to as the reference implementation of WASI,
does not accept any exports except functions and the only limited variables like "table", "memory".
* merge syscall_{baremetal,wasi}.go
* fix js target build
* mv wasi functions to syscall/wasi && implement sleepTicks
* WASI: set visibility hidden for globals variables
* mv back syscall/wasi/* to runtime package
* WASI: add test
* unexport wasi types
* WASI test: fix wasmtime path
* stop changing visibility of runtime.alloc
* use GOOS=linux, GOARCH=arm for wasi target
Signed-off-by: mathetake <takeshi@tetrate.io>
* WASI: fix build tags for os/runtime packages
Signed-off-by: mathetake <takeshi@tetrate.io>
* run WASI test only on Linux
Signed-off-by: mathetake <takeshi@tetrate.io>
* set InternalLinkage instead of changing visibility
Signed-off-by: mathetake <takeshi@tetrate.io>
This commit refactors both determining the current time and sleeping for
a given time. It also improves precision for many chips.
* The nrf chips had a long-standing TODO comment about a slightly
inaccurate clock. This should now be fixed.
* The SAM D2x/D5x chips may have a slightly more accurate clock,
although probably within the error margin of the RTC. Also, by
working with RTC ticks and converting in the least number of places,
code size is often slightly reduced (usually just a few bytes, up to
around 1kB in some cases).
* I believe the HiFive1 rev B timer was slightly wrong (32768Hz vs
30517.6Hz). Because the datasheet says the clock runs at 32768Hz,
I've used the same conversion code here as in the nrf and sam cases.
* I couldn't test both stm32 timers, so I kept them as they currently
are. It may be possible to make them more efficient by using the
native tick frequency instead of using microseconds everywhere.
This is the kind that is used in Go (actually CGo) for exporting
functions. I think it's best to use //export instead of our custom
//go:export pragma, for consistency (they are equivalent in TinyGo).
Therefore I've updated all instances to the standard format (except for
two that are updated in https://github.com/tinygo-org/tinygo/pull/1024).
No smoke tests changed (when comparing the output hash), except for some
wasm tests that include DWARF debug info and tend to be flaky anyway.
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.
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 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
This can be used in the future to trigger garbage collection. For now,
it provides a more useful error message in case the heap is completely
filled up.
Make sure every to-be-implemented GC can use the same interface. As a
result, a 1MB chunk of RAM is allocated on Unix systems on init instead
of allocating on demand.
Let each target handle its own initialization/finalization sequence
instead of providing one in the runtime with hooks for memory
initialization etc. This is much more flexible although it causes a
little bit of code duplication.
This increases code size by 1 instruction (2 bytes) because LLVM isn't
yet smart enough to recognize that it doesn't need to clear a register
to use 0: it can just use r1 which is always 0 according to the
convention. It makes initialization a lot easier to read, however.
time.Sleep now compiles on all systems, so lets use that.
Additionally, do a few improvements in time unit handling for the
scheduler. This should lead to somewhat longer sleep durations without
wrapping (on some platforms).
Some examples got smaller, some got bigger. In particular, code using
the scheduler got bigger and the blinky1 example got smaller (especially
on Arduino: 380 -> 314 bytes).
This specifically fixes unix alloc(): previously when allocation fails
it would (recursively) call alloc() again to create an interface due to
lacking escape analysis.
Also, all other cases shouldn't try to allocate just because something
bad happens at runtime.
TODO: implement escape analysis.
CGo depends on syscall, which (in the standard library) depends on sync,
which depends on the runtime. There are also other import cycles. To be
able to use the syscall package from upstream, stop using CGo.