docs: change links in README and remove old ReadTheDocs pages to point to TinyGo.org site

Signed-off-by: Ron Evans <ron@hybridgroup.com>
Этот коммит содержится в:
Ron Evans 2019-01-04 15:54:40 +01:00 коммит произвёл Ayke van Laethem
родитель 8d1284cfe7
коммит b4dd2dbf60
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
13 изменённых файлов: 22 добавлений и 1016 удалений

Просмотреть файл

@ -1,6 +1,5 @@
# TinyGo - Go compiler for microcontrollers # TinyGo - Go compiler for microcontrollers
[![Documentation Status](https://readthedocs.org/projects/tinygo/badge/?version=latest)](https://tinygo.readthedocs.io/)
[![Build Status](https://travis-ci.com/aykevl/tinygo.svg?branch=master)](https://travis-ci.com/aykevl/tinygo) [![Build Status](https://travis-ci.com/aykevl/tinygo.svg?branch=master)](https://travis-ci.com/aykevl/tinygo)
> We never expected Go to be an embedded language and so it's got serious > We never expected Go to be an embedded language and so it's got serious
@ -69,7 +68,7 @@ Not yet supported:
## Installation ## Installation
See the [installation instructions](https://tinygo.readthedocs.io/en/latest/installation.html). See the [getting started instructions](https://tinygo.org/getting-started/).
### Running with Docker ### Running with Docker
@ -92,7 +91,7 @@ The following architectures/systems are currently supported:
* WebAssembly * WebAssembly
For more information, see [this list of targets and For more information, see [this list of targets and
boards](https://tinygo.readthedocs.io/en/latest/targets.html). Pull requests for boards](https://tinygo.org/targets/). Pull requests for
broader support are welcome! broader support are welcome!
## Analysis and optimizations ## Analysis and optimizations
@ -139,8 +138,9 @@ Non-goals:
## Documentation ## Documentation
Documentation is currently maintained on a [dedicated ReadTheDocs Documentation is currently maintained on a dedicated web site located at [https://tinygo.org/](https://tinygo.org/).
page](https://tinygo.readthedocs.io/en/latest/).
You can find the web site code at [https://github.com/tinygo-org/tinygo-site](https://github.com/tinygo-org/tinygo-site).
## Getting help ## Getting help

Просмотреть файл

@ -5,9 +5,8 @@ import (
"golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa"
) )
// For a description of the calling convention in prose, see docs/internals.rst // For a description of the calling convention in prose, see:
// or the online version of this document: // https://tinygo.org/compiler-internals/calling-convention/
// https://tinygo.readthedocs.io/en/latest/internals.html#calling-convention
// The maximum number of arguments that can be expanded from a single struct. If // The maximum number of arguments that can be expanded from a single struct. If
// a struct contains more fields, it is passed as a struct without expanding. // a struct contains more fields, it is passed as a struct without expanding.

Просмотреть файл

@ -1,36 +0,0 @@
.. _docker:
.. highlight:: none
Using with Docker
=================
A docker container exists for easy access to the ``tinygo`` CLI. For example, to
compile ``wasm.wasm`` for the WebAssembly example, from the root of the
repository::
docker run --rm -v $(pwd):/src tinygo/tinygo tinygo build -o /src/wasm.wasm -target wasm examples/wasm
To compile ``blinky1.hex`` targeting an ARM microcontroller, such as the PCA10040::
docker run --rm -v $(pwd):/src tinygo/tinygo tinygo build -o /src/blinky1.hex -size=short -target=pca10040 examples/blinky1
To compile ``blinky1.hex`` targeting an AVR microcontroller such as the Arduino::
docker run --rm -v $(pwd):/src tinygo/tinygo tinygo build -o /src/blinky1.hex -size=short -target=arduino examples/blinky1
For projects that have remote dependencies outside of the standard library and go code within your own project, you will need to map your entire GOPATH into the docker image in order for those dependencies to be found::
docker run -v $(PWD):/mysrc -v $GOPATH:/gohost -e "GOPATH=$GOPATH:/gohost" tinygo/tinygo tinygo build -o /mysrc/wasmout.wasm -target wasm /mysrc/wasm-main.go
.. note::
At this time, tinygo does not resolve dependencies from the /vendor/ folder within your project.
For microcontroller development you must flash your hardware devices
from your host environment, since you cannot run ``tinygo flash`` from inside
the docker container.
So your workflow could be:
- Compile TinyGo code using the Docker container into a HEX file.
- Flash the HEX file from your host environment to the target microcontroller.

Просмотреть файл

@ -1,162 +0,0 @@
.. _faq:
Frequently Asked Questions
==========================
What is TinyGo exactly?
-----------------------
A new compiler and a new runtime implementation.
Specifically:
* A new compiler using (mostly) the standard library to parse Go programs and
using LLVM to optimize the code and generate machine code for the target
architecture.
* A new runtime library that implements some compiler intrinsics, like a
memory allocator, a scheduler, and operations on strings. Also, some
packages that are strongly connected to the runtime like the ``sync``
package and the ``reflect`` package have been or will be re-implemented for
use with this new compiler.
Why a new compiler?
-------------------
Why not modify the existing compiler to produce binaries for microcontrollers?
There are several reasons for this:
* The standard Go compiler (``gc``) does not support instruction sets as used
on microcontrollers:
* The Thumb instruction set is unsupported, but it should be possible to
add support for it as it already has an ARM backend.
* The AVR instruction set (as used in the Arduino Uno) is unsupported and
unlikely to be ever supported.
Of course, it is possible to use ``gccgo``, but that has different problems
(see below).
* The runtime is really big. A standard 'hello world' on a desktop PC produces
a binary of about 1MB, even when using the builtin ``println`` function and
nothing else. All this overhead is due to the runtime. Of course, it may be
possible to use a different runtime with the same compiler but that will be
kind of painful as the exact ABI as used by the compiler has to be matched,
limiting optimization opportunities (see below).
* The compiler is optimized for speed, not for code size or memory
consumption (which are usually far more important on MCUs). This results in
design choices like allocating memory on every value → interface conversion
while TinyGo sacrifices some performance for reduced GC pressure.
* With the existing Go libraries for parsing Go code and the pretty awesome
LLVM optimizer/backend it is relatively easy to get simple Go programs
working with a very small binary size. Extra features can be added where
needed in a pay-as-you-go manner similar to C++ avoiding their cost when
unused. Most programs on microcontrollers are relatively small so a
not-complete compiler is still useful.
* The standard Go compilers do not allocate global variables as static data,
but as zero-initialized data that is initialized during program startup.
This is not a big deal on desktop computers but prevents allocating these
values in flash on microcontrollers. Part of this is due to how the
`language specification defines package initialization
<https://golang.org/ref/spec#Package_initialization>`_, but this can be
worked around to a large extent.
* The standard Go compilers do a few special things for CGo calls. This is
necessary because only Go code can use the (small) Go stack while C code
will need a much bigger stack. A new compiler can avoid this limitation if
it ensures stacks are big enough for C, greatly reducing the C ↔ Go calling
overhead.
`At one point <https://github.com/aykevl/tinygo-gccgo>`_, a real Go compiler
had been used to produce binaries for various platforms, and the result was
painful enough to start writing a new compiler:
* The ABI was fixed, so could not be optimized for speed. Also, the ABI
didn't seem to be documented anywhere.
* Working arount limitations in the ``go`` toolchain was rather burdensome
and quite a big hack.
* The binaries produced were quite bloated, for various reasons:
* The Go calling convention places all arguments on the stack. Due to
this, stack usage was really bad and code size was bigger than it
needed to be.
* Global initialization was very inefficient, see above.
* There seemed to be no way to optimize across packages.
Why Go instead of Rust?
-----------------------
Rust is another "new" and safer language that is now made ready for embedded
processors. There is `a fairly active community around it
<https://rust-embedded.github.io/blog/>`_.
However, apart from personal language preference, Go has a few advantages:
* Subjective, but in general Go is `easier to learn
<https://matthias-endler.de/2017/go-vs-rust/>`_. Rust is in general far more
complicated than Go, with difficult-to-grasp ownership rules, traits,
generics, etc. Go prides itself on being a simple and slightly dumb
language, sacrificing some expressiveness for readability.
* Built-in support for concurrency with goroutines and channels that do not
rely on a particular implementation threads. This avoids the need for a
custom `RTOS-like framework <https://blog.japaric.io/rtfm-v2/>`_ or a
`full-blown RTOS <https://github.com/rust-embedded/wg/issues/45>`_ with the
associated API one has to learn. In Go, everything is handled by goroutines
which are built into the language itself.
* A batteries-included standard library that consists of loosely-coupled
packages. Rust uses a monolithic standard library that is currently unusable
on bare-metal, while the Go standard library is much more loosely coupled so
is more likely to be (partially) supported. Also, non-standard packages in
Go do not have to be marked with something like ``#![no_std]`` to be usable
on bare metal. Note: most standard library packages cannot yet be compiled,
but this situation will hopefully improve in the future.
At the same time, Rust has other advantages:
* Unlike Go, Rust does not have a garbage collector by default and carefully
written Rust code can avoid most or all uses of the heap. Go relies heavily
on garbage collection and often implicitly allocates memory on the heap.
* Rust has stronger memory-safety guarantees.
* In general, Rust is more low-level and easier to support on a
microcontroller. Of course, this doesn't mean one shouldn't try to run Go on
a microcontroller, just that it is more difficult. When even dynamic
languages like `Python <https://micropython.org/>`_, `Lua
<https://nodemcu.readthedocs.io/en/master/>`_ and `JavaScript
<https://www.espruino.com/>`_ can run on a microcontroller, then certainly
Go can.
.. _faq-esp:
What about the ESP8266/ESP32?
-----------------------------
These chips use the rather obscure Xtensa instruction set. While a port of GCC
exists and Espressif provides precompiled GNU toolchains, there is no support
yet in LLVM (although there have been `multiple attempts
<http://lists.llvm.org/pipermail/llvm-dev/2018-July/124789.html>`_).
There are two ways these chips might be supported in the future, and both will
take a considerable amount of work:
* The compiled LLVM IR can be converted into (ugly) C and then be compiled
with a supported C compiler (like GCC for Xtensa). This has been `done
before <https://github.com/JuliaComputing/llvm-cbe>`_ so should be doable.
* One of the work-in-progress LLVM backends can be worked on to get it in a
usable state. If this is finished, a true TinyGo port is possible.

Просмотреть файл

@ -3,7 +3,7 @@
You can adapt this file completely to your liking, but it should at least You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive. contain the root `toctree` directive.
Welcome to TinyGo's documentation! The TinyGo site has moved!
================================== ==================================
Contents: Contents:
@ -11,11 +11,4 @@ Contents:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
installation moved
docker
usage
targets
microcontrollers
webassembly
faq
internals

Просмотреть файл

@ -1,109 +0,0 @@
.. _installation:
.. highlight:: none
Installation instructions
=========================
Requirements
------------
These are the base requirements and enough for most (desktop) use.
* Go 1.11+
* LLVM 7 (for example, from `apt.llvm.org <http://apt.llvm.org/>`_)
Linking a binary needs an installed C compiler (``cc``). At the moment it
expects GCC or a recent Clang.
ARM Cortex-M
~~~~~~~~~~~~
The Cortex-M family of microcontrollers is well supported, as it uses the stable
ARM LLVM backend (which is even used in the propietary C compiler from ARM).
Compiling to object code should be supported out of the box, but compiling the
final binary and flashing it needs some extra tools.
* binutils (``arm-none-eabi-ld``, ``arm-none-eabi-objcopy``) for linking and
for producing .hex files for flashing.
* Clang 7 (``clang-7``) for building assembly files and the `compiler
runtime library <https://compiler-rt.llvm.org/>`_ .
* The flashing tool for the particular chip, like ``openocd`` or
``nrfjprog``.
AVR (Arduino)
~~~~~~~~~~~~~
The AVR backend has similar requirements as the `ARM Cortex-M`_ backend. It
needs the following tools:
* binutils (``avr-objcopy``) for flashing.
* GCC (``avr-gcc``) for linking object files.
* libc (``avr-libc``), which is not installed on Debian as a dependency of
``avr-gcc``.
* ``avrdude`` for flashing to an Arduino.
WebAssembly
~~~~~~~~~~~
The WebAssembly backend only needs a special linker from the LLVM project:
* LLVM linker (``ld.lld-7``) for linking WebAssembly files together.
Installation
------------
First download the sources. This may take a while. ::
go get -u github.com/aykevl/tinygo
If you get an error like this::
/usr/local/go/pkg/tool/linux_amd64/link: running g++ failed: exit status 1
/usr/bin/ld: error: cannot find -lLLVM-7
cgo-gcc-prolog:58: error: undefined reference to 'LLVMVerifyFunction'
cgo-gcc-prolog:80: error: undefined reference to 'LLVMVerifyModule'
[...etc...]
Or like this::
../go-llvm/analysis.go:17:93: fatal error: llvm-c/Analysis.h: No such file or directory
#include "llvm-c/Analysis.h" // If you are getting an error here read bindings/go/README.txt
It means something is wrong with your LLVM installation. Make sure LLVM 7 is
installed (Debian package ``llvm-7-dev``). If it still doesn't work, you can
try running::
cd $GOPATH/github.com/aykevl/go-llvm
make config
And retry::
go install github.com/aykevl/tinygo
Usage
-----
TinyGo should now be installed. Test it by running a test program::
tinygo run examples/test
Before anything can be built for a bare-metal target, you need to generate some
files first::
make gen-device
This will generate register descriptions, interrupt vectors, and linker scripts
for various devices. Also, you may need to re-run this command after updates,
as some updates cause changes to the generated files.
Now you can run a blinky example. For the `PCA10040
<https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF52-DK>`_
development board::
tinygo flash -target=pca10040 examples/blinky2
Or for an `Arduino Uno <https://store.arduino.cc/arduino-uno-rev3>`_::
tinygo flash -target=arduino examples/blinky1

Просмотреть файл

@ -1,213 +0,0 @@
.. _internals:
Compiler internals
==================
Differences from ``go``
-----------------------
* A whole program is compiled in a single step, without intermediate linking.
This makes incremental development much slower for large programs but
enables far more optimization opportunities. In the future, an option should
be added for incremental compilation during edit-compile-test cycles.
* Interfaces are always represented as a ``{typecode, value}`` pair. `Unlike
Go <https://research.swtch.com/interfaces>`_, TinyGo will not precompute a
list of function pointers for fast interface method calls. Instead, all
interface method calls are looked up where they are used. This may sound
expensive, but it avoids memory allocation at interface creation.
* Global variables are computed during compilation whenever possible (unlike
Go, which does not have the equivalent of a ``.data`` section). This is an
important optimization for several reasons:
* Startup time is reduced. This is nice, but not the main reason.
* Initializing globals by copying the initial data from flash to RAM costs
much less flash space as only the actual data needs to be stored,
instead of all instructions to initialize these globals.
* Data can often be statically allocated instead of dynamically allocated
at startup.
* Dead globals are trivially optimized away by LLVM.
* Constant globals are trivially recognized by LLVM and marked
``constant``. This makes sure they can be stored in flash instead of
RAM.
* Global constants are useful for constant propagation and thus for dead
code elimination (like an ``if`` that depends on a global variable).
Datatypes
---------
TinyGo uses a different representation for some data types than standard Go.
string
A string is encoded as a ``{ptr, len}`` tuple. The type is actually defined
in the runtime as ``runtime._string``, in `src/runtime/string.go
<https://github.com/aykevl/tinygo/blob/master/src/runtime/string.go>`_. That
file also contains some compiler intrinsics for dealing with strings and
UTF-8.
slice
A slice is encoded as a ``{ptr, len, cap}`` tuple. There is no runtime
definition of it as slices are a generic type and the pointer type is
different for each slice. That said, the bit layout is exactly the same for
every slice and generic ``copy`` and ``append`` functions are implemented in
`src/runtime/slice.go
<https://github.com/aykevl/tinygo/blob/master/src/runtime/slice.go>`_.
array
Arrays are simple: they are simply lowered to a LLVM array type.
complex
Complex numbers are implemented in the most obvious way: as a vector of
floating point numbers with length 2.
map
The map type is a very complex type and is implemented as an (incomplete)
hashmap. It is defined as ``runtime.hashmap`` in `src/runtime/hashmap.go
<https://github.com/aykevl/tinygo/blob/master/src/runtime/hashmap.go>`_. As
maps are reference types, they are lowered to a pointer to the
aforementioned struct. See for example ``runtime.hashmapMake`` that is the
compiler intrinsic to create a new hashmap.
interface
An interface is a ``{typecode, value}`` tuple and is defined as
``runtime._interface`` in `src/runtime/interface.go
<https://github.com/aykevl/tinygo/blob/master/src/runtime/interface.go>`_.
The typecode is a small integer unique to the type of the value. See
interface.go for a detailed description of how typeasserts and interface
calls are implemented.
function value
A function value is a fat function pointer in the form of ``{context,
function pointer}`` where context is a pointer which may have any value.
The function pointer is expected to be called with the context as the last
parameter in all cases.
goroutine
A goroutine is a linked list of `LLVM coroutines
<https://llvm.org/docs/Coroutines.html>`_. Every blocking call will create a
new coroutine, pass the resulting coroutine to the scheduler, and will mark
itself as waiting for a return. Once the called blocking function returns,
it re-activates its parent coroutine. Non-blocking calls are normal calls,
unaware of the fact that they're running on a particular goroutine. For
details, see `src/runtime/scheduler.go
<https://github.com/aykevl/tinygo/blob/master/src/runtime/scheduler.go>`_.
This is rather expensive and should be optimized in the future. But the way
it works now, a single stack can be used for all goroutines lowering memory
consumption.
Calling convention
------------------
Go uses a stack-based calling convention and passes a pointer to the argument
list as the first argument in the function. There were/are `plans to switch to a
register-based calling convention <https://github.com/golang/go/issues/18597>`_
but they're now on hold.
.. highlight:: llvm
TinyGo, however, uses a register based calling convention. In fact it is
somewhat compatible with the C calling convention but with a few quirks:
* Struct parameters are split into separate arguments, if the number of fields
(after flattening recursively) is 3 or lower. This is similar to the `Swift
calling convention
<https://github.com/apple/swift/blob/master/docs/CallingConvention.rst#physical-conventions>`_.
In the case of TinyGo, the size of each field does not matter, a field can
even be an array. ::
{i8*, i32} -> i8*, i32
{{i8*, i32}, i16} -> i8*, i32, i16
{{i64}} -> i64
{} ->
{i8*, i32, i8, i8} -> {i8*, i32, i8, i8}
{{i8*, i32, i8}, i8} -> {i8*, i32, i8, i8}
Note that all native Go data types that are lowered to aggregate types in
LLVM are expanded this way: ``string``, slices, interfaces, and fat function
pointers. This avoids some overhead in the C calling convention and makes
the work of the LLVM optimizers easier.
* The WebAssembly target by default doesn't export or import ``i64`` (``int64``,
``uint64``) parameters. Instead, it replaces them with ``i64*``, allocating
the value on the stack. In other words, imported functions are called with a
64-bit integer on the stack and exported functions must be called with a
pointer to a 64-bit integer somewhere in linear memory.
This is a workaround for a limitation in JavaScript, which only deals with
doubles and can therefore only work with integers up to 32-bit in size (a
64-bit integer cannot be represented exactly in a double, a 32-bit integer
can). It is expected that 64-bit integers will be `added in the near future
<https://github.com/WebAssembly/design/issues/1172>`_ at which point this
calling convention workaround may be removed. Also see `this wasm-bindgen
issue <https://github.com/rustwasm/wasm-bindgen/issues/35>`_.
Currently there are also non-browser WebAssembly execution environments
that do not have this limitation. Use the `-wasm-abi=generic` flag to remove
the behavior described above and enable emitting functions with i64
parameters directly.
* The WebAssembly target does not return variables directly that cannot be
handled by JavaScript (see above about ``i64``, also ``struct``, multiple
return values, etc). Instead, they are stored into a pointer passed as the
first parameter by the caller.
This is the calling convention as implemented by LLVM, with the extension
that ``i64`` return values are returned in the same way as aggregate types.
* Blocking functions have a coroutine pointer prepended to the argument list,
see `src/runtime/scheduler.go
<https://github.com/aykevl/tinygo/blob/master/src/runtime/scheduler.go>`_
for details. Whether a function is blocking is determined by the
AnalyseBlockingRecursive pass.
This calling convention may change in the future. Changes will be documented
here. However, even though it may change, it is expected that function
signatures that only contain integers and pointers will remain stable.
Pipeline
--------
Like most compilers, TinyGo is a compiler built as a pipeline of
transformations, that each translate an input to a simpler output version (also
called lowering). However, most of these part are not in TinyGo itself. The
frontend is mostly implemented by external Go libraries, and most optimizations
and code generation is implemented by LLVM.
This is roughly the pipeline for TinyGo:
* Lexing, parsing, typechecking and `AST
<https://en.wikipedia.org/wiki/Abstract_syntax_tree>`_ building is done by
packages in the `standard library <https://godoc.org/go>`_ and in the
`golang.org/x/tools/go library <https://godoc.org/golang.org/x/tools/go>`_.
* `SSA <https://en.wikipedia.org/wiki/Static_single_assignment_form>`_
construction (a very important step) is done by the
`golang.org/x/tools/go/ssa <https://godoc.org/golang.org/x/tools/go/ssa>`_
package.
* This SSA form is then analyzed by the `ir package
<https://godoc.org/github.com/aykevl/tinygo/ir>`_ to learn all kinds of
things about the code that help the optimizer.
* The Go SSA is then transformed into LLVM IR by the `compiler package
<https://godoc.org/github.com/aykevl/tinygo/compiler>`_. Both forms are SSA,
but because Go SSA is higher level and contains Go-specific constructs (like
interfaces and goroutines) this is non-trivial. However, the vast majority
of the work is simply lowering the available Go SSA into LLVM IR, possibly
calling some runtime library intrinsics in the process (for example,
operations on maps).
* This LLVM IR is then optimized by the LLVM optimizer, which has a large
array of standard `optimization passes
<https://llvm.org/docs/Passes.html>`_. Currently, the standard optimization
pipeline is used as is also be used by Clang, but a pipeline better tuned
for TinyGo might be used in the future.
* After all optimizations have run, a few fixups are needed for AVR for
globals. This is implemented by the compiler package.
* Finally, the resulting machine code is emitted by LLVM to an object file, to
be linked by an architecture-specific linker in a later step.
After this whole list of compiler phases, the Go source has been transformed
into object code. It can then be emitted directly to a file (for linking in a
different build system), or it can be linked directly or even be flashed to a
target by TinyGo (using external tools under the hood).

Просмотреть файл

@ -1,149 +0,0 @@
.. _microcontrollers:
.. highlight:: go
Go on microcontrollers
======================
TinyGo was designed to run on microcontrollers, but the Go language wasn't.
This means there are a few challenges to writing Go code for microcontrollers.
Microcontrollers have very little RAM and execute code directly from flash.
Also, constant globals are generally put in flash whenever possible. The Go
language itself heavily relies on garbage collection so care must be taken to
avoid dynamic memory allocation.
Heap allocation
---------------
Many operations in Go rely on heap allocation. Some of these heap allocations
are optimized away, but not all of them. Also, TinyGo does not yet contain a
garbage collector so heap allocation must be avoided whenever possible outside
of initialization code.
These operations currently do heap allocations:
* Taking the pointer of a local variable. This will result in a heap
allocation, unless the compiler can see the resulting pointer never
escapes. This causes a heap allocation::
var global *int
func foo() {
i := 3
global = &i
}
This does not cause a heap allocation::
func foo() {
i := 3
bar(&i)
}
func bar(i *int) {
println(*i)
}
* Converting between ``string`` and ``[]byte``. In general, this causes a
heap allocation because one is constant while the other is not: for
example, a ``[]byte`` is not allowed to write to the underlying buffer of a
``string``. However, there is an optimization that avoids a heap allocation
when converting a string to a ``[]byte`` when the compiler can see the
slice is never written to. For example, this ``WriteString`` function does
not cause a heap allocation::
func WriteString(s string) {
Write([]byte(s))
}
func Write(buf []byte) {
for _, c := range buf {
WriteByte(c)
}
}
* Converting a ``byte`` or ``rune`` into a ``string``. This operation is
actually a conversion from a Unicode code point into a single-character
string so is similar to the previous point.
* Concatenating strings, unless one of them is zero length.
* Creating an interface with a value larger than a pointer. Interfaces in Go
are not a zero-cost abstraction and should be used carefully on
microcontrollers.
* Closures where the collection of shared variables between the closure and
the main function is larger than a pointer.
* Creating and modifying maps. Maps have *very* little support at the moment
and should not yet be used. They exist mostly for compatibility with some
standard library packages.
* Starting goroutines. There is limited support for goroutines and currently
they are not at all efficient. Also, there is no support for channels yet
so their usefulness is limited.
The ``volatile`` keyword
------------------------
Go does not have the ``volatile`` keyword like C/C++. This keyword is
unnecessary in most desktop use cases but is required for memory mapped I/O on
microcontrollers and interrupt handlers. As a workaround, any variable of a
type annotated with the ``//go:volatile`` pragma will be marked volatile. For
example::
//go:volatile
type volatileBool bool
var isrFlag volatileBool
This is a workaround for a limitation in the Go language and should at some
point be replaced with something else.
Inline assembly
---------------
The device-specific packages like ``device/avr`` and ``device/arm`` provide
``Asm`` functions which you can use to write inline assembly::
arm.Asm("wfi")
You can also pass parameters to the inline assembly::
var result int32
arm.AsmFull(`
lsls {value}, #1
str {value}, {result}
`, map[string]interface{}{
"value": 42,
"result": &result,
})
println("result:", result)
In general, types are autodetected. That is, integer types are passed as raw
registers and pointer types are passed as memory locations. This means you can't
easily do pointer arithmetic. To do that, convert a pointer value to a
``uintptr``.
Inline assembly support is expected to change in the future and may change in a
backwards-incompatible manner.
Harvard architectures (AVR)
---------------------------
The AVR architecture is a modified Harvard architecture, which means that flash
and RAM live in different address spaces. In practice, this means that any
given pointer may either point to RAM or flash, but this is not visible from
the pointer itself.
To get TinyGo to work on the Arduino, which uses the AVR architecutre, all
global variables (which include string constants!) are marked non-constant and
thus are stored in RAM and all pointer dereferences assume that pointers point
to RAM. At some point this should be optimized so that obviously constant data
is kept in read-only memory but this optimization has not yet been implemented.

12
docs/moved.rst Обычный файл
Просмотреть файл

@ -0,0 +1,12 @@
.. _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!

Просмотреть файл

@ -1,71 +0,0 @@
.. _targets:
.. |br| raw:: html
<br>
Supported targets
=================
TinyGo makes it easy to add new targets. If your target isn't listed here,
please raise an issue in the `issue tracker
<https://github.com/aykevl/tinygo/issues>`_.
POSIX-like
----------
Only Linux is supported at the moment, but it should be trivial to add support
for more POSIX-like systems.
ARM / Cortex-M
--------------
Cortex-M processors are well supported. There is support for multiple chips and
the backend appears to be stable. In fact, it uses the same underlying
technology (LLVM) as the proprietary ARM compiler for code generation.
* `BBC micro:bit <https://microbit.org/>`_ (`nRF51822
<https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF51822>`_)
* `Nordic PCA10031
<https://www.nordicsemi.com/eng/Products/nRF51-Dongle>`_
(`nRF51422
<https://www.nordicsemi.com/eng/Products/ANT/nRF51422>`_)
* `Nordic PCA10040
<https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF52-DK>`_
(`nRF52832
<https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF52832>`_)
* `nRF52840-MDK <https://wiki.makerdiary.com/nrf52840-mdk/>`_ (`nRF52840
<https://www.nordicsemi.com/eng/Products/nRF52840>`_)
* `reel board <https://www.phytec.eu/product-eu/internet-of-things/reelboard/>`_ (`nRF52840
<https://www.nordicsemi.com/eng/Products/nRF52840>`_)
* `Nordic PCA10056 <https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK>`_ (`nRF52840
<https://www.nordicsemi.com/eng/Products/nRF52840>`_)
* `QEMU <https://wiki.qemu.org/Documentation/Platforms/ARM>`_ (`LM3S6965
<http://www.ti.com/product/LM3S6965>`_) |br|
This target is supported only for testing purposes. It has not been tested
on real hardware.
AVR
---
Note: the AVR backend of LLVM is still experimental so you may encounter bugs.
* `Arduino Uno <https://store.arduino.cc/arduino-uno-rev3>`_ (`ATmega328p
<https://www.microchip.com/wwwproducts/en/ATmega328p>`_)
* `Digispark <http://digistump.com/products/1>`_ (`ATtiny85
<https://www.microchip.com/wwwproducts/en/ATtiny85>`_) |br|
Very limited support at the moment.
WebAssembly
-----------
WebAssembly support is relatively new but appears to be stable.
.. note::
Support for the ESP8266/ESP32 chips will take a lot of work if they ever get
support. See :ref:`this FAQ entry <faq-esp>` for details.

Просмотреть файл

@ -1,211 +0,0 @@
.. _usage:
.. highlight:: none
Using ``tinygo``
================
.. note::
This page assumes you already have TinyGo installed, either :ref:`using
Docker <docker>` or by :ref:`installing it manualling <installation>`.
Subcommands
-----------
The TinyGo tries to be similar to the main ``go`` command in usage. It consists
of the following main subcommands:
``build``
Compile the given program. The output binary is specified using the ``-o``
parameter. The generated file type depends on the extension:
``.o``
Create a relocatable object file. You can use this option if you don't
want to use the TinyGo build system or want to do other custom things.
``.ll``
Create textual LLVM IR, after optimization. This is mainly useful for
debugging.
``.bc``
Create LLVM bitcode, after optimization. This may be useful for
debugging or for linking into other programs using LTO.
``.hex``
Create an `Intel HEX <https://en.wikipedia.org/wiki/Intel_HEX>`_ file to
flash it to a microcontroller.
``.bin``
Similar, but create a binary file.
``.wasm``
Compile and link a WebAssembly file.
(all other)
Compile and link the program into a regular executable. For
microcontrollers, it is common to use the .elf file extension to
indicate a linked ELF file is generated. For Linux, it is common to
build binaries with no extension at all.
``run``
Run the program, either directly on the host or in an emulated environment
(depending on ``-target``).
``flash``
Flash the program to a microcontroller.
``gdb``
Compile the program, optionally flash it to a microcontroller if it is a
remote target, and drop into a GDB shell. From here you can break the
current program (Ctrl-C), single-step, show a backtrace, etc. A debugger
must be specified for your particular target in the target .json file and
the required tools (like GDB for your target) must be installed as well.
``clean``
Clean the cache directory, normally stored in ``$HOME/.cache/tinygo``. This is
not normally needed.
``help``
Print a short summary of the available commands, plus a list of command
flags.
Important build options
-----------------------
There are a few flags to control how binaries are built:
``-o``
Output filename, see the ``build`` command above.
``-target``
Select the target you want to use. Leave it empty to compile for the host.
Example targets:
wasm
WebAssembly target. Creates .wasm files that can be run in a web
browser.
arduino
Compile using the experimental AVR backend to run Go programs on an
Arduino Uno.
microbit
Compile programs for the `BBC micro:bit <https://microbit.org/>`_.
qemu
Run on a Stellaris LM3S as emulated by QEMU.
This switch also configures the emulator, flash tool and debugger to use so
you don't have to fiddle with those options.
Read :ref:`supported targets <targets>` for a list of supported targets.
``-port``
Specify the serial port used for flashing. This is used for the Arduino Uno,
which is flashed over a serial port. It defaults to ``/dev/ttyACM0`` as that
is the default port on Linux.
``-opt``
Which optimization level to use. Optimization levels roughly follow standard
``-O`` level options like ``-O2``, ``-Os``, etc. Available optimization
levels:
``-opt=0``
Disable as much optimizations as possible. There are still a few
optimization passes that run to make sure the program executes
correctly, but all LLVM passes that can be disabled are disabled.
``-opt=1``
Enable only a few optimization passes. In particular, this keeps the
inliner disabled. It can be useful when you want to look at the
generated IR but want to avoid the noise that is common in non-optimized
code.
``-opt=2``
A good optimization level for use cases not strongly limited by code
size. Provided here for completeness. It enables most optimizations and
will likely result in the fastest code.
``-opt=s``
Like ``-opt=2``, but while being more careful about code size. It
provides a balance between performance and code size.
``-opt=z`` (default)
Like ``-opt=s``, but more aggressive about code size. This pass also
reduces the inliner threshold by a large margin. Use this pass if you
care a lot about code size.
``-ocd-output``
Print output of the on-chip debugger tool (like OpenOCD) while in a ``tinygo
gdb`` session. This can be useful to diagnose connection problems.
``-gc``
Use the specified memory manager.
``-gc=none``
Do not use a memory manager at all. This will cause a link error at
every place in the program that tries to allocate memory. The primary
use case for this is finding such locations.
``-gc=dumb``
Only allocate memory, never free it. This is the simplest allocator
possible and uses very few resources while being very portable. Also,
allocation is very fast. Larger programs will likely need a real garbage
collector.
``-gc=marksweep``
Simple conservative mark/sweep garbage collector. This collector does
not yet work on all platforms. Also, the performance of the collector is
highly unpredictable as any allocation may trigger a garbage collection
cycle.
Miscellaneous options
---------------------
``-no-debug``
Disable outputting debug symbols. This can be useful for WebAssembly, as
there is no debugger for .wasm files yet and .wasm files are generally
served directly. Avoiding debug symbols can have a big impact on generated
binary size, reducing them by more than half.
This is not necessary on microcontrollers because debugging symbols are not
flashed to the microcontroller. Additionally, you will need it when you use
``tinygo gdb``. In general, it is recommended to include debug symbols
unless you have a good reason not to.
Note: while there is some support for debug symbols, only line numbers have
been implemented so far. That means single-stepping and stacktraces work
just fine, but no variables can be inspected.
``-size``
Print size (``none``, ``short``, or ``full``) of the output (linked) binary.
Note that the calculated size includes RAM reserved for the stack.
``none`` (default)
Print nothing.
``short``
Print size statistics, roughly like what the ``size`` binutils program
would print but with useful flash and RAM columns::
code data bss | flash ram
5780 144 2132 | 5924 2276
``full``
Try to determine per package how much space is used. Note that these
calculations are merely guesses and can somethimes be way off due to
various reasons like inlining. ::
code rodata data bss | flash ram | package
876 0 4 0 | 880 4 | (bootstrap)
38 0 0 0 | 38 0 | device/arm
0 0 0 66 | 0 66 | machine
2994 440 124 0 | 3558 124 | main
948 127 4 1 | 1079 5 | runtime
4856 567 132 67 | 5555 199 | (sum)
5780 - 144 2132 | 5924 2276 | (all)
Compiler debugging
------------------
These options are designed to make the task of writing the compiler
significantly easier. They are seldomly useful outside of development work.
``-printir``
Dump generated IR to the console before it is optimized.
``-dumpssa``
Dump Go SSA to the console while the program is being compiled. This also
includes the SSA of package initializers while they are being interpreted.

Просмотреть файл

@ -1,47 +0,0 @@
.. _webassembly:
WebAssembly
===========
.. highlight:: go
You can call a JavaScript function from Go and call a Go function from WebAssembly::
package main
// This calls a JS function from Go.
func main() {
println("adding two numbers:", add(2, 3)) // expecting 5
}
// This function is imported from JavaScript, as it doesn't define a body.
// You should define a function named 'main.add' in the WebAssembly 'env'
// module from JavaScript.
func add(x, y int)
// This function is exported to JavaScript, so can be called using
// exports.add() in JavaScript.
//go:export multiply
func multiply(x, y int) int {
return x * y;
}
.. highlight:: javascript
Related JavaScript would look something like this::
// Providing the environment object, used in WebAssembly.instantiateStreaming.
env: {
'main.add': function(x, y) {
return x + y
}
// ... other functions
}
// Calling the multiply function:
console.log('multiplied two numbers:', wasm.exports.multiply(5, 3));
A more complete example is provided in the `wasm example
<https://github.com/aykevl/tinygo/tree/master/src/examples/wasm>`_.

Просмотреть файл

@ -61,4 +61,4 @@ other benefits:
allocated in flash instead of RAM. allocated in flash instead of RAM.
For more details, see [this section of the For more details, see [this section of the
documentation](https://tinygo.readthedocs.io/en/latest/internals.html#differences-from-go). documentation](https://tinygo.org/compiler-internals/differences-from-go/).