
TinyGo: New Go Compiler Based on LLVM - dcu
https://tinygo.org/
======
pcwalton
> Garbage collection is currently only supported on ARM microcontrollers
> (Cortex-M). For this platform, a simple conservative mark-sweep collector
> has been implemented. Other platforms will just allocate memory without ever
> freeing it.

Conservative garbage collection has serious problems on 32-bit. Stuck pointers
happen quite often. The usual culprit is floats, which thankfully don't
usually appear in embedded code, but by no means is the problem limited to
floats.

~~~
0815test
I have some trouble seeing the point of a Go compiler/implementation _without_
any working GC, or with the only GC being a problematic mark+sweep
implementation. Is this just a proof-of-concept effort, or do they expect to
add workable GC down the line?

~~~
mook
While I have no insight to their plans, perhaps a non-GC toolchain could still
be used for short-lived programs (such as command line tools)? Don't even need
to free anything if it's short enough, the OS can deal with it when the
process exits

~~~
antisemiotic
>a non-GC toolchain could still be used for short-lived programs (such as
command line tools)

Or missile firmware:
[https://groups.google.com/forum/message/raw?msg=comp.lang.ad...](https://groups.google.com/forum/message/raw?msg=comp.lang.ada/E9bNCvDQ12k/1tezW24ZxdAJ)

------
sethammons
How is this different than gollvm? And how does it combat the problems from
the Go FAQ:

> At the beginning of the project we considered using LLVM for gc but decided
> it was too large and slow to meet our performance goals. More important in
> retrospect, starting with LLVM would have made it harder to introduce some
> of the ABI and related changes, such as stack management, that Go requires
> but not are not part of the standard C setup. A new LLVM implementation is
> starting to come together now, however.

~~~
aykevl
There are 3 LLVM-based Go compilers that I'm aware of: gollvm, llgo, and
tinygo. Of those, only TinyGo reimplements the runtime that causes lots of
(code size) overhead in the other compilers.

There is more to a toolchain than translating source code to machine code. I'm
sure the others do that job just as well, but only TinyGo combines that with a
reimplemented runtime that optimizes size over speed and allows it to be used
directly on bare metal hardware: binaries of just a few kB are not uncommon.

------
tomcam
Congratulations on this new project. It’s compelling, your website is
informative and easy to read, and the mission statement is very clear. Plus,
it just looks like a lot of fun. Well done!

In my opinion, this feels very much in the hallowed traditions of Tiny Basic
and Tiny C, but with modern tool chains.

~~~
Seirdy
I disagree that this is in the tradition of projects like TinyC; I wouldn't
call this project "tiny" in the same way I would call TinyC "tiny" because
this project uses LLVM, which is quite large and complex.

~~~
aykevl
Hehe, LLVM takes about an hour to compile on my laptop. The compiler itself is
not tiny in any way. It really refers to the size of the binaries produced
which is usually very small. For example, for WebAssembly, reductions to 3% of
the original size are not uncommon.

~~~
justinclift
3% seems common (in my testing), with 2% occasionally happening as well. ;)

------
snops
I would be interested to see some more complex examples for this than the ones
provided[1], specifically around interrupts and DMA, both are somewhat
"concurrent" resources that in C need to be managed manually, with careful use
of the volatile keyword and similar.

For instance, UART transmit looks to be implemented using blocking IO[2]. I
don't know Go very well, but it would be interesting if this could be
implemented as a buffered channel [3], which would provide a nice abstraction
for the hardware FIFO buffer used by the UART, and allow the CPU to be doing
other things. The same could also be used for the I2S support I think, which
will often be used to send much more data (streaming audio) than the UART.

On closer inspection, looking at the issue tracker, it appears this is already
in planning, which is great [4].

[1] [https://github.com/tinygo-
org/tinygo/tree/master/src/example...](https://github.com/tinygo-
org/tinygo/tree/master/src/examples) [2] [https://github.com/tinygo-
org/tinygo/blob/515daa7d3c9af18c78...](https://github.com/tinygo-
org/tinygo/blob/515daa7d3c9af18c78fd97d43cafda7e4dec6290/src/machine/machine_stm32f103xx.go#L156-L163)
[3] [https://gobyexample.com/channel-
buffering](https://gobyexample.com/channel-buffering) [4]
[https://github.com/tinygo-
org/tinygo/issues/9#issuecomment-5...](https://github.com/tinygo-
org/tinygo/issues/9#issuecomment-502468619)

------
inlined
LLVM has a lot of optimizations. Does anyone have information about
performance of applications built by each complier? I’d especially be curious
about apps well tuned to reduce usage on the naive GC that TinyGo uses.

------
jsd1982
I'd love to see this targeted towards PICs. Really I'd like to just see any
modern language targeting low power microcontrollers allowing for optimization
of code size or performance. 8-bit processors using a banked memory model are
hard for languages with modern (flat) memory models to adapt to.

~~~
networkimprov
Zig lets you bring your own allocator.
[https://ziglang.org/](https://ziglang.org/)

~~~
comex
I don’t think LLVM (which Zig uses) can currently target PIC.

~~~
pjmlp
Basic and Pascal might not be modern, but they surely are alternatives to C
for targeting PIC.

------
epynonymous
golang compiler on a raspberry pi 3 compiles applications really slowly, think
minutes, but there's a workaround which is to cross compile on x86, think
seconds plus sftp transfer. i assume the primary use case is to speed up
compilation and create smaller binary sizes? this could be helpful as binary
sizes for golang compiled binaries are pretty large, my apps typically are
around 2-20MB, but i understand they include all dependencies.

~~~
ori_b
> i assume the primary use case is to speed up compilation and create smaller
> binary sizes?

LLVM is going to be much slower than the Go toolchain. It may produce smaller
binaries, but mainly through dropping the bulk of the runtime on the floor.
The main thing that LLVM does is (apparently) reduce the stack usage.

But it does support the CPUs that the author wants to target out of the box.

~~~
nappy-doo
I believe LLVM toolchains also (by default) exclude debug information, which
gc (go compiler) would need to be told to explicitly exclude.

~~~
ori_b
You generally need to run the code through some rewriters that, as far as I
recall, drop those symbols anyways -- these CPUs can't execute an elf binary
directly from flash.

------
CameronNemo
I wonder if this could be adapted to bootstrap the standard Go compiler on new
architectures. Big if true.

~~~
tptacek
Is that a problem the Go team has with their current compiler?

~~~
inlined
Maybe? They wouldn’t be able to do the current bootstrap of each Go version
being built with the previous but they could go back to the first release.
There’s a canonical version where Go bootstrapping starts, so it might be
possible to avoid fixing unportable C in the early days.

