## 1. Project Overview & Quickstart (tinygo-org/tinygo)

## File: README.md

# TinyGo - Go compiler for small places

[](https://github.com/tinygo-org/tinygo/actions/workflows/linux.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/build-macos.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/windows.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/docker.yml) [](https://github.com/tinygo-org/tinygo/actions/workflows/nix.yml)

TinyGo is a Go compiler intended for use in small places such as microcontrollers, WebAssembly (wasm/wasi), and command-line tools.

It reuses libraries used by the [Go language tools](https://golang.org/pkg/go/) alongside [LLVM](http://llvm.org) to provide an alternative way to compile programs written in the Go programming language.

> [!IMPORTANT]
> You can help TinyGo with a financial contribution using OpenCollective. Please see https://opencollective.com/tinygo for more information. Thank you!

## Embedded

Here is an example program that blinks the built-in LED when run directly on any supported board with onboard LED:

```go
package main

import (
    "machine"
    "time"
)

func main() {
    led := machine.LED
    led.Configure(machine.PinConfig{Mode: machine.PinOutput})
    for {
        led.Low()
        time.Sleep(time.Millisecond * 1000)

        led.High()
        time.Sleep(time.Millisecond * 1000)
    }
}
```

The above program can be compiled and run without modification on an [Arduino Uno](https://tinygo.org/docs/reference/microcontrollers/boards/arduino-uno), an [Adafruit Circuit Playground Express](https://tinygo.org/docs/reference/microcontrollers/featured/circuitplay-express), a [Seeed Studio XIAO-ESP32S3](https://tinygo.org/docs/reference/microcontrollers/featured/xiao-esp32s3) or any of the many supported boards that have a built-in LED, just by setting the correct TinyGo compiler target. For example, this compiles and flashes an Arduino Uno:

```shell
tinygo flash -target arduino-uno examples/blinky1
```

## WebAssembly

TinyGo is very useful for compiling programs both for use in browsers (WASM) as well as for use on servers and other edge devices (WASI).

TinyGo programs can run in [Fastly Compute](https://www.fastly.com/documentation/guides/compute/go/), [Fermyon Spin](https://developer.fermyon.com/spin/go-components), [wazero](https://wazero.io/languages/tinygo/) and many other WebAssembly runtimes.

Here is a small TinyGo program for use by a WASI host application:

```go
package main

//go:wasmexport add
func add(x, y uint32) uint32 {
	return x + y
}
```

This compiles the above TinyGo program for use on any WASI Preview 1 runtime:

```shell
tinygo build -buildmode=c-shared -o add.wasm -target=wasip1 add.go
```

You can also use the same syntax as Go 1.24+:

```shell
GOOS=wasip1 GOARCH=wasm tinygo build -buildmode=c-shared -o add.wasm add.go
```

## Installation

See the [getting started instructions](https://tinygo.org/getting-started/) for information on how to install TinyGo, as well as how to run the TinyGo compiler using our Docker container.

## Supported targets

### Embedded

You can compile TinyGo programs for over 150 different microcontroller boards.

For more information, please see https://tinygo.org/docs/reference/microcontrollers/

### WebAssembly

TinyGo programs can be compiled for both WASM and WASI targets.

For more information, see https://tinygo.org/docs/guides/webassembly/

### Operating Systems

You can also compile programs for Linux, macOS, and Windows targets.

For more information:

- Linux https://tinygo.org/docs/guides/linux/

- macOS https://tinygo.org/docs/guides/macos/

- Windows https://tinygo.org/docs/guides/windows/

## Currently supported features:

For a description of currently supported Go language features, please see [https://tinygo.org/lang-support/](https://tinygo.org/lang-support/).

## Documentation

Documentation is located on our web site at [https://tinygo.org/](https://tinygo.org/).

You can find the web site code at [https://github.com/tinygo-org/tinygo-site](https://github.com/tinygo-org/tinygo-site).

## Getting help

If you're looking for a more interactive way to discuss TinyGo usage or
development, we have a [#TinyGo channel](https://gophers.slack.com/messages/CDJD3SUP6/)
on the [Gophers Slack](https://gophers.slack.com).

If you need an invitation for the Gophers Slack, you can generate one here which
should arrive fairly quickly (under 1 min): https://invite.slack.golangbridge.org

## Contributing

Your contributions are welcome!

Please take a look at our [Contributing](https://tinygo.org/docs/guides/contributing/) page on our web site for details.

## Project Scope

Goals:

* Have very small binary sizes. Don't pay for what you don't use.
* Support for most common microcontroller boards.
* Be usable on the web using WebAssembly.
* Good CGo support, with no more overhead than a regular function call.
* Support most standard library packages and compile most Go code without modification.

Non-goals:

* Be efficient while using zillions of goroutines. However, good goroutine support is certainly a goal.
* Be as fast as `gc`. However, LLVM will probably be better at optimizing certain things so TinyGo might actually turn out to be faster for number crunching.
* Be able to compile every Go program out there.

## Why this project exists

> We never expected Go to be an embedded language, and so it’s got serious problems...

-- Rob Pike, [GopherCon 2014 Opening Keynote](https://www.youtube.com/watch?v=VoS7DsT1rdM&feature=youtu.be&t=2799)

TinyGo is a project to bring Go to microcontrollers and small systems with a single processor core. It is similar to [emgo](https://github.com/ziutek/emgo) but a major difference is that we want to keep the Go memory model (which implies garbage collection of some sort). Another difference is that TinyGo uses LLVM internally instead of emitting C, which hopefully leads to smaller and more efficient code and certainly leads to more flexibility.

The original reasoning was: if [Python](https://micropython.org/) can run on microcontrollers, then certainly [Go](https://golang.org/) should be able to run on even lower level micros.

## License

This project is licensed under the BSD 3-clause license, just like the [Go project](https://golang.org/LICENSE) itself.

Some code has been copied from the LLVM project and is therefore licensed under [a variant of the Apache 2.0 license](http://releases.llvm.org/11.0.0/LICENSE.TXT). This has been clearly indicated in the header of these files.

Some code has been copied and/or ported from Paul Stoffregen's Teensy libraries and is therefore licensed under PJRC's license. This has been clearly indicated in the header of these files.

---

## File: docs/index.rst

.. TinyGo documentation master file, created by
   sphinx-quickstart on Sat Sep 22 15:05:19 2018.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

The TinyGo site has moved!
==================================

Contents:

.. toctree::
   :maxdepth: 2

   moved

---

## File: docs/moved.rst

.. _moved:

.. highlight:: none

The TinyGo Docs Site Has Moved
=========================

The documentation web site for TinyGo has moved. 

You can find the new web site at `tinygo.org <https://tinygo.org/>`_

Thank you!

---

## File: hooks/README.md

# Hooks for Docker Hub

Files in this directory are custom commands to be run during the different Docker Hub build phases.

See https://docs.docker.com/docker-hub/builds/advanced/#custom-build-phase-hooks

---

## File: interp/README.md

# Partial evaluation of initialization code in Go

For several reasons related to code size and memory consumption (see below), it
is best to try to evaluate as much initialization code at compile time as
possible and only run unknown expressions (e.g. external calls) at runtime. This
is in practice a partial evaluator of the `runtime.initAll` function, which
calls each package initializer.

This package is a rewrite of a previous partial evaluator that worked
directly on LLVM IR and used the module and LLVM constants as intermediate
values. This newer version instead uses a mostly Go intermediate form. It
compiles functions and extracts relevant data first (compiler.go), then
executes those functions (interpreter.go) in a memory space that can be
rolled back per function (memory.go). This means that it is not necessary to
scan functions to see whether they can be run at compile time, which was very
error prone. Instead it just tries to execute everything and if it hits
something it cannot interpret (such as a store to memory-mapped I/O) it rolls
back the execution of that function and runs the function at runtime instead.
All in all, this design provides several benefits:

  * Much better error handling. By being able to revert to runtime execution
    without the need for scanning functions, this version is able to
    automatically work around many bugs in the previous implementation.
  * More correct memory model. This is not inherent to the new design, but the
    new design also made the memory model easier to reason about.
  * Faster execution of initialization code. While it is not much faster for
    normal interpretation (maybe 25% or so) due to the compilation overhead,
    it should be a whole lot faster for loops as it doesn't have to call into
    LLVM (via CGo) for every operation.

As mentioned, this partial evaluator comes in three parts: a compiler, an
interpreter, and a memory manager.

## Compiler

The main task of the compiler is that it extracts all necessary data from
every instruction in a function so that when this instruction is interpreted,
no additional CGo calls are necessary. This is not currently done for all
instructions (`runtime.alloc` is a notable exception), but at least it does
so for the vast majority of instructions.

## Interpreter

The interpreter runs an instruction just like it would if it were executed
'for real'. The vast majority of instructions can be executed at compile
time. As indicated above, some instructions need to be executed at runtime
instead.

## Memory

Memory is represented as objects (the `object` type) that contains data that
will eventually be stored in a global and values (the `value` interface) that
can be worked with while running the interpreter. Values therefore are only
used locally and are always passed by value (just like most LLVM constants)
while objects represent the backing storage (like LLVM globals). Some values
are pointer values, and point to an object.

Importantly, this partial evaluator can roll back the execution of a
function. This is implemented by creating a new memory view per function
activation, which makes sure that any change to a global (such as a store
instruction) is stored in the memory view. It creates a copy of the object
and stores that in the memory view to be modified. Once the function has
executed successfully, all these modified objects are then copied into the
parent function, up to the root function invocation which (on successful
execution) writes the values back into the LLVM module. This way, function
invocations can be rolled back without leaving a trace.

Pointer values point to memory objects, but not to a particular memory
object. Every memory object is given an index, and pointers use that index to
look up the current active object for the pointer to load from or to copy
when storing to it.

Rolling back a function should roll back everything, including the few
instructions emitted at runtime. This is done by treating instructions much
like memory objects and removing the created instructions when necessary.

## Why is this necessary?

A partial evaluator is hard to get right, so why go through all the trouble of
writing one?

The answer is that globals with initializers are much easier to optimize by
LLVM than initialization code. Also, there are a few other benefits:

  * Dead globals are trivial to optimize away.
  * Constant globals are easier to detect. Remember that Go does not have global
    constants in the same sense as that C has them. Constants are useful because
    they can be propagated and provide some opportunities for other
    optimizations (like dead code elimination when branching on the contents of
    a global).
  * Constants are much more efficient on microcontrollers, as they can be
    allocated in flash instead of RAM.

The Go SSA package does not create constant initializers for globals.
Instead, it emits initialization functions, so if you write the following:

```go
var foo = []byte{1, 2, 3, 4}
```

It would generate something like this:

```go
var foo []byte

func init() {
    foo = make([]byte, 4)
    foo[0] = 1
    foo[1] = 2
    foo[2] = 3
    foo[3] = 4
}
```

This is of course hugely wasteful, it's much better to create `foo` as a
global array instead of initializing it at runtime.

For more details, see [this section of the
documentation](https://tinygo.org/compiler-internals/differences-from-go/).

---

## File: src/examples/wasm/main/README.md

# WebAssembly main execution example

A simple hello world that prints to the browser console.

## License

Note that `index.html` is copied almost verbatim from the Go 1.12 source at
`$GOROOT/misc/wasm/wasm_exec.html`. Its license applies to this file.

---

## File: src/examples/wasm/README.md

# TinyGo WebAssembly examples

The examples here show two different ways of using WebAssembly with TinyGo:

1. Defining and exporting functions via the `//export <name>` directive. See
[the export folder](./export) for an example of this.  Additionally, the Wasm
module (which has a default value of `env`) can be specified using
`//go:wasm-module <module>`.
1. Defining and executing a `func main()`. This is similar to how the Go
standard library implementation works. See [the main folder](./main) for an
example of this.

## Building

Build using the `tinygo` compiler:

```bash
$ tinygo build -o ./wasm.wasm -target wasm ./main/main.go
```

This creates a `wasm.wasm` file, which we can load in JavaScript and execute in
a browser.

Next, choose which example you want to use:
* [callback](callback): Defines and configures callbacks in Wasm.
* [export](export): Defines callbacks in Wasm, but configures them in JavaScript.
* [invoke](invoke): Invokes a function defined in JavaScript from Wasm.
* [main](main): Prints a message to the JavaScript console from Wasm.
* [slices](slices): Splits an Array defined in JavaScript from Wasm.

Let's say you chose [main](main), you'd build it like so:
```bash
$ make main
```

## Running

Start the local web server:

```bash
$ go run server.go
Serving ./html on http://localhost:8080
```

Use your web browser to visit http://localhost:8080.

* Tip: Open the browser development tools (e.g. Right-click, Inspect in
  FireFox) to see console output.

## How it works

Execution of the contents require a few JavaScript helper functions which are
called from WebAssembly.

We have defined these in [wasm_exec.js](../../../targets/wasm_exec.js).  It is
based on `$GOROOT/misc/wasm/wasm_exec.js` from the standard library, but is
slightly different. Ensure you are using the same version of `wasm_exec.js` as
the version of `tinygo` you are using to compile.

The general steps required to run the WebAssembly file in the browser includes
loading it into JavaScript with `WebAssembly.instantiateStreaming`, or
`WebAssembly.instantiate` in some browsers:

```js
const go = new Go(); // Defined in wasm_exec.js
const WASM_URL = 'wasm.wasm';

var wasm;

if ('instantiateStreaming' in WebAssembly) {
	WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) {
		wasm = obj.instance;
		go.run(wasm);
	})
} else {
	fetch(WASM_URL).then(resp =>
		resp.arrayBuffer()
	).then(bytes =>
		WebAssembly.instantiate(bytes, go.importObject).then(function (obj) {
			wasm = obj.instance;
			go.run(wasm);
		})
	)
}
```

If you have used explicit exports, you can call them by invoking them under the
`wasm.exports` namespace. See the [`export`](./export/wasm.js) directory for an
example of this.

In addition to the JavaScript, it is important the wasm file is served with the
[`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type)
header set to `application/wasm`.  Without it, most browsers won't run it.

```go
package main

import (
	"log"
	"net/http"
	"strings"
)

const dir = "./html"

func main() {
	fs := http.FileServer(http.Dir(dir))
	log.Print("Serving " + dir + " on http://localhost:8080")
	http.ListenAndServe(":8080", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		resp.Header().Add("Cache-Control", "no-cache")
		if strings.HasSuffix(req.URL.Path, ".wasm") {
			resp.Header().Set("content-type", "application/wasm")
		}
		fs.ServeHTTP(resp, req)
	}))}
```

This simple server serves anything inside the `./html` directory on port
`8080`, setting any `*.wasm` files `Content-Type` header appropriately.

For development purposes (**only!**), it also sets the `Cache-Control` header
so your browser doesn't cache the files.  This is useful while developing, to
ensure your browser displays the newest wasm when you recompile.

In a production environment you **probably wouldn't** want to set the
`Cache-Control` header like this.  Caching is generally beneficial for end
users.

Further information on the `Cache-Control` header can be found here:

* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control

---

## File: src/examples/systick/README.md

# TinyGo ARM SysTick example

This example uses the ARM System Timer to blink an LED.  The timer fires
an interrupt 10 times per second.  The interrupt handler toggles the LED on
and off.

Many ARM-based chips have this timer feature.  If you run the example and the
LED blinks, then you have one.

The System Timer runs from a cycle counter.  The more cycles, the slower the
LED will blink.  This counter is 24 bits wide, which places an upper bound on
the number of cycles, and the slowness of the blinking.

## 2. Official Technical Reference & Guides (tinygo-org/tinygo-site)

# TinyGo Web Site

[](https://app.netlify.com/sites/tinygo/deploys)

This is the web site for TinyGo.

Built using Hugo:

http://gohugo.io/

and the Hugo "Docsy" theme:

https://github.com/google/docsy

## Prerequisites

Install [Hugo](https://gohugo.io/installation/) command line tool for your
operating system with the "extended". Note that the most recent compatible
version of Hugo is `v0.139.5`.

    CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@v0.139.5

Hugo will automatically download the [docsy](https://www.docsy.dev/docs/get-started/docsy-as-module/)
NodeJS modules needed for processing the site CSS.

## Installation

Clone this repo using:

    git clone git@github.com:tinygo-org/tinygo-site.git

Change directories into the tinygo-site directory:

    cd tinygo-site

You are now able to run the site locally, "Docsy" theme will be automatically downloaded as module:

    hugo serve

Once the site code is running locally, you can navigate to it by going to http://localhost:1313

## Deploy to Netlify

Pushing to the `release` branch automatically deploys the latest site to Netlify.

That's it.

## TODO:

- ?