kodablah 6 years ago

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

  • aykevl 6 years ago

    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 6 years ago

      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 :)

      • aykevl 6 years ago

        That's pretty cool!

        If you want something now, I've also written and abandoned this: https://github.com/aykevl/tinygo-gccgo

        It actually worked fairly well, but the code was way too bloated to be useful.

        • jsolson 6 years ago

          Honestly for what I'm doing what you have here is a pretty reasonable start. I'm comfortable writing (and calling into) C where the Go bits aren't in place yet, and I'm a lot more familiar with LLVM's internals than with GCC's if I need to debug something. We'll see what I get up to after brunch.

          One request: if you're open to PRs (I can't promise I'll send any, but I'm trying to get into a habit of contributing to OSS with my hobby hackery), can you add a LICENSE file (context: the OSS patching policy I'm bound by is very friendly for projects on Github under most licenses -- https://opensource.google.com/docs/patching/ -- it's more problematic when the license for the code is undefined)?

          • aykevl 6 years ago

            I'm certainly open to PRs :)

            Good catch on the LICENSE file, I totally forgot about it. I've added it now.

      • kodablah 6 years ago

        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 6 years ago

          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 :)

SiVal 6 years ago

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.

  • abstractbeliefs 6 years ago

    If I remember right though, the smallest devices running Java (comparable to the AVR devices in specs) were mostly designed at the hardware level to run Java, so there were lots of considerations made that wont be true for an AVR microcontroller that has a first-class C toolchain.

    Additionally, the Java Card specification was a pretty cut down version of Java that didn't have the same "Not _yet_ supported" feature list here.

  • stmw 6 years ago

    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 6 years ago

      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 6 years ago

        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.

akavel 6 years ago

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 6 years ago

    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 6 years ago

      > 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

  • j1elo 6 years ago

    Watch out because the bits don't necessarily state anything about the "level" of the microcontroller... at least in some cases. I'm currently writing code for a 32-bit AVR32 UC3C family chip, and that's for sure closer to an old-school 8-bit AVR than it is to a "full fledged" 32-bit ARM

sbinet 6 years ago

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

  • chewxy 6 years ago

    go get llvm.org/llvm/bindings/go/llvm

    I'm actually using it for some things

    • aykevl 6 years ago

      I'm using this exactly. It's not the nicest interface but it supports almost everything that LLVM does. 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.