site: Adds languages page, starting with TinyGo (#759)

This consolidates common notes we've had into a landing page.
This is intentionally only simplified content for TinyGo to make the
first review easier (as well the writing easier). After this, PRs will
happen to consolidate the other notes we have sporadically in the
examples directory.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2022-08-23 15:40:29 +08:00
committed by GitHub
parent 1a46d471f8
commit 6d1d7d33aa
4 changed files with 141 additions and 11 deletions

View File

@@ -15,14 +15,4 @@ Under the covers, [greet.go](testdata/greet.go) does a few things of interest:
* Uses `reflect.StringHeader` to build back a string from a pointer, len pair.
* Relies on TinyGo not eagerly freeing pointers returned.
Go does not export allocation functions, but when TinyGo generates WebAssembly,
it exports "malloc" and "free", which we use for that purpose. These are not
documented, so not necessarily a best practice. See the following issues for
updates:
* WebAssembly exports for allocation: https://github.com/tinygo-org/tinygo/issues/2788
* Memory ownership of TinyGo allocated pointers: https://github.com/tinygo-org/tinygo/issues/2787
Note: While folks here are familiar with TinyGo, wazero isn't a TinyGo project.
We hope this gets you started. For next steps, consider reading the
[TinyGo Using WebAssembly Guide](https://tinygo.org/docs/guides/webassembly/)
or joining the [#TinyGo channel on the Gophers Slack](https://github.com/tinygo-org/tinygo#getting-help).
See https://wazero.io/languages/tinygo/ for more tips.

View File

@@ -46,3 +46,9 @@ googleAnalytics = "G-LG7LD9G4ZB"
identifier = "specs"
name = "Specifications"
weight = 1
[[languages.en.menu.main]]
parent = "appendix"
url = "/languages/"
identifier = "languages"
name = "Languages"
weight = 1

View File

@@ -0,0 +1,27 @@
+++
title = "Languages"
layout = "single"
+++
WebAssembly has a virtual machine architecture where the host is the embedding
process and the guest is a program compiled into the WebAssembly Binary Format,
also known as wasm. The first step is to take a source file and compile it into
the wasm bytecode.
Ex. If your source is in Go, you might compile it with TinyGo.
```goat
.-----------. .----------------------. .-----------.
/ main.go /---->| tinygo -target=wasi +---->/ main.wasm /
'-----+-----' '----------------------' '-----------'
```
Below are a list of languages notes wazero contributed so far.
* [TinyGo](tinygo) Ex. `tinygo build -o X.wasm -scheduler=none --no-debug -target=wasi X.go`
Note: These are not official documentation, and may be out of date. Please help
us [maintain][1] these and [star our GitHub repository][2] if they are helpful.
Together, we can help make WebAssembly easier on the next person.
[1]: https://github.com/tetratelabs/wazero/tree/main/site/content/languages
[2]: https://github.com/tetratelabs/wazero/stargazers

View File

@@ -0,0 +1,107 @@
+++
title = "TinyGo"
+++
## Introduction
[TinyGo][1] is an alternative compiler for Go source code. It can generate
`%.wasm` files instead of architecture-specific binaries through its `wasi`
target. The resulting wasm depends on a subset of features in the [WebAssembly
2.0 Core specification][2], as well [WASI][3] host imports. TinyGo also
supports importing custom host functions and exporting functions back to the
host.
## Example
Here's a basic example of source in TinyGo:
```go
package main
//export add
func add(x, y uint32) uint32 {
return x + y
}
```
The following flags will result in the most compact (smallest) wasm file.
```bash
tinygo build -o main.wasm -scheduler=none --no-debug -target=wasi main.go
```
The resulting wasm exports the `add` function so that the embedding host can
call it, regardless of if the host is written in Go or not.
## Disclaimer
This document includes notes contributed by the wazero community. While wazero
includes TinyGo examples, and maintainers often contribute to TinyGo, this
isn't a TinyGo official document. For more help, consider the [TinyGo Using
WebAssembly Guide][4] or joining the [#TinyGo channel on the Gophers Slack][5].
Meanwhile, please help us [maintain][6] this document and [star our GitHub
repository][7], if it is helpful. Together, we can help make WebAssembly easier
on the next person.
## Constraints
Like other compilers that can target wasm, there are constraints using TinyGo.
These constraints affect the library design and dependency choices in your Go
source.
The first constraint people notice is that `encoding/json` usage compiles, but
panics at runtime. This is due to limited support for reflection.
## Memory
When TinyGo compiles go into wasm, it treats a portion of the WebAssembly
linear memory as heap. The embedding host can allocate and free memory using
TinyGo's allocator via WebAssembly exported functions: `malloc` and `free`.
Here is what the signatures look like when inspecting wasm generated by TinyGo:
```webassembly
(func (export "malloc") (param $size i32) (result (;$ptr;) i32))
(func (export "free") (param $ptr i32))
```
Note that TinyGo compiles a `unsafe.Pointer` as a linear memory offset.
The general flow is that the host allocates memory by calling `malloc`, then
using the result as the memory offset to write data. Once the host is finished,
it calls `free` with that same memory offset. wazero includes an [example
project][8] that shows allocation in wasm generated by TinyGo.
These are not documented, though widely used. See the following issues for
clarifications:
* [WebAssembly exports for allocation][9]
* [Memory ownership of TinyGo allocated pointers][10]
## Frequently Asked Questions
### How do I use json?
TinyGo doesn't yet implement [reflection APIs][11] needed by `encoding/json`.
Meanwhile, most users resort to non-reflective parsers, such as [gjson][12].
### Why does my wasm import WASI functions even when I don't use it?
TinyGo does not have a standalone wasm target, rather only `wasi`. Some users
are surprised to see [WASI][3] imports even when there is no main function and
the compiled function uses no memory. Most notably, `fd_write` is used to
implement panics.
### Why is my wasm so big?
TinyGo minimally needs to implement garbage collection and `panic`, and the
wasm to implement that is often not considered big (~4KB). What's often
surprising to users are APIs that seem simple, but require a lot of supporting
functions, such as `fmt.Println`, which can require 100KB of wasm.
[1]: https://tinygo.org/
[2]: https://www.w3.org/TR/2022/WD-wasm-core-2-20220419/
[3]: https://github.com/WebAssembly/WASI
[4]: https://tinygo.org/docs/guides/webassembly/
[5]: https://github.com/tinygo-org/tinygo#getting-help
[6]: https://github.com/tetratelabs/wazero/tree/main/site/content/languages/tinygo.md
[7]: https://github.com/tetratelabs/wazero/stargazers
[8]: https://github.com/tetratelabs/wazero/tree/main/examples/allocation/tinygo
[9]: https://github.com/tinygo-org/tinygo/issues/2788
[10]: https://github.com/tinygo-org/tinygo/issues/2787
[11]: https://github.com/tinygo-org/tinygo/issues/2660
[12]: https://github.com/tidwall/gjson