
Show HN: TinyGo – LLVM-based Go compiler for microcontrollers - ngaut
https://github.com/aykevl/tinygo
======
pjmlp
Nice project!

With enough love it might follow Oberon's footsteps.

[http://www.astrobe.com](http://www.astrobe.com)

------
sbinet
Next step is to directly generate IR with (link:
[https://github.com/llir/llvm](https://github.com/llir/llvm))
github.com/llir/llvm. And then rewrite all of llvm in Go :)

~~~
chewxy
go get llvm.org/llvm/bindings/go/llvm

I'm actually using it for some things

~~~
aykevl
I'm using this exactly. It's not the nicest interface but it supports almost
everything that LLVM does.
[https://github.com/llir/llvm](https://github.com/llir/llvm) looks nice but I
don't think you can interface with LLVM from there, which is needed if you
want to do more advanced stuff.

------
akavel
Didn't find it in the readme: does anyone know what general "level" of
microcontrollers are the project author(s) hoping to target? I suppose that
because of the Go spec already, the minimum required architecture must be at
least 32bit?

~~~
aykevl
Hi, I'm the author of the compiler.

All backends supported by LLVM should be fairly easily supported by TinyGo. In
fact, I've had the blinky example running on an Arduino a while back (8-bit,
2kB RAM, 32kB flash). There is nothing in the Go spec that requires a 32-bit
system, just like there is nothing in the C standard that requires a 16-bit
system (ints are at least 16 bits).

The biggest obstacle is not the fact that it is 8-bit, but the fact that it is
a Harvard-style processor with a separate address space for code and data.
I've added a section to the README to explain this. Also, garbage collection
is going to be painful.

~~~
UncleEntity
> We hope that the support built into the LLVM IR is sufficient to support a
> broad class of garbage collected languages including Scheme, ML, Java, C#,
> Perl, Python, Lua, Ruby, other scripting languages, and more.[0]

Maybe "and more" means there's hope for Go style garbage collection.

[0][https://llvm.org/docs/GarbageCollection.html](https://llvm.org/docs/GarbageCollection.html)

------
SiVal
Go tends to be at least as fast as Java with a much smaller memory footprint.
It ought to run well on any device that can run Java, which includes a lot of
small devices.

~~~
stmw
I actually wouldn't expect Go to be considerably better in memory footprint
(or other things) than "embedded" Java in embedded environments. Once you
accept the idea of having GC, it puts some constraints on things. Of course,
you can't compare "server java" with embedded java -- those are as different
as TinyGo and "real" Go, if not more so...

~~~
lossolo
_Normal_ Go is a lot more memory efficient than _normal_ Java, it has value
types and no VM/JIT overhead. In my own measurements it was up to 50x times
more memory efficient.

~~~
crawshaw
Also: UTF-8 instead of UTF-16 can make a surprising difference on memory use,
especially if you interact with services in UTF-8 and so spend a lot of memory
in Java copying back and forth.

------
kodablah
Neat. I've always considered Go, with its (relatively) simple design and
significant quantity of decent libraries to be very retargetable (I'm toying
with targeting the JVM now).

I could see this as a little less likely though for limited resource use cases
since much of the code is not written with that in mind. I'd be curious how
the LLVM IR looks compiled to WASM compared to Go's built in (as of 1.11)
support. Specifically the initialization of the unicode package with all its
exposed structs and init struct creation has been a startup and binary size
burden on any size-restricted context Go runs in. Causes lots of bloat on the
WASM side.

I created an issue on some of the WASM bloat [0], but it's not really going to
be addressed now.

0 -
[https://github.com/golang/go/issues/26622](https://github.com/golang/go/issues/26622)

~~~
aykevl
Yeah the heavyweight standard library is a big problem. I'm trying to solve it
(in part) with smart analysis that tries much harder to remove dead code and
dead global data. Maybe even try to run some initializers at compile time so
the result can be put in flash instead of RAM.

In my experience, it's not the unicode package that's big but the run-time
typing information and the reflect package used by packages like fmt. The fmt
package doesn't know what types it will need to accept so it literally
supports everything (including unused types).

And as you mention WASM: I've been thinking about supporting that too, exactly
because WASM and microcontrollers have some surprising similarities (small
code size, fast startup, little OS-support).

~~~
jsolson
I suppose it's not strange to see WASM come up -- last weekend I was
considering doing something even weirder: writing a WASM to Thumb2 AoT
compiler so I could leverage Go's built-in WASM support.

This project seems more immediately useful :)

~~~
kodablah
Yeah, just wait until you see multiple megabytes of WASM instructions for tiny
progs or the realize the team does not care about non-web targets. You're much
better off leveraging Rust's WASM support for resource limited, non-web WASM
targets.

~~~
jsolson
In my case I was less interested in the WASM part of it than I was in
something targeting a "no OS" environment. That said, for my target (those
little Pine64 RTL8710 Cortex M3 MCU) you're almost certainly right. On the
other hand it's a hobby project, and I like writing Go while I find writing
Rust to be a bit of a chore. Also, it's a hobby project, so distractions like
re-targeting WASM to the ARMv7-M are half of the fun :)

