9 ms·
TinyGo: New Go Compiler Based on LLVM
- CameronNemo 7y agoI wonder if this could be adapted to bootstrap the standard Go compiler on new architectures. Big if true.
- tptacek 7y agoIs that a problem the Go team has with their current compiler?
- inlined 7y agoMaybe? 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.
- eikenberry 7y agoDoesn't the GCC, and thus the GCC Go implementation, already cover more architectures than LLVM?
- sanxiyn 7y agoStandard Go compiler can be bootstrapped on new architectures with cross compilation. It does not need any new implementation.
- pcwalton 7y ago> 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.
- learnfromstory 7y agoCan you elaborate? How are pointers to floats problematic? Or is it something else?
- munificent 7y agoConservative GCs don't know which bytes in memory are actually pointers, so they treat every word in memory as being a pointer if it looks like one. This means if you have some other value that happens to look like a pointer — in this case a float — the GC will think it's pointing to some other memory and keep that memory around even though it isn't used.
- viraptor 7y agoConservative GC is pretty much: look at all reachable memory, whatever looks like a pointer to a range which is allocated keeps that range allocated. Pros: you don't have to care about type information and precise stack/structure walking. Cons: If you have range 0x8000-0x8010 allocated, and have a variable with integer value 0x8001 somewhere in the memory, it will keep that range allocated. It doesn't matter that it's an int, not a pointer. Floats and 32-bit pointers have quite a lot of accidental collisions that way.
- pcwalton 7y agoBecause 1.0 is 0x3f800000, which is often right in the middle of the heap.
- 0815test 7y agoI 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?
- tyingq 7y agoPersonally, I welcome all comers, regardless of intent or completeness. That they offer a minimal refcounted implementation for the platform more likely to need it sooner seems to signal good intent. I say this watching 30+ years of alternate implementations of different languages and runtimes. Even those that failed (or maybe moreso) indirectly inspired positive changes in the survivors.
- sethammons 7y agoHow 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.
- danielparks 7y agohttps://go.googlesource.com/gollvm/ https://go.googlesource.com/gollvm/
- aykevl 7y agoThere 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.
- jsd1982 7y agoI'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 7y agoZig lets you bring your own allocator. https://ziglang.org/ https://ziglang.org/
- aykevl 7y agoThat should be possible: there is also experimental AVR support. Experimental because the LLVM backend is unfortunately too buggy to be used in real programs (but is improving!). The first step to make this happen, would be to add a PIC backend to LLVM.
- epynonymous 7y agogolang 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 7y ago> 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 7y agoI believe LLVM toolchains also (by default) exclude debug information, which gc (go compiler) would need to be told to explicitly exclude.
- ori_b 7y agoYou 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.
- justinclift 7y agoAs a data point, TinyGo includes the debug info by default. There is a "-no-debug" option to turn off the inclusion though.
- dekhn 7y agoI compiled go as an x86-64 to ARM cross compiler (ubuntu to raspi). Worked great. I even confused myself a bit by running the ARM binary on the x86-64 machine (turns out binfmt will detect the binary and run it under QEMU).
- tomcam 7y agoCongratulations 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 7y agoI 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 7y agoHehe, 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 7y ago3% seems common (in my testing), with 2% occasionally happening as well. ;)
- snops 7y agoI 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/examples https://github.com/tinygo-org/tinygo/tree/master/src/example... [2] https://github.com/tinygo-org/tinygo/blob/515daa7d3c9af18c78fd97d43cafda7e4dec6290/src/machine/machine_stm32f103xx.go#L156-L163 https://github.com/tinygo-org/tinygo/blob/515daa7d3c9af18c78... [3] https://gobyexample.com/channel-buffering https://gobyexample.com/channel-buffering [4] https://github.com/tinygo-org/tinygo/issues/9#issuecomment-502468619 https://github.com/tinygo-org/tinygo/issues/9#issuecomment-5...
- inlined 7y agoLLVM 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.