Giter Site home page Giter Site logo

tinygo-org / tinygo Goto Github PK

View Code? Open in Web Editor NEW
14.5K 171.0 845.0 10.74 MB

Go compiler for small places. Microcontrollers, WebAssembly (WASM/WASI), and command-line tools. Based on LLVM.

Home Page: https://tinygo.org

License: Other

Makefile 1.16% Go 95.08% Assembly 2.17% Dockerfile 0.03% HTML 0.08% JavaScript 0.48% C 0.10% C++ 0.74% Shell 0.01% Python 0.08% Nix 0.09%
microcontroller tinygo llvm wasm webassembly arduino arm microbit samd21 stm32

tinygo's Introduction

TinyGo - Go compiler for small places

Linux macOS Windows Docker Nix CircleCI

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 alongside LLVM to provide an alternative way to compile programs written in the Go programming language.

Embedded

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

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, an Adafruit ItsyBitsy M0, or any of the 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:

tinygo flash -target arduino 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@Edge (https://developer.fastly.com/learning/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:

package main

//go:wasm-module yourmodulename
//export add
func add(x, y uint32) uint32 {
	return x + y
}

// main is required for the `wasi` target, even if it isn't used.
func main() {}

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

tinygo build -o main.wasm -target=wasi main.go

Installation

See the getting started instructions 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 94 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:

Currently supported features:

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

Documentation

Documentation is located on our web site at https://tinygo.org/.

You can find the web site code at 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 on the Gophers Slack.

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 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 its got serious problems...

-- Rob Pike, GopherCon 2014 Opening Keynote

TinyGo is a project to bring Go to microcontrollers and small systems with a single processor core. It is similar to 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 can run on microcontrollers, then certainly Go 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 itself.

Some code has been copied from the LLVM project and is therefore licensed under a variant of the Apache 2.0 license. 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.

tinygo's People

Contributors

achille-roussel avatar anuraaga avatar ardnew avatar aykevl avatar bgould avatar codefromthecrypt avatar conejoninja avatar deadprogram avatar dgryski avatar dkegel-fastly avatar eliasnaur avatar fgsch avatar firelizzard18 avatar johanbrandhorst avatar justinclift avatar kenbell avatar kyegupov avatar niaow avatar ofauchon avatar qulogic avatar racerxdl avatar rvolosatovs avatar sago35 avatar scottfeldman avatar soypat avatar suda avatar yannishuber avatar ysoldak avatar zaubernerd avatar zdima avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tinygo's Issues

AVR: any way to hookup an interrupt?

I'd like to be able to use an interrupt to handle buffering of incoming UART data. Basically the same as this:

ISR (USART_RX_vect) 
{
   // read register to get next RX byte and add to ring buffer
}

Is there a way to do this?

License

Question: What license applies to this code?

Sometimes WASM code generates calls to memmove, not runime.memmove

E.g. I have a struct "block" with a struct field "header".
An assignment in the form of header := block.header sometimes (when LLVM inlining doesn't kick in) generates a code like this:

i32.const 120
call $runtime.alloc
get_local 5
i32.const 120
call $memmove

And that causes also (import "env" "memmove" (func $memmove (type 1))) to appear, even though we have perfectly good $runtime.memmove function.

tinygo.org

I just discovered that someone has registered tinygo.org and redirected it to this repository.

I'm going to assume that was only meant to be helpful, however I'd really like to keep such things centralized. And at least I would have liked to know that this domain was registered and who owns it now.
So here is a request: can whoever registered the domain contact me? Either here in the issue tracker or by mail. I'm reachable at [email protected]. Then we can discuss what to do with it, for example host a real homepage.

Cryptic compiler error on using non-int parameters in make

The following code compiles by mainline Go:

buf := make([]byte, x.methodReturningUint64())

but, when attempting to use that code in TinyGo, it crashes with the following error:

Call parameter type does not match function signature!
  %10 = call i64 @"(TypeOfX).methodReturningUint64"(i32 %8, i8* %9, i8* undef), !dbg !24845
 i32  call void @runtime.sliceBoundsCheckMake(i64 %10, i64 %10, i8* undef), !dbg !24846

wasm: encoding/png causes reflect errors during import

docker run --rm -v /home/stephen/go/src/github.com/trashhalo/tiny-wasm:/go/src/github.com/trashhalo/tiny-wasm tinygo \
build -o /go/src/github.com/trashhalo/tiny-wasm/wasm.wasm -target wasm -dumpssa github.com/trashhalo/tiny-wasm
/usr/local/go/src/encoding/binary/binary.go:587:26: invalid operation: v (variable of type reflect.Value) has no field or method CanSet
/usr/local/go/src/encoding/binary/binary.go:522:26: invalid operation: v (variable of type reflect.Value) has no field or method CanSet
/usr/local/go/src/encoding/binary/binary.go:397:17: invalid operation: t (variable of type reflect.Type) has no field or method Len
/usr/local/go/src/encoding/binary/binary.go:402:20: invalid operation: t (variable of type reflect.Type) has no field or method NumField
/usr/local/go/src/encoding/binary/binary.go:403:27: invalid operation: t.Field(i) (value of type reflect.StructField) has no field or method Type
/usr/local/go/src/encoding/binary/binary.go:415:16: invalid operation: t (variable of type reflect.Type) has no field or method Size
/usr/local/go/src/encoding/binary/binary.go:375:26: Indirect not declared by package reflect
/usr/local/go/src/encoding/binary/binary.go:359:15: Indirect not declared by package reflect
error: couldn't load packages due to errors: encoding/binary
Makefile:9: recipe for target 'build' failed
make: *** [build] Error 1

https://github.com/trashhalo/tiny-wasm/blob/encoding-png/wasm.go

LLVM-C/Analysis.h file not found

When doing go get -u github.com/aykevl/tinygo I'm getting

go/src/github.com/aykevl/llvm/bindings/go/llvm/analysis.go:17:10: fatal error: 'llvm-c/Analysis.h' file not found
#include "llvm-c/Analysis.h" // If you are getting an error here read bindings/go/README.txt
         ^~~~~~~~~~~~~~~~~~~
1 error generated.

After doing exactly as in the bindings/go/README.txt from github.com/aykevl/llvm/bindings/go/llvm. The build of llvm-go was a success but TinyGo is still receiving the error show above.

How to use UART on AVR

I am trying to build the following code for AVR:

package main

import (
	"time"
)

func main() {
	for {
		println("Hello world from Go!")
		time.Sleep(time.Millisecond * 1000)
	}
}

However it give the following on build:

$ make flash-serial TARGET=arduino
./build/tgo build -target arduino -o build/serial.elf examples/serial
tgo: /home/ron/.gvm/pkgsets/go1.11/global/src/github.com/aykevl/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:$
039: void llvm::SelectionDAGISel::LowerArguments(const llvm::Function&): Assertion `InVals.size() == Ins.size() && "Lo$
erFormalArguments didn't emit the correct number of values!"' failed.

Seems like perhaps the putchar() functionality that is in https://github.com/aykevl/tinygo/blob/master/src/runtime/runtime_avr.go#L43 is not hooked up yet?

I thought the runtime would call that itself from just using the println() function, but did not work as expected.

TinyGo and WebAssembly?

@aykevl Out of curiosity, are you familiar with WebAssembly (wasm)?

Kind of wondering how feasible it would be, to add wasm as a target for TinyGo compilation.

With TinyGo generating to LLVM, and LLVM able to compile wasm... could that be a useful avenue to explore for golang/go#27766 ?

Help needed in debugging AVR compilation errors

I am working on the I2C interface for the AVR. The WIP branch is located here:

hybridgroup@f3c8e28

My problem is that the compile works with the code I just committed, but if I uncomment this line https://github.com/hybridgroup/tinygo/blob/feature/avr-i2c/src/examples/i2clcd/i2clcd.go#L52 in my sample, the compile fails with:

$ make flash-i2clcd TARGET=arduino                                                                                     
./build/tgo build -target arduino -size=short -o build/i2clcd.elf examples/i2clcd
ROLW unimplemented
UNREACHABLE executed at /home/ron/.gvm/pkgsets/go1.11/global/src/github.com/aykevl/llvm/lib/Target/AVR/AVRExpandPseudo$
nsts.cpp:1316!
SIGABRT: abort
PC=0x7f7ec3df0428 m=4 sigcode=18446744073709551610

If I uncomment the following line instead https://github.com/hybridgroup/tinygo/blob/feature/avr-i2c/src/examples/i2clcd/i2clcd.go#L53

I get this error:

$ make flash-i2clcd TARGET=arduino
go build -o build/tgo -i .
./build/tgo build -target arduino -size=short -o build/i2clcd.elf examples/i2clcd
tgo: /home/ron/.gvm/pkgsets/go1.11/global/src/github.com/aykevl/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:9
039: void llvm::SelectionDAGISel::LowerArguments(const llvm::Function&): Assertion `InVals.size() == Ins.size() && "Low
erFormalArguments didn't emit the correct number of values!"' failed.
SIGABRT: abort
PC=0x7f633a6f8428 m=5 sigcode=18446744073709551610

Perhaps this has to do with not yet implemented features on AVR?

From Go directly to ARM microcontroller

Hi,

I've been wondering about something here. Go has support to build for the ARM architecture that some micro-controllers has. Such as Cortex M4 which is ARMv7 (ARMv7E-M).

Why isn't the Go code just compiled straight to ARM binary, and then flashed into a certain position in flash memory where it's suppose to be run at?

I was thinking that using for example the https://wiki.makerdiary.com/nrf52840-mdk/ board, which has extra external 64-Mb QSPI FLASH memory, wouldn't it just be super cool and easy to just do that? Compile to ARM binary, flash into position, and run it like that. Binary would be a few MB and surely fit, right?

Maybe it will use too much resources, and would need better CPU clock? And a library layer to talk to the peripherals (like is done with tinygo I suppose)

Why wouldn't such a thing work?

Thanks!

Downcasting an interface to an empty struct confuses the compiler

Code:

package main

import "fmt"

type empty struct{}
type iface interface {
	Yo()
}

func (e empty) Yo() {
}

func main() {
	var s iface = empty{}
	_, ok := s.(empty)
	fmt.Println(ok)
}

Result:

tinygo build -o es.wasm es.go
es.go:15:13: undefined local var (from cgo?)

Interface treating byte and rune as distinct types

package main

func hai(i interface{}) {
	switch i.(type) {
		case []byte:
		println("[]byte")
		case []rune:
		println("[]rune")
		default:
		println("dunno")
	}
}

func main() {
	var b []uint8
	var r []int32
	hai(b)
	hai(r)
}
root@8b968cc9f43a:/opt/tinygo/src/look# tinygo run .
dunno
dunno
root@8b968cc9f43a:/opt/tinygo/src/look# go run .
[]byte
[]rune

nrf52840-mdk support

I really like this tinygo project and am trying to figure out how to add support for this neat little thing: https://wiki.makerdiary.com/nrf52840-mdk/

I've managed to add this as target:

{
	"llvm-target": "armv7em-none-eabi",
	"build-tags": ["nrf52840_mdk", "nrf52840", "nrf", "arm", "js", "wasm"],
	"linker": "arm-none-eabi-gcc",
	"pre-link-args": ["-nostdlib", "-nostartfiles", "-mcpu=cortex-m4", "-mthumb", "-T", "targets/nrf52.ld", "-Wl,--gc-sections", "-fno-exceptions", "-fno-unwind-tables", "-ffunction-sections", "-fdata-sections", "-Os", "-DNRF52840_XXAA", "-Ilib/CMSIS/CMSIS/Include", "lib/nrfx/mdk/system_nrf52.c", "src/device/nrf/nrf52.s"],
	"objcopy": "arm-none-eabi-objcopy",
	"flash": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset"
}

And added machine/board_nrf52840-mdk.go (which is just a copy of board_pca10040.go for now)

// +build nrf,nrf52840_mdk

package machine

// LEDs on the nrf52840-mdk (nRF52840 dev board)
const (
	LED  = LED1
	LED1 = 17
	LED2 = 18
	LED3 = 19
	LED4 = 20
)

// Buttons on the nrf52840-mdk (nRF52840 dev board)
const (
	BUTTON  = BUTTON1
	BUTTON1 = 13
	BUTTON2 = 14
	BUTTON3 = 15
	BUTTON4 = 16
)

When I now run: tinygo flash -target=nrf52840-mdk examples/button

I get:

github.com/aykevl/tinygo/src/runtime/runtime_nrf.go:33:12: invalid operation: nrf.UART0 (variable of type *device/nrf.UART_Type) has no field or method PSELTXD

So, obviously, I'm missing something. But, I can't add "nrf52" to the build-tags, because then I get a bunch of re-declaration errors:

GPIO_PIN_CNF_DRIVE_D0S1 redeclared in this block
...

So, anyone here wanna help me adding support for this dev board? I'm new to this code, and figured it would be quicker to ask about this here since I couldn't find anything on the wiki about how to add a new board. Wasn't as straight forward as I thought, unless I'm missing something.

Thanks!

tinygo flash command can only compile HEX files

At the moment, the command tinygo flash will automatically assume that the target file to be compiled should be a HEX file, due to this parameter here: https://github.com/aykevl/tinygo/blob/master/main.go#L313

This is a small problem when using the bossac command with the UF2 bootloader. bossac works as expected only when flashing .BIN files. It will appear to flash the HEX file, but does not correctly complete the process of setting the user's code for execution. Hence when the MCU restarts, it returns to the bootloader mode, instead of starting up the user's code.

What I propose is to add a new key named "outputFormat" to the target.json file, which lets you set a desired output format. The default can be .hex if not specified.

Unable to build blinky example for Arduino

When trying to build/run the blinky2 example with TARGET=arduino I get the following errors:

$ make run-blinky2 TARGET=arduino                                                                                      
./build/tgo -target arduino -runtime build/runtime-arduino-combined.bc -o build/blinky2.o examples/blinky2
src/machine/machine_avr.go:38:9: PORTD not declared by package avr
src/machine/machine_avr.go:40:9: PORTB not declared by package avr
src/machine/machine_avr.go:44:9: PORTB not declared by package avr
src/machine/machine_avr.go:46:9: PORTB not declared by package avr
src/machine/machine_avr.go:22:9: DDRD not declared by package avr
src/machine/machine_avr.go:24:9: DDRB not declared by package avr
src/machine/machine_avr.go:28:9: DDRD not declared by package avr
src/machine/machine_avr.go:30:9: DDRB not declared by package avr
src/runtime/runtime_avr.go:76:7: WDTCSR not declared by package avr
src/runtime/runtime_avr.go:76:21: WDTCSR_WDCE not declared by package avr
src/runtime/runtime_avr.go:76:39: WDTCSR_WDE not declared by package avr
src/runtime/runtime_avr.go:78:20: WDTCSR_WDIE not declared by package avr
src/runtime/runtime_avr.go:78:38: RegValue not declared by package avr
src/runtime/runtime_avr.go:78:7: WDTCSR not declared by package avr
src/runtime/runtime_avr.go:84:29: SMCR_SE not declared by package avr
src/runtime/runtime_avr.go:84:7: SMCR not declared by package avr
src/runtime/runtime_avr.go:90:7: SMCR not declared by package avr
src/runtime/runtime_avr.go:46:12: UCSR0A not declared by package avr
src/runtime/runtime_avr.go:46:25: UCSR0A_UDRE0 not declared by package avr
src/runtime/runtime_avr.go:49:18: RegValue not declared by package avr
src/runtime/runtime_avr.go:49:7: UDR0 not declared by package avr
src/runtime/runtime_avr.go:39:7: UBRR0H not declared by package avr
src/runtime/runtime_avr.go:40:7: UBRR0L not declared by package avr
src/runtime/runtime_avr.go:41:20: UCSR0B_RXEN0 not declared by package avr
src/runtime/runtime_avr.go:41:39: UCSR0B_TXEN0 not declared by package avr
src/runtime/runtime_avr.go:41:7: UCSR0B not declared by package avr
src/runtime/runtime_avr.go:42:20: UCSR0C_UCSZ0 not declared by package avr
src/runtime/runtime_avr.go:42:7: UCSR0C not declared by package avr
src/examples/blinky2/blinky2.go:33:30: LED2 not declared by package machine
error: src/runtime/runtime_avr.go:76:7: WDTCSR not declared by package avr
Makefile:99: recipe for target 'build/blinky2.o' failed
make: *** [build/blinky2.o] Error 1

NRF: missing registers for PWM implementation

I am looking at how to add the PWM implementation for NRF, and I need some help getting started.

Currently looking at https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/3f959e9776f38e5bc4427f902ac705603bcd3265/cores/nRF5/HardwarePWM.cpp as a reference for how the registers work.

I am not sure how to translate that code to how TinyGo works. Some guidance will be appreciated.

EDIT: this might be the actual implementation, but same thing needed: https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/3f959e9776f38e5bc4427f902ac705603bcd3265/cores/nRF5/wiring_analog_nRF52.c#L167

wasm: panic: runtime error: slice out of range

panic: runtime error: slice out of range

runtime.runtimePanic (wasm-77de193e-12:8)
runtime.sliceBoundsCheck (wasm-77de193e-13:15)
(*bytes.Buffer).tryGrowByReslice (wasm-77de193e-17:37)
(*bytes.Buffer).WriteString (wasm-77de193e-16:18)
mouse (wasm-77de193e-11:10)
document.getElementById.onmousemove (wasm.js:61)

===
https://github.com/trashhalo/tiny-wasm/blob/master/wasm.go
You can reproduce this issue by cloning the repo above

  1. make deps
  2. make build
  3. ./http
  4. Send your browser to http://localhost:8080
  5. move your mouse around the red box and see panics in console

Flawed a fortiori argument

I'll admit this isn't a bug, just responding to this sentence in the README:

My original reasoning was: if Python can run on microcontrollers, then certainly Go should be able to and run on even lower level micros.

The problem here is the last part: "even lower level micros." Now, consider this valid argument from Wikipedia:

If driving 10 mph over the speed limit is punishable by a fine of $50, it can be inferred a fortiori that driving 20 mph over the speed limit is also punishable by a fine of at least $50.
(https://en.wikipedia.org/wiki/Argumentum_a_fortiori)

If I were to say the same thing, but finish with "20 mph . . . at least $100," that would be an invalid deduction. My suggestion here is to correct the README to say ". . . then certainly Go should be able to run on microcontrollers and potentially lower level micros."

Package/symbol name problem

Test program tst.go:

package main

func x() int

func main() {
        println(x())
}

Build tinygo build -target wasm -o withfile.ll tst.go output contains:
declare i32 @main.x() local_unnamed_addr as expected, import object key 'main.x'

Build tinygo build -target wasm -o withdot.ll . output contains:
declare i32 @..x() local_unnamed_addr import object key '..x'

Initial setup confusion

Hi @aykevl this project looks really cool.

So I am trying to get my environment setup correctly. Seems like I should be using your fork of llvm. https://github.com/aykevl/llvm since it has several important looking commits. The Makefile has it located in the GOPATH https://github.com/aykevl/tinygo/blob/master/Makefile#L9 would this be where I should check that repo out? Also, where should the llvm-build and llvm-inst directories be set to?

Thanks for helping me get started with tinygo.

Reduce memory usage of slices

Since slices are copied all over the place, it might be a good idea to, instead of having a struct with {ptr, len, cap}, have one with {ptr, len} only, and calculate cap on demand. Aligning len to the next power of two would work, but also waste some bytes as the slice grows. Maybe a different sequence, like the one Python has for lists, would be better?

(Inlining the calculation would probably not be a good idea, though, so this has to be considered.)

stm32: missing files/directory?

I think perhaps the recent commit to add initial stm32 support might be missing some files from the check-in:

$ make gen-device-stm32
./tools/gen-device-svd.py lib/cmsis-svd/data/STMicro/ src/device/stm32/ --source=https://github.com/posborne/cmsis-svd/tree/master/data/STMicro
go fmt ./src/device/stm32
can't load package: package github.com/aykevl/tinygo/src/device/stm32: no Go files in /home/ron/.gvm/pkgsets/go1.11/global/src/github.com/aykevl/tinygo/src/device/stm32
Makefile:70: recipe for target 'gen-device-stm32' failed
make: *** [gen-device-stm32] Error 1

I do not see a directory named stm32 in the repo: https://github.com/aykevl/tinygo/tree/master/src/device

wasm: importing image package causes unknown convert

        errors.New: return t2
        bufio.init: *ErrAdvanceTooFar = t8
        bufio.init: t9 = errors.New("final token":string)
        errors.New: t0 = new errorString (complit)
        errors.New: t1 = &t0.s [#0]
        errors.New: *t1 = text
        errors.New: t2 = make error <- *errorString (t0)
        errors.New: return t2
        bufio.init: *ErrFinalToken = t9
        bufio.init: t10 = convert []byte <- string ("�":string)
error: todo: init: unknown convert: convert []byte <- string ("�":string)
Makefile:9: recipe for target 'build' failed
make: *** [build] Error 1

Reproduction repo
https://github.com/trashhalo/tiny-wasm/blob/images/wasm.go

  1. make deps
  2. make build

How to call CGo from TinyGo

I would like to be able to call CGo from TinyGo, for example the NRF5 sdk.

Is there a way I can currently do this from TinyGo?

Miscompilation of printstring at high optimization levels

As reported by @deadprogram in PR #12, this code does not print the string:

package main

import (
	"machine"
	"time"
)

func main() {
	machine.InitADC()

	led := machine.GPIO{machine.LED}
	led.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})

	sensor := machine.ADC{machine.ADC2}
	sensor.Configure()

	for {
		val := sensor.Get()
		if val < 512 {
			led.Low()
		} else {
			led.High()
		}

		println("Value is", val) // this prints only the numeric value of val, not the string prefix "Value is"
		time.Sleep(time.Millisecond * 100)
	}
}

So far, I've found it's related to optimization levels (see params to Optimize() in main.go). Size level 0 and 1 compile just fine, but 2 fails. Optimization level 1 and 2 have no difference.

What does "no garbage collection" mean?

From the readme:

not yet supported:
...

  • garbage collection

What does this mean? Does this mean that all values are on stack memory? Does this mean that all pointers are allocated on the heap and never freed?

The "time" package

With docker image:

cat demo.go && tinygo run demo.go && date +%s
package main

import "time"

func main() {
        println(time.Now().Unix())
}
22598
1541263654

Off by orders of magnitude, nanoseconds output also looks suspicious.

cat demo2.go && tinygo run demo2.go 
package main

import "time"

func main() {
        println(time.Now().String())
}
Call parameter type does not match function signature!
  %101 = extractvalue { i8, i1 } %100, 0
 i32  call void @runtime.sliceBoundsCheck(i32 %109, i8 %101, i32 %108)
Both operands to a binary operator are not of the same type!
  %111 = sub i32 %108, i8 %101
Both operands to a binary operator are not of the same type!
  %112 = sub i32 %109, i8 %101
LLVM ERROR: Broken module found, compilation aborted!

Support MCU development with Docker

Currently, the generated Docker image misses a few things important for microcontroller development:

  • autogenerated register descriptors (make gen-device)
  • build tools, like binutils, gcc, etc.

Preferably, ARM targets should move to Clang first so we don't depend on GCC, avoiding the extra dependency.

Generated nrf52.go is missing IRQ_SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1

While trying (and so far failing) to get the I2C interface working on the pca10040 I noticed that there is a missing interrupt value.

const (
	IRQ_POWER_CLOCK                       = 0  // Power control // Clock control
	IRQ_RADIO                             = 1  // 2.4 GHz Radio
	IRQ_UARTE0_UART0                      = 2  // UART with EasyDMA // Universal Asynchronous Receiver/Transmitter
	IRQ_SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 = 3  // Serial Peripheral Interface Master with EasyDMA 0 // SPI Slave 0 // I2C compatible Two-Wire Master Interface with EasyDMA 0 // I2C compatible Two-Wire Slave Interface with EasyDMA 0 // Serial Peripheral Interface 0 // I2C compatible Two-Wire Interface 0
	IRQ_NFCT                              = 5  // NFC-A compatible radio
	IRQ_GPIOTE                            = 6  // GPIO Tasks and Events
...

Notice that IRQ 4 is missing. It is supposed to be
IRQ_SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 = 4 according to the nrf52.svd file:

    <peripheral derivedFrom="TWIM0">
      <name>TWIM1</name>
      <description>I2C compatible Two-Wire Master Interface with EasyDMA 1</description>
      <baseAddress>0x40004000</baseAddress>
      <alternatePeripheral>SPIM1</alternatePeripheral>
      <interrupt>
        <name>SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1</name>
        <value>4</value>
      </interrupt>
    </peripheral>

This value is of course also missing from the generated nrf52.s file.

Split small structs into basic values during parameter passing

Currently, all values are passed as-is in LLVM, including structs. It would be better to break down structs of (for example) 3 or less elements into individual parameters - including strings, interfaces and slices. Swift has a similar trick to improve performance.

Reasons why this is a good idea:

  1. It will help LLVM optimizers. Optimizers aren't good at looking into structs. By breaking down structs they might optimize away the 'cap' part of a slice, for example (see #11).
  2. The AVR backend currently can't deal with structs passed as a parameter. The fact it currently sometimes works is only because functions get inlined and thus don't need to pass a struct as a parameter.

wasm: slice copy bombing out

A little toy program I was working on keeps hitting an error in the webassembly code for slicecopy. I don't see anything obviously wrong, so it might be a bug. happens if I try and call updatePage from javascript.

package main

import (
	"strconv"
	"strings"
)

func main() {
}

//go:export updatePage
func updatePage(x, y int) string {
	page := strings.Join([]string{
		"<div style=\"",
		"position:absolute; ",
		"width:50px; ",
		"height:50px; ",
		"background: red; ",
		"left: ",
		strconv.Itoa(x),
		"px; top: ",
		strconv.Itoa(y),
		"px;\"></div>",
	}, "")
	return page
}

Support of maps needs clarification

The map type support is described as "very rough, unfinished" and "incomplete" in the documentation.
This is not helpful to developers: what is working and what is not?

Having this clarified would help the users of tinygo and might encourage to submit fixing pull requests and patches.

OS X

Currently, TinyGo doesn't appear to work on OS X with LLVM 7 from homebrew.

  • Support OS X
  • Optional: build on OS X in Travis

WASM Target Not Supported on OSX

Adding a tracking case for monitoring progress of WASM target when building from OSX.

OSX developers cannot use tinygo to build WASM targets because WASM is an experimental feature in LLVM

$ tinygo build -o test.wasm test.go
error: No available targets are compatible with this triple.

The Facts:

  • Tinygo can build on OSX when LLVM 7 is installed via brew. However, WASM targets are experimental in LLVM 7 and not supported by the homebrew recipe.
  • WASM will be supported in LLVM 8 (Expected release March 2019)

RELATED:

Possible Workarounds:

  • Wait for LLVM 8 in March of 2019
  • Build LLVM 7 from source with full WASM support (Does this work?)
  • ???

String to []rune conversion

cat demo.go && tinygo run demo.go 
package main

func main() {
        runes := []rune("Hello Sailor")
        copy(runes,[]rune("PLUGH"))
}

error: compiler: todo: convert from string: rune

wasm: importing math/rand has init issues

error: todo: init call: math/rand.NewSource

        math/rand.init: *t1748 = -4300543082831323144:int64
        math/rand.init: *t1749 = -6344160503358350167:int64
        math/rand.init: *t1750 = 5896236396443472108:int64
        math/rand.init: *t1751 = -758328221503023383:int64
        math/rand.init: *t1752 = -1894351639983151068:int64
        math/rand.init: *t1753 = -307900319840287220:int64
        math/rand.init: *t1754 = -6278469401177312761:int64
        math/rand.init: *t1755 = -2171292963361310674:int64
        math/rand.init: *t1756 = 8382142935188824023:int64
        math/rand.init: *t1757 = 9103922860780351547:int64
        math/rand.init: *t1758 = 4152330101494654406:int64
        math/rand.init: t1759 = new lockedSource (complit)
        math/rand.init: t1760 = &t1759.src [#1]
        math/rand.init: t1761 = NewSource(1:int64)
Makefile:9: recipe for target 'build' failed
make: *** [build] Error 1
// +build wasm,!arm,!avr

package main

import (
	_ "math/rand"
)

func main() {
}

AVR: UART not working with latest master

I tried the latest master branch this morning, and seems like the UART is no longer functioning as expected. No data is received by the serial port from the connected host computer when running the serial example on AVR. It does work as expected on pca10040.

Cannot initialize a top-level func var by applying a function to another top-level func var

Discovered when trying to write a deserializer for structures with "generic" (e.g. interface) fields.

A simple example:

package factoryfactory

type ifoo interface{}
type ibar interface{}

type foo struct{ bar ibar }
type bar struct{}

func noop(x ifoo) {}

func ifooFactory(ibarFactory func() ibar) func() ifoo {
	return func() ifoo { return foo{ibarFactory()} }
}

var myIbarFactory = func() ibar { return bar{} }
var myIfooFactory = ifooFactory(myIbarFactory)

func main() {
	var x ifoo = myIfooFactory()
	noop(x) // not unused
	return
}

Compilation failure:

$ tinygo build -wasm-abi=generic -o ff.wasm factoryfactory.go 
panic: interp: load from a pointer bitcast: &PointerCastValue{Value: &AllocaValue{Type: PointerType(StructType(PointerType(StructType(PointerType(IntegerType(8 bits)), PointerType(FunctionType(PointerType(IntegerType(8 bits))):%runtime._interface: StructType(IntegerType(32 bits), PointerType(IntegerType(8 bits))))))))}, CastType: PointerType(PointerType(IntegerType(8 bits)))}

Support compiling basic Vecty/Vugu examples to WASM

This is just a tracking issue for any outstanding work required for us to compile a vecty-style web app into WASM with tinygo. I think this would be a fantastic milestone for this repo and the Go WASM community at large, so lets see what remains outstanding.

  • Channels
  • syscall/js callback support
  • a subset of reflect including
    • reflect.ValueOf, reflect.TypeOf, reflect.New and the following functions of the reflect.Value type:
      • Kind, Elem, String, Interface, Type, NumField, Field, Set

Would love to have @slimsag take a quick look at this if possible, but otherwise I think @bketelsen will know the best what is outstanding.

Question: Can tinygo be build from windows?

I have windows 10 OS and when I tied to make congig in go-llvm I got his error:
..github.com\aykevl\go-llvm> make config
process_begin: CreateProcess(NULL, uname -s, ...) failed.
process_begin: CreateProcess(NULL, llvm-config-7 --cppflags, ...) failed.
process_begin: CreateProcess(NULL, llvm-config-7 --ldflags --libs --system-libs all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines debuginfodwarf executionengine instrumentation interpreter ipo irreader linker mc mcjit objcarcopts option profiledata scalaropts support target, ...) failed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.