 Thank you for the introduction. I'm Ike, I'm going to talk about TinyGo, which is a new Go compiler for embedded systems and Web assembly. I started the project because the main Go compiler wasn't able to do this in a good way. But I'll show a demo first. So let's see. This is the, may recognize this. This is a small, blinky example like you would use on our Arduino, for example. Even if you don't know Go, you probably recognize how it works. It figures an LED, and then in a loop, it turns it on and off. And I can run, wait, flash it to a market controller, using this command. It's compiling and flashing. And probably not visible from behind, but this is the LED blinking. And this is written using Go. So I think that's pretty cool. However, so this is what Arduino does as well, basically. But I think we can go even further by simulating this word, BERT. This is the same program running inside the IDE. And you can see the same LED blinking here. And this is especially useful for small modifications to see what happens, for example, might turn to blink a little bit faster. This just works. I won't go into detail how this exactly works. But basically, it compiles the same program to WebAssembly instead of to a native binary. But it uses the same hardware abstraction layer. So the backend, so to say, of the hardware abstraction layer is talks to the JavaScript in the simulator. But it's the same layer. So the machine package here just talks to WebAssembly instead, to the JavaScript instead of to the real hardware. And I think that can be a very productive way to write software. So for example, here I have a slightly more complicated example. And I wrote this entirely in the simulator. And it's visible here. Just adjusting the brightness and the color speed, et cetera, all in the simulator. And when I run it on the first on the simulator, and this is how I run it on the board itself, it's compiling. And here you see the same program running in, sorry. Oh, there you go. I think this is visible because the LEDs are pretty bright. But this is basically the same program. Well, I discovered the bug in the simulator. But otherwise, it worked on the first try. So I think that's pretty cool. Let's see. That's a demo. So if you don't know Go, it's a programming language designed by Google about 12 years ago, which is actually pretty young for a programming language. Python is 30 years old, and C is probably older than most of you. So it's pretty young. And Google designed it to solve their problems. So it was intended for large servers with many cores. So it was entirely not designed to do this. But I like language. It's quite simple to learn. I started getting into embedded development myself via Arduino, like most people probably. And I really liked being able to control hardware because electronics was a hobby of mine before, but I sort of ignored it because I didn't get any further. But at some point I discovered I could program these electronics using software. And I got very excited. But I really didn't really like the C++ dialect that Arduino uses. It's fine, but not what I like. So when I discovered MicroPython, which is used on the MCH batch, for example, it's written in Python, I basically found a love. I contributed some patches. And I really liked the project. Unfortunately, I also wanted to do LED animations like this. And it's just a little bit too slow for what I wanted to do. So at that point I also discovered Go, as I previously described. And I was like, I mean, how hard can it be? So I just hacked around and see how far it got. And four years later, it's gotten quite far. Most of the Go programming language features already work, like basically all basic features. And so what mainly doesn't work is, for example, parallelism. So you can use multiple threads or multiple cores because most of these chips don't even have a multiple cores. And the Reflect Packages package, which is runtime reflection, like runtime type information, et cetera, which partially works, but it's not complete enough for JSON serialization, for example. But that's something I work on. But because there are small parts that are still missing, large parts of the standard library don't cope out because one dependency of a dependency somewhere doesn't work yet. But otherwise, most of it just works. It's the same language. So my goal is to be compatible with a wider ecosystem. And of course, CGo, which is a way of Go to interact with C code. The main Go compiler has trouble cross-compiling when CGo is in use. However, in TineGo, the main way to use it is by cross-compiling, because the chip here is different than my x86 laptop. So in my opinion, in many cases, it works even better than the normal implementation. Let's see. So I want to just say quickly, I use the word embedded software and microcrawlers somewhat interchangeable, but it's not quite the same. Embedded systems are a bit of a vague category. But basically, the way I describe them is everything that runs code but doesn't look like a computer, which is almost every electronic device nowadays. A more specific category is microcrawlers. And this is just some general properties that most of them have, but there are always exceptions, of course. There are many architectures. There's a wide range of RAM, but it's usually very limited. They are relatively slow. They execute code directly from flash memory instead of loading it into RAM first, like Windows or Linux do, for example. They don't have memory protection usually, and they don't have virtual memory. However, what they do have is a large range of peripherals, which means they have various ways of interacting with other non-programmable chips, for example gyroscopes, or displays, or whatever. Programming, these chips is almost always done in CRC++. There are some exceptions, like the batch, for example. But underneath is also CNC++. Sometimes, other languages are used, like Rust, or maybe even Ada in some cases. But almost always it's CRC++. But how this is done is usually by using silicon vendor provided hardware abstraction layers, which tend to be rather difficult to use. Well, it's not difficult, but not very portable, because you're locked into the system. And well, it's software written by hardware designers, which is not usually of the greatest quality. So yeah, that's one reason why I don't really like using CNC. But there are also other practical reasons. For example, CNC is by default very memory unsafe. According to both research by Microsoft and Google, 70% of their security vulnerabilities were found in memory due to memory and safety. For example, double freeze, or buffer overruns, or things like that. And so that's one reason to not use a language that has this unsafety. Rust, for example, solved this in a very interesting way. Another reason is undefined behavior. Technically, memory and safety is, I guess, also undefined behavior. But there are also integer overflows, for example, and many other things that seem to work, but sometimes that don't. And CNC is often presented as portable. But actually, it isn't really. It's sort of. But all the implementations are slightly different. Integer sizes can differ. Available headers can differ. Yeah, it's a little bit of a mess, but because of the long history of CNC. So that's why I prefer using all the languages. One contender is, of course, Rust. And I think it's a very good language for programming market controllers, especially for safety critical systems. But there are some reasons why you might not want to use it. For example, it has gotten a lot better over the years, but it's still a little bit hard to learn. But for example, you might also have existing Go code you might want to use on a market controller or existing developers that are familiar with Go but not with Rust. So having options is great. But then again, Rust is probably a nice language, just not my language. So that's why I like using a different language. And now I would like to go into a little bit more detail how a tiny Go is structured, because most people probably think of compiler as a big black box, and you put source code in, and an object file comes out in the end. And so it is very complicated when you look at it this way. But like all complicated problems in software engineering, you just split it up into multiple smaller parts that are more easily solvable. So for a tiny Go, for example, I use the Go has some standard library packages which already supports parsing and type checking the language, which is useful. And so what tiny Go basically does is converts this intermediate form that these compilers are structured in layers. And every layer simplifies the code a bit and optimizes them in a way that is appropriate for this layer. And in tiny Go, I use a few packages. For the first part, I use the standard library packages, as I described. And for generating object files, I use LVM, which is a compiler framework. Many well-known compilers are written using LVM. For example, Rust, as I mentioned before, Swift, Clang, and many other compilers are using LVM in the back end. What it does is basically a compiler can generate a language-independent intermediate representation. And LVM will then optimize this language-independent form and generate machine codes in the end. So that takes away lots of the hard work of writing a compiler. So basically, what tiny Go does is only to convert this Go intermediate form into LVM intermediate form, which, for the most part, is pretty simple. But of course, in Go, you can start with Go routines, which are kind of graying threads. And that, of course, LVM doesn't support things like that. So that's basically a runtime call. So this part of the compiler is not too difficult. What is more interesting, probably, is the runtime. The runtime basically does a lot of stuff behind the back. You can see a list here. When a chip like this resets, nothing is initialized yet. Memory has to be initialized. Clocks have to be initialized. Often, the chip has to be set to a higher frequency, stuff like that. So that's the startup code, which is in runtime. And then it calls the main function. As I showed earlier in the code, like this one. And of course, there are many other things, like scheduling. Go has Go routines, which are basically green threads. And the scheduler is there to start them and switch between them and prioritize them, et cetera. And Go has channels, which are, I think, other languages have them, but not frequently used, I think. Erlang. Yeah, probably. Thank you. I think you're correct. So that's one thing that's implemented in the runtime. And garbage collection, of course. Language specification doesn't describe how memory is managed. It just says, this allocates memory. In practice, that means you have to use a garbage collector, like Java or JavaScript or, I believe, Erlang, but I'm sure. And I basically copied the garbage collector from MicroPython, more or less, at least the design. And it's just a few hundred lines, I believe. It's like a textbook implementation of a garbage collector. But it's also in the runtime and time handling, because every chip has a different way of controlling time. Many have an RTC, a real-time clock, real-time, because at the chip reset, it's set back to zero. But this specific hardware implementation has to be converted back to the time.now and time.sleep in Go. And that's what the runtime does. And of course, all the things like the HashMap implementation, which is, of course, optimized for size instead of for speed, and many other small things that are just a little bit too complicated to do directly in line with our separate functions. Let's see. I think I have some time left. So yeah, that's the runtime. And the runtime is also the, I've used a different, some people have suggested using the existing runtime for more compatibility. However, the goals of TinyGo are so different from normal in Go that I decided to use a different runtime. Because for example, the garbage collector is super simple, which is necessary, because otherwise it's just too large. And for like 16K of RAM, you don't need an advanced garbage collector. And many other things are designed specifically for a small and better system instead of large servers. However, all of my intention with this project is to be entirely compatible with the existing Go ecosystem so that existing code can be reused on microcontrollers or WebAssembly, which is what many people are into, but I'm not really, to be honest. So some people have, for example, suggested strapping some parts from the language to make it smaller, but then you're working compatibility. And that's the whole point of the compiler being compatible with existing code. Otherwise, you might as well just start a new language, write a new language. So yeah, that's mainly my goal. I just want a compiler for existing codes that's but for a very different use case than it was used before. Thank you. Any questions? So yes, we do have time for questions. So please, microphone in the middle of the front. Hi. Compliments on the idea of mapping. Sorry? Compliments on the idea of mapping an advanced language directly to binary code and making it very thin. Two questions or remarks, I don't know, about complexity. First is micro IP. I don't know if you've heard about it, but it used to be a TCP IP stack that fitted in 16 kilobytes. And it was based on coroutines. So you might want to be interested in looking. Sorry, I haven't. Micro IP is a TCP IP stack that fits in 16 kilobytes. It used to be run on micro controllers. And it works through coroutines. To? Coroutines. Coroutines. So you might not look into it. In C or? Yeah. Interesting. Yeah. Maybe you have to move on to the next question. Please, just one question. But you can discuss afterwards. It's useful for the net package, which is not implemented yet. But thank you. I was wondering, you spoke about the intention to support a full-go ecosystem. How do you plan to deal with file system operations or other operations that would deal with an OS that is definitely not present in the embedded world? So the file system, in Go, we have the OS package, which is an abstraction layer over the operating system, of course. And what we've done in TinyGo is, basically, there's a function you can call to set a virtual file system at a certain path. OK, next question. And that's how you can put in some file systems. OK, then next question, please, front micro. Hello. I was wondering, there's the main issue with Go is it's too large to fit into microcontrollers. And therefore, you wrote a new runtime, which is smaller so it can run on microcontrollers. But the language itself, you were just saying you wrote a Go compiler. Couldn't you just use the default compiler instead? Because what are the differences there? I was very curious about that. So I basically tried this. I tried to use GCC Go. GCC also has Go support. And my first attempt was using, and GCC also has a extend support for the batch, for example. And basically, what I tried was enabling the Go parts. And it did, in fact, work surprisingly. However, I found that the way, so the Go part was not very optimized. It uses all variables. When you call a function, for example, all parameters are passed on the stack. And this wastes a lot of stack space. So it works on the ESP, which is pretty large. But on an AVR, it probably would be very difficult to get working. So I've looked into it, but the accessing design was just not right. OK. Are there any questions on the internet? No? Then next question, please. A question about the garbage collection. Of course, garbage collection can get away with real-time performance, which may be a big problem for an embedded system. Have you taken care of that, for example, by trying to schedule it in downtime while it's waiting just before it goes to sleep doing some garbage collection? I've looked into it a lot, but right now, it doesn't support this. However, what you can do is run the time critical stuff and interrupts. And interrupts are not allowed to allocate memory. So this way, you can just do a garbage collection cycle while an interrupt is running, basically interrupts the cycle with an interrupt. So you can still write interrupt real-time codes and just not use heap allocations in there. So it's possible. OK. And one last really quick question. Thank you. Sorry. Front micro. Work? Yeah, out again. I was also thinking about a system which was also meant for small processors, the Java 2 Micro Edition, which run on the Nokia sensor on. Could you use ideas from there? Because that was also a very small system, which a garbage collector, in case of Java. Sorry, I didn't get that entirely. The question is to what are? Could you use ideas which were used in Java 2 Micro Edition because that was also meant for very small systems? And it ran in Java, which also needs garbage collection. You mean compile Go to the Java bytecorders? And did you take maybe you could steal some ideas, so to speak? I honestly didn't really look into it, but I know there are parts of Java's cats too. Or Java, I don't know. OK, so that's something you can maybe discuss afterwards because time is up. If you have more questions, I'll be back here. And please give a warm round of applause, because that was a great talk.