├── bin └── .keep ├── testdata ├── gc.txt ├── zeroalloc.txt ├── alias.txt ├── init_multi.txt ├── zeroalloc.go ├── cgo │ ├── extra.go │ ├── out.txt │ └── main.c ├── stdlib.txt ├── init.txt ├── init_multi.go ├── structs.txt ├── string.txt ├── print.txt ├── coroutines.txt ├── calls.txt ├── string.go ├── slice.txt ├── stdlib.go ├── interface.txt ├── alias.go ├── binop.txt ├── channel.txt ├── float.txt ├── print.go ├── init.go └── map.txt ├── lib └── picolibc-include │ └── picolibc.h ├── src ├── examples │ ├── wasm │ │ ├── .gitignore │ │ ├── main │ │ │ ├── main.go │ │ │ ├── README.md │ │ │ └── index.html │ │ ├── invoke │ │ │ ├── wasm.go │ │ │ ├── index.html │ │ │ └── wasm.js │ │ ├── slices │ │ │ ├── wasm.go │ │ │ ├── index.html │ │ │ └── wasm.js │ │ ├── callback │ │ │ ├── index.html │ │ │ ├── wasm.js │ │ │ └── wasm.go │ │ ├── export │ │ │ ├── index.html │ │ │ ├── wasm.go │ │ │ └── wasm.js │ │ ├── server.go │ │ └── Makefile │ ├── serial │ │ └── serial.go │ ├── blinky1 │ │ └── blinky1.go │ ├── gba-display │ │ └── gba-display.go │ ├── systick │ │ ├── systick.go │ │ └── README.md │ ├── button │ │ └── button.go │ ├── i2s │ │ └── i2s.go │ ├── adc │ │ └── adc.go │ ├── microbit-blink │ │ └── microbit-blink.go │ ├── blinkm │ │ └── blinkm.go │ ├── blinky2 │ │ └── blinky2.go │ ├── echo │ │ └── echo.go │ ├── pwm │ │ └── pwm.go │ ├── button2 │ │ └── button2.go │ └── mcp3008 │ │ └── mcp3008.go ├── runtime │ ├── cgo │ │ └── cgo.go │ ├── internal │ │ └── sys │ │ │ └── zversion.go │ ├── os_js.go │ ├── os_linux.go │ ├── os_darwin.go │ ├── os_freebsd.go │ ├── runtime_unix_noheap.go │ ├── runtime_stm32.go │ ├── defer.go │ ├── bytes.go │ ├── runtime_fe310_baremetal.go │ ├── arch_386.go │ ├── arch_arm64.go │ ├── scheduler_tasks.go │ ├── scheduler_coroutines.go │ ├── stack.go │ ├── runtime_attiny.go │ ├── interrupt │ │ ├── interrupt_hwvector.go │ │ ├── interrupt_sifive.go │ │ ├── interrupt_cortexm.go │ │ └── interrupt_gameboyadvance.go │ ├── runtime_unix_heap.go │ ├── arch_avr.go │ ├── sync.go │ ├── strings_go111.go │ ├── arch_arm.go │ ├── arch_cortexm.go │ ├── arch_amd64.go │ ├── gc_globals_conservative.go │ ├── arch_tinygoriscv.go │ ├── runtime_fe310_qemu.go │ ├── scheduler_gba.S │ ├── scheduler_any.go │ ├── scheduler_none.go │ ├── atomic.go │ ├── arch_wasm.go │ ├── scheduler_tinygoriscv.S │ ├── gc_none.go │ ├── poll.go │ ├── string_count.go │ ├── runtime_tinygoriscv.go │ ├── baremetal.go │ ├── runtime_cortexm_qemu.go │ ├── gc_globals_precise.go │ ├── func.go │ ├── runtime_atmega.go │ ├── gc_leaking.go │ ├── gc_stack_raw.go │ ├── gc_stack_portable.go │ ├── runtime_tinygoriscv_qemu.go │ ├── volatile │ │ └── volatile.go │ ├── runtime_atsamd21e18.go │ ├── float.go │ ├── runtime_arm7tdmi.go │ ├── runtime_atsamd51g19.go │ └── runtime_atsamd51j19.go ├── syscall │ ├── syscall.go │ ├── str.go │ ├── errno.go │ ├── syscall_libc.go │ └── syscall_darwin.go ├── machine │ ├── usb_nrf52840_reset_none.go │ ├── board_pca10056_baremetal.go │ ├── board_reelboard_baremetal.go │ ├── board_stm32.go │ ├── board_hifive1b_baremetal.go │ ├── board_digispark.go │ ├── board_arduino.go │ ├── board_arduino_nano.go │ ├── machine_atmega1284p.go │ ├── board_fe310.go │ ├── machine_attiny.go │ ├── board_x9pro.go │ ├── machine_attiny85.go │ ├── board_pca10031.go │ ├── board_nrf52840-mdk.go │ ├── board_circuitplay_express_baremetal.go │ ├── machine_nrf51.go │ ├── board_pca10040.go │ ├── board_pca10056.go │ ├── board_arduino_nano33_baremetal.go │ ├── board_hifive1b.go │ ├── buffer.go │ ├── i2s.go │ ├── machine_atmega328p.go │ ├── machine_atsamd51g19.go │ ├── machine_stm32.go │ ├── machine.go │ ├── usb_nrf52840_reset_uf2.go │ ├── board_atsamd21.go │ └── board_microbit.go ├── reflect │ └── swapper.go ├── testing │ ├── doc.go │ └── benchmark.go ├── sync │ ├── once.go │ ├── pool.go │ ├── mutex.go │ └── map.go ├── device │ ├── riscv │ │ └── riscv.go │ ├── avr │ │ └── avr.go │ ├── nrf │ │ └── README.markdown │ ├── stm32 │ │ └── stm32f407xx-altfunc-bitfields.go │ └── arm │ │ └── cortexm.s ├── internal │ ├── task │ │ ├── task.go │ │ └── task_none.go │ └── reflectlite │ │ └── reflect.go └── os │ ├── proc.go │ ├── file_unix.go │ └── file_other.go ├── cgo ├── testdata │ ├── include │ │ └── foo.h │ ├── basic.go │ ├── const.go │ ├── basic.out.go │ ├── flags.go │ ├── const.out.go │ ├── errors.go │ ├── flags.out.go │ └── errors.out.go ├── libclang_config_llvm9.go ├── libclang_config.go └── sync.go ├── targets ├── pca10040-s132v6.json ├── pca10056-s140v7.json ├── reelboard-s140v7.json ├── particle-argon.json ├── particle-boron.json ├── particle-xenon.json ├── nrf52-s132v6.json ├── fe310.json ├── nrf52840-s140v7.json ├── nrf52840-mdk.json ├── particle-3rd-gen.json ├── pca10031.json ├── microbit.json ├── stm32.ld ├── lm3s6965.ld ├── nrf52840.ld ├── stm32f103rb.ld ├── stm32f407.ld ├── hifive1-qemu.json ├── hifive1b.ld ├── reelboard.json ├── nrf51.ld ├── nrf52.ld ├── pyportal.json ├── x9pro.json ├── arduino-nano33.json ├── pca10040.json ├── hifive1b.json ├── pybadge.json ├── pca10056.json ├── riscv-qemu.json ├── feather-m0.json ├── feather-m4.json ├── itsybitsy-m0.json ├── pinetime-devkit0.json ├── trinket-m0.json ├── itsybitsy-m4.json ├── nrf52840-s140v7.ld ├── arduino-mega2560.json ├── arduino.json ├── atsamd21.ld ├── metro-m4-airlift.json ├── atsamd51.ld ├── circuitplay-express.json ├── nrf52-s132v6.ld ├── arduino-nano.json ├── atsamd21e18a.json ├── atsamd21g18a.json ├── atsamd51g19a.json ├── atsamd51j19a.json ├── atsamd51j20a.json ├── hifive1-qemu.ld ├── clue_alpha.json ├── avr.json ├── circuitplay-bluefruit.json ├── circuitplay-bluefruit.ld ├── cortex-m-qemu.json ├── bluepill.json ├── atmega328p.json ├── stm32f4disco.json ├── nrf51.json ├── nucleo-f103rb.json ├── atmega2560.json ├── nrf52.json ├── nrf52840.json ├── riscv-qemu.ld ├── wasm.json ├── digispark.json ├── atmega1284p.json ├── cortex-m.json ├── riscv.json ├── gameboy-advance.json └── avr.ld ├── version.go ├── transform ├── allocs_test.go ├── testdata │ ├── globals-non-const.ll │ ├── globals-non-const.out.ll │ ├── globals-function-sections.ll │ ├── globals-function-sections.out.ll │ ├── wasm-abi.ll │ ├── panic.ll │ ├── panic.out.ll │ ├── stringtobytes.out.ll │ ├── stringtobytes.ll │ ├── wasm-abi.out.ll │ ├── gc-globals.ll │ └── maps.out.ll ├── panic_test.go ├── func-lowering_test.go ├── stringtobytes_test.go ├── goroutine_test.go ├── interface-lowering_test.go ├── wasm-abi_test.go ├── gc_test.go ├── globals_test.go ├── interrupt_test.go ├── maps_test.go ├── transform.go ├── panic.go ├── globals.go └── maps.go ├── tests └── tinygotest │ ├── main.go │ └── main_test.go ├── interp └── testdata │ ├── interface.out.ll │ ├── consteval.out.ll │ ├── slice-copy.out.ll │ ├── basic.out.ll │ ├── consteval.ll │ └── interface.ll ├── docs ├── moved.rst └── index.rst ├── .gitignore ├── util_windows.go ├── go.mod ├── util_unix.go ├── loader ├── ssa.go └── errors.go ├── compileopts ├── target_test.go └── options.go ├── CONTRIBUTORS ├── .gitmodules ├── colorwriter.go └── compiler ├── volatile.go └── ircheck └── errors.go /bin/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /testdata/gc.txt: -------------------------------------------------------------------------------- 1 | ok 2 | -------------------------------------------------------------------------------- /testdata/zeroalloc.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/picolibc-include/picolibc.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/examples/wasm/.gitignore: -------------------------------------------------------------------------------- 1 | html/* 2 | -------------------------------------------------------------------------------- /cgo/testdata/include/foo.h: -------------------------------------------------------------------------------- 1 | #define FOO_H 1 2 | -------------------------------------------------------------------------------- /testdata/alias.txt: -------------------------------------------------------------------------------- 1 | x 2 | apple 3 | true 4 | false 5 | -------------------------------------------------------------------------------- /testdata/init_multi.txt: -------------------------------------------------------------------------------- 1 | init1 2 | init2 3 | main 4 | -------------------------------------------------------------------------------- /cgo/testdata/basic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "C" 4 | -------------------------------------------------------------------------------- /src/runtime/cgo/cgo.go: -------------------------------------------------------------------------------- 1 | package cgo 2 | 3 | // dummy 4 | -------------------------------------------------------------------------------- /src/syscall/syscall.go: -------------------------------------------------------------------------------- 1 | package syscall 2 | 3 | func Exit(code int) 4 | -------------------------------------------------------------------------------- /targets/pca10040-s132v6.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["pca10040", "nrf52-s132v6"] 3 | } 4 | -------------------------------------------------------------------------------- /src/runtime/internal/sys/zversion.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | const TheVersion = `go0.1.0` 4 | -------------------------------------------------------------------------------- /src/runtime/os_js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package runtime 4 | 5 | const GOOS = "js" 6 | -------------------------------------------------------------------------------- /targets/pca10056-s140v7.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["pca10056", "nrf52840-s140v7"] 3 | } 4 | -------------------------------------------------------------------------------- /targets/reelboard-s140v7.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["reelboard", "nrf52840-s140v7"] 3 | } 4 | -------------------------------------------------------------------------------- /src/runtime/os_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package runtime 4 | 5 | const GOOS = "linux" 6 | -------------------------------------------------------------------------------- /src/runtime/os_darwin.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | package runtime 4 | 5 | const GOOS = "darwin" 6 | -------------------------------------------------------------------------------- /src/examples/wasm/main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | println("Hello world!") 5 | } 6 | -------------------------------------------------------------------------------- /src/runtime/os_freebsd.go: -------------------------------------------------------------------------------- 1 | // +build freebsd 2 | 3 | package runtime 4 | 5 | const GOOS = "freebsd" 6 | -------------------------------------------------------------------------------- /targets/particle-argon.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["particle-3rd-gen"], 3 | "build-tags": ["particle_argon"] 4 | } 5 | -------------------------------------------------------------------------------- /targets/particle-boron.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["particle-3rd-gen"], 3 | "build-tags": ["particle_boron"] 4 | } 5 | -------------------------------------------------------------------------------- /targets/particle-xenon.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["particle-3rd-gen"], 3 | "build-tags": ["particle_xenon"] 4 | } 5 | -------------------------------------------------------------------------------- /testdata/zeroalloc.go: -------------------------------------------------------------------------------- 1 | package main 2 | func main() { 3 | p := []byte{} 4 | for len(p) >= 1 { 5 | p = p[1:] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /targets/nrf52-s132v6.json: -------------------------------------------------------------------------------- 1 | { 2 | "build-tags": ["softdevice", "s132v6"], 3 | "linkerscript": "targets/nrf52-s132v6.ld" 4 | } 5 | -------------------------------------------------------------------------------- /targets/fe310.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["riscv"], 3 | "features": ["+a", "+c", "+m"], 4 | "build-tags": ["fe310", "sifive"] 5 | } 6 | -------------------------------------------------------------------------------- /targets/nrf52840-s140v7.json: -------------------------------------------------------------------------------- 1 | { 2 | "build-tags": ["softdevice", "s140v7"], 3 | "linkerscript": "targets/nrf52840-s140v7.ld" 4 | } 5 | -------------------------------------------------------------------------------- /testdata/cgo/extra.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Make sure CGo supports multiple files. 4 | 5 | // int fortytwo(void); 6 | import "C" 7 | -------------------------------------------------------------------------------- /src/machine/usb_nrf52840_reset_none.go: -------------------------------------------------------------------------------- 1 | // +build nrf52840,!nrf52840_reset_uf2 2 | 3 | package machine 4 | 5 | func checkShouldReset() { 6 | } 7 | -------------------------------------------------------------------------------- /src/reflect/swapper.go: -------------------------------------------------------------------------------- 1 | package reflect 2 | 3 | func Swapper(slice interface{}) func(i, j int) { 4 | panic("unimplemented: reflect.Swapper") 5 | } 6 | -------------------------------------------------------------------------------- /testdata/stdlib.txt: -------------------------------------------------------------------------------- 1 | stdin: 0 2 | stdout: 1 3 | stderr: 2 4 | pseudorandom number: 1298498081 5 | strings.IndexByte: 2 6 | strings.Replace: An-example-string 7 | -------------------------------------------------------------------------------- /version.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // version of this package. 4 | // Update this value before release of new version of software. 5 | const version = "0.13.1" 6 | -------------------------------------------------------------------------------- /src/testing/doc.go: -------------------------------------------------------------------------------- 1 | package testing 2 | 3 | /* 4 | This is a sad stub of the upstream testing package because it doesn't compile 5 | with tinygo right now. 6 | */ 7 | -------------------------------------------------------------------------------- /src/machine/board_pca10056_baremetal.go: -------------------------------------------------------------------------------- 1 | // +build nrf52840,pca10056 2 | 3 | package machine 4 | 5 | // UART0 is the NRF UART 6 | var ( 7 | UART0 = NRF_UART0 8 | ) 9 | -------------------------------------------------------------------------------- /src/machine/board_reelboard_baremetal.go: -------------------------------------------------------------------------------- 1 | // +build nrf52840,reelboard 2 | 3 | package machine 4 | 5 | // UART0 is the NRF UART 6 | var ( 7 | UART0 = NRF_UART0 8 | ) 9 | -------------------------------------------------------------------------------- /testdata/init.txt: -------------------------------------------------------------------------------- 1 | init 2 | main 3 | v1: 3 4 | v2: 2 5 5 | v3: 4 4 2 7 6 | v4: 0 true 7 | v5: 0 false 8 | v6: false 9 | v7: 3 foo 10 | 3 11 | 3 12 | 5 13 | 5 14 | -------------------------------------------------------------------------------- /targets/nrf52840-mdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52840"], 3 | "build-tags": ["nrf52840_mdk"], 4 | "flash-method": "openocd", 5 | "openocd-interface": "cmsis-dap" 6 | } 7 | -------------------------------------------------------------------------------- /cgo/testdata/const.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #define foo 3 5 | #define bar foo 6 | */ 7 | import "C" 8 | 9 | const ( 10 | Foo = C.foo 11 | Bar = C.bar 12 | ) 13 | -------------------------------------------------------------------------------- /src/runtime/runtime_unix_noheap.go: -------------------------------------------------------------------------------- 1 | // +build darwin linux,!baremetal freebsd,!baremetal 2 | 3 | // +build gc.none gc.extalloc 4 | 5 | package runtime 6 | 7 | func preinit() {} 8 | -------------------------------------------------------------------------------- /targets/particle-3rd-gen.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52840"], 3 | "build-tags": ["particle_3rd_gen"], 4 | "flash-method": "openocd", 5 | "openocd-interface": "cmsis-dap" 6 | } 7 | -------------------------------------------------------------------------------- /src/examples/serial/serial.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | func main() { 6 | for { 7 | println("hello world!") 8 | time.Sleep(time.Second) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testdata/init_multi.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func init() { 4 | println("init1") 5 | } 6 | 7 | func init() { 8 | println("init2") 9 | } 10 | 11 | func main() { 12 | println("main") 13 | } 14 | -------------------------------------------------------------------------------- /targets/pca10031.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf51"], 3 | "build-tags": ["pca10031"], 4 | "flash-command": "nrfjprog -f nrf51 --sectorerase --program {hex} --reset", 5 | "openocd-interface": "cmsis-dap" 6 | } 7 | -------------------------------------------------------------------------------- /transform/allocs_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestAllocs(t *testing.T) { 8 | t.Parallel() 9 | testTransform(t, "testdata/allocs", OptimizeAllocs) 10 | } 11 | -------------------------------------------------------------------------------- /tests/tinygotest/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | Thing() 9 | fmt.Println("normal main") 10 | } 11 | 12 | func Thing() { 13 | fmt.Println("THING") 14 | } 15 | -------------------------------------------------------------------------------- /testdata/structs.txt: -------------------------------------------------------------------------------- 1 | test0 2 | test1 1 3 | test2 1 2 4 | test3 1 2 3 5 | test4 1 2 3 4 6 | test4b 1 2 3 4 7 | test4bp 1 2 3 4 8 | test5 1 2 3 9 | test6 foo 3 5 10 | test7 (0:nil) 8 11 | test8 2 3 12 13 6 12 | test9 nil 13 | -------------------------------------------------------------------------------- /transform/testdata/globals-non-const.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 2 | target triple = "armv7em-none-eabi" 3 | 4 | @globalIntConst = constant i32 3 5 | @globalIntVar = global i32 5 6 | -------------------------------------------------------------------------------- /targets/microbit.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf51"], 3 | "build-tags": ["microbit"], 4 | "flash-method": "msd", 5 | "openocd-interface": "cmsis-dap", 6 | "msd-volume-name": "MICROBIT", 7 | "msd-firmware-name": "firmware.hex" 8 | } 9 | -------------------------------------------------------------------------------- /targets/stm32.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 64K 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K 6 | } 7 | 8 | _stack_size = 2K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /transform/panic_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestReplacePanicsWithTrap(t *testing.T) { 8 | t.Parallel() 9 | testTransform(t, "testdata/panic", ReplacePanicsWithTrap) 10 | } 11 | -------------------------------------------------------------------------------- /transform/testdata/globals-non-const.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 2 | target triple = "armv7em-none-eabi" 3 | 4 | @globalIntConst = global i32 3 5 | @globalIntVar = global i32 5 6 | -------------------------------------------------------------------------------- /src/runtime/runtime_stm32.go: -------------------------------------------------------------------------------- 1 | // +build stm32 2 | 3 | package runtime 4 | 5 | type timeUnit int64 6 | 7 | func postinit() {} 8 | 9 | //export Reset_Handler 10 | func main() { 11 | preinit() 12 | run() 13 | abort() 14 | } 15 | -------------------------------------------------------------------------------- /targets/lm3s6965.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 256K 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K 6 | } 7 | 8 | _stack_size = 4K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /targets/nrf52840.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 1M 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K 6 | } 7 | 8 | _stack_size = 4K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /targets/stm32f103rb.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 128K 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K 6 | } 7 | 8 | _stack_size = 2K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /targets/stm32f407.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 1M 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K 6 | } 7 | 8 | _stack_size = 4K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /transform/func-lowering_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFuncLowering(t *testing.T) { 8 | t.Parallel() 9 | testTransform(t, "testdata/func-lowering", LowerFuncValues) 10 | } 11 | -------------------------------------------------------------------------------- /src/runtime/defer.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | // Some helper types for the defer statement. 4 | // See compiler/defer.go for details. 5 | 6 | type _defer struct { 7 | callback uintptr // callback number 8 | next *_defer 9 | } 10 | -------------------------------------------------------------------------------- /targets/hifive1-qemu.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["fe310"], 3 | "build-tags": ["hifive1b", "qemu"], 4 | "linkerscript": "targets/hifive1-qemu.ld", 5 | "emulator": ["qemu-system-riscv32", "-machine", "sifive_e", "-nographic", "-kernel"] 6 | } 7 | -------------------------------------------------------------------------------- /targets/hifive1b.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x20010000, LENGTH = 0x6a120 5 | RAM (xrw) : ORIGIN = 0x80000000, LENGTH = 0x4000 6 | } 7 | 8 | _stack_size = 2K; 9 | 10 | INCLUDE "targets/riscv.ld" 11 | -------------------------------------------------------------------------------- /targets/reelboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52840"], 3 | "build-tags": ["reelboard"], 4 | "flash-method": "msd", 5 | "msd-volume-name": "reel-board", 6 | "msd-firmware-name": "firmware.hex", 7 | "openocd-interface": "cmsis-dap" 8 | } 9 | -------------------------------------------------------------------------------- /transform/testdata/globals-function-sections.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 2 | target triple = "armv7em-none-eabi" 3 | 4 | declare void @foo() 5 | 6 | define void @bar() { 7 | ret void 8 | } 9 | -------------------------------------------------------------------------------- /targets/nrf51.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 256K /* .text */ 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K 6 | } 7 | 8 | _stack_size = 2K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /targets/nrf52.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 256K /* .text */ 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K 6 | } 7 | 8 | _stack_size = 2K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /testdata/string.txt: -------------------------------------------------------------------------------- 1 | 0 97 2 | 1 98 3 | 2 99 4 | 3 252 5 | 5 162 6 | 7 8364 7 | 10 66376 8 | 14 176 9 | 16 120 10 | 0 97 11 | 1 98 12 | 2 99 13 | 3 252 14 | 4 162 15 | 5 8364 16 | 6 66376 17 | 7 176 18 | 8 120 19 | string from runes: abcü¢€𐍈°x 20 | -------------------------------------------------------------------------------- /targets/pyportal.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd51j20a"], 3 | "build-tags": ["pyportal"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "PORTALBOOT", 7 | "msd-firmware-name": "firmware.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /src/runtime/bytes.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | //go:linkname indexBytePortable internal/bytealg.IndexByte 4 | func indexBytePortable(s []byte, c byte) int { 5 | for i, b := range s { 6 | if b == c { 7 | return i 8 | } 9 | } 10 | return -1 11 | } 12 | -------------------------------------------------------------------------------- /src/sync/once.go: -------------------------------------------------------------------------------- 1 | package sync 2 | 3 | type Once struct { 4 | done bool 5 | m Mutex 6 | } 7 | 8 | func (o *Once) Do(f func()) { 9 | o.m.Lock() 10 | defer o.m.Unlock() 11 | if o.done { 12 | return 13 | } 14 | o.done = true 15 | f() 16 | } 17 | -------------------------------------------------------------------------------- /targets/x9pro.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52"], 3 | "build-tags": ["x9pro"], 4 | "flash-method": "openocd", 5 | "flash-command": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset", 6 | "openocd-interface": "jlink", 7 | "openocd-transport": "swd" 8 | } 9 | -------------------------------------------------------------------------------- /targets/arduino-nano33.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd21g18a"], 3 | "build-tags": ["sam", "atsamd21g18a", "arduino_nano33"], 4 | "flash-command": "bossac -d -i -e -w -v -R --port={port} --offset=0x2000 {bin}", 5 | "flash-1200-bps-reset": "true" 6 | } 7 | -------------------------------------------------------------------------------- /transform/testdata/globals-function-sections.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 2 | target triple = "armv7em-none-eabi" 3 | 4 | declare void @foo() 5 | 6 | define void @bar() section ".text.bar" { 7 | ret void 8 | } 9 | -------------------------------------------------------------------------------- /targets/pca10040.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52"], 3 | "build-tags": ["pca10040"], 4 | "flash-method": "openocd", 5 | "flash-command": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset", 6 | "openocd-interface": "jlink", 7 | "openocd-transport": "swd" 8 | } 9 | -------------------------------------------------------------------------------- /interp/testdata/interface.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 2 | target triple = "x86_64--linux" 3 | 4 | @main.v1 = local_unnamed_addr global i1 true 5 | 6 | define void @runtime.initAll() unnamed_addr { 7 | entry: 8 | ret void 9 | } 10 | -------------------------------------------------------------------------------- /targets/hifive1b.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["fe310"], 3 | "build-tags": ["hifive1b"], 4 | "linkerscript": "targets/hifive1b.ld", 5 | "flash-method": "msd", 6 | "msd-volume-name": "HiFive", 7 | "msd-firmware-name": "firmware.hex", 8 | "jlink-device": "fe310" 9 | } 10 | -------------------------------------------------------------------------------- /targets/pybadge.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd51j19a"], 3 | "build-tags": ["sam", "atsamd51j19a", "pybadge"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "PYBADGEBOOT", 7 | "msd-firmware-name": "arcade.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /targets/pca10056.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52840"], 3 | "build-tags": ["pca10056"], 4 | "flash-method": "command", 5 | "flash-command": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset", 6 | "msd-volume-name": "JLINK", 7 | "msd-firmware-name": "firmware.hex" 8 | } 9 | -------------------------------------------------------------------------------- /targets/riscv-qemu.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["riscv"], 3 | "features": ["+a", "+c", "+m"], 4 | "build-tags": ["virt", "qemu"], 5 | "linkerscript": "targets/riscv-qemu.ld", 6 | "emulator": ["qemu-system-riscv32", "-machine", "virt", "-nographic", "-bios", "none", "-kernel"] 7 | } 8 | -------------------------------------------------------------------------------- /targets/feather-m0.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd21g18a"], 3 | "build-tags": ["sam", "atsamd21g18a", "feather_m0"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "FEATHERBOOT", 7 | "msd-firmware-name": "firmware.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /targets/feather-m4.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd51j19a"], 3 | "build-tags": ["sam", "atsamd51j19a", "feather_m4"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "FEATHERBOOT", 7 | "msd-firmware-name": "firmware.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /targets/itsybitsy-m0.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd21g18a"], 3 | "build-tags": ["sam", "atsamd21g18a", "itsybitsy_m0"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "ITSYBOOT", 7 | "msd-firmware-name": "firmware.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /targets/pinetime-devkit0.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52"], 3 | "build-tags": ["pinetime_devkit0"], 4 | "flash-method": "openocd", 5 | "flash-command": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset", 6 | "openocd-interface": "jlink", 7 | "openocd-transport": "swd" 8 | } 9 | -------------------------------------------------------------------------------- /targets/trinket-m0.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd21e18a"], 3 | "build-tags": ["sam", "atsamd21e18a", "trinket_m0"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "TRINKETBOOT", 7 | "msd-firmware-name": "firmware.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /docs/moved.rst: -------------------------------------------------------------------------------- 1 | .. _moved: 2 | 3 | .. highlight:: none 4 | 5 | The TinyGo Docs Site Has Moved 6 | ========================= 7 | 8 | The documentation web site for TinyGo has moved. 9 | 10 | You can find the new web site at `tinygo.org `_ 11 | 12 | Thank you! 13 | -------------------------------------------------------------------------------- /targets/itsybitsy-m4.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd51g19a"], 3 | "build-tags": ["sam", "atsamd51g19a", "itsybitsy_m4"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "ITSYM4BOOT", 7 | "msd-firmware-name": "firmware.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /targets/nrf52840-s140v7.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000 + 0x00027000, LENGTH = 1M - 0x00027000 5 | RAM (xrw) : ORIGIN = 0x20000000 + 0x000039c0, LENGTH = 256K - 0x000039c0 6 | } 7 | 8 | _stack_size = 4K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /src/machine/board_stm32.go: -------------------------------------------------------------------------------- 1 | // +build bluepill nucleof103rb stm32f4disco 2 | 3 | package machine 4 | 5 | // Peripheral abstraction layer for the stm32. 6 | 7 | const ( 8 | portA Pin = iota * 16 9 | portB 10 | portC 11 | portD 12 | portE 13 | portF 14 | portG 15 | portH 16 | ) 17 | -------------------------------------------------------------------------------- /targets/arduino-mega2560.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atmega2560"], 3 | "build-tags": ["arduino_mega2560"], 4 | "ldflags": [ 5 | "-Wl,--defsym=_bootloader_size=8192" 6 | ], 7 | "flash-command":"avrdude -c wiring -b 115200 -p atmega2560 -P {port} -U flash:w:{hex} -v -D" 8 | } 9 | -------------------------------------------------------------------------------- /targets/arduino.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atmega328p"], 3 | "build-tags": ["arduino"], 4 | "ldflags": [ 5 | "-Wl,--defsym=_bootloader_size=512", 6 | "-Wl,--defsym=_stack_size=512" 7 | ], 8 | "flash-command": "avrdude -c arduino -p atmega328p -P {port} -U flash:w:{hex}:i" 9 | } 10 | -------------------------------------------------------------------------------- /targets/atsamd21.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */ 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00008000 6 | } 7 | 8 | _stack_size = 2K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /targets/metro-m4-airlift.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd51j19a"], 3 | "build-tags": ["sam", "atsamd51j19a", "metro_m4_airlift"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "METROM4BOOT", 7 | "msd-firmware-name": "firmware.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /targets/atsamd51.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */ 5 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x00030000 6 | } 7 | 8 | _stack_size = 4K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /targets/circuitplay-express.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atsamd21g18a"], 3 | "build-tags": ["sam", "atsamd21g18a", "circuitplay_express"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "CPLAYBOOT", 7 | "msd-firmware-name": "firmware.uf2" 8 | } 9 | -------------------------------------------------------------------------------- /src/runtime/runtime_fe310_baremetal.go: -------------------------------------------------------------------------------- 1 | // +build fe310,!qemu 2 | 3 | package runtime 4 | 5 | import ( 6 | "device/riscv" 7 | ) 8 | 9 | const tickMicros = 32768 // RTC clock runs at 32.768kHz 10 | 11 | func abort() { 12 | // lock up forever 13 | for { 14 | riscv.Asm("wfi") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /targets/nrf52-s132v6.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000 + 0x00026000 , LENGTH = 256K - 0x00026000 /* .text */ 5 | RAM (xrw) : ORIGIN = 0x20000000 + 0x000039c0, LENGTH = 64K - 0x000039c0 6 | } 7 | 8 | _stack_size = 4K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /src/examples/wasm/main/README.md: -------------------------------------------------------------------------------- 1 | # WebAssembly main execution example 2 | 3 | A simple hello world that prints to the browser console. 4 | 5 | ## License 6 | 7 | Note that `index.html` is copied almost verbatim from the Go 1.12 source at 8 | `$GOROOT/misc/wasm/wasm_exec.html`. Its license applies to this file. 9 | -------------------------------------------------------------------------------- /targets/arduino-nano.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["atmega328p"], 3 | "build-tags": ["arduino_nano"], 4 | "ldflags": [ 5 | "-Wl,--defsym=_bootloader_size=512", 6 | "-Wl,--defsym=_stack_size=512" 7 | ], 8 | "flash-command": "avrdude -c arduino -p atmega328p -b 57600 -P {port} -U flash:w:{hex}:i" 9 | } 10 | -------------------------------------------------------------------------------- /src/runtime/arch_386.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | const GOARCH = "386" 4 | 5 | // The bitness of the CPU (e.g. 8, 32, 64). 6 | const TargetBits = 32 7 | 8 | // Align on word boundary. 9 | func align(ptr uintptr) uintptr { 10 | return (ptr + 3) &^ 3 11 | } 12 | 13 | func getCurrentStackPointer() uintptr 14 | -------------------------------------------------------------------------------- /src/runtime/arch_arm64.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | const GOARCH = "arm64" 4 | 5 | // The bitness of the CPU (e.g. 8, 32, 64). 6 | const TargetBits = 64 7 | 8 | // Align on word boundary. 9 | func align(ptr uintptr) uintptr { 10 | return (ptr + 7) &^ 7 11 | } 12 | 13 | func getCurrentStackPointer() uintptr 14 | -------------------------------------------------------------------------------- /src/runtime/scheduler_tasks.go: -------------------------------------------------------------------------------- 1 | // +build scheduler.tasks 2 | 3 | package runtime 4 | 5 | // getSystemStackPointer returns the current stack pointer of the system stack. 6 | // This is not necessarily the same as the current stack pointer. 7 | //export tinygo_getSystemStackPointer 8 | func getSystemStackPointer() uintptr 9 | -------------------------------------------------------------------------------- /src/runtime/scheduler_coroutines.go: -------------------------------------------------------------------------------- 1 | // +build scheduler.coroutines 2 | 3 | package runtime 4 | 5 | // getSystemStackPointer returns the current stack pointer of the system stack. 6 | // This is always the current stack pointer. 7 | func getSystemStackPointer() uintptr { 8 | return getCurrentStackPointer() 9 | } 10 | -------------------------------------------------------------------------------- /src/runtime/stack.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | type Func struct { 4 | } 5 | 6 | func FuncForPC(pc uintptr) *Func { 7 | return nil 8 | } 9 | 10 | func (f *Func) Name() string { 11 | return "" 12 | } 13 | 14 | func Caller(skip int) (pc uintptr, file string, line int, ok bool) { 15 | return 0, "", 0, false 16 | } 17 | -------------------------------------------------------------------------------- /interp/testdata/consteval.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 2 | target triple = "x86_64--linux" 3 | 4 | @intToPtrResult = local_unnamed_addr global i8 2 5 | @ptrToIntResult = local_unnamed_addr global i8 2 6 | 7 | define void @runtime.initAll() local_unnamed_addr { 8 | ret void 9 | } 10 | -------------------------------------------------------------------------------- /testdata/print.txt: -------------------------------------------------------------------------------- 1 | hello world! 2 | 42 3 | 100000000 4 | abc 5 | a b c 6 | 123 7 | 123 8 | -123 9 | 12345 10 | 12345 11 | -12345 12 | 12345678 13 | 12345678 14 | -12345678 15 | 123456789012 16 | 123456789012 17 | -123456789012 18 | +3.140000e+000 19 | (+5.000000e+000+1.234500e+000i) 20 | (0:nil) 21 | map[2] 22 | true false 23 | -------------------------------------------------------------------------------- /src/machine/board_hifive1b_baremetal.go: -------------------------------------------------------------------------------- 1 | // +build fe310,hifive1b 2 | 3 | package machine 4 | 5 | import "device/sifive" 6 | 7 | // SPI on the HiFive1. 8 | var ( 9 | SPI1 = SPI{ 10 | Bus: sifive.QSPI1, 11 | } 12 | ) 13 | 14 | // I2C on the HiFive1 rev B. 15 | var ( 16 | I2C0 = I2C{ 17 | Bus: sifive.I2C0, 18 | } 19 | ) 20 | -------------------------------------------------------------------------------- /src/examples/wasm/invoke/wasm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "syscall/js" 5 | ) 6 | 7 | func runner(this js.Value, args []js.Value) interface{} { 8 | return args[0].Invoke(args[1]).String() 9 | } 10 | 11 | func main() { 12 | wait := make(chan struct{}, 0) 13 | js.Global().Set("runner", js.FuncOf(runner)) 14 | <-wait 15 | } 16 | -------------------------------------------------------------------------------- /src/runtime/runtime_attiny.go: -------------------------------------------------------------------------------- 1 | // +build avr,attiny 2 | 3 | package runtime 4 | 5 | import ( 6 | "device/avr" 7 | ) 8 | 9 | func sleepWDT(period uint8) { 10 | // TODO: use the watchdog timer instead of a busy loop. 11 | for i := 0x45; i != 0; i-- { 12 | for i := 0xff; i != 0; i-- { 13 | avr.Asm("nop") 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | docs/_build 3 | src/device/avr/*.go 4 | src/device/avr/*.ld 5 | src/device/avr/*.s 6 | src/device/nrf/*.go 7 | src/device/nrf/*.s 8 | src/device/sam/*.go 9 | src/device/sam/*.s 10 | src/device/sifive/*.go 11 | src/device/sifive/*.s 12 | src/device/stm32/*.go 13 | src/device/stm32/*.s 14 | vendor 15 | llvm-build 16 | llvm-project 17 | -------------------------------------------------------------------------------- /src/machine/board_digispark.go: -------------------------------------------------------------------------------- 1 | // +build digispark 2 | 3 | package machine 4 | 5 | // Return the current CPU frequency in hertz. 6 | func CPUFrequency() uint32 { 7 | return 16000000 8 | } 9 | 10 | const ( 11 | P0 Pin = PB0 12 | P1 Pin = PB1 13 | P2 Pin = PB2 14 | P3 Pin = PB3 15 | P4 Pin = PB4 16 | P5 Pin = PB5 17 | 18 | LED = P1 19 | ) 20 | -------------------------------------------------------------------------------- /transform/stringtobytes_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | 6 | "tinygo.org/x/go-llvm" 7 | ) 8 | 9 | func TestOptimizeStringToBytes(t *testing.T) { 10 | t.Parallel() 11 | testTransform(t, "testdata/stringtobytes", func(mod llvm.Module) { 12 | // Run optimization pass. 13 | OptimizeStringToBytes(mod) 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /util_windows.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // This file contains utility functions for Windows. 4 | 5 | import ( 6 | "os/exec" 7 | ) 8 | 9 | // setCommandAsDaemon makes sure this command does not receive signals sent to 10 | // the parent. It is unimplemented on Windows. 11 | func setCommandAsDaemon(daemon *exec.Cmd) { 12 | // Not implemented. 13 | } 14 | -------------------------------------------------------------------------------- /src/runtime/interrupt/interrupt_hwvector.go: -------------------------------------------------------------------------------- 1 | // +build avr cortexm 2 | 3 | package interrupt 4 | 5 | // Register is used to declare an interrupt. You should not normally call this 6 | // function: it is only for telling the compiler about the mapping between an 7 | // interrupt number and the interrupt handler name. 8 | func Register(id int, handlerName string) int 9 | -------------------------------------------------------------------------------- /targets/atsamd21e18a.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv6m-none-eabi", 4 | "build-tags": ["atsamd21e18", "atsamd21", "sam"], 5 | "cflags": [ 6 | "--target=armv6m-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/atsamd21.ld", 10 | "extra-files": [ 11 | "src/device/sam/atsamd21e18a.s" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /targets/atsamd21g18a.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv6m-none-eabi", 4 | "build-tags": ["atsamd21g18", "atsamd21", "sam"], 5 | "cflags": [ 6 | "--target=armv6m-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/atsamd21.ld", 10 | "extra-files": [ 11 | "src/device/sam/atsamd21g18a.s" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /targets/atsamd51g19a.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7em-none-eabi", 4 | "build-tags": ["atsamd51g19", "atsamd51", "sam"], 5 | "cflags": [ 6 | "--target=armv7em-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/atsamd51.ld", 10 | "extra-files": [ 11 | "src/device/sam/atsamd51g19a.s" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /targets/atsamd51j19a.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7em-none-eabi", 4 | "build-tags": ["atsamd51j19", "atsamd51", "sam"], 5 | "cflags": [ 6 | "--target=armv7em-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/atsamd51.ld", 10 | "extra-files": [ 11 | "src/device/sam/atsamd51j19a.s" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /transform/goroutine_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | "tinygo.org/x/go-llvm" 6 | ) 7 | 8 | func TestGoroutineLowering(t *testing.T) { 9 | t.Parallel() 10 | testTransform(t, "testdata/coroutines", func(mod llvm.Module) { 11 | err := LowerCoroutines(mod, false) 12 | if err != nil { 13 | panic(err) 14 | } 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /src/runtime/runtime_unix_heap.go: -------------------------------------------------------------------------------- 1 | // +build darwin linux,!baremetal freebsd,!baremetal 2 | 3 | // +build gc.conservative gc.leaking 4 | 5 | package runtime 6 | 7 | const heapSize = 1 * 1024 * 1024 // 1MB to start 8 | 9 | var heapStart, heapEnd uintptr 10 | 11 | func preinit() { 12 | heapStart = uintptr(malloc(heapSize)) 13 | heapEnd = heapStart + heapSize 14 | } 15 | -------------------------------------------------------------------------------- /transform/interface-lowering_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | 6 | "tinygo.org/x/go-llvm" 7 | ) 8 | 9 | func TestInterfaceLowering(t *testing.T) { 10 | t.Parallel() 11 | testTransform(t, "testdata/interface", func(mod llvm.Module) { 12 | err := LowerInterfaces(mod) 13 | if err != nil { 14 | t.Error(err) 15 | } 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /targets/atsamd51j20a.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7em-none-eabi", 4 | "build-tags": ["sam", "atsamd51", "atsamd51j20", "atsamd51j20a"], 5 | "cflags": [ 6 | "--target=armv7em-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/atsamd51.ld", 10 | "extra-files": [ 11 | "src/device/sam/atsamd51j20a.s" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /targets/hifive1-qemu.ld: -------------------------------------------------------------------------------- 1 | 2 | /* memory map: 3 | * https://github.com/sifive/freedom-e-sdk/blob/v201908-branch/bsp/sifive-hifive1/metal.default.lds 4 | */ 5 | MEMORY 6 | { 7 | FLASH_TEXT (rw) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000 8 | RAM (xrw) : ORIGIN = 0x80000000, LENGTH = 0x4000 9 | } 10 | 11 | _stack_size = 2K; 12 | 13 | INCLUDE "targets/riscv.ld" 14 | -------------------------------------------------------------------------------- /testdata/coroutines.txt: -------------------------------------------------------------------------------- 1 | main 1 2 | sub 1 3 | main 2 4 | sub 2 5 | main 3 6 | wait: 7 | wait start 8 | wait end 9 | end waiting 10 | value produced after some time: 42 11 | non-blocking goroutine 12 | done with non-blocking goroutine 13 | async interface method call 14 | slept inside func pointer 8 15 | slept inside closure, with value: 20 8 16 | closure go call result: 1 17 | -------------------------------------------------------------------------------- /targets/clue_alpha.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52840"], 3 | "build-tags": ["clue_alpha","nrf52840_reset_uf2"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "FTHR840BOOT", 7 | "msd-firmware-name": "firmware.uf2", 8 | "uf2-family-id": "0xADA52840", 9 | "linkerscript": "targets/circuitplay-bluefruit.ld" 10 | } 11 | -------------------------------------------------------------------------------- /targets/avr.json: -------------------------------------------------------------------------------- 1 | { 2 | "build-tags": ["avr", "baremetal", "linux", "arm"], 3 | "goos": "linux", 4 | "goarch": "arm", 5 | "compiler": "avr-gcc", 6 | "gc": "conservative", 7 | "linker": "avr-gcc", 8 | "scheduler": "none", 9 | "ldflags": [ 10 | "-T", "targets/avr.ld", 11 | "-Wl,--gc-sections" 12 | ], 13 | "extra-files": [ 14 | "src/runtime/scheduler_avr.S" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/runtime/arch_avr.go: -------------------------------------------------------------------------------- 1 | // +build avr 2 | 3 | package runtime 4 | 5 | const GOARCH = "arm" // avr pretends to be arm 6 | 7 | // The bitness of the CPU (e.g. 8, 32, 64). 8 | const TargetBits = 8 9 | 10 | // Align on a word boundary. 11 | func align(ptr uintptr) uintptr { 12 | // No alignment necessary on the AVR. 13 | return ptr 14 | } 15 | 16 | func getCurrentStackPointer() uintptr 17 | -------------------------------------------------------------------------------- /src/runtime/sync.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | // This file contains stub implementations for internal/poll. 4 | 5 | //go:linkname semacquire internal/poll.runtime_Semacquire 6 | func semacquire(sema *uint32) { 7 | panic("todo: semacquire") 8 | } 9 | 10 | //go:linkname semrelease internal/poll.runtime_Semrelease 11 | func semrelease(sema *uint32) { 12 | panic("todo: semrelease") 13 | } 14 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. TinyGo documentation master file, created by 2 | sphinx-quickstart on Sat Sep 22 15:05:19 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | The TinyGo site has moved! 7 | ================================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | moved 15 | -------------------------------------------------------------------------------- /targets/circuitplay-bluefruit.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["nrf52840"], 3 | "build-tags": ["circuitplay_bluefruit","nrf52840_reset_uf2"], 4 | "flash-1200-bps-reset": "true", 5 | "flash-method": "msd", 6 | "msd-volume-name": "CPLAYBTBOOT", 7 | "msd-firmware-name": "firmware.uf2", 8 | "uf2-family-id": "0xADA52840", 9 | "linkerscript": "targets/circuitplay-bluefruit.ld" 10 | } 11 | -------------------------------------------------------------------------------- /testdata/calls.txt: -------------------------------------------------------------------------------- 1 | hello from function pointer: 5 2 | deferring... 3 | Thing.Print: foo arg: bar 4 | ...run as defer 3 5 | ...run closure deferred: 4 6 | ...run as defer 1 7 | ...exported defer 8 | loop 3 9 | loop 2 10 | loop 1 11 | loop 0 12 | bound method: foo 13 | thing inside closure: foo 14 | inside fp closure: foo 3 15 | Thing.Print: arg: functional args 1 16 | Thing.Print: named thing arg: functional args 2 17 | -------------------------------------------------------------------------------- /transform/wasm-abi_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | 6 | "tinygo.org/x/go-llvm" 7 | ) 8 | 9 | func TestWasmABI(t *testing.T) { 10 | t.Parallel() 11 | testTransform(t, "testdata/wasm-abi", func(mod llvm.Module) { 12 | // Run ABI change pass. 13 | err := ExternalInt64AsPtr(mod) 14 | if err != nil { 15 | t.Errorf("failed to change wasm ABI: %v", err) 16 | } 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /src/runtime/strings_go111.go: -------------------------------------------------------------------------------- 1 | // +build !go1.12 2 | 3 | package runtime 4 | 5 | // indexByte provides compatibility with Go 1.11. 6 | // See the following: 7 | // https://github.com/tinygo-org/tinygo/issues/351 8 | // https://github.com/golang/go/commit/ad4a58e31501bce5de2aad90a620eaecdc1eecb8 9 | //go:linkname indexByte strings.IndexByte 10 | func indexByte(s string, c byte) int { 11 | return indexByteString(s, c) 12 | } 13 | -------------------------------------------------------------------------------- /src/runtime/arch_arm.go: -------------------------------------------------------------------------------- 1 | // +build arm,!baremetal arm,arm7tdmi 2 | 3 | package runtime 4 | 5 | import "device/arm" 6 | 7 | const GOARCH = "arm" 8 | 9 | // The bitness of the CPU (e.g. 8, 32, 64). 10 | const TargetBits = 32 11 | 12 | // Align on word boundary. 13 | func align(ptr uintptr) uintptr { 14 | return (ptr + 3) &^ 3 15 | } 16 | 17 | func getCurrentStackPointer() uintptr { 18 | return arm.ReadRegister("sp") 19 | } 20 | -------------------------------------------------------------------------------- /src/runtime/arch_cortexm.go: -------------------------------------------------------------------------------- 1 | // +build cortexm 2 | 3 | package runtime 4 | 5 | import ( 6 | "device/arm" 7 | ) 8 | 9 | const GOARCH = "arm" 10 | 11 | // The bitness of the CPU (e.g. 8, 32, 64). 12 | const TargetBits = 32 13 | 14 | // Align on word boundary. 15 | func align(ptr uintptr) uintptr { 16 | return (ptr + 3) &^ 3 17 | } 18 | 19 | func getCurrentStackPointer() uintptr { 20 | return arm.ReadRegister("sp") 21 | } 22 | -------------------------------------------------------------------------------- /targets/circuitplay-bluefruit.ld: -------------------------------------------------------------------------------- 1 | 2 | MEMORY 3 | { 4 | FLASH_TEXT (rw) : ORIGIN = 0x00000000+0x26000, LENGTH = 0xED000-0x26000 /* SoftDevice S140. See https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/hathach-memory-map. Application starts at 0x26000; user data starts at 0xED000 */ 5 | RAM (xrw) : ORIGIN = 0x20004180, LENGTH = 37K 6 | } 7 | 8 | _stack_size = 2K; 9 | 10 | INCLUDE "targets/arm.ld" 11 | -------------------------------------------------------------------------------- /src/runtime/arch_amd64.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | const GOARCH = "amd64" 4 | 5 | // The bitness of the CPU (e.g. 8, 32, 64). 6 | const TargetBits = 64 7 | 8 | // Align a pointer. 9 | // Note that some amd64 instructions (like movaps) expect 16-byte aligned 10 | // memory, thus the result must be 16-byte aligned. 11 | func align(ptr uintptr) uintptr { 12 | return (ptr + 15) &^ 15 13 | } 14 | 15 | func getCurrentStackPointer() uintptr 16 | -------------------------------------------------------------------------------- /src/runtime/gc_globals_conservative.go: -------------------------------------------------------------------------------- 1 | // +build gc.conservative gc.extalloc 2 | // +build baremetal 3 | 4 | package runtime 5 | 6 | // markGlobals marks all globals, which are reachable by definition. 7 | // 8 | // This implementation marks all globals conservatively and assumes it can use 9 | // linker-defined symbols for the start and end of the .data section. 10 | func markGlobals() { 11 | markRoots(globalsStart, globalsEnd) 12 | } 13 | -------------------------------------------------------------------------------- /src/examples/blinky1/blinky1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // This is the most minimal blinky example and should run almost everywhere. 4 | 5 | import ( 6 | "machine" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | led := machine.LED 12 | led.Configure(machine.PinConfig{Mode: machine.PinOutput}) 13 | for { 14 | led.Low() 15 | time.Sleep(time.Millisecond * 500) 16 | 17 | led.High() 18 | time.Sleep(time.Millisecond * 500) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /targets/cortex-m-qemu.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7m-none-eabi", 4 | "build-tags": ["qemu", "lm3s6965"], 5 | "cflags": [ 6 | "--target=armv7m-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/lm3s6965.ld", 10 | "extra-files": [ 11 | "targets/cortex-m-qemu.s" 12 | ], 13 | "emulator": ["qemu-system-arm", "-machine", "lm3s6965evb", "-semihosting", "-nographic", "-kernel"] 14 | } 15 | -------------------------------------------------------------------------------- /src/device/riscv/riscv.go: -------------------------------------------------------------------------------- 1 | package riscv 2 | 3 | // Run the given assembly code. The code will be marked as having side effects, 4 | // as it doesn't produce output and thus would normally be eliminated by the 5 | // optimizer. 6 | func Asm(asm string) 7 | 8 | // ReadRegister returns the contents of the specified register. The register 9 | // must be a processor register, reachable with the "mov" instruction. 10 | func ReadRegister(name string) uintptr 11 | -------------------------------------------------------------------------------- /src/examples/gba-display/gba-display.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Draw a red square on the GameBoy Advance screen. 4 | 5 | import ( 6 | "image/color" 7 | "machine" 8 | ) 9 | 10 | var display = machine.Display 11 | 12 | func main() { 13 | display.Configure() 14 | 15 | for x := int16(30); x < 50; x++ { 16 | for y := int16(80); y < 100; y++ { 17 | display.SetPixel(x, y, color.RGBA{255, 0, 0, 255}) 18 | } 19 | } 20 | display.Display() 21 | } 22 | -------------------------------------------------------------------------------- /src/runtime/arch_tinygoriscv.go: -------------------------------------------------------------------------------- 1 | // +build tinygo.riscv 2 | 3 | package runtime 4 | 5 | import "device/riscv" 6 | 7 | const GOARCH = "arm" // riscv pretends to be arm 8 | 9 | // The bitness of the CPU (e.g. 8, 32, 64). 10 | const TargetBits = 32 11 | 12 | // Align on word boundary. 13 | func align(ptr uintptr) uintptr { 14 | return (ptr + 3) &^ 3 15 | } 16 | 17 | func getCurrentStackPointer() uintptr { 18 | return riscv.ReadRegister("sp") 19 | } 20 | -------------------------------------------------------------------------------- /cgo/libclang_config_llvm9.go: -------------------------------------------------------------------------------- 1 | // +build !byollvm 2 | // +build llvm9 3 | 4 | package cgo 5 | 6 | /* 7 | #cgo linux CFLAGS: -I/usr/lib/llvm-9/include 8 | #cgo darwin CFLAGS: -I/usr/local/opt/llvm@9/include 9 | #cgo freebsd CFLAGS: -I/usr/local/llvm9/include 10 | #cgo linux LDFLAGS: -L/usr/lib/llvm-9/lib -lclang 11 | #cgo darwin LDFLAGS: -L/usr/local/opt/llvm@9/lib -lclang -lffi 12 | #cgo freebsd LDFLAGS: -L/usr/local/llvm9/lib -lclang 13 | */ 14 | import "C" 15 | -------------------------------------------------------------------------------- /cgo/libclang_config.go: -------------------------------------------------------------------------------- 1 | // +build !byollvm 2 | // +build !llvm9 3 | 4 | package cgo 5 | 6 | /* 7 | #cgo linux CFLAGS: -I/usr/lib/llvm-10/include 8 | #cgo darwin CFLAGS: -I/usr/local/opt/llvm@10/include 9 | #cgo freebsd CFLAGS: -I/usr/local/llvm10/include 10 | #cgo linux LDFLAGS: -L/usr/lib/llvm-10/lib -lclang 11 | #cgo darwin LDFLAGS: -L/usr/local/opt/llvm@10/lib -lclang -lffi 12 | #cgo freebsd LDFLAGS: -L/usr/local/llvm10/lib -lclang 13 | */ 14 | import "C" 15 | -------------------------------------------------------------------------------- /targets/bluepill.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7m-none-eabi", 4 | "build-tags": ["bluepill", "stm32f103xx", "stm32"], 5 | "cflags": [ 6 | "--target=armv7m-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/stm32.ld", 10 | "extra-files": [ 11 | "src/device/stm32/stm32f103xx.s" 12 | ], 13 | "flash-method": "openocd", 14 | "openocd-interface": "stlink-v2", 15 | "openocd-target": "stm32f1x" 16 | } 17 | -------------------------------------------------------------------------------- /src/sync/pool.go: -------------------------------------------------------------------------------- 1 | package sync 2 | 3 | // Pool is a very simple implementation of sync.Pool. It does not actually 4 | // implement a pool. 5 | type Pool struct { 6 | New func() interface{} 7 | } 8 | 9 | // Get returns the value of calling Pool.New(). 10 | func (p *Pool) Get() interface{} { 11 | if p.New == nil { 12 | return nil 13 | } 14 | return p.New() 15 | } 16 | 17 | // Put drops the value put into the pool. 18 | func (p *Pool) Put(x interface{}) { 19 | } 20 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tinygo-org/tinygo 2 | 3 | go 1.11 4 | 5 | require ( 6 | github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 7 | github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf 8 | github.com/marcinbor85/gohex v0.0.0-20180128172054-7a43cd876e46 9 | go.bug.st/serial v1.0.0 10 | golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2 11 | google.golang.org/appengine v1.4.0 // indirect 12 | tinygo.org/x/go-llvm v0.0.0-20200401165421-8d120882fc7a 13 | ) 14 | -------------------------------------------------------------------------------- /targets/atmega328p.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["avr"], 3 | "llvm-target": "avr-atmel-none", 4 | "cpu": "atmega328p", 5 | "build-tags": ["atmega328p", "atmega", "avr5"], 6 | "cflags": [ 7 | "-mmcu=atmega328p" 8 | ], 9 | "ldflags": [ 10 | "-mmcu=avr5" 11 | ], 12 | "linkerscript": "src/device/avr/atmega328p.ld", 13 | "extra-files": [ 14 | "targets/avr.S", 15 | "src/device/avr/atmega328p.s" 16 | ], 17 | "emulator": ["simavr", "-m", "atmega328p", "-f", "16000000"] 18 | } 19 | -------------------------------------------------------------------------------- /transform/gc_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | 6 | "tinygo.org/x/go-llvm" 7 | ) 8 | 9 | func TestAddGlobalsBitmap(t *testing.T) { 10 | t.Parallel() 11 | testTransform(t, "testdata/gc-globals", func(mod llvm.Module) { 12 | AddGlobalsBitmap(mod) 13 | }) 14 | } 15 | 16 | func TestMakeGCStackSlots(t *testing.T) { 17 | t.Parallel() 18 | testTransform(t, "testdata/gc-stackslots", func(mod llvm.Module) { 19 | MakeGCStackSlots(mod) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /targets/stm32f4disco.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7em-none-eabi", 4 | "build-tags": ["stm32f4disco", "stm32f407", "stm32"], 5 | "cflags": [ 6 | "--target=armv7em-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/stm32f407.ld", 10 | "extra-files": [ 11 | "src/device/stm32/stm32f407.s" 12 | ], 13 | "flash-method": "openocd", 14 | "openocd-interface": "stlink-v2", 15 | "openocd-target": "stm32f4x" 16 | } 17 | -------------------------------------------------------------------------------- /src/runtime/runtime_fe310_qemu.go: -------------------------------------------------------------------------------- 1 | // +build fe310,qemu 2 | 3 | package runtime 4 | 5 | import ( 6 | "runtime/volatile" 7 | "unsafe" 8 | ) 9 | 10 | const tickMicros = 100 // CLINT.MTIME increments every 100ns 11 | 12 | // Special memory-mapped device to exit tests, created by SiFive. 13 | var testExit = (*volatile.Register32)(unsafe.Pointer(uintptr(0x100000))) 14 | 15 | var timestamp timeUnit 16 | 17 | func abort() { 18 | // Signal a successful exit. 19 | testExit.Set(0x5555) 20 | } 21 | -------------------------------------------------------------------------------- /targets/nrf51.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv6m-none-eabi", 4 | "build-tags": ["nrf51822", "nrf51", "nrf"], 5 | "cflags": [ 6 | "--target=armv6m-none-eabi", 7 | "-Qunused-arguments", 8 | "-DNRF51", 9 | "-I{root}/lib/CMSIS/CMSIS/Include", 10 | "-I{root}/lib/nrfx/mdk" 11 | ], 12 | "linkerscript": "targets/nrf51.ld", 13 | "extra-files": [ 14 | "lib/nrfx/mdk/system_nrf51.c", 15 | "src/device/nrf/nrf51.s" 16 | ], 17 | "openocd-target": "nrf51" 18 | } 19 | -------------------------------------------------------------------------------- /targets/nucleo-f103rb.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7m-none-eabi", 4 | "build-tags": ["nucleof103rb", "stm32f103xx", "stm32"], 5 | "cflags": [ 6 | "--target=armv7m-none-eabi", 7 | "-Qunused-arguments" 8 | ], 9 | "linkerscript": "targets/stm32f103rb.ld", 10 | "extra-files": [ 11 | "src/device/stm32/stm32f103xx.s" 12 | ], 13 | "flash-method": "openocd", 14 | "openocd-interface": "stlink-v2-1", 15 | "openocd-target": "stm32f1x" 16 | } 17 | -------------------------------------------------------------------------------- /targets/atmega2560.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["avr"], 3 | "llvm-target": "avr-atmel-none", 4 | "cpu": "atmega2560", 5 | "build-tags": ["atmega2560", "atmega"], 6 | "cflags": [ 7 | "-mmcu=atmega2560" 8 | ], 9 | "ldflags": [ 10 | "-mmcu=avr6", 11 | "-Wl,--defsym=_stack_size=512" 12 | ], 13 | "linkerscript": "src/device/avr/atmega2560.ld", 14 | "extra-files": [ 15 | "targets/avr.S", 16 | "src/device/avr/atmega2560.s" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /util_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package main 4 | 5 | // This file contains utility functions for Unix-like systems (e.g. Linux). 6 | 7 | import ( 8 | "os/exec" 9 | "syscall" 10 | ) 11 | 12 | // setCommandAsDaemon makes sure this command does not receive signals sent to 13 | // the parent. 14 | func setCommandAsDaemon(daemon *exec.Cmd) { 15 | // https://stackoverflow.com/a/35435038/559350 16 | daemon.SysProcAttr = &syscall.SysProcAttr{ 17 | Setpgid: true, 18 | Pgid: 0, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /transform/globals_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | 6 | "tinygo.org/x/go-llvm" 7 | ) 8 | 9 | func TestApplyFunctionSections(t *testing.T) { 10 | t.Parallel() 11 | testTransform(t, "testdata/globals-function-sections", func(mod llvm.Module) { 12 | ApplyFunctionSections(mod) 13 | }) 14 | } 15 | 16 | func TestNonConstGlobals(t *testing.T) { 17 | t.Parallel() 18 | testTransform(t, "testdata/globals-non-const", func(mod llvm.Module) { 19 | NonConstGlobals(mod) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /targets/nrf52.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7em-none-eabi", 4 | "build-tags": ["nrf52", "nrf"], 5 | "cflags": [ 6 | "--target=armv7em-none-eabi", 7 | "-mfloat-abi=soft", 8 | "-Qunused-arguments", 9 | "-DNRF52832_XXAA", 10 | "-I{root}/lib/CMSIS/CMSIS/Include", 11 | "-I{root}/lib/nrfx/mdk" 12 | ], 13 | "linkerscript": "targets/nrf52.ld", 14 | "extra-files": [ 15 | "lib/nrfx/mdk/system_nrf52.c", 16 | "src/device/nrf/nrf52.s" 17 | ], 18 | "openocd-target": "nrf51" 19 | } 20 | -------------------------------------------------------------------------------- /loader/ssa.go: -------------------------------------------------------------------------------- 1 | package loader 2 | 3 | import ( 4 | "golang.org/x/tools/go/ssa" 5 | ) 6 | 7 | // LoadSSA constructs the SSA form of the loaded packages. 8 | // 9 | // The program must already be parsed and type-checked with the .Parse() method. 10 | func (p *Program) LoadSSA() *ssa.Program { 11 | prog := ssa.NewProgram(p.fset, ssa.SanityCheckFunctions|ssa.BareInits|ssa.GlobalDebug) 12 | 13 | for _, pkg := range p.Sorted() { 14 | prog.CreatePackage(pkg.Pkg, pkg.Files, &pkg.Info, true) 15 | } 16 | 17 | return prog 18 | } 19 | -------------------------------------------------------------------------------- /src/examples/wasm/slices/wasm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strings" 5 | "syscall/js" 6 | ) 7 | 8 | func splitter(this js.Value, args []js.Value) interface{} { 9 | values := strings.Split(args[0].String(), ",") 10 | 11 | result := make([]interface{}, 0) 12 | for _, each := range values { 13 | result = append(result, each) 14 | } 15 | 16 | return js.ValueOf(result) 17 | } 18 | 19 | func main() { 20 | wait := make(chan struct{}, 0) 21 | js.Global().Set("splitter", js.FuncOf(splitter)) 22 | <-wait 23 | } 24 | -------------------------------------------------------------------------------- /src/runtime/scheduler_gba.S: -------------------------------------------------------------------------------- 1 | .section .text.tinygo_scanCurrentStack 2 | .global tinygo_scanCurrentStack 3 | .type tinygo_scanCurrentStack, %function 4 | tinygo_scanCurrentStack: 5 | // Save callee-saved registers onto the stack. 6 | mov r0, r8 7 | mov r1, r9 8 | mov r2, r10 9 | mov r3, r11 10 | push {r0-r3, lr} 11 | push {r4-r7} 12 | 13 | // Scan the stack. 14 | mov r0, sp 15 | bl tinygo_scanstack 16 | 17 | // Restore stack state and return. 18 | add sp, #32 19 | pop {pc} 20 | -------------------------------------------------------------------------------- /testdata/string.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func testRangeString() { 4 | for i, c := range "abcü¢€𐍈°x" { 5 | println(i, c) 6 | } 7 | } 8 | 9 | func testStringToRunes() { 10 | var s = "abcü¢€𐍈°x" 11 | for i, c := range []rune(s) { 12 | println(i, c) 13 | } 14 | } 15 | 16 | func testRunesToString(r []rune) { 17 | println("string from runes:", string(r)) 18 | } 19 | 20 | func main() { 21 | testRangeString() 22 | testStringToRunes() 23 | testRunesToString([]rune{97, 98, 99, 252, 162, 8364, 66376, 176, 120}) 24 | } 25 | -------------------------------------------------------------------------------- /src/internal/task/task.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | // Task is a state of goroutine for scheduling purposes. 8 | type Task struct { 9 | // Next is a field which can be used to make a linked list of tasks. 10 | Next *Task 11 | 12 | // Ptr is a field which can be used for storing a pointer. 13 | Ptr unsafe.Pointer 14 | 15 | // Data is a field which can be used for storing state information. 16 | Data uint 17 | 18 | // state is the underlying running state of the task. 19 | state state 20 | } 21 | -------------------------------------------------------------------------------- /targets/nrf52840.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["cortex-m"], 3 | "llvm-target": "armv7em-none-eabi", 4 | "build-tags": ["nrf52840", "nrf"], 5 | "cflags": [ 6 | "--target=armv7em-none-eabi", 7 | "-mfloat-abi=soft", 8 | "-Qunused-arguments", 9 | "-DNRF52840_XXAA", 10 | "-I{root}/lib/CMSIS/CMSIS/Include", 11 | "-I{root}/lib/nrfx/mdk" 12 | ], 13 | "linkerscript": "targets/nrf52840.ld", 14 | "extra-files": [ 15 | "lib/nrfx/mdk/system_nrf52840.c", 16 | "src/device/nrf/nrf52840.s" 17 | ], 18 | "openocd-target": "nrf51" 19 | } 20 | -------------------------------------------------------------------------------- /targets/riscv-qemu.ld: -------------------------------------------------------------------------------- 1 | 2 | /* Memory map: 3 | * https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c 4 | * RAM and flash are set to 1MB each. That should be enough for the foreseeable 5 | * future. QEMU does not seem to limit the flash/RAM size and in fact doesn't 6 | * seem to differentiate between it. 7 | */ 8 | MEMORY 9 | { 10 | FLASH_TEXT (rw) : ORIGIN = 0x80000000, LENGTH = 0x100000 11 | RAM (xrw) : ORIGIN = 0x80100000, LENGTH = 0x100000 12 | } 13 | 14 | _stack_size = 2K; 15 | 16 | INCLUDE "targets/riscv.ld" 17 | -------------------------------------------------------------------------------- /compileopts/target_test.go: -------------------------------------------------------------------------------- 1 | package compileopts 2 | 3 | import "testing" 4 | 5 | func TestLoadTarget(t *testing.T) { 6 | _, err := LoadTarget("arduino") 7 | if err != nil { 8 | t.Error("LoadTarget test failed:", err) 9 | } 10 | 11 | _, err = LoadTarget("notexist") 12 | if err == nil { 13 | t.Error("LoadTarget should have failed with non existing target") 14 | } 15 | 16 | if err.Error() != "expected a full LLVM target or a custom target in -target flag" { 17 | t.Error("LoadTarget failed for wrong reason:", err) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /testdata/slice.txt: -------------------------------------------------------------------------------- 1 | foo is nil? false false 2 | foo: len=4 cap=4 data: 1 2 4 5 3 | bar: len=3 cap=5 data: 0 0 0 4 | foo[1:2]: len=1 cap=3 data: 2 5 | sum foo: 12 6 | copy foo -> bar: 3 7 | bar: len=3 cap=5 data: 1 2 4 8 | slice is nil? true true 9 | grow: len=0 cap=0 data: 10 | grow: len=1 cap=1 data: 42 11 | grow: len=3 cap=4 data: 42 -1 -2 12 | grow: len=7 cap=8 data: 42 -1 -2 1 2 4 5 13 | grow: len=7 cap=8 data: 42 -1 -2 1 2 4 5 14 | grow: len=14 cap=16 data: 42 -1 -2 1 2 4 5 42 -1 -2 1 2 4 5 15 | bytes: len=6 cap=6 data: 1 2 3 102 111 111 16 | -------------------------------------------------------------------------------- /src/examples/systick/systick.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "device/arm" 5 | "machine" 6 | ) 7 | 8 | func main() { 9 | machine.LED.Configure(machine.PinConfig{Mode: machine.PinOutput}) 10 | 11 | // timer fires 10 times per second 12 | arm.SetupSystemTimer(machine.CPUFrequency() / 10) 13 | 14 | for { 15 | } 16 | } 17 | 18 | var led_state bool 19 | 20 | //export SysTick_Handler 21 | func timer_isr() { 22 | if led_state { 23 | machine.LED.Low() 24 | } else { 25 | machine.LED.High() 26 | } 27 | led_state = !led_state 28 | } 29 | -------------------------------------------------------------------------------- /src/machine/board_arduino.go: -------------------------------------------------------------------------------- 1 | // +build arduino 2 | 3 | package machine 4 | 5 | // Return the current CPU frequency in hertz. 6 | func CPUFrequency() uint32 { 7 | return 16000000 8 | } 9 | 10 | // LED on the Arduino 11 | const LED Pin = 13 12 | 13 | // ADC on the Arduino 14 | const ( 15 | ADC0 Pin = 0 16 | ADC1 Pin = 1 17 | ADC2 Pin = 2 18 | ADC3 Pin = 3 19 | ADC4 Pin = 4 // Used by TWI for SDA 20 | ADC5 Pin = 5 // Used by TWI for SCL 21 | ) 22 | 23 | // UART pins 24 | const ( 25 | UART_TX_PIN Pin = 1 26 | UART_RX_PIN Pin = 0 27 | ) 28 | -------------------------------------------------------------------------------- /src/examples/wasm/slices/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Go WebAssembly 8 | 9 | 10 | 11 | 12 | 13 | 14 |

WebAssembly

15 |

type values separated by comma, using WebAssembly:

16 | ==
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/machine/board_arduino_nano.go: -------------------------------------------------------------------------------- 1 | // +build arduino_nano 2 | 3 | package machine 4 | 5 | // Return the current CPU frequency in hertz. 6 | func CPUFrequency() uint32 { 7 | return 16000000 8 | } 9 | 10 | // LED on the Arduino 11 | const LED Pin = 13 12 | 13 | // ADC on the Arduino 14 | const ( 15 | ADC0 Pin = 0 16 | ADC1 Pin = 1 17 | ADC2 Pin = 2 18 | ADC3 Pin = 3 19 | ADC4 Pin = 4 // Used by TWI for SDA 20 | ADC5 Pin = 5 // Used by TWI for SCL 21 | ) 22 | 23 | // UART pins 24 | const ( 25 | UART_TX_PIN Pin = 1 26 | UART_RX_PIN Pin = 0 27 | ) 28 | -------------------------------------------------------------------------------- /src/examples/wasm/invoke/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Go WebAssembly 8 | 9 | 10 | 11 | 12 | 13 | 14 |

WebAssembly

15 |

Edit on either side to mimic values, using WebAssembly:

16 | == 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /transform/interrupt_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | 6 | "tinygo.org/x/go-llvm" 7 | ) 8 | 9 | func TestInterruptLowering(t *testing.T) { 10 | t.Parallel() 11 | for _, subtest := range []string{"avr", "cortexm"} { 12 | t.Run(subtest, func(t *testing.T) { 13 | testTransform(t, "testdata/interrupt-"+subtest, func(mod llvm.Module) { 14 | errs := LowerInterrupts(mod) 15 | if len(errs) != 0 { 16 | t.Fail() 17 | for _, err := range errs { 18 | t.Error(err) 19 | } 20 | } 21 | }) 22 | }) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /transform/maps_test.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "testing" 5 | 6 | "tinygo.org/x/go-llvm" 7 | ) 8 | 9 | func TestOptimizeMaps(t *testing.T) { 10 | t.Parallel() 11 | testTransform(t, "testdata/maps", func(mod llvm.Module) { 12 | // Run optimization pass. 13 | OptimizeMaps(mod) 14 | 15 | // Run an optimization pass, to clean up the result. 16 | // This shows that all code related to the map is really eliminated. 17 | pm := llvm.NewPassManager() 18 | defer pm.Dispose() 19 | pm.AddDeadStoreEliminationPass() 20 | pm.Run(mod) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /src/machine/machine_atmega1284p.go: -------------------------------------------------------------------------------- 1 | // +build avr,atmega1284p 2 | 3 | package machine 4 | 5 | import ( 6 | "device/avr" 7 | "runtime/volatile" 8 | ) 9 | 10 | const irq_USART0_RX = avr.IRQ_USART0_RX 11 | 12 | // Return the current CPU frequency in hertz. 13 | func CPUFrequency() uint32 { 14 | return 20000000 15 | } 16 | 17 | func (p Pin) getPortMask() (*volatile.Register8, uint8) { 18 | if p < 8 { 19 | return avr.PORTD, 1 << uint8(p) 20 | } else if p < 14 { 21 | return avr.PORTB, 1 << uint8(p-8) 22 | } else { 23 | return avr.PORTC, 1 << uint8(p-14) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /testdata/stdlib.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | func main() { 11 | // package os, fmt 12 | fmt.Println("stdin: ", os.Stdin.Fd()) 13 | fmt.Println("stdout:", os.Stdout.Fd()) 14 | fmt.Println("stderr:", os.Stderr.Fd()) 15 | 16 | // package math/rand 17 | fmt.Println("pseudorandom number:", rand.Int31()) 18 | 19 | // package strings 20 | fmt.Println("strings.IndexByte:", strings.IndexByte("asdf", 'd')) 21 | fmt.Println("strings.Replace:", strings.Replace("An example string", " ", "-", -1)) 22 | } 23 | -------------------------------------------------------------------------------- /src/examples/systick/README.md: -------------------------------------------------------------------------------- 1 | # TinyGo ARM SysTick example 2 | 3 | This example uses the ARM System Timer to blink an LED. The timer fires 4 | an interrupt 10 times per second. The interrupt handler toggles the LED on 5 | and off. 6 | 7 | Many ARM-based chips have this timer feature. If you run the example and the 8 | LED blinks, then you have one. 9 | 10 | The System Timer runs from a cycle counter. The more cycles, the slower the 11 | LED will blink. This counter is 24 bits wide, which places an upper bound on 12 | the number of cycles, and the slowness of the blinking. 13 | -------------------------------------------------------------------------------- /src/os/proc.go: -------------------------------------------------------------------------------- 1 | // Package os implements a subset of the Go "os" package. See 2 | // https://godoc.org/os for details. 3 | // 4 | // Note that the current implementation is blocking. This limitation should be 5 | // removed in a future version. 6 | package os 7 | 8 | import ( 9 | "syscall" 10 | ) 11 | 12 | // Exit causes the current program to exit with the given status code. 13 | // Conventionally, code zero indicates success, non-zero an error. 14 | // The program terminates immediately; deferred functions are not run. 15 | func Exit(code int) { 16 | syscall.Exit(code) 17 | } 18 | -------------------------------------------------------------------------------- /targets/wasm.json: -------------------------------------------------------------------------------- 1 | { 2 | "llvm-target": "wasm32--wasi", 3 | "build-tags": ["js", "wasm"], 4 | "goos": "js", 5 | "goarch": "wasm", 6 | "compiler": "clang", 7 | "linker": "wasm-ld", 8 | "cflags": [ 9 | "--target=wasm32--wasi", 10 | "--sysroot={root}/lib/wasi-libc/sysroot", 11 | "-Oz" 12 | ], 13 | "ldflags": [ 14 | "--allow-undefined", 15 | "--no-threads", 16 | "--stack-first", 17 | "--export-all", 18 | "{root}/lib/wasi-libc/sysroot/lib/wasm32-wasi/libc.a" 19 | ], 20 | "emulator": ["node", "targets/wasm_exec.js"] 21 | } 22 | -------------------------------------------------------------------------------- /tests/tinygotest/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" // This is the tinygo testing package 5 | ) 6 | 7 | func TestFail1(t *testing.T) { 8 | t.Error("TestFail1 failed because of stuff and things") 9 | } 10 | 11 | func TestFail2(t *testing.T) { 12 | t.Fatalf("TestFail2 failed for %v ", "reasons") 13 | } 14 | 15 | func TestFail3(t *testing.T) { 16 | t.Fail() 17 | t.Logf("TestFail3 failed for %v ", "reasons") 18 | } 19 | 20 | func TestPass(t *testing.T) { 21 | t.Log("TestPass passed") 22 | } 23 | 24 | func BenchmarkNotImplemented(b *testing.B) { 25 | } 26 | -------------------------------------------------------------------------------- /src/examples/wasm/callback/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Go WebAssembly 8 | 9 | 10 | 11 | 12 | 13 | 14 |

WebAssembly

15 |

Add two numbers, using WebAssembly:

16 | + = 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/examples/wasm/export/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Go WebAssembly 8 | 9 | 10 | 11 | 12 | 13 | 14 |

WebAssembly

15 |

Add two numbers, using WebAssembly:

16 | + = 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/examples/wasm/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "strings" 7 | ) 8 | 9 | const dir = "./html" 10 | 11 | func main() { 12 | fs := http.FileServer(http.Dir(dir)) 13 | log.Print("Serving " + dir + " on http://localhost:8080") 14 | http.ListenAndServe(":8080", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 15 | resp.Header().Add("Cache-Control", "no-cache") 16 | if strings.HasSuffix(req.URL.Path, ".wasm") { 17 | resp.Header().Set("content-type", "application/wasm") 18 | } 19 | fs.ServeHTTP(resp, req) 20 | })) 21 | } 22 | -------------------------------------------------------------------------------- /interp/testdata/slice-copy.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 2 | target triple = "x86_64--linux" 3 | 4 | declare void @runtime.printuint8(i8) local_unnamed_addr 5 | 6 | declare void @runtime.printint16(i16) local_unnamed_addr 7 | 8 | define void @runtime.initAll() unnamed_addr { 9 | entry: 10 | ret void 11 | } 12 | 13 | define void @main() unnamed_addr { 14 | entry: 15 | call void @runtime.printuint8(i8 3) 16 | call void @runtime.printuint8(i8 3) 17 | call void @runtime.printint16(i16 5) 18 | call void @runtime.printint16(i16 5) 19 | ret void 20 | } 21 | -------------------------------------------------------------------------------- /testdata/interface.txt: -------------------------------------------------------------------------------- 1 | thing: foo 2 | Thing.Print: foo 3 | is int: 5 4 | is byte: 120 5 | is string: foo 6 | is Foo: 18 7 | is Thing: foo 8 | is *Thing: foo 9 | is *Thing: foo 10 | is struct{n int} 11 | is struct{n int `foo:"bar"`} 12 | is Doubler: 6 13 | is Tuple: 1 7 11 13 14 | Array len: 4 15 | is Tuple: 1 7 11 13 16 | ArrayStruct.Print: 4 3 17 | is Tuple: 0 8 16 24 18 | SmallPair.Print: 3 5 19 | Stringer.String(): foo 20 | Stringer.(*Thing).String(): foo 21 | s has String() method: foo 22 | nested switch: true 23 | non-blocking call on sometimes-blocking interface 24 | slept 1ms 25 | slept 1ms 26 | -------------------------------------------------------------------------------- /src/examples/button/button.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "machine" 5 | "time" 6 | ) 7 | 8 | // This example assumes that the button is connected to pin 8. Change the value 9 | // below to use a different pin. 10 | const ( 11 | led = machine.LED 12 | button = machine.Pin(8) 13 | ) 14 | 15 | func main() { 16 | led.Configure(machine.PinConfig{Mode: machine.PinOutput}) 17 | button.Configure(machine.PinConfig{Mode: machine.PinInput}) 18 | 19 | for { 20 | if button.Get() { 21 | led.Low() 22 | } else { 23 | led.High() 24 | } 25 | 26 | time.Sleep(time.Millisecond * 10) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/examples/wasm/export/wasm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strconv" 5 | "syscall/js" 6 | ) 7 | 8 | func main() { 9 | } 10 | 11 | //export add 12 | func add(a, b int) int { 13 | return a + b 14 | } 15 | 16 | //export update 17 | func update() { 18 | document := js.Global().Get("document") 19 | aStr := document.Call("getElementById", "a").Get("value").String() 20 | bStr := document.Call("getElementById", "b").Get("value").String() 21 | a, _ := strconv.Atoi(aStr) 22 | b, _ := strconv.Atoi(bStr) 23 | result := add(a, b) 24 | document.Call("getElementById", "result").Set("value", result) 25 | } 26 | -------------------------------------------------------------------------------- /cgo/testdata/basic.out.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "unsafe" 4 | 5 | var _ unsafe.Pointer 6 | 7 | type C.int16_t = int16 8 | type C.int32_t = int32 9 | type C.int64_t = int64 10 | type C.int8_t = int8 11 | type C.uint16_t = uint16 12 | type C.uint32_t = uint32 13 | type C.uint64_t = uint64 14 | type C.uint8_t = uint8 15 | type C.uintptr_t = uintptr 16 | type C.char uint8 17 | type C.int int32 18 | type C.long int32 19 | type C.longlong int64 20 | type C.schar int8 21 | type C.short int16 22 | type C.uchar uint8 23 | type C.uint uint32 24 | type C.ulong uint32 25 | type C.ulonglong uint64 26 | type C.ushort uint16 27 | -------------------------------------------------------------------------------- /targets/digispark.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["avr"], 3 | "llvm-target": "avr-atmel-none", 4 | "cpu": "attiny85", 5 | "build-tags": ["digispark", "attiny85", "attiny", "avr2", "avr25"], 6 | "cflags": [ 7 | "-mmcu=attiny85" 8 | ], 9 | "ldflags": [ 10 | "-mmcu=avr25", 11 | "-Wl,--defsym=_bootloader_size=2180", 12 | "-Wl,--defsym=_stack_size=128" 13 | ], 14 | "linkerscript": "src/device/avr/attiny85.ld", 15 | "extra-files": [ 16 | "targets/avr.S", 17 | "src/device/avr/attiny85.s" 18 | ], 19 | "flash-command": "micronucleus --run {hex}", 20 | "emulator": ["simavr", "-m", "attiny85", "-f", "16000000"] 21 | } 22 | -------------------------------------------------------------------------------- /src/runtime/scheduler_any.go: -------------------------------------------------------------------------------- 1 | // +build !scheduler.none 2 | 3 | package runtime 4 | 5 | import "internal/task" 6 | 7 | // Pause the current task for a given time. 8 | //go:linkname sleep time.Sleep 9 | func sleep(duration int64) { 10 | addSleepTask(task.Current(), duration) 11 | task.Pause() 12 | } 13 | 14 | // run is called by the program entry point to execute the go program. 15 | // With a scheduler, init and the main function are invoked in a goroutine before starting the scheduler. 16 | func run() { 17 | initHeap() 18 | go func() { 19 | initAll() 20 | postinit() 21 | callMain() 22 | }() 23 | scheduler() 24 | } 25 | -------------------------------------------------------------------------------- /targets/atmega1284p.json: -------------------------------------------------------------------------------- 1 | { 2 | "inherits": ["avr"], 3 | "llvm-target": "avr-atmel-none", 4 | "cpu": "atmega1284p", 5 | "build-tags": ["atmega1284p", "atmega"], 6 | "cflags": [ 7 | "-mmcu=atmega1284p" 8 | ], 9 | "ldflags": [ 10 | "-mmcu=avr51", 11 | "-Wl,--defsym=_bootloader_size=0", 12 | "-Wl,--defsym=_stack_size=512" 13 | ], 14 | "linkerscript": "src/device/avr/atmega1284p.ld", 15 | "extra-files": [ 16 | "targets/avr.S", 17 | "src/device/avr/atmega1284p.s" 18 | ], 19 | "emulator": ["simavr", "-m", "atmega1284p", "-f", "20000000"] 20 | } 21 | -------------------------------------------------------------------------------- /src/examples/i2s/i2s.go: -------------------------------------------------------------------------------- 1 | // Example using the i2s hardware interface on the Adafruit Circuit Playground Express 2 | // to read data from the onboard MEMS microphone. 3 | // 4 | package main 5 | 6 | import ( 7 | "machine" 8 | ) 9 | 10 | func main() { 11 | machine.I2S0.Configure(machine.I2SConfig{ 12 | Mode: machine.I2SModePDM, 13 | ClockSource: machine.I2SClockSourceExternal, 14 | Stereo: true, 15 | }) 16 | 17 | data := make([]uint32, 64) 18 | 19 | for { 20 | // get the next group of samples 21 | machine.I2S0.Read(data) 22 | 23 | println("data", data[0], data[1], data[2], data[4], "...") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/testing/benchmark.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | // 5 | // This file has been modified for use by the TinyGo compiler. 6 | 7 | package testing 8 | 9 | // B is a type passed to Benchmark functions to manage benchmark timing and to 10 | // specify the number of iterations to run. 11 | // 12 | // TODO: Implement benchmarks. This struct allows test files containing 13 | // benchmarks to compile and run, but will not run the benchmarks themselves. 14 | type B struct { 15 | common 16 | N int 17 | } 18 | -------------------------------------------------------------------------------- /cgo/testdata/flags.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | // this name doesn't exist 5 | #cgo NOFLAGS: -foo 6 | 7 | // unknown flag 8 | #cgo CFLAGS: -fdoes-not-exist -DNOTDEFINED 9 | 10 | #cgo CFLAGS: -DFOO 11 | 12 | #cgo CFLAGS: -Iinclude 13 | #include "foo.h" 14 | 15 | #if defined(FOO) 16 | #define BAR 3 17 | #else 18 | #define BAR 5 19 | #endif 20 | 21 | #if defined(NOTDEFINED) 22 | #warning flag must not be defined 23 | #endif 24 | 25 | // Check Compiler flags 26 | #cgo LDFLAGS: -lc 27 | 28 | // This flag is not valid ldflags 29 | #cgo LDFLAGS: -does-not-exists 30 | 31 | */ 32 | import "C" 33 | 34 | var ( 35 | _ = C.BAR 36 | _ = C.FOO_H 37 | ) 38 | -------------------------------------------------------------------------------- /compileopts/options.go: -------------------------------------------------------------------------------- 1 | package compileopts 2 | 3 | // Options contains extra options to give to the compiler. These options are 4 | // usually passed from the command line. 5 | type Options struct { 6 | Target string 7 | Opt string 8 | GC string 9 | PanicStrategy string 10 | Scheduler string 11 | PrintIR bool 12 | DumpSSA bool 13 | VerifyIR bool 14 | Debug bool 15 | PrintSizes string 16 | CFlags []string 17 | LDFlags []string 18 | Tags string 19 | WasmAbi string 20 | HeapSize int64 21 | TestConfig TestConfig 22 | Programmer string 23 | } 24 | -------------------------------------------------------------------------------- /src/syscall/str.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package syscall 6 | 7 | func itoa(val int) string { // do it here rather than with fmt to avoid dependency 8 | if val < 0 { 9 | return "-" + uitoa(uint(-val)) 10 | } 11 | return uitoa(uint(val)) 12 | } 13 | 14 | func uitoa(val uint) string { 15 | var buf [32]byte // big enough for int64 16 | i := len(buf) - 1 17 | for val >= 10 { 18 | buf[i] = byte(val%10 + '0') 19 | i-- 20 | val /= 10 21 | } 22 | buf[i] = byte(val + '0') 23 | return string(buf[i:]) 24 | } 25 | -------------------------------------------------------------------------------- /cgo/testdata/const.out.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "unsafe" 4 | 5 | var _ unsafe.Pointer 6 | 7 | const C.bar = C.foo 8 | const C.foo = 3 9 | 10 | type C.int16_t = int16 11 | type C.int32_t = int32 12 | type C.int64_t = int64 13 | type C.int8_t = int8 14 | type C.uint16_t = uint16 15 | type C.uint32_t = uint32 16 | type C.uint64_t = uint64 17 | type C.uint8_t = uint8 18 | type C.uintptr_t = uintptr 19 | type C.char uint8 20 | type C.int int32 21 | type C.long int32 22 | type C.longlong int64 23 | type C.schar int8 24 | type C.short int16 25 | type C.uchar uint8 26 | type C.uint uint32 27 | type C.ulong uint32 28 | type C.ulonglong uint64 29 | type C.ushort uint16 30 | -------------------------------------------------------------------------------- /testdata/alias.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type x struct{} 4 | 5 | func (x x) name() string { 6 | return "x" 7 | } 8 | 9 | type y = x 10 | 11 | type a struct { 12 | n int 13 | } 14 | 15 | func (a a) fruit() string { 16 | return "apple" 17 | } 18 | 19 | type b = a 20 | 21 | type fruit interface { 22 | fruit() string 23 | } 24 | 25 | type f = fruit 26 | 27 | func main() { 28 | // test a basic alias 29 | println(y{}.name()) 30 | 31 | // test using a type alias value as an interface 32 | var v f = b{} 33 | println(v.fruit()) 34 | 35 | // test comparing an alias interface with the referred-to type 36 | println(a{} == b{}) 37 | println(a{2} == b{3}) 38 | } 39 | -------------------------------------------------------------------------------- /src/examples/adc/adc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "machine" 5 | "time" 6 | ) 7 | 8 | // This example assumes that an analog sensor such as a rotary dial is connected to pin ADC0. 9 | // When the dial is turned past the midway point, the built-in LED will light up. 10 | 11 | func main() { 12 | machine.InitADC() 13 | 14 | led := machine.LED 15 | led.Configure(machine.PinConfig{Mode: machine.PinOutput}) 16 | 17 | sensor := machine.ADC{machine.ADC2} 18 | sensor.Configure() 19 | 20 | for { 21 | val := sensor.Get() 22 | if val < 0x8000 { 23 | led.Low() 24 | } else { 25 | led.High() 26 | } 27 | time.Sleep(time.Millisecond * 100) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This is the official list of TinyGo authors for copyright purposes. 2 | # 3 | # This file is not actively maintained. 4 | # To be included, send a change adding the individual or 5 | # company who owns a contribution's copyright. 6 | # 7 | # Names should be added to this file as one of 8 | # Organization's name 9 | # Individual's name 10 | # Individual's name 11 | # 12 | # Please keep the list sorted. 13 | 14 | Ayke van Laethem 15 | Daniel Esteban 16 | Loon, LLC. 17 | Ron Evans 18 | Jaden Weiss 19 | -------------------------------------------------------------------------------- /src/examples/wasm/callback/wasm.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const WASM_URL = 'wasm.wasm'; 4 | 5 | var wasm; 6 | 7 | function init() { 8 | const go = new Go(); 9 | if ('instantiateStreaming' in WebAssembly) { 10 | WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) { 11 | wasm = obj.instance; 12 | go.run(wasm); 13 | }) 14 | } else { 15 | fetch(WASM_URL).then(resp => 16 | resp.arrayBuffer() 17 | ).then(bytes => 18 | WebAssembly.instantiate(bytes, go.importObject).then(function (obj) { 19 | wasm = obj.instance; 20 | go.run(wasm); 21 | }) 22 | ) 23 | } 24 | } 25 | 26 | init(); 27 | -------------------------------------------------------------------------------- /src/machine/board_fe310.go: -------------------------------------------------------------------------------- 1 | // +build hifive1b 2 | 3 | package machine 4 | 5 | const ( 6 | P00 Pin = 0 7 | P01 Pin = 1 8 | P02 Pin = 2 9 | P03 Pin = 3 10 | P04 Pin = 4 11 | P05 Pin = 5 12 | P06 Pin = 6 13 | P07 Pin = 7 14 | P08 Pin = 8 15 | P09 Pin = 9 16 | P10 Pin = 10 17 | P11 Pin = 11 18 | P12 Pin = 12 19 | P13 Pin = 13 20 | P14 Pin = 14 21 | P15 Pin = 15 22 | P16 Pin = 16 23 | P17 Pin = 17 24 | P18 Pin = 18 25 | P19 Pin = 19 26 | P20 Pin = 20 27 | P21 Pin = 21 28 | P22 Pin = 22 29 | P23 Pin = 23 30 | P24 Pin = 24 31 | P25 Pin = 25 32 | P26 Pin = 26 33 | P27 Pin = 27 34 | P28 Pin = 28 35 | P29 Pin = 29 36 | P30 Pin = 30 37 | P31 Pin = 31 38 | ) 39 | -------------------------------------------------------------------------------- /src/runtime/scheduler_none.go: -------------------------------------------------------------------------------- 1 | // +build scheduler.none 2 | 3 | package runtime 4 | 5 | //go:linkname sleep time.Sleep 6 | func sleep(duration int64) { 7 | sleepTicks(timeUnit(duration / tickMicros)) 8 | } 9 | 10 | // getSystemStackPointer returns the current stack pointer of the system stack. 11 | // This is always the current stack pointer. 12 | func getSystemStackPointer() uintptr { 13 | return getCurrentStackPointer() 14 | } 15 | 16 | // run is called by the program entry point to execute the go program. 17 | // With the "none" scheduler, init and the main function are invoked directly. 18 | func run() { 19 | initHeap() 20 | initAll() 21 | postinit() 22 | callMain() 23 | } 24 | -------------------------------------------------------------------------------- /src/runtime/interrupt/interrupt_sifive.go: -------------------------------------------------------------------------------- 1 | // +build sifive 2 | 3 | package interrupt 4 | 5 | import "device/sifive" 6 | 7 | // Enable enables this interrupt. Right after calling this function, the 8 | // interrupt may be invoked if it was already pending. 9 | func (irq Interrupt) Enable() { 10 | sifive.PLIC.ENABLE[irq.num/32].SetBits(1 << (uint(irq.num) % 32)) 11 | } 12 | 13 | // SetPriority sets the interrupt priority for this interrupt. A higher priority 14 | // number means a higher priority (unlike Cortex-M). Priority 0 effectively 15 | // disables the interrupt. 16 | func (irq Interrupt) SetPriority(priority uint8) { 17 | sifive.PLIC.PRIORITY[irq.num].Set(uint32(priority)) 18 | } 19 | -------------------------------------------------------------------------------- /src/examples/wasm/callback/wasm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strconv" 5 | "syscall/js" 6 | ) 7 | 8 | var a, b int 9 | 10 | func main() { 11 | document := js.Global().Get("document") 12 | document.Call("getElementById", "a").Set("oninput", updater(&a)) 13 | document.Call("getElementById", "b").Set("oninput", updater(&b)) 14 | update() 15 | } 16 | 17 | func updater(n *int) js.Func { 18 | return js.FuncOf(func(this js.Value, args []js.Value) interface{} { 19 | *n, _ = strconv.Atoi(this.Get("value").String()) 20 | update() 21 | return nil 22 | }) 23 | } 24 | 25 | func update() { 26 | js.Global().Get("document").Call("getElementById", "result").Set("value", a+b) 27 | } 28 | -------------------------------------------------------------------------------- /src/runtime/atomic.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | // This file contains implementations for the sync/atomic package. 4 | 5 | // All implementations assume there are no goroutines, threads or interrupts. 6 | 7 | //go:linkname loadUint64 sync/atomic.LoadUint64 8 | func loadUint64(addr *uint64) uint64 { 9 | return *addr 10 | } 11 | 12 | //go:linkname storeUint32 sync/atomic.StoreUint32 13 | func storeUint32(addr *uint32, val uint32) { 14 | *addr = val 15 | } 16 | 17 | //go:linkname compareAndSwapUint64 sync/atomic.CompareAndSwapUint64 18 | func compareAndSwapUint64(addr *uint64, old, new uint64) bool { 19 | if *addr == old { 20 | *addr = new 21 | return true 22 | } 23 | return false 24 | } 25 | -------------------------------------------------------------------------------- /targets/cortex-m.json: -------------------------------------------------------------------------------- 1 | { 2 | "build-tags": ["cortexm", "baremetal", "linux", "arm"], 3 | "goos": "linux", 4 | "goarch": "arm", 5 | "compiler": "clang", 6 | "gc": "conservative", 7 | "scheduler": "tasks", 8 | "linker": "ld.lld", 9 | "rtlib": "compiler-rt", 10 | "libc": "picolibc", 11 | "cflags": [ 12 | "-Oz", 13 | "-mthumb", 14 | "-Werror", 15 | "-fshort-enums", 16 | "-fomit-frame-pointer", 17 | "-fno-exceptions", "-fno-unwind-tables", 18 | "-ffunction-sections", "-fdata-sections" 19 | ], 20 | "ldflags": [ 21 | "--gc-sections" 22 | ], 23 | "extra-files": [ 24 | "src/device/arm/cortexm.s", 25 | "src/runtime/scheduler_cortexm.S" 26 | ], 27 | "gdb": "gdb-multiarch" 28 | } 29 | -------------------------------------------------------------------------------- /src/runtime/arch_wasm.go: -------------------------------------------------------------------------------- 1 | // +build wasm 2 | 3 | package runtime 4 | 5 | import ( 6 | "unsafe" 7 | ) 8 | 9 | const GOARCH = "wasm" 10 | 11 | // The bitness of the CPU (e.g. 8, 32, 64). 12 | const TargetBits = 32 13 | 14 | //go:extern __heap_base 15 | var heapStartSymbol [0]byte 16 | 17 | //export llvm.wasm.memory.size.i32 18 | func wasm_memory_size(index int32) int32 19 | 20 | var ( 21 | heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) 22 | heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize) 23 | ) 24 | 25 | const wasmPageSize = 64 * 1024 26 | 27 | // Align on word boundary. 28 | func align(ptr uintptr) uintptr { 29 | return (ptr + 3) &^ 3 30 | } 31 | 32 | func getCurrentStackPointer() uintptr 33 | -------------------------------------------------------------------------------- /src/device/avr/avr.go: -------------------------------------------------------------------------------- 1 | package avr 2 | 3 | // Run the given assembly code. The code will be marked as having side effects, 4 | // as it doesn't produce output and thus would normally be eliminated by the 5 | // optimizer. 6 | func Asm(asm string) 7 | 8 | // Run the given inline assembly. The code will be marked as having side 9 | // effects, as it would otherwise be optimized away. The inline assembly string 10 | // recognizes template values in the form {name}, like so: 11 | // 12 | // avr.AsmFull( 13 | // "str {value}, {result}", 14 | // map[string]interface{}{ 15 | // "value": 1 16 | // "result": &dest, 17 | // }) 18 | func AsmFull(asm string, regs map[string]interface{}) 19 | -------------------------------------------------------------------------------- /testdata/binop.txt: -------------------------------------------------------------------------------- 1 | string equality 2 | true 3 | false 4 | false 5 | true 6 | string inequality 7 | false 8 | true 9 | false 10 | true 11 | false 12 | true 13 | false 14 | true 15 | false 16 | true 17 | false 18 | true 19 | true 20 | false 21 | false 22 | true 23 | array equality 24 | true 25 | false 26 | false 27 | false 28 | false 29 | true 30 | struct equality 31 | true 32 | false 33 | false 34 | false 35 | false 36 | true 37 | true 38 | true 39 | blank fields in structs 40 | true 41 | false 42 | true 43 | false 44 | complex numbers 45 | true 46 | false 47 | false 48 | false 49 | true 50 | true 51 | false 52 | false 53 | false 54 | true 55 | true 56 | true 57 | shifts 58 | true 59 | true 60 | true 61 | true 62 | true 63 | true 64 | true 65 | -------------------------------------------------------------------------------- /src/runtime/scheduler_tinygoriscv.S: -------------------------------------------------------------------------------- 1 | .section .text.tinygo_scanCurrentStack 2 | .global tinygo_scanCurrentStack 3 | .type tinygo_scanCurrentStack, %function 4 | tinygo_scanCurrentStack: 5 | // Push callee-saved registers onto the stack. 6 | addi sp, sp, -64 7 | sw ra, 60(sp) 8 | sw s11, 56(sp) 9 | sw s10, 52(sp) 10 | sw s9, 48(sp) 11 | sw s8, 44(sp) 12 | sw s7, 40(sp) 13 | sw s6, 36(sp) 14 | sw s5, 32(sp) 15 | sw s4, 28(sp) 16 | sw s3, 24(sp) 17 | sw s2, 20(sp) 18 | sw s1, 16(sp) 19 | sw s0, 12(sp) 20 | 21 | // Scan the stack. 22 | mv a0, sp 23 | call tinygo_scanstack 24 | 25 | // Restore stack state. 26 | addi sp, sp, 64 27 | 28 | // Return to the caller. 29 | ret 30 | -------------------------------------------------------------------------------- /targets/riscv.json: -------------------------------------------------------------------------------- 1 | { 2 | "llvm-target": "riscv32--none", 3 | "goos": "linux", 4 | "goarch": "arm", 5 | "build-tags": ["tinygo.riscv", "baremetal", "linux", "arm"], 6 | "gc": "conservative", 7 | "compiler": "clang", 8 | "linker": "ld.lld", 9 | "rtlib": "compiler-rt", 10 | "libc": "picolibc", 11 | "cflags": [ 12 | "--target=riscv32--none", 13 | "-march=rv32imac", 14 | "-mabi=ilp32", 15 | "-Os", 16 | "-Werror", 17 | "-fno-exceptions", "-fno-unwind-tables", 18 | "-ffunction-sections", "-fdata-sections" 19 | ], 20 | "ldflags": [ 21 | "-melf32lriscv", 22 | "--gc-sections" 23 | ], 24 | "extra-files": [ 25 | "src/device/riscv/start.S", 26 | "src/runtime/scheduler_tinygoriscv.S" 27 | ], 28 | "gdb": "riscv64-unknown-elf-gdb" 29 | } 30 | -------------------------------------------------------------------------------- /src/examples/microbit-blink/microbit-blink.go: -------------------------------------------------------------------------------- 1 | // blink program for the BBC micro:bit 2 | package main 3 | 4 | import ( 5 | "machine" 6 | "time" 7 | ) 8 | 9 | // The LED matrix in the micro:bit is a multiplexed display: https://en.wikipedia.org/wiki/Multiplexed_display 10 | // Driver for easier control: https://github.com/tinygo-org/drivers/tree/master/microbitmatrix 11 | func main() { 12 | ledrow := machine.LED_ROW_1 13 | ledrow.Configure(machine.PinConfig{Mode: machine.PinOutput}) 14 | ledcol := machine.LED_COL_1 15 | ledcol.Configure(machine.PinConfig{Mode: machine.PinOutput}) 16 | ledcol.Low() 17 | for { 18 | ledrow.Low() 19 | time.Sleep(time.Millisecond * 500) 20 | 21 | ledrow.High() 22 | time.Sleep(time.Millisecond * 500) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/machine/machine_attiny.go: -------------------------------------------------------------------------------- 1 | // +build avr,attiny 2 | 3 | package machine 4 | 5 | // UART on the AVR is a dummy implementation. UART has not been implemented for ATtiny 6 | // devices. 7 | type UART struct { 8 | Buffer *RingBuffer 9 | } 10 | 11 | // Configure is a dummy implementation. UART has not been implemented for ATtiny 12 | // devices. 13 | func (uart UART) Configure(config UARTConfig) { 14 | } 15 | 16 | // WriteByte is a dummy implementation. UART has not been implemented for ATtiny 17 | // devices. 18 | func (uart UART) WriteByte(c byte) error { 19 | return nil 20 | } 21 | 22 | // Tx is a dummy implementation. I2C has not been implemented for ATtiny 23 | // devices. 24 | func (i2c I2C) Tx(addr uint16, w, r []byte) error { 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /src/device/nrf/README.markdown: -------------------------------------------------------------------------------- 1 | # Generated Go files for Nordic Semiconductors devices 2 | 3 | In this directory, Go register description files are stored that are generated 4 | by `gen-device.py` from .svd files provided by Nordic. See the SVD files [over 5 | here](https://github.com/NordicSemiconductor/nrfx/tree/master/mdk). 6 | 7 | The original files are provided under the 3-clause BSD license, see [this 8 | post](https://devzone.nordicsemi.com/b/blog/posts/introducing-nordics-new-software-licensing-schemes) 9 | for details. As the generated files transform most of the original file, I think 10 | they should be licensed under the same license as the original files. Generated 11 | files will contain the license statement that is included in the original SVD 12 | files. 13 | -------------------------------------------------------------------------------- /cgo/testdata/errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | #warning some warning 5 | 6 | typedef struct { 7 | int x; 8 | int y; 9 | } point_t; 10 | 11 | typedef someType noType; // undefined type 12 | 13 | #define SOME_CONST_1 5) // invalid const syntax 14 | #define SOME_CONST_2 6) // const not used (so no error) 15 | #define SOME_CONST_3 1234 // const too large for byte 16 | */ 17 | import "C" 18 | 19 | // Make sure that errors for the following lines won't change with future 20 | // additions to the CGo preamble. 21 | //line errors.go:100 22 | var ( 23 | // constant too large 24 | _ C.uint8_t = 2 << 10 25 | 26 | // z member does not exist 27 | _ C.point_t = C.point_t{z: 3} 28 | 29 | // constant has syntax error 30 | _ = C.SOME_CONST_1 31 | 32 | _ byte = C.SOME_CONST_3 33 | ) 34 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/nrfx"] 2 | path = lib/nrfx 3 | url = https://github.com/NordicSemiconductor/nrfx.git 4 | [submodule "lib/CMSIS"] 5 | path = lib/CMSIS 6 | url = https://github.com/ARM-software/CMSIS.git 7 | [submodule "lib/avr"] 8 | path = lib/avr 9 | url = https://github.com/avr-rust/avr-mcu.git 10 | [submodule "lib/cmsis-svd"] 11 | path = lib/cmsis-svd 12 | url = https://github.com/posborne/cmsis-svd 13 | [submodule "lib/compiler-rt"] 14 | path = lib/compiler-rt 15 | url = https://github.com/llvm-mirror/compiler-rt.git 16 | branch = release_80 17 | [submodule "lib/wasi-libc"] 18 | path = lib/wasi-libc 19 | url = https://github.com/CraneStation/wasi-libc 20 | [submodule "lib/picolibc"] 21 | path = lib/picolibc 22 | url = https://github.com/keith-packard/picolibc.git 23 | -------------------------------------------------------------------------------- /src/runtime/interrupt/interrupt_cortexm.go: -------------------------------------------------------------------------------- 1 | // +build cortexm 2 | 3 | package interrupt 4 | 5 | import ( 6 | "device/arm" 7 | ) 8 | 9 | // Enable enables this interrupt. Right after calling this function, the 10 | // interrupt may be invoked if it was already pending. 11 | func (irq Interrupt) Enable() { 12 | arm.EnableIRQ(uint32(irq.num)) 13 | } 14 | 15 | // SetPriority sets the interrupt priority for this interrupt. A lower number 16 | // means a higher priority. Additionally, most hardware doesn't implement all 17 | // priority bits (only the uppoer bits). 18 | // 19 | // Examples: 0xff (lowest priority), 0xc0 (low priority), 0x00 (highest possible 20 | // priority). 21 | func (irq Interrupt) SetPriority(priority uint8) { 22 | arm.SetPriority(uint32(irq.num), uint32(priority)) 23 | } 24 | -------------------------------------------------------------------------------- /transform/testdata/wasm-abi.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 2 | target triple = "wasm32-unknown-unknown-wasm" 3 | 4 | declare i64 @externalCall(i8*, i32, i64) 5 | 6 | define internal i64 @testCall(i8* %ptr, i32 %len, i64 %foo) { 7 | %val = call i64 @externalCall(i8* %ptr, i32 %len, i64 %foo) 8 | ret i64 %val 9 | } 10 | 11 | define internal i64 @testCallNonEntry(i8* %ptr, i32 %len) { 12 | entry: 13 | br label %bb1 14 | 15 | bb1: 16 | %val = call i64 @externalCall(i8* %ptr, i32 %len, i64 3) 17 | ret i64 %val 18 | } 19 | 20 | define void @exportedFunction(i64 %foo) { 21 | %unused = shl i64 %foo, 1 22 | ret void 23 | } 24 | 25 | define internal void @callExportedFunction(i64 %foo) { 26 | call void @exportedFunction(i64 %foo) 27 | ret void 28 | } 29 | -------------------------------------------------------------------------------- /transform/testdata/panic.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 2 | target triple = "armv7m-none-eabi" 3 | 4 | @"runtime.lookupPanic$string" = constant [18 x i8] c"index out of range" 5 | 6 | declare void @runtime.runtimePanic(i8*, i32) 7 | 8 | declare void @runtime._panic(i32, i8*) 9 | 10 | define void @runtime.lookupPanic() { 11 | call void @runtime.runtimePanic(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"runtime.lookupPanic$string", i64 0, i64 0), i32 18) 12 | ret void 13 | } 14 | 15 | ; This is equivalent to the following code: 16 | ; func someFunc(x interface{}) { 17 | ; panic(x) 18 | ; } 19 | define void @someFunc(i32 %typecode, i8* %value) { 20 | call void @runtime._panic(i32 %typecode, i8* %value) 21 | unreachable 22 | } 23 | -------------------------------------------------------------------------------- /src/runtime/gc_none.go: -------------------------------------------------------------------------------- 1 | // +build gc.none 2 | 3 | package runtime 4 | 5 | // This GC strategy provides no memory allocation at all. It can be useful to 6 | // detect where in a program memory is allocated, or to combine this runtime 7 | // with a separate (external) garbage collector. 8 | 9 | import ( 10 | "unsafe" 11 | ) 12 | 13 | func alloc(size uintptr) unsafe.Pointer 14 | 15 | func free(ptr unsafe.Pointer) { 16 | // Nothing to free when nothing gets allocated. 17 | } 18 | 19 | func GC() { 20 | // Unimplemented. 21 | } 22 | 23 | func KeepAlive(x interface{}) { 24 | // Unimplemented. Only required with SetFinalizer(). 25 | } 26 | 27 | func SetFinalizer(obj interface{}, finalizer interface{}) { 28 | // Unimplemented. 29 | } 30 | 31 | func initHeap() { 32 | // Nothing to initialize. 33 | } 34 | -------------------------------------------------------------------------------- /transform/transform.go: -------------------------------------------------------------------------------- 1 | // Package transform contains transformation passes for the TinyGo compiler. 2 | // These transformation passes may be optimization passes or lowering passes. 3 | // 4 | // Optimization passes transform the IR in such a way that they increase the 5 | // performance of the generated code and/or help the LLVM optimizer better do 6 | // its job by simplifying the IR. This usually means that certain 7 | // TinyGo-specific runtime calls are removed or replaced with something simpler 8 | // if that is a valid operation. 9 | // 10 | // Lowering passes are usually required to run. One example is the interface 11 | // lowering pass, which replaces stub runtime calls to get an interface method 12 | // with the method implementation (either a direct call or a thunk). 13 | package transform 14 | -------------------------------------------------------------------------------- /src/machine/board_x9pro.go: -------------------------------------------------------------------------------- 1 | // +build x9pro 2 | 3 | package machine 4 | 5 | // https://hackaday.io/project/144350-hacking-wearables-for-mental-health-and-more/details 6 | const ( 7 | LED Pin = 4 // HR LED pin 8 | UART_TX_PIN Pin = NoPin 9 | UART_RX_PIN Pin = NoPin 10 | SCL_PIN Pin = NoPin 11 | SDA_PIN Pin = NoPin 12 | SPI0_SCK_PIN Pin = 18 13 | SPI0_MISO_PIN Pin = 19 14 | SPI0_MOSI_PIN Pin = 20 15 | ) 16 | 17 | // LCD pins. 18 | const ( 19 | OLED_CS Pin = 15 // chip select 20 | OLED_RES Pin = 14 // reset pin 21 | OLED_DC Pin = 13 // data/command 22 | OLED_SCK Pin = 12 // SPI clock 23 | OLED_MOSI Pin = 11 // SPI MOSI (master-out, slave-in) 24 | OLED_LED_POW Pin = 16 25 | OLED_IC_POW Pin = 17 26 | ) 27 | 28 | const HasLowFrequencyCrystal = true 29 | -------------------------------------------------------------------------------- /src/runtime/poll.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | // This file implements stub functions for internal/poll. 4 | 5 | //go:linkname poll_runtime_pollServerInit internal/poll.runtime_pollServerInit 6 | func poll_runtime_pollServerInit() { 7 | panic("todo: runtime_pollServerInit") 8 | } 9 | 10 | //go:linkname poll_runtime_pollOpen internal/poll.runtime_pollOpen 11 | func poll_runtime_pollOpen(fd uintptr) (uintptr, int) { 12 | panic("todo: runtime_pollOpen") 13 | } 14 | 15 | //go:linkname poll_runtime_pollClose internal/poll.runtime_pollClose 16 | func poll_runtime_pollClose(ctx uintptr) { 17 | panic("todo: runtime_pollClose") 18 | } 19 | 20 | //go:linkname poll_runtime_pollUnblock internal/poll.runtime_pollUnblock 21 | func poll_runtime_pollUnblock(ctx uintptr) { 22 | panic("todo: runtime_pollUnblock") 23 | } 24 | -------------------------------------------------------------------------------- /src/machine/machine_attiny85.go: -------------------------------------------------------------------------------- 1 | // +build attiny85 2 | 3 | package machine 4 | 5 | import ( 6 | "device/avr" 7 | "runtime/volatile" 8 | ) 9 | 10 | const ( 11 | PB0 Pin = iota 12 | PB1 13 | PB2 14 | PB3 15 | PB4 16 | PB5 17 | ) 18 | 19 | // Configure sets the pin to input or output. 20 | func (p Pin) Configure(config PinConfig) { 21 | if config.Mode == PinOutput { // set output bit 22 | avr.DDRB.SetBits(1 << uint8(p)) 23 | } else { // configure input: clear output bit 24 | avr.DDRB.ClearBits(1 << uint8(p)) 25 | } 26 | } 27 | 28 | func (p Pin) getPortMask() (*volatile.Register8, uint8) { 29 | return avr.PORTB, 1 << uint8(p) 30 | } 31 | 32 | // Get returns the current value of a GPIO pin. 33 | func (p Pin) Get() bool { 34 | val := avr.PINB.Get() & (1 << uint8(p)) 35 | return (val > 0) 36 | } 37 | -------------------------------------------------------------------------------- /src/os/file_unix.go: -------------------------------------------------------------------------------- 1 | // +build darwin linux,!baremetal freebsd,!baremetal 2 | 3 | package os 4 | 5 | import ( 6 | "syscall" 7 | ) 8 | 9 | // Read reads up to len(b) bytes from the File. It returns the number of bytes 10 | // read and any error encountered. At end of file, Read returns 0, io.EOF. 11 | func (f *File) Read(b []byte) (n int, err error) { 12 | return syscall.Read(int(f.fd), b) 13 | } 14 | 15 | // Write writes len(b) bytes to the File. It returns the number of bytes written 16 | // and an error, if any. Write returns a non-nil error when n != len(b). 17 | func (f *File) Write(b []byte) (n int, err error) { 18 | return syscall.Write(int(f.fd), b) 19 | } 20 | 21 | // Close closes the File, rendering it unusable for I/O. 22 | func (f *File) Close() error { 23 | return syscall.Close(int(f.fd)) 24 | } 25 | -------------------------------------------------------------------------------- /src/os/file_other.go: -------------------------------------------------------------------------------- 1 | // +build baremetal wasm 2 | 3 | package os 4 | 5 | import ( 6 | _ "unsafe" 7 | ) 8 | 9 | // Read is unsupported on this system. 10 | func (f *File) Read(b []byte) (n int, err error) { 11 | return 0, errUnsupported 12 | } 13 | 14 | // Write writes len(b) bytes to the output. It returns the number of bytes 15 | // written or an error if this file is not stdout or stderr. 16 | func (f *File) Write(b []byte) (n int, err error) { 17 | switch f.fd { 18 | case Stdout.fd, Stderr.fd: 19 | for _, c := range b { 20 | putchar(c) 21 | } 22 | return len(b), nil 23 | default: 24 | return 0, errUnsupported 25 | } 26 | } 27 | 28 | // Close is unsupported on this system. 29 | func (f *File) Close() error { 30 | return errUnsupported 31 | } 32 | 33 | //go:linkname putchar runtime.putchar 34 | func putchar(c byte) 35 | -------------------------------------------------------------------------------- /testdata/channel.txt: -------------------------------------------------------------------------------- 1 | len, cap of channel: 0 0 false 2 | recv from open channel: 1 true 3 | received num: 2 4 | received num: 3 5 | slept 6 | received num: 4 7 | received num: 5 8 | received num: 6 9 | received num: 7 10 | received num: 8 11 | recv from closed channel: 0 false 12 | complex128: (+7.000000e+000+1.050000e+001i) 13 | sum of n: 149 14 | sum: 25 15 | sum: 29 16 | sum: 33 17 | sum(100): 4950 18 | deadlocking 19 | select no-op 20 | after no-op 21 | sum: 5 22 | did send one 23 | select one n: 0 24 | select n from chan: 55 25 | select n from closed chan: 0 26 | select send 27 | sum: 235 28 | non-concurrent channel recieve: 1 29 | non-concurrent channel recieve: 2 30 | closed buffered channel recieve: 3 31 | closed buffered channel recieve: 4 32 | closed buffered channel recieve: 0 33 | hybrid buffered channel recieve: 2 34 | blocking select sum: 3 35 | -------------------------------------------------------------------------------- /src/internal/task/task_none.go: -------------------------------------------------------------------------------- 1 | // +build scheduler.none 2 | 3 | package task 4 | 5 | import "unsafe" 6 | 7 | //go:linkname runtimePanic runtime.runtimePanic 8 | func runtimePanic(str string) 9 | 10 | func Pause() { 11 | runtimePanic("scheduler is disabled") 12 | } 13 | 14 | func Current() *Task { 15 | runtimePanic("scheduler is disabled") 16 | return nil 17 | } 18 | 19 | //go:noinline 20 | func start(fn uintptr, args unsafe.Pointer) { 21 | // The compiler will error if this is reachable. 22 | runtimePanic("scheduler is disabled") 23 | } 24 | 25 | type state struct{} 26 | 27 | func (t *Task) Resume() { 28 | runtimePanic("scheduler is disabled") 29 | } 30 | 31 | // OnSystemStack returns whether the caller is running on the system stack. 32 | func OnSystemStack() bool { 33 | // This scheduler does not do any stack switching. 34 | return true 35 | } 36 | -------------------------------------------------------------------------------- /transform/testdata/panic.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 2 | target triple = "armv7m-none-eabi" 3 | 4 | @"runtime.lookupPanic$string" = constant [18 x i8] c"index out of range" 5 | 6 | declare void @runtime.runtimePanic(i8*, i32) 7 | 8 | declare void @runtime._panic(i32, i8*) 9 | 10 | define void @runtime.lookupPanic() { 11 | call void @llvm.trap() 12 | call void @runtime.runtimePanic(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"runtime.lookupPanic$string", i64 0, i64 0), i32 18) 13 | ret void 14 | } 15 | 16 | define void @someFunc(i32 %typecode, i8* %value) { 17 | call void @llvm.trap() 18 | call void @runtime._panic(i32 %typecode, i8* %value) 19 | unreachable 20 | } 21 | 22 | ; Function Attrs: cold noreturn nounwind 23 | declare void @llvm.trap() #0 24 | 25 | attributes #0 = { cold noreturn nounwind } 26 | -------------------------------------------------------------------------------- /cgo/testdata/flags.out.go: -------------------------------------------------------------------------------- 1 | // CGo errors: 2 | // testdata/flags.go:5:7: invalid #cgo line: NOFLAGS 3 | // testdata/flags.go:8:13: invalid flag: -fdoes-not-exist 4 | // testdata/flags.go:29:14: invalid flag: -does-not-exists 5 | 6 | package main 7 | 8 | import "unsafe" 9 | 10 | var _ unsafe.Pointer 11 | 12 | const C.BAR = 3 13 | const C.FOO_H = 1 14 | 15 | type C.int16_t = int16 16 | type C.int32_t = int32 17 | type C.int64_t = int64 18 | type C.int8_t = int8 19 | type C.uint16_t = uint16 20 | type C.uint32_t = uint32 21 | type C.uint64_t = uint64 22 | type C.uint8_t = uint8 23 | type C.uintptr_t = uintptr 24 | type C.char uint8 25 | type C.int int32 26 | type C.long int32 27 | type C.longlong int64 28 | type C.schar int8 29 | type C.short int16 30 | type C.uchar uint8 31 | type C.uint uint32 32 | type C.ulong uint32 33 | type C.ulonglong uint64 34 | type C.ushort uint16 35 | -------------------------------------------------------------------------------- /transform/testdata/stringtobytes.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 2 | target triple = "x86_64--linux" 3 | 4 | @str = constant [6 x i8] c"foobar" 5 | 6 | declare { i8*, i64, i64 } @runtime.stringToBytes(i8*, i64) 7 | 8 | declare void @printSlice(i8* nocapture readonly, i64, i64) 9 | 10 | declare void @writeToSlice(i8* nocapture, i64, i64) 11 | 12 | define void @testReadOnly() { 13 | entry: 14 | call fastcc void @printSlice(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str, i32 0, i32 0), i64 6, i64 6) 15 | ret void 16 | } 17 | 18 | define void @testReadWrite() { 19 | entry: 20 | %0 = call fastcc { i8*, i64, i64 } @runtime.stringToBytes(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str, i32 0, i32 0), i64 6) 21 | %1 = extractvalue { i8*, i64, i64 } %0, 0 22 | call fastcc void @writeToSlice(i8* %1, i64 6, i64 6) 23 | ret void 24 | } 25 | -------------------------------------------------------------------------------- /src/machine/board_pca10031.go: -------------------------------------------------------------------------------- 1 | // +build pca10031 2 | 3 | // pca10031 is a nrf51 based dongle, intended for use in wireless applications. 4 | // 5 | // https://infocenter.nordicsemi.com/pdf/nRF51_Dongle_UG_v1.0.pdf 6 | package machine 7 | 8 | // The pca10031 has a 32kHz crystal on board. 9 | const HasLowFrequencyCrystal = true 10 | 11 | // LED on the pca10031 12 | const ( 13 | LED Pin = LED_RED 14 | LED1 Pin = LED_RED 15 | LED2 Pin = LED_GREEN 16 | LED3 Pin = LED_BLUE 17 | LED_RED Pin = 21 18 | LED_GREEN Pin = 22 19 | LED_BLUE Pin = 23 20 | ) 21 | 22 | // UART pins 23 | const ( 24 | UART_TX_PIN Pin = 9 25 | UART_RX_PIN Pin = 11 26 | ) 27 | 28 | // I2C pins (disabled) 29 | const ( 30 | SDA_PIN = NoPin 31 | SCL_PIN = NoPin 32 | ) 33 | 34 | // SPI pins (unused) 35 | const ( 36 | SPI0_SCK_PIN = NoPin 37 | SPI0_MOSI_PIN = NoPin 38 | SPI0_MISO_PIN = NoPin 39 | ) 40 | -------------------------------------------------------------------------------- /targets/gameboy-advance.json: -------------------------------------------------------------------------------- 1 | { 2 | "llvm-target": "arm4-none-eabi", 3 | "cpu": "arm7tdmi", 4 | "build-tags": ["gameboyadvance", "arm7tdmi", "baremetal", "linux", "arm"], 5 | "goos": "linux", 6 | "goarch": "arm", 7 | "compiler": "clang", 8 | "linker": "ld.lld", 9 | "rtlib": "compiler-rt", 10 | "libc": "picolibc", 11 | "cflags": [ 12 | "-g", 13 | "--target=arm4-none-eabi", 14 | "-mcpu=arm7tdmi", 15 | "-Oz", 16 | "-Werror", 17 | "-fshort-enums", 18 | "-fomit-frame-pointer", 19 | "-Qunused-arguments", 20 | "-fno-exceptions", "-fno-unwind-tables", 21 | "-ffunction-sections", "-fdata-sections" 22 | ], 23 | "ldflags": [ 24 | "--gc-sections" 25 | ], 26 | "linkerscript": "targets/gameboy-advance.ld", 27 | "extra-files": [ 28 | "targets/gameboy-advance.s", 29 | "src/runtime/scheduler_gba.S" 30 | ], 31 | "gdb": "gdb-multiarch", 32 | "emulator": ["mgba", "-3"] 33 | } 34 | -------------------------------------------------------------------------------- /src/runtime/string_count.go: -------------------------------------------------------------------------------- 1 | // +build amd64 arm,go1.13 arm64 ppc64le ppc64 s390x 2 | 3 | package runtime 4 | 5 | // This file implements the string counting functions used by the strings 6 | // package, for example. It must be reimplemented here as a replacement for the 7 | // Go stdlib asm implementations, but only when the asm implementations are used 8 | // (this varies by Go version). 9 | // Track this file for updates: 10 | // https://github.com/golang/go/blob/master/src/internal/bytealg/count_native.go 11 | 12 | // countString copies the implementation from 13 | // https://github.com/golang/go/blob/67f181bfd84dfd5942fe9a29d8a20c9ce5eb2fea/src/internal/bytealg/count_generic.go#L1 14 | //go:linkname countString internal/bytealg.CountString 15 | func countString(s string, c byte) int { 16 | n := 0 17 | for i := 0; i < len(s); i++ { 18 | if s[i] == c { 19 | n++ 20 | } 21 | } 22 | return n 23 | } 24 | -------------------------------------------------------------------------------- /src/examples/wasm/export/wasm.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const WASM_URL = 'wasm.wasm'; 4 | 5 | var wasm; 6 | 7 | function updateResult() { 8 | wasm.exports.update(); 9 | } 10 | 11 | function init() { 12 | document.querySelector('#a').oninput = updateResult; 13 | document.querySelector('#b').oninput = updateResult; 14 | 15 | const go = new Go(); 16 | if ('instantiateStreaming' in WebAssembly) { 17 | WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) { 18 | wasm = obj.instance; 19 | go.run(wasm); 20 | updateResult(); 21 | }) 22 | } else { 23 | fetch(WASM_URL).then(resp => 24 | resp.arrayBuffer() 25 | ).then(bytes => 26 | WebAssembly.instantiate(bytes, go.importObject).then(function (obj) { 27 | wasm = obj.instance; 28 | go.run(wasm); 29 | updateResult(); 30 | }) 31 | ) 32 | } 33 | } 34 | 35 | init(); 36 | -------------------------------------------------------------------------------- /src/runtime/runtime_tinygoriscv.go: -------------------------------------------------------------------------------- 1 | // +build tinygo.riscv 2 | 3 | package runtime 4 | 5 | import "unsafe" 6 | 7 | //go:extern _sbss 8 | var _sbss [0]byte 9 | 10 | //go:extern _ebss 11 | var _ebss [0]byte 12 | 13 | //go:extern _sdata 14 | var _sdata [0]byte 15 | 16 | //go:extern _sidata 17 | var _sidata [0]byte 18 | 19 | //go:extern _edata 20 | var _edata [0]byte 21 | 22 | func preinit() { 23 | // Initialize .bss: zero-initialized global variables. 24 | ptr := unsafe.Pointer(&_sbss) 25 | for ptr != unsafe.Pointer(&_ebss) { 26 | *(*uint32)(ptr) = 0 27 | ptr = unsafe.Pointer(uintptr(ptr) + 4) 28 | } 29 | 30 | // Initialize .data: global variables initialized from flash. 31 | src := unsafe.Pointer(&_sidata) 32 | dst := unsafe.Pointer(&_sdata) 33 | for dst != unsafe.Pointer(&_edata) { 34 | *(*uint32)(dst) = *(*uint32)(src) 35 | dst = unsafe.Pointer(uintptr(dst) + 4) 36 | src = unsafe.Pointer(uintptr(src) + 4) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/machine/board_nrf52840-mdk.go: -------------------------------------------------------------------------------- 1 | // +build nrf52840_mdk 2 | 3 | package machine 4 | 5 | const HasLowFrequencyCrystal = true 6 | 7 | // LEDs on the nrf52840-mdk (nRF52840 dev board) 8 | const ( 9 | LED Pin = LED_GREEN 10 | LED_GREEN Pin = 22 11 | LED_RED Pin = 23 12 | LED_BLUE Pin = 24 13 | ) 14 | 15 | // UART pins 16 | const ( 17 | UART_TX_PIN Pin = 20 18 | UART_RX_PIN Pin = 19 19 | ) 20 | 21 | // UART0 is the USB device 22 | var ( 23 | UART0 = USB 24 | ) 25 | 26 | // I2C pins (unused) 27 | const ( 28 | SDA_PIN = NoPin 29 | SCL_PIN = NoPin 30 | ) 31 | 32 | // SPI pins (unused) 33 | const ( 34 | SPI0_SCK_PIN = NoPin 35 | SPI0_MOSI_PIN = NoPin 36 | SPI0_MISO_PIN = NoPin 37 | ) 38 | 39 | // USB CDC identifiers 40 | const ( 41 | usb_STRING_PRODUCT = "Makerdiary nRF52840 MDK USB Dongle" 42 | usb_STRING_MANUFACTURER = "Makerdiary" 43 | ) 44 | 45 | var ( 46 | usb_VID uint16 = 0x1915 47 | usb_PID uint16 = 0xCAFE 48 | ) 49 | -------------------------------------------------------------------------------- /src/runtime/baremetal.go: -------------------------------------------------------------------------------- 1 | // +build baremetal 2 | 3 | package runtime 4 | 5 | import ( 6 | "unsafe" 7 | ) 8 | 9 | //go:extern _heap_start 10 | var heapStartSymbol [0]byte 11 | 12 | //go:extern _heap_end 13 | var heapEndSymbol [0]byte 14 | 15 | //go:extern _globals_start 16 | var globalsStartSymbol [0]byte 17 | 18 | //go:extern _globals_end 19 | var globalsEndSymbol [0]byte 20 | 21 | //go:extern _stack_top 22 | var stackTopSymbol [0]byte 23 | 24 | var ( 25 | heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) 26 | heapEnd = uintptr(unsafe.Pointer(&heapEndSymbol)) 27 | globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol)) 28 | globalsEnd = uintptr(unsafe.Pointer(&globalsEndSymbol)) 29 | stackTop = uintptr(unsafe.Pointer(&stackTopSymbol)) 30 | ) 31 | 32 | //export malloc 33 | func libc_malloc(size uintptr) unsafe.Pointer { 34 | return alloc(size) 35 | } 36 | 37 | //export free 38 | func libc_free(ptr unsafe.Pointer) { 39 | free(ptr) 40 | } 41 | -------------------------------------------------------------------------------- /src/machine/board_circuitplay_express_baremetal.go: -------------------------------------------------------------------------------- 1 | // +build sam,atsamd21,circuitplay_express 2 | 3 | package machine 4 | 5 | import ( 6 | "device/sam" 7 | "runtime/interrupt" 8 | ) 9 | 10 | // UART1 on the Circuit Playground Express. 11 | var ( 12 | UART1 = UART{ 13 | Buffer: NewRingBuffer(), 14 | Bus: sam.SERCOM4_USART, 15 | SERCOM: 4, 16 | } 17 | ) 18 | 19 | func init() { 20 | UART1.Interrupt = interrupt.New(sam.IRQ_SERCOM4, UART1.handleInterrupt) 21 | } 22 | 23 | // I2C on the Circuit Playground Express. 24 | var ( 25 | // external device 26 | I2C0 = I2C{ 27 | Bus: sam.SERCOM5_I2CM, 28 | SERCOM: 5, 29 | } 30 | // internal device 31 | I2C1 = I2C{ 32 | Bus: sam.SERCOM1_I2CM, 33 | SERCOM: 1, 34 | } 35 | ) 36 | 37 | // SPI on the Circuit Playground Express. 38 | var ( 39 | SPI0 = SPI{ 40 | Bus: sam.SERCOM3_SPI, 41 | SERCOM: 3, 42 | } 43 | ) 44 | 45 | // I2S on the Circuit Playground Express. 46 | var ( 47 | I2S0 = I2S{Bus: sam.I2S} 48 | ) 49 | -------------------------------------------------------------------------------- /src/runtime/runtime_cortexm_qemu.go: -------------------------------------------------------------------------------- 1 | // +build cortexm,qemu 2 | 3 | package runtime 4 | 5 | // This file implements the Stellaris LM3S6965 Cortex-M3 chip as implemented by 6 | // QEMU. 7 | 8 | import ( 9 | "device/arm" 10 | "runtime/volatile" 11 | "unsafe" 12 | ) 13 | 14 | type timeUnit int64 15 | 16 | const tickMicros = 1 17 | 18 | var timestamp timeUnit 19 | 20 | func postinit() {} 21 | 22 | //export Reset_Handler 23 | func main() { 24 | preinit() 25 | run() 26 | arm.SemihostingCall(arm.SemihostingReportException, arm.SemihostingApplicationExit) 27 | abort() 28 | } 29 | 30 | const asyncScheduler = false 31 | 32 | func sleepTicks(d timeUnit) { 33 | // TODO: actually sleep here for the given time. 34 | timestamp += d 35 | } 36 | 37 | func ticks() timeUnit { 38 | return timestamp 39 | } 40 | 41 | // UART0 output register. 42 | var stdoutWrite = (*volatile.Register8)(unsafe.Pointer(uintptr(0x4000c000))) 43 | 44 | func putchar(c byte) { 45 | stdoutWrite.Set(uint8(c)) 46 | } 47 | -------------------------------------------------------------------------------- /src/examples/wasm/slices/wasm.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const WASM_URL = 'wasm.wasm'; 4 | 5 | var wasm; 6 | 7 | function update() { 8 | const value = document.getElementById("a").value; 9 | document.getElementById("b").innerHTML = JSON.stringify(window.splitter(value)); 10 | } 11 | 12 | function init() { 13 | document.querySelector('#a').oninput = update; 14 | 15 | const go = new Go(); 16 | if ('instantiateStreaming' in WebAssembly) { 17 | WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) { 18 | wasm = obj.instance; 19 | go.run(wasm); 20 | }) 21 | } else { 22 | fetch(WASM_URL).then(resp => 23 | resp.arrayBuffer() 24 | ).then(bytes => 25 | WebAssembly.instantiate(bytes, go.importObject).then(function (obj) { 26 | wasm = obj.instance; 27 | go.run(wasm); 28 | }) 29 | ) 30 | } 31 | } 32 | 33 | init(); 34 | -------------------------------------------------------------------------------- /colorwriter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // ANSI escape codes for terminal colors. 8 | const ( 9 | TermColorReset = "\x1b[0m" 10 | TermColorYellow = "\x1b[93m" 11 | ) 12 | 13 | // ColorWriter wraps an io.Writer but adds a prefix and a terminal color. 14 | type ColorWriter struct { 15 | Out io.Writer 16 | Color string 17 | Prefix string 18 | line []byte 19 | } 20 | 21 | // Write implements io.Writer, but with an added prefix and terminal color. 22 | func (w *ColorWriter) Write(p []byte) (n int, err error) { 23 | for _, c := range p { 24 | if c == '\n' { 25 | w.line = append(w.line, []byte(TermColorReset)...) 26 | w.line = append(w.line, '\n') 27 | // Write this line. 28 | _, err := w.Out.Write(w.line) 29 | w.line = w.line[:0] 30 | w.line = append(w.line, []byte(w.Color+w.Prefix)...) 31 | if err != nil { 32 | return 0, err 33 | } 34 | } else { 35 | w.line = append(w.line, c) 36 | } 37 | } 38 | return len(p), nil 39 | } 40 | -------------------------------------------------------------------------------- /src/examples/wasm/Makefile: -------------------------------------------------------------------------------- 1 | invoke: clean wasm_exec 2 | tinygo build -o ./html/wasm.wasm -target wasm -no-debug ./invoke/wasm.go 3 | cp ./invoke/wasm.js ./html/ 4 | cp ./invoke/index.html ./html/ 5 | 6 | export: clean wasm_exec 7 | tinygo build -o ./html/wasm.wasm -target wasm -no-debug ./export/wasm.go 8 | cp ./export/wasm.js ./html/ 9 | cp ./export/index.html ./html/ 10 | 11 | callback: clean wasm_exec 12 | tinygo build -o ./html/wasm.wasm -target wasm ./callback/wasm.go 13 | cp ./callback/wasm.js ./html/ 14 | cp ./callback/index.html ./html/ 15 | 16 | slices: clean wasm_exec 17 | tinygo build -o ./html/wasm.wasm -target wasm -no-debug ./slices/wasm.go 18 | cp ./slices/wasm.js ./html/ 19 | cp ./slices/index.html ./html/ 20 | 21 | 22 | main: clean wasm_exec 23 | tinygo build -o ./html/wasm.wasm -target wasm -no-debug ./main/main.go 24 | cp ./main/index.html ./html/ 25 | 26 | wasm_exec: 27 | cp ../../../targets/wasm_exec.js ./html/ 28 | 29 | clean: 30 | rm -rf ./html 31 | mkdir ./html 32 | -------------------------------------------------------------------------------- /src/machine/machine_nrf51.go: -------------------------------------------------------------------------------- 1 | // +build nrf51 2 | 3 | package machine 4 | 5 | import ( 6 | "device/nrf" 7 | ) 8 | 9 | var ( 10 | UART0 = NRF_UART0 11 | ) 12 | 13 | func CPUFrequency() uint32 { 14 | return 16000000 15 | } 16 | 17 | // Get peripheral and pin number for this GPIO pin. 18 | func (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) { 19 | return nrf.GPIO, uint32(p) 20 | } 21 | 22 | func (uart UART) setPins(tx, rx Pin) { 23 | nrf.UART0.PSELTXD.Set(uint32(tx)) 24 | nrf.UART0.PSELRXD.Set(uint32(rx)) 25 | } 26 | 27 | func (i2c I2C) setPins(scl, sda Pin) { 28 | i2c.Bus.PSELSCL.Set(uint32(scl)) 29 | i2c.Bus.PSELSDA.Set(uint32(sda)) 30 | } 31 | 32 | // SPI 33 | func (spi SPI) setPins(sck, mosi, miso Pin) { 34 | if sck == 0 { 35 | sck = SPI0_SCK_PIN 36 | } 37 | if mosi == 0 { 38 | mosi = SPI0_MOSI_PIN 39 | } 40 | if miso == 0 { 41 | miso = SPI0_MISO_PIN 42 | } 43 | spi.Bus.PSELSCK.Set(uint32(sck)) 44 | spi.Bus.PSELMOSI.Set(uint32(mosi)) 45 | spi.Bus.PSELMISO.Set(uint32(miso)) 46 | } 47 | -------------------------------------------------------------------------------- /src/sync/mutex.go: -------------------------------------------------------------------------------- 1 | package sync 2 | 3 | // These mutexes assume there is only one thread of operation: no goroutines, 4 | // interrupts or anything else. 5 | 6 | type Mutex struct { 7 | locked bool 8 | } 9 | 10 | func (m *Mutex) Lock() { 11 | if m.locked { 12 | panic("todo: block on locked mutex") 13 | } 14 | m.locked = true 15 | } 16 | 17 | func (m *Mutex) Unlock() { 18 | if !m.locked { 19 | panic("sync: unlock of unlocked Mutex") 20 | } 21 | m.locked = false 22 | } 23 | 24 | type RWMutex struct { 25 | m Mutex 26 | readers uint32 27 | } 28 | 29 | func (rw *RWMutex) Lock() { 30 | rw.m.Lock() 31 | } 32 | 33 | func (rw *RWMutex) Unlock() { 34 | rw.m.Unlock() 35 | } 36 | 37 | func (rw *RWMutex) RLock() { 38 | if rw.readers == 0 { 39 | rw.m.Lock() 40 | } 41 | rw.readers++ 42 | } 43 | 44 | func (rw *RWMutex) RUnlock() { 45 | if rw.readers == 0 { 46 | panic("sync: unlock of unlocked RWMutex") 47 | } 48 | rw.readers-- 49 | if rw.readers == 0 { 50 | rw.m.Unlock() 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/examples/blinkm/blinkm.go: -------------------------------------------------------------------------------- 1 | // Connects to an BlinkM I2C RGB LED. 2 | // http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf 3 | package main 4 | 5 | import ( 6 | "machine" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | machine.I2C0.Configure(machine.I2CConfig{}) 12 | 13 | // Init BlinkM 14 | machine.I2C0.WriteRegister(0x09, 'o', nil) 15 | 16 | version := []byte{0, 0} 17 | machine.I2C0.ReadRegister(0x09, 'Z', version) 18 | println("Firmware version:", string(version[0]), string(version[1])) 19 | 20 | count := 0 21 | for { 22 | switch count { 23 | case 0: 24 | // Crimson 25 | machine.I2C0.WriteRegister(0x09, 'n', []byte{0xdc, 0x14, 0x3c}) 26 | count = 1 27 | case 1: 28 | // MediumPurple 29 | machine.I2C0.WriteRegister(0x09, 'n', []byte{0x93, 0x70, 0xdb}) 30 | count = 2 31 | case 2: 32 | // MediumSeaGreen 33 | machine.I2C0.WriteRegister(0x09, 'n', []byte{0x3c, 0xb3, 0x71}) 34 | count = 0 35 | } 36 | 37 | time.Sleep(100 * time.Millisecond) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/device/stm32/stm32f407xx-altfunc-bitfields.go: -------------------------------------------------------------------------------- 1 | // These are the supported alternate function numberings on the stm32f407 2 | // +build stm32,stm32f407 3 | 4 | // Alternate function settings on the stm32f4xx series 5 | 6 | package stm32 7 | 8 | const ( 9 | // Alternative peripheral pin functions 10 | // AF0_SYSTEM is defined im the common bitfields package 11 | AF1_TIM1_2 AltFunc = 1 12 | AF2_TIM3_4_5 = 2 13 | AF3_TIM8_9_10_11 = 3 14 | AF4_I2C1_2_3 = 4 15 | AF5_SPI1_SPI2 = 5 16 | AF6_SPI3 = 6 17 | AF7_USART1_2_3 = 7 18 | AF8_USART4_5_6 = 8 19 | AF9_CAN1_CAN2_TIM12_13_14 = 9 20 | AF10_OTG_FS_OTG_HS = 10 21 | AF11_ETH = 11 22 | AF12_FSMC_SDIO_OTG_HS_1 = 12 23 | AF13_DCMI = 13 24 | AF14 = 14 25 | AF15_EVENTOUT = 15 26 | ) 27 | -------------------------------------------------------------------------------- /src/examples/blinky2/blinky2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // This blinky is a bit more advanced than blink1, with two goroutines running 4 | // at the same time and blinking a different LED. The delay of led2 is slightly 5 | // less than half of led1, which would be hard to do without some sort of 6 | // concurrency. 7 | 8 | import ( 9 | "machine" 10 | "time" 11 | ) 12 | 13 | func main() { 14 | go led1() 15 | led2() 16 | } 17 | 18 | func led1() { 19 | led := machine.LED1 20 | led.Configure(machine.PinConfig{Mode: machine.PinOutput}) 21 | for { 22 | println("+") 23 | led.Low() 24 | time.Sleep(time.Millisecond * 1000) 25 | 26 | println("-") 27 | led.High() 28 | time.Sleep(time.Millisecond * 1000) 29 | } 30 | } 31 | 32 | func led2() { 33 | led := machine.LED2 34 | led.Configure(machine.PinConfig{Mode: machine.PinOutput}) 35 | for { 36 | println(" +") 37 | led.Low() 38 | time.Sleep(time.Millisecond * 420) 39 | 40 | println(" -") 41 | led.High() 42 | time.Sleep(time.Millisecond * 420) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /testdata/float.txt: -------------------------------------------------------------------------------- 1 | +3.141593e+000 2 | +6.666667e-001 3 | +1.666667e+000 4 | -3.333333e-001 5 | +1.333333e+000 6 | +3.333333e-001 7 | +6.666667e-001 8 | +1.666667e+000 9 | -3.333333e-001 10 | +1.333333e+000 11 | +3.333333e-001 12 | +6.666667e-001 13 | +6.666667e-001 14 | 3 5 -2 -11 15 | +5.300000e+001 -8.000000e+000 +2.000000e+001 16 | (+6.666667e-001+1.200000e+000i) 17 | +6.666667e-001 18 | +1.200000e+000 19 | (+6.666667e-001-2.000000e+000i) 20 | +6.666667e-001 21 | -2.000000e+000 22 | (+2.000000e+000+1.000000e+000i) 23 | (+2.000000e+000-2.000000e+000i) 24 | (+6.666667e-001-2.000000e+000i) 25 | (+6.666667e-001+1.200000e+000i) 26 | complex64 add: (+2.000000e+000+1.000000e+001i) 27 | complex64 sub: (+8.000000e+000+1.000000e+001i) 28 | complex64 mul: (-1.500000e+001+2.000000e+000i) 29 | complex64 div: (-1.666667e+000+7.333333e+000i) 30 | complex128 add: (-3.000000e+000+8.000000e+000i) 31 | complex128 sub: (-7.000000e+000+8.000000e+000i) 32 | complex128 mul: (-1.000000e+001+1.000000e+001i) 33 | complex128 div: (-2.500000e+000+7.000000e+000i) 34 | -------------------------------------------------------------------------------- /interp/testdata/basic.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 2 | target triple = "x86_64--linux" 3 | 4 | @main.nonConst1 = local_unnamed_addr global [4 x i64] zeroinitializer 5 | @main.nonConst2 = local_unnamed_addr global i64 0 6 | 7 | declare void @runtime.printint64(i64) unnamed_addr 8 | 9 | declare void @runtime.printnl() unnamed_addr 10 | 11 | define void @runtime.initAll() unnamed_addr { 12 | entry: 13 | call void @runtime.printint64(i64 5) 14 | call void @runtime.printnl() 15 | %value1 = call i64 @someValue() 16 | store i64 %value1, i64* getelementptr inbounds ([4 x i64], [4 x i64]* @main.nonConst1, i32 0, i32 0) 17 | %value2 = load i64, i64* getelementptr inbounds ([4 x i64], [4 x i64]* @main.nonConst1, i32 0, i32 0) 18 | store i64 %value2, i64* @main.nonConst2 19 | ret void 20 | } 21 | 22 | define void @main() unnamed_addr { 23 | entry: 24 | call void @runtime.printint64(i64 3) 25 | call void @runtime.printnl() 26 | ret void 27 | } 28 | 29 | declare i64 @someValue() local_unnamed_addr 30 | -------------------------------------------------------------------------------- /src/machine/board_pca10040.go: -------------------------------------------------------------------------------- 1 | // +build pca10040 2 | 3 | package machine 4 | 5 | // The PCA10040 has a low-frequency (32kHz) crystal oscillator on board. 6 | const HasLowFrequencyCrystal = true 7 | 8 | // LEDs on the PCA10040 (nRF52832 dev board) 9 | const ( 10 | LED Pin = LED1 11 | LED1 Pin = 17 12 | LED2 Pin = 18 13 | LED3 Pin = 19 14 | LED4 Pin = 20 15 | ) 16 | 17 | // Buttons on the PCA10040 (nRF52832 dev board) 18 | const ( 19 | BUTTON Pin = BUTTON1 20 | BUTTON1 Pin = 13 21 | BUTTON2 Pin = 14 22 | BUTTON3 Pin = 15 23 | BUTTON4 Pin = 16 24 | ) 25 | 26 | // UART pins for NRF52840-DK 27 | const ( 28 | UART_TX_PIN Pin = 6 29 | UART_RX_PIN Pin = 8 30 | ) 31 | 32 | // ADC pins 33 | const ( 34 | ADC0 Pin = 3 35 | ADC1 Pin = 4 36 | ADC2 Pin = 28 37 | ADC3 Pin = 29 38 | ADC4 Pin = 30 39 | ADC5 Pin = 31 40 | ) 41 | 42 | // I2C pins 43 | const ( 44 | SDA_PIN Pin = 26 45 | SCL_PIN Pin = 27 46 | ) 47 | 48 | // SPI pins 49 | const ( 50 | SPI0_SCK_PIN Pin = 25 51 | SPI0_MOSI_PIN Pin = 23 52 | SPI0_MISO_PIN Pin = 24 53 | ) 54 | -------------------------------------------------------------------------------- /src/syscall/errno.go: -------------------------------------------------------------------------------- 1 | package syscall 2 | 3 | // Most code here has been copied from the Go sources: 4 | // https://github.com/golang/go/blob/go1.12/src/syscall/syscall_js.go 5 | // It has the following copyright note: 6 | // 7 | // Copyright 2018 The Go Authors. All rights reserved. 8 | // Use of this source code is governed by a BSD-style 9 | // license that can be found in the LICENSE file. 10 | 11 | // An Errno is an unsigned number describing an error condition. 12 | // It implements the error interface. The zero Errno is by convention 13 | // a non-error, so code to convert from Errno to error should use: 14 | // err = nil 15 | // if errno != 0 { 16 | // err = errno 17 | // } 18 | type Errno uintptr 19 | 20 | func (e Errno) Error() string { 21 | return "errno " + itoa(int(e)) 22 | } 23 | 24 | func (e Errno) Temporary() bool { 25 | return e == EINTR || e == EMFILE || e.Timeout() 26 | } 27 | 28 | func (e Errno) Timeout() bool { 29 | return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT 30 | } 31 | -------------------------------------------------------------------------------- /testdata/print.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | // test basic printing 5 | println("hello world!") 6 | println(42) 7 | println(100000000) 8 | 9 | // check that this one doesn't print an extra space between args 10 | print("a", "b", "c") 11 | println() 12 | // ..but this one does 13 | println("a", "b", "c") 14 | 15 | // print integers 16 | println(uint8(123)) 17 | println(int8(123)) 18 | println(int8(-123)) 19 | println(uint16(12345)) 20 | println(int16(12345)) 21 | println(int16(-12345)) 22 | println(uint32(12345678)) 23 | println(int32(12345678)) 24 | println(int32(-12345678)) 25 | println(uint64(123456789012)) 26 | println(int64(123456789012)) 27 | println(int64(-123456789012)) 28 | 29 | // print float64 30 | println(3.14) 31 | 32 | // print complex128 33 | println(5 + 1.2345i) 34 | 35 | // print interface 36 | println(interface{}(nil)) 37 | 38 | // print map 39 | println(map[string]int{"three": 3, "five": 5}) 40 | 41 | // TODO: print pointer 42 | 43 | // print bool 44 | println(true, false) 45 | } 46 | -------------------------------------------------------------------------------- /transform/panic.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "tinygo.org/x/go-llvm" 5 | ) 6 | 7 | // ReplacePanicsWithTrap replaces each call to panic (or similar functions) with 8 | // calls to llvm.trap, to reduce code size. This is the -panic=trap command-line 9 | // option. 10 | func ReplacePanicsWithTrap(mod llvm.Module) { 11 | ctx := mod.Context() 12 | builder := ctx.NewBuilder() 13 | defer builder.Dispose() 14 | 15 | trap := mod.NamedFunction("llvm.trap") 16 | if trap.IsNil() { 17 | trapType := llvm.FunctionType(ctx.VoidType(), nil, false) 18 | trap = llvm.AddFunction(mod, "llvm.trap", trapType) 19 | } 20 | for _, name := range []string{"runtime._panic", "runtime.runtimePanic"} { 21 | fn := mod.NamedFunction(name) 22 | if fn.IsNil() { 23 | continue 24 | } 25 | for _, use := range getUses(fn) { 26 | if use.IsACallInst().IsNil() || use.CalledValue() != fn { 27 | panic("expected use of a panic function to be a call") 28 | } 29 | builder.SetInsertPointBefore(use) 30 | builder.CreateCall(trap, nil, "") 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /compiler/volatile.go: -------------------------------------------------------------------------------- 1 | package compiler 2 | 3 | // This file implements volatile loads/stores in runtime/volatile.LoadT and 4 | // runtime/volatile.StoreT as compiler builtins. 5 | 6 | import ( 7 | "golang.org/x/tools/go/ssa" 8 | "tinygo.org/x/go-llvm" 9 | ) 10 | 11 | // createVolatileLoad is the implementation of the intrinsic function 12 | // runtime/volatile.LoadT(). 13 | func (b *builder) createVolatileLoad(instr *ssa.CallCommon) (llvm.Value, error) { 14 | addr := b.getValue(instr.Args[0]) 15 | b.createNilCheck(instr.Args[0], addr, "deref") 16 | val := b.CreateLoad(addr, "") 17 | val.SetVolatile(true) 18 | return val, nil 19 | } 20 | 21 | // createVolatileStore is the implementation of the intrinsic function 22 | // runtime/volatile.StoreT(). 23 | func (b *builder) createVolatileStore(instr *ssa.CallCommon) (llvm.Value, error) { 24 | addr := b.getValue(instr.Args[0]) 25 | val := b.getValue(instr.Args[1]) 26 | b.createNilCheck(instr.Args[0], addr, "deref") 27 | store := b.CreateStore(val, addr) 28 | store.SetVolatile(true) 29 | return llvm.Value{}, nil 30 | } 31 | -------------------------------------------------------------------------------- /loader/errors.go: -------------------------------------------------------------------------------- 1 | package loader 2 | 3 | import ( 4 | "go/token" 5 | "strings" 6 | ) 7 | 8 | // Errors contains a list of parser errors or a list of typechecker errors for 9 | // the given package. 10 | type Errors struct { 11 | Pkg *Package 12 | Errs []error 13 | } 14 | 15 | func (e Errors) Error() string { 16 | return "could not compile: " + e.Errs[0].Error() 17 | } 18 | 19 | // ImportCycleErrors is returned when encountering an import cycle. The list of 20 | // packages is a list from the root package to the leaf package that imports one 21 | // of the packages in the list. 22 | type ImportCycleError struct { 23 | Packages []string 24 | ImportPositions []token.Position 25 | } 26 | 27 | func (e *ImportCycleError) Error() string { 28 | var msg strings.Builder 29 | msg.WriteString("import cycle:\n\t") 30 | msg.WriteString(strings.Join(e.Packages, "\n\t")) 31 | msg.WriteString("\n at ") 32 | for i, pos := range e.ImportPositions { 33 | if i > 0 { 34 | msg.WriteString(", ") 35 | } 36 | msg.WriteString(pos.String()) 37 | } 38 | return msg.String() 39 | } 40 | -------------------------------------------------------------------------------- /src/device/arm/cortexm.s: -------------------------------------------------------------------------------- 1 | .syntax unified 2 | 3 | .section .text.HardFault_Handler 4 | .global HardFault_Handler 5 | .type HardFault_Handler, %function 6 | HardFault_Handler: 7 | // Put the old stack pointer in the first argument, for easy debugging. This 8 | // is especially useful on Cortex-M0, which supports far fewer debug 9 | // facilities. 10 | mov r0, sp 11 | 12 | // Load the default stack pointer from address 0 so that we can call normal 13 | // functions again that expect a working stack. However, it will corrupt the 14 | // old stack so the function below must not attempt to recover from this 15 | // fault. 16 | movs r3, #0 17 | ldr r3, [r3] 18 | mov sp, r3 19 | 20 | // Continue handling this error in Go. 21 | bl handleHardFault 22 | 23 | // This is a convenience function for semihosting support. 24 | // At some point, this should be replaced by inline assembly. 25 | .section .text.SemihostingCall 26 | .global SemihostingCall 27 | .type SemihostingCall, %function 28 | SemihostingCall: 29 | bkpt 0xab 30 | bx lr 31 | -------------------------------------------------------------------------------- /interp/testdata/consteval.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 2 | target triple = "x86_64--linux" 3 | 4 | @intToPtrResult = global i8 0 5 | @ptrToIntResult = global i8 0 6 | 7 | define void @runtime.initAll() { 8 | call void @main.init() 9 | ret void 10 | } 11 | 12 | define internal void @main.init() { 13 | call void @testIntToPtr() 14 | call void @testPtrToInt() 15 | ret void 16 | } 17 | 18 | define internal void @testIntToPtr() { 19 | %nil = icmp eq i8* inttoptr (i64 1024 to i8*), null 20 | br i1 %nil, label %a, label %b 21 | a: 22 | ; should not be reached 23 | store i8 1, i8* @intToPtrResult 24 | ret void 25 | b: 26 | ; should be reached 27 | store i8 2, i8* @intToPtrResult 28 | ret void 29 | } 30 | 31 | define internal void @testPtrToInt() { 32 | %zero = icmp eq i64 ptrtoint (i8* @ptrToIntResult to i64), 0 33 | br i1 %zero, label %a, label %b 34 | a: 35 | ; should not be reached 36 | store i8 1, i8* @ptrToIntResult 37 | ret void 38 | b: 39 | ; should be reached 40 | store i8 2, i8* @ptrToIntResult 41 | ret void 42 | } 43 | -------------------------------------------------------------------------------- /src/sync/map.go: -------------------------------------------------------------------------------- 1 | package sync 2 | 3 | // This file implements just enough of sync.Map to get packages to compile. It 4 | // is no more efficient than a map with a lock. 5 | 6 | type Map struct { 7 | lock Mutex 8 | m map[interface{}]interface{} 9 | } 10 | 11 | func (m *Map) Delete(key interface{}) { 12 | m.lock.Lock() 13 | defer m.lock.Unlock() 14 | delete(m.m, key) 15 | } 16 | 17 | func (m *Map) Load(key interface{}) (value interface{}, ok bool) { 18 | m.lock.Lock() 19 | defer m.lock.Unlock() 20 | value, ok = m.m[key] 21 | return 22 | } 23 | 24 | func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { 25 | m.lock.Lock() 26 | defer m.lock.Unlock() 27 | if m.m == nil { 28 | m.m = make(map[interface{}]interface{}) 29 | } 30 | if existing, ok := m.m[key]; ok { 31 | return existing, true 32 | } 33 | m.m[key] = value 34 | return value, false 35 | } 36 | 37 | func (m *Map) Store(key, value interface{}) { 38 | m.lock.Lock() 39 | defer m.lock.Unlock() 40 | if m.m == nil { 41 | m.m = make(map[interface{}]interface{}) 42 | } 43 | m.m[key] = value 44 | } 45 | -------------------------------------------------------------------------------- /src/examples/echo/echo.go: -------------------------------------------------------------------------------- 1 | // This is a echo console running on the device UART. 2 | // Connect using default baudrate for this hardware, 8-N-1 with your terminal program. 3 | package main 4 | 5 | import ( 6 | "machine" 7 | "time" 8 | ) 9 | 10 | // change these to test a different UART or pins if available 11 | var ( 12 | uart = machine.UART0 13 | tx = machine.UART_TX_PIN 14 | rx = machine.UART_RX_PIN 15 | ) 16 | 17 | func main() { 18 | uart.Configure(machine.UARTConfig{TX: tx, RX: rx}) 19 | uart.Write([]byte("Echo console enabled. Type something then press enter:\r\n")) 20 | 21 | input := make([]byte, 64) 22 | i := 0 23 | for { 24 | if uart.Buffered() > 0 { 25 | data, _ := uart.ReadByte() 26 | 27 | switch data { 28 | case 13: 29 | // return key 30 | uart.Write([]byte("\r\n")) 31 | uart.Write([]byte("You typed: ")) 32 | uart.Write(input[:i]) 33 | uart.Write([]byte("\r\n")) 34 | i = 0 35 | default: 36 | // just echo the character 37 | uart.WriteByte(data) 38 | input[i] = data 39 | i++ 40 | } 41 | } 42 | time.Sleep(10 * time.Millisecond) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /testdata/init.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func init() { 4 | println("init") 5 | } 6 | 7 | func main() { 8 | println("main") 9 | println("v1:", v1) 10 | println("v2:", v2.x, v2.y) 11 | println("v3:", len(v3), cap(v3), v3[0], v3[3]) 12 | println("v4:", len(v4), v4 == nil) 13 | println("v5:", len(v5), v5 == nil) 14 | println("v6:", v6) 15 | println("v7:", cap(v7), string(v7)) 16 | 17 | println(uint8SliceSrc[0]) 18 | println(uint8SliceDst[0]) 19 | println(intSliceSrc[0]) 20 | println(intSliceDst[0]) 21 | } 22 | 23 | type ( 24 | t2 struct { 25 | x int 26 | y int 27 | } 28 | ) 29 | 30 | var ( 31 | v1 = 3 32 | v2 = t2{2, 5} 33 | v3 = []int{2, 3, 5, 7} 34 | v4 map[string]int 35 | v5 = map[string]int{} 36 | v6 = float64(v1) < 2.6 37 | v7 = []byte("foo") 38 | 39 | uint8SliceSrc = []uint8{3, 100} 40 | uint8SliceDst []uint8 41 | intSliceSrc = []int16{5, 123, 1024} 42 | intSliceDst []int16 43 | ) 44 | 45 | func init() { 46 | uint8SliceDst = make([]uint8, len(uint8SliceSrc)) 47 | copy(uint8SliceDst, uint8SliceSrc) 48 | 49 | intSliceDst = make([]int16, len(intSliceSrc)) 50 | copy(intSliceDst, intSliceSrc) 51 | } 52 | -------------------------------------------------------------------------------- /src/runtime/gc_globals_precise.go: -------------------------------------------------------------------------------- 1 | // +build gc.conservative gc.extalloc 2 | // +build !baremetal 3 | 4 | package runtime 5 | 6 | import ( 7 | "unsafe" 8 | ) 9 | 10 | //go:extern runtime.trackedGlobalsStart 11 | var trackedGlobalsStart uintptr 12 | 13 | //go:extern runtime.trackedGlobalsLength 14 | var trackedGlobalsLength uintptr 15 | 16 | //go:extern runtime.trackedGlobalsBitmap 17 | var trackedGlobalsBitmap [0]uint8 18 | 19 | // markGlobals marks all globals, which are reachable by definition. 20 | // 21 | // This implementation relies on a compiler pass that stores all globals in a 22 | // single global (adjusting all uses of them accordingly) and creates a bit 23 | // vector with the locations of each pointer. This implementation then walks the 24 | // bit vector and for each pointer it indicates, it marks the root. 25 | // 26 | //go:nobounds 27 | func markGlobals() { 28 | for i := uintptr(0); i < trackedGlobalsLength; i++ { 29 | if trackedGlobalsBitmap[i/8]&(1<<(i%8)) != 0 { 30 | addr := trackedGlobalsStart + i*unsafe.Alignof(uintptr(0)) 31 | root := *(*uintptr)(unsafe.Pointer(addr)) 32 | markRoot(addr, root) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/examples/pwm/pwm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "machine" 5 | "time" 6 | ) 7 | 8 | // This example assumes that an RGB LED is connected to pins 3, 5 and 6 on an Arduino. 9 | // Change the values below to use different pins. 10 | const ( 11 | redPin = 3 12 | greenPin = 5 13 | bluePin = 6 14 | ) 15 | 16 | // cycleColor is just a placeholder until math/rand or some equivalent is working. 17 | func cycleColor(color uint8) uint8 { 18 | if color < 10 { 19 | return color + 1 20 | } else if color < 200 { 21 | return color + 10 22 | } else { 23 | return 0 24 | } 25 | } 26 | 27 | func main() { 28 | machine.InitPWM() 29 | 30 | red := machine.PWM{redPin} 31 | red.Configure() 32 | 33 | green := machine.PWM{greenPin} 34 | green.Configure() 35 | 36 | blue := machine.PWM{bluePin} 37 | blue.Configure() 38 | 39 | var rc uint8 40 | var gc uint8 = 20 41 | var bc uint8 = 30 42 | 43 | for { 44 | rc = cycleColor(rc) 45 | gc = cycleColor(gc) 46 | bc = cycleColor(bc) 47 | 48 | red.Set(uint16(rc) << 8) 49 | green.Set(uint16(gc) << 8) 50 | blue.Set(uint16(bc) << 8) 51 | 52 | time.Sleep(time.Millisecond * 500) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/runtime/func.go: -------------------------------------------------------------------------------- 1 | package runtime 2 | 3 | // This file implements some data types that may be useful for some 4 | // implementations of func values. 5 | 6 | import ( 7 | "unsafe" 8 | ) 9 | 10 | // funcValue is the underlying type of func values, depending on which func 11 | // value representation was used. 12 | type funcValue struct { 13 | context unsafe.Pointer // function context, for closures and bound methods 14 | id uintptr // ptrtoint of *funcValueWithSignature before lowering, opaque index (non-0) after lowering 15 | } 16 | 17 | // funcValueWithSignature is used before the func lowering pass. 18 | type funcValueWithSignature struct { 19 | funcPtr uintptr // ptrtoint of the actual function pointer 20 | signature *typecodeID // pointer to identify this signature (the value is undef) 21 | } 22 | 23 | // getFuncPtr is a dummy function that may be used if the func lowering pass is 24 | // not used. It is generally too slow but may be a useful fallback to debug the 25 | // func lowering pass. 26 | func getFuncPtr(val funcValue, signature *typecodeID) uintptr { 27 | return (*funcValueWithSignature)(unsafe.Pointer(val.id)).funcPtr 28 | } 29 | -------------------------------------------------------------------------------- /src/runtime/runtime_atmega.go: -------------------------------------------------------------------------------- 1 | // +build avr,atmega 2 | 3 | package runtime 4 | 5 | import ( 6 | "device/avr" 7 | ) 8 | 9 | // Sleep for a given period. The period is defined by the WDT peripheral, and is 10 | // on most chips (at least) 3 bits wide, in powers of two from 16ms to 2s 11 | // (0=16ms, 1=32ms, 2=64ms...). Note that the WDT is not very accurate: it can 12 | // be off by a large margin depending on temperature and supply voltage. 13 | // 14 | // TODO: disable more peripherals etc. to reduce sleep current. 15 | func sleepWDT(period uint8) { 16 | // Configure WDT 17 | avr.Asm("cli") 18 | avr.Asm("wdr") 19 | // Start timed sequence. 20 | avr.WDTCSR.SetBits(avr.WDTCSR_WDCE | avr.WDTCSR_WDE) 21 | // Enable WDT and set new timeout 22 | avr.WDTCSR.SetBits(avr.WDTCSR_WDIE | period) 23 | avr.Asm("sei") 24 | 25 | // Set sleep mode to idle and enable sleep mode. 26 | // Note: when using something other than idle, the UART won't work 27 | // correctly. This needs to be fixed, though, so we can truly sleep. 28 | avr.SMCR.Set((0 << 1) | avr.SMCR_SE) 29 | 30 | // go to sleep 31 | avr.Asm("sleep") 32 | 33 | // disable sleep 34 | avr.SMCR.Set(0) 35 | } 36 | -------------------------------------------------------------------------------- /src/examples/button2/button2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "machine" 5 | "time" 6 | ) 7 | 8 | // This example assumes that you are using the pca10040 board 9 | 10 | func main() { 11 | led1 := machine.LED1 12 | led1.Configure(machine.PinConfig{Mode: machine.PinOutput}) 13 | 14 | led2 := machine.LED2 15 | led2.Configure(machine.PinConfig{Mode: machine.PinOutput}) 16 | 17 | led3 := machine.LED3 18 | led3.Configure(machine.PinConfig{Mode: machine.PinOutput}) 19 | 20 | led4 := machine.LED4 21 | led4.Configure(machine.PinConfig{Mode: machine.PinOutput}) 22 | 23 | button1 := machine.BUTTON1 24 | button1.Configure(machine.PinConfig{Mode: machine.PinInputPullup}) 25 | 26 | button2 := machine.BUTTON2 27 | button2.Configure(machine.PinConfig{Mode: machine.PinInputPullup}) 28 | 29 | button3 := machine.BUTTON3 30 | button3.Configure(machine.PinConfig{Mode: machine.PinInputPullup}) 31 | 32 | button4 := machine.BUTTON4 33 | button4.Configure(machine.PinConfig{Mode: machine.PinInputPullup}) 34 | 35 | for { 36 | led1.Set(button1.Get()) 37 | led2.Set(button2.Get()) 38 | led3.Set(button3.Get()) 39 | led4.Set(button4.Get()) 40 | 41 | time.Sleep(time.Millisecond * 10) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/machine/board_pca10056.go: -------------------------------------------------------------------------------- 1 | // +build pca10056 2 | 3 | package machine 4 | 5 | const HasLowFrequencyCrystal = true 6 | 7 | // LEDs on the pca10056 8 | const ( 9 | LED Pin = LED1 10 | LED1 Pin = 13 11 | LED2 Pin = 14 12 | LED3 Pin = 15 13 | LED4 Pin = 16 14 | ) 15 | 16 | // Buttons on the pca10056 17 | const ( 18 | BUTTON Pin = BUTTON1 19 | BUTTON1 Pin = 11 20 | BUTTON2 Pin = 12 21 | BUTTON3 Pin = 24 22 | BUTTON4 Pin = 25 23 | ) 24 | 25 | // UART pins 26 | const ( 27 | UART_TX_PIN Pin = 6 28 | UART_RX_PIN Pin = 8 29 | ) 30 | 31 | // ADC pins 32 | const ( 33 | ADC0 Pin = 3 34 | ADC1 Pin = 4 35 | ADC2 Pin = 28 36 | ADC3 Pin = 29 37 | ADC4 Pin = 30 38 | ADC5 Pin = 31 39 | ) 40 | 41 | // I2C pins 42 | const ( 43 | SDA_PIN Pin = 26 // P0.26 44 | SCL_PIN Pin = 27 // P0.27 45 | ) 46 | 47 | // SPI pins 48 | const ( 49 | SPI0_SCK_PIN Pin = 47 // P1.15 50 | SPI0_MOSI_PIN Pin = 45 // P1.13 51 | SPI0_MISO_PIN Pin = 46 // P1.14 52 | ) 53 | 54 | // USB CDC identifiers 55 | const ( 56 | usb_STRING_PRODUCT = "Nordic nRF52840DK (PCA10056)" 57 | usb_STRING_MANUFACTURER = "Nordic Semiconductor" 58 | ) 59 | 60 | var ( 61 | usb_VID uint16 = 0x239A 62 | usb_PID uint16 = 0x8029 63 | ) 64 | -------------------------------------------------------------------------------- /src/examples/mcp3008/mcp3008.go: -------------------------------------------------------------------------------- 1 | // Connects to an MCP3008 ADC via SPI. 2 | // Datasheet: https://www.microchip.com/wwwproducts/en/en010530 3 | package main 4 | 5 | import ( 6 | "errors" 7 | "machine" 8 | "time" 9 | ) 10 | 11 | // cs is the pin used for Chip Select (CS). Change to whatever is in use on your board. 12 | const cs = machine.Pin(3) 13 | 14 | var ( 15 | tx []byte 16 | rx []byte 17 | val, result uint16 18 | ) 19 | 20 | func main() { 21 | cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) 22 | 23 | machine.SPI0.Configure(machine.SPIConfig{ 24 | Frequency: 4000000, 25 | Mode: 3}) 26 | 27 | tx = make([]byte, 3) 28 | rx = make([]byte, 3) 29 | 30 | for { 31 | val, _ = Read(0) 32 | println(val) 33 | time.Sleep(50 * time.Millisecond) 34 | } 35 | } 36 | 37 | // Read analog data from channel 38 | func Read(channel int) (uint16, error) { 39 | if channel < 0 || channel > 7 { 40 | return 0, errors.New("Invalid channel for read") 41 | } 42 | 43 | tx[0] = 0x01 44 | tx[1] = byte(8+channel) << 4 45 | tx[2] = 0x00 46 | 47 | cs.Low() 48 | machine.SPI0.Tx(tx, rx) 49 | result = uint16((rx[1]&0x3))<<8 + uint16(rx[2]) 50 | cs.High() 51 | 52 | return result, nil 53 | } 54 | -------------------------------------------------------------------------------- /src/runtime/interrupt/interrupt_gameboyadvance.go: -------------------------------------------------------------------------------- 1 | // +build gameboyadvance 2 | 3 | package interrupt 4 | 5 | import ( 6 | "runtime/volatile" 7 | "unsafe" 8 | ) 9 | 10 | var ( 11 | regInterruptEnable = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000200))) 12 | regInterruptRequestFlags = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000202))) 13 | regInterruptMasterEnable = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000208))) 14 | ) 15 | 16 | // Enable enables this interrupt. Right after calling this function, the 17 | // interrupt may be invoked if it was already pending. 18 | func (irq Interrupt) Enable() { 19 | regInterruptEnable.SetBits(1 << uint(irq.num)) 20 | } 21 | 22 | //export handleInterrupt 23 | func handleInterrupt() { 24 | flags := regInterruptRequestFlags.Get() 25 | for i := 0; i < 14; i++ { 26 | if flags&(1<RAM 25 | 26 | _sidata = LOADADDR(.data); 27 | 28 | .data : 29 | { 30 | _sdata = .; /* used by startup code */ 31 | *(.data) 32 | *(.data*) 33 | _edata = .; /* used by startup code */ 34 | } >RAM AT>FLASH_TEXT 35 | 36 | .bss : 37 | { 38 | _sbss = .; /* used by startup code */ 39 | *(.bss) 40 | *(.bss*) 41 | *(COMMON) 42 | _ebss = .; /* used by startup code */ 43 | } >RAM 44 | } 45 | 46 | /* For the memory allocator. */ 47 | _heap_start = _ebss; 48 | _heap_end = ORIGIN(RAM) + LENGTH(RAM); 49 | _globals_start = _sdata; 50 | _globals_end = _ebss; 51 | -------------------------------------------------------------------------------- /transform/globals.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import "tinygo.org/x/go-llvm" 4 | 5 | // This file implements small transformations on globals (functions and global 6 | // variables) for specific ABIs/architectures. 7 | 8 | // ApplyFunctionSections puts every function in a separate section. This makes 9 | // it possible for the linker to remove dead code. It is the equivalent of 10 | // passing -ffunction-sections to a C compiler. 11 | func ApplyFunctionSections(mod llvm.Module) { 12 | llvmFn := mod.FirstFunction() 13 | for !llvmFn.IsNil() { 14 | if !llvmFn.IsDeclaration() { 15 | name := llvmFn.Name() 16 | llvmFn.SetSection(".text." + name) 17 | } 18 | llvmFn = llvm.NextFunction(llvmFn) 19 | } 20 | } 21 | 22 | // NonConstGlobals turns all global constants into global variables. This works 23 | // around a limitation on Harvard architectures (e.g. AVR), where constant and 24 | // non-constant pointers point to a different address space. Normal pointer 25 | // behavior is restored by using the data space only, at the cost of RAM for 26 | // constant global variables. 27 | func NonConstGlobals(mod llvm.Module) { 28 | global := mod.FirstGlobal() 29 | for !global.IsNil() { 30 | global.SetGlobalConstant(false) 31 | global = llvm.NextGlobal(global) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cgo/sync.go: -------------------------------------------------------------------------------- 1 | package cgo 2 | 3 | import ( 4 | "sync" 5 | "unsafe" 6 | ) 7 | 8 | // #include 9 | import "C" 10 | 11 | // refMap is a convenient way to store opaque references that can be passed to 12 | // C. It is useful if an API uses function pointers and you cannot pass a Go 13 | // pointer but only a C pointer. 14 | type refMap struct { 15 | refs map[unsafe.Pointer]interface{} 16 | lock sync.Mutex 17 | } 18 | 19 | // Put stores a value in the map. It can later be retrieved using Get. It must 20 | // be removed using Remove to avoid memory leaks. 21 | func (m *refMap) Put(v interface{}) unsafe.Pointer { 22 | m.lock.Lock() 23 | defer m.lock.Unlock() 24 | if m.refs == nil { 25 | m.refs = make(map[unsafe.Pointer]interface{}, 1) 26 | } 27 | ref := C.malloc(1) 28 | m.refs[ref] = v 29 | return ref 30 | } 31 | 32 | // Get returns a stored value previously inserted with Put. Use the same 33 | // reference as you got from Put. 34 | func (m *refMap) Get(ref unsafe.Pointer) interface{} { 35 | m.lock.Lock() 36 | defer m.lock.Unlock() 37 | return m.refs[ref] 38 | } 39 | 40 | // Remove deletes a single reference from the map. 41 | func (m *refMap) Remove(ref unsafe.Pointer) { 42 | m.lock.Lock() 43 | defer m.lock.Unlock() 44 | delete(m.refs, ref) 45 | C.free(ref) 46 | } 47 | -------------------------------------------------------------------------------- /cgo/testdata/errors.out.go: -------------------------------------------------------------------------------- 1 | // CGo errors: 2 | // testdata/errors.go:4:2: warning: some warning 3 | // testdata/errors.go:11:9: error: unknown type name 'someType' 4 | // testdata/errors.go:13:23: unexpected token ) 5 | 6 | // Type checking errors after CGo processing: 7 | // testdata/errors.go:102: 2 << 10 (untyped int constant 2048) overflows uint8 8 | // testdata/errors.go:105: unknown field z in struct literal 9 | // testdata/errors.go:108: undeclared name: C.SOME_CONST_1 10 | // testdata/errors.go:110: C.SOME_CONST_3 (untyped int constant 1234) overflows byte 11 | 12 | package main 13 | 14 | import "unsafe" 15 | 16 | var _ unsafe.Pointer 17 | 18 | const C.SOME_CONST_3 = 1234 19 | 20 | type C.int16_t = int16 21 | type C.int32_t = int32 22 | type C.int64_t = int64 23 | type C.int8_t = int8 24 | type C.uint16_t = uint16 25 | type C.uint32_t = uint32 26 | type C.uint64_t = uint64 27 | type C.uint8_t = uint8 28 | type C.uintptr_t = uintptr 29 | type C.char uint8 30 | type C.int int32 31 | type C.long int32 32 | type C.longlong int64 33 | type C.schar int8 34 | type C.short int16 35 | type C.uchar uint8 36 | type C.uint uint32 37 | type C.ulong uint32 38 | type C.ulonglong uint64 39 | type C.ushort uint16 40 | type C.point_t = struct { 41 | x C.int 42 | y C.int 43 | } 44 | -------------------------------------------------------------------------------- /src/examples/wasm/invoke/wasm.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const WASM_URL = 'wasm.wasm'; 4 | 5 | var wasm; 6 | 7 | function updateRight() { 8 | const value = document.getElementById("a").value; 9 | window.runner(function (value) { 10 | document.getElementById("b").value = value; 11 | }, value); 12 | } 13 | 14 | function updateLeft() { 15 | const value = document.getElementById("b").value; 16 | window.runner(function (value) { 17 | document.getElementById("a").value = value; 18 | }, value); 19 | } 20 | 21 | function init() { 22 | document.querySelector('#a').oninput = updateRight; 23 | document.querySelector('#b').oninput = updateLeft; 24 | 25 | const go = new Go(); 26 | if ('instantiateStreaming' in WebAssembly) { 27 | WebAssembly.instantiateStreaming(fetch(WASM_URL), go.importObject).then(function (obj) { 28 | wasm = obj.instance; 29 | go.run(wasm); 30 | }) 31 | } else { 32 | fetch(WASM_URL).then(resp => 33 | resp.arrayBuffer() 34 | ).then(bytes => 35 | WebAssembly.instantiate(bytes, go.importObject).then(function (obj) { 36 | wasm = obj.instance; 37 | go.run(wasm); 38 | }) 39 | ) 40 | } 41 | } 42 | 43 | init(); 44 | -------------------------------------------------------------------------------- /src/machine/board_arduino_nano33_baremetal.go: -------------------------------------------------------------------------------- 1 | // +build sam,atsamd21,arduino_nano33 2 | 3 | package machine 4 | 5 | import ( 6 | "device/sam" 7 | "runtime/interrupt" 8 | ) 9 | 10 | // UART1 on the Arduino Nano 33 connects to the onboard NINA-W102 WiFi chip. 11 | var ( 12 | UART1 = UART{ 13 | Buffer: NewRingBuffer(), 14 | Bus: sam.SERCOM3_USART, 15 | SERCOM: 3, 16 | } 17 | ) 18 | 19 | // UART2 on the Arduino Nano 33 connects to the normal TX/RX pins. 20 | var ( 21 | UART2 = UART{ 22 | Buffer: NewRingBuffer(), 23 | Bus: sam.SERCOM5_USART, 24 | SERCOM: 5, 25 | } 26 | ) 27 | 28 | func init() { 29 | UART1.Interrupt = interrupt.New(sam.IRQ_SERCOM3, UART1.handleInterrupt) 30 | UART2.Interrupt = interrupt.New(sam.IRQ_SERCOM5, UART2.handleInterrupt) 31 | } 32 | 33 | // I2C on the Arduino Nano 33. 34 | var ( 35 | I2C0 = I2C{ 36 | Bus: sam.SERCOM4_I2CM, 37 | SERCOM: 4, 38 | } 39 | ) 40 | 41 | // SPI on the Arduino Nano 33. 42 | var ( 43 | SPI0 = SPI{ 44 | Bus: sam.SERCOM1_SPI, 45 | SERCOM: 1, 46 | } 47 | ) 48 | 49 | // SPI1 is connected to the NINA-W102 chip on the Arduino Nano 33. 50 | var ( 51 | SPI1 = SPI{ 52 | Bus: sam.SERCOM2_SPI, 53 | SERCOM: 2, 54 | } 55 | NINA_SPI = SPI1 56 | ) 57 | 58 | // I2S on the Arduino Nano 33. 59 | var ( 60 | I2S0 = I2S{Bus: sam.I2S} 61 | ) 62 | -------------------------------------------------------------------------------- /src/machine/board_hifive1b.go: -------------------------------------------------------------------------------- 1 | // +build hifive1b 2 | 3 | package machine 4 | 5 | const ( 6 | D0 = P16 7 | D1 = P17 8 | D2 = P18 9 | D3 = P19 // Green LED/PWM (PWM1_PWM1) 10 | D4 = P20 // PWM (PWM1_PWM0) 11 | D5 = P21 // Blue LED/PWM (PWM1_PWM2) 12 | D6 = P22 // Red LED/PWM (PWM1_PWM3) 13 | D7 = P16 14 | D8 = NoPin // PWM? 15 | D9 = P01 16 | D10 = P02 // SPI1_CS0 17 | D11 = P03 // SPI1_DQ0 18 | D12 = P04 // SPI1_DQ1 19 | D13 = P05 // SPI1_SCK 20 | D14 = NoPin // not connected 21 | D15 = P09 // does not seem to work? 22 | D16 = P10 // PWM (PWM2_PWM0) 23 | D17 = P11 // PWM (PWM2_PWM1) 24 | D18 = P12 // SDA (I2C0_SDA)/PWM (PWM2_PWM2) 25 | D19 = P13 // SDL (I2C0_SCL)/PWM (PWM2_PWM3) 26 | ) 27 | 28 | const ( 29 | LED = LED1 30 | LED1 = LED_RED 31 | LED2 = LED_GREEN 32 | LED3 = LED_BLUE 33 | LED_RED = P22 34 | LED_GREEN = P19 35 | LED_BLUE = P21 36 | ) 37 | 38 | const ( 39 | // TODO: figure out the pin numbers for these. 40 | UART_TX_PIN = NoPin 41 | UART_RX_PIN = NoPin 42 | ) 43 | 44 | // SPI pins 45 | const ( 46 | SPI0_SCK_PIN = NoPin 47 | SPI0_MOSI_PIN = NoPin 48 | SPI0_MISO_PIN = NoPin 49 | 50 | SPI1_SCK_PIN = D13 51 | SPI1_MOSI_PIN = D11 52 | SPI1_MISO_PIN = D12 53 | ) 54 | 55 | // I2C pins 56 | const ( 57 | I2C0_SDA_PIN = D18 58 | I2C0_SCL_PIN = D19 59 | ) 60 | -------------------------------------------------------------------------------- /src/runtime/gc_leaking.go: -------------------------------------------------------------------------------- 1 | // +build gc.leaking 2 | 3 | package runtime 4 | 5 | // This GC implementation is the simplest useful memory allocator possible: it 6 | // only allocates memory and never frees it. For some constrained systems, it 7 | // may be the only memory allocator possible. 8 | 9 | import ( 10 | "unsafe" 11 | ) 12 | 13 | // Ever-incrementing pointer: no memory is freed. 14 | var heapptr = heapStart 15 | 16 | func alloc(size uintptr) unsafe.Pointer { 17 | // TODO: this can be optimized by not casting between pointers and ints so 18 | // much. And by using platform-native data types (e.g. *uint8 for 8-bit 19 | // systems). 20 | size = align(size) 21 | addr := heapptr 22 | heapptr += size 23 | if heapptr >= heapEnd { 24 | runtimePanic("out of memory") 25 | } 26 | for i := uintptr(0); i < uintptr(size); i += 4 { 27 | ptr := (*uint32)(unsafe.Pointer(addr + i)) 28 | *ptr = 0 29 | } 30 | return unsafe.Pointer(addr) 31 | } 32 | 33 | func free(ptr unsafe.Pointer) { 34 | // Memory is never freed. 35 | } 36 | 37 | func GC() { 38 | // No-op. 39 | } 40 | 41 | func KeepAlive(x interface{}) { 42 | // Unimplemented. Only required with SetFinalizer(). 43 | } 44 | 45 | func SetFinalizer(obj interface{}, finalizer interface{}) { 46 | // Unimplemented. 47 | } 48 | 49 | func initHeap() { 50 | // Nothing to initialize. 51 | } 52 | -------------------------------------------------------------------------------- /src/syscall/syscall_libc.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | package syscall 4 | 5 | import ( 6 | "unsafe" 7 | ) 8 | 9 | func Close(fd int) (err error) { 10 | return ENOSYS // TODO 11 | } 12 | 13 | func Write(fd int, p []byte) (n int, err error) { 14 | buf, count := splitSlice(p) 15 | n = libc_write(int32(fd), buf, uint(count)) 16 | if n < 0 { 17 | err = getErrno() 18 | } 19 | return 20 | } 21 | 22 | func Read(fd int, p []byte) (n int, err error) { 23 | return 0, ENOSYS // TODO 24 | } 25 | 26 | func Seek(fd int, offset int64, whence int) (off int64, err error) { 27 | return 0, ENOSYS // TODO 28 | } 29 | 30 | func Open(path string, mode int, perm uint32) (fd int, err error) { 31 | return 0, ENOSYS // TODO 32 | } 33 | 34 | func Kill(pid int, sig Signal) (err error) { 35 | return ENOSYS // TODO 36 | } 37 | 38 | func Getpid() (pid int) { 39 | panic("unimplemented: getpid") // TODO 40 | } 41 | 42 | func Getenv(key string) (value string, found bool) { 43 | return "", false // TODO 44 | } 45 | 46 | func splitSlice(p []byte) (buf *byte, len uintptr) { 47 | slice := (*struct { 48 | buf *byte 49 | len uintptr 50 | cap uintptr 51 | })(unsafe.Pointer(&p)) 52 | return slice.buf, slice.len 53 | } 54 | 55 | // ssize_t write(int fd, const void *buf, size_t count) 56 | //export write 57 | func libc_write(fd int32, buf *byte, count uint) int 58 | -------------------------------------------------------------------------------- /transform/testdata/stringtobytes.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 2 | target triple = "x86_64--linux" 3 | 4 | @str = constant [6 x i8] c"foobar" 5 | 6 | declare { i8*, i64, i64 } @runtime.stringToBytes(i8*, i64) 7 | 8 | declare void @printSlice(i8* nocapture readonly, i64, i64) 9 | 10 | declare void @writeToSlice(i8* nocapture, i64, i64) 11 | 12 | ; Test that runtime.stringToBytes can be fully optimized away. 13 | define void @testReadOnly() { 14 | entry: 15 | %0 = call fastcc { i8*, i64, i64 } @runtime.stringToBytes(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str, i32 0, i32 0), i64 6) 16 | %1 = extractvalue { i8*, i64, i64 } %0, 0 17 | %2 = extractvalue { i8*, i64, i64 } %0, 1 18 | %3 = extractvalue { i8*, i64, i64 } %0, 2 19 | call fastcc void @printSlice(i8* %1, i64 %2, i64 %3) 20 | ret void 21 | } 22 | 23 | ; Test that even though the slice is written to, some values can be propagated. 24 | define void @testReadWrite() { 25 | entry: 26 | %0 = call fastcc { i8*, i64, i64 } @runtime.stringToBytes(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @str, i32 0, i32 0), i64 6) 27 | %1 = extractvalue { i8*, i64, i64 } %0, 0 28 | %2 = extractvalue { i8*, i64, i64 } %0, 1 29 | %3 = extractvalue { i8*, i64, i64 } %0, 2 30 | call fastcc void @writeToSlice(i8* %1, i64 %2, i64 %3) 31 | ret void 32 | } 33 | -------------------------------------------------------------------------------- /interp/testdata/interface.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 2 | target triple = "x86_64--linux" 3 | 4 | %runtime.typecodeID = type { %runtime.typecodeID*, i64 } 5 | %runtime.interfaceMethodInfo = type { i8*, i64 } 6 | %runtime.typeInInterface = type { %runtime.typecodeID*, %runtime.interfaceMethodInfo* } 7 | 8 | @main.v1 = global i1 0 9 | @"reflect/types.type:named:main.foo" = private constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:basic:int", i64 0 } 10 | @"reflect/types.type:basic:int" = external constant %runtime.typecodeID 11 | @"typeInInterface:reflect/types.type:named:main.foo" = private constant %runtime.typeInInterface { %runtime.typecodeID* @"reflect/types.type:named:main.foo", %runtime.interfaceMethodInfo* null } 12 | 13 | 14 | declare i1 @runtime.typeAssert(i64, %runtime.typecodeID*, i8*, i8*) 15 | 16 | define void @runtime.initAll() unnamed_addr { 17 | entry: 18 | call void @main.init() 19 | ret void 20 | } 21 | 22 | define internal void @main.init() unnamed_addr { 23 | entry: 24 | ; Test type asserts. 25 | %typecode = call i1 @runtime.typeAssert(i64 ptrtoint (%runtime.typeInInterface* @"typeInInterface:reflect/types.type:named:main.foo" to i64), %runtime.typecodeID* @"reflect/types.type:named:main.foo", i8* undef, i8* null) 26 | store i1 %typecode, i1* @main.v1 27 | ret void 28 | } 29 | -------------------------------------------------------------------------------- /src/runtime/gc_stack_raw.go: -------------------------------------------------------------------------------- 1 | // +build gc.conservative gc.extalloc 2 | // +build baremetal 3 | 4 | package runtime 5 | 6 | import "internal/task" 7 | 8 | // markStack marks all root pointers found on the stack. 9 | // 10 | // This implementation is conservative and relies on the stack top (provided by 11 | // the linker) and getting the current stack pointer from a register. Also, it 12 | // assumes a descending stack. Thus, it is not very portable. 13 | func markStack() { 14 | // Scan the current stack, and all current registers. 15 | scanCurrentStack() 16 | 17 | if !task.OnSystemStack() { 18 | // Mark system stack. 19 | markRoots(getSystemStackPointer(), stackTop) 20 | } 21 | } 22 | 23 | //go:export tinygo_scanCurrentStack 24 | func scanCurrentStack() 25 | 26 | //go:export tinygo_scanstack 27 | func scanstack(sp uintptr) { 28 | // Mark current stack. 29 | // This function is called by scanCurrentStack, after pushing all registers onto the stack. 30 | // Callee-saved registers have been pushed onto stack by tinygo_localscan, so this will scan them too. 31 | if task.OnSystemStack() { 32 | // This is the system stack. 33 | // Scan all words on the stack. 34 | markRoots(sp, stackTop) 35 | } else { 36 | // This is a goroutine stack. 37 | // It is an allocation, so scan it as if it were a value in a global. 38 | markRoot(0, sp) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /testdata/cgo/out.txt: -------------------------------------------------------------------------------- 1 | fortytwo: 42 2 | add: 8 3 | myint: 3 5 4 | myint size: 2 5 | longlong: -1099511627776 6 | global: 3 7 | defined ints: 5 5 8 | defined floats: +5.800000e+000 +5.800000e+000 9 | defined string: defined string 10 | defined char: 99 11 | 15: 15 12 | 25: 25 13 | callback 1: 50 14 | callback 2: 600 15 | bool: true true 16 | float: +3.100000e+000 17 | double: +3.200000e+000 18 | complex float: (+4.100000e+000+3.300000e+000i) 19 | complex double: (+4.200000e+000+3.400000e+000i) 20 | complex long double: (+4.300000e+000+3.500000e+000i) 21 | char match: true 22 | void* match: true true true 23 | int64_t match: true 24 | struct: true 256 -123456 +3.140000e+000 25 | array: 5 6 7 26 | union: true 27 | union s: 22 28 | union f: +3.140000e+000 29 | union global data: 5 8 1 30 | union local data: 5 8 1 31 | union s: true 32 | union f: +6.280000e+000 33 | union field: +6.280000e+000 34 | bitfield a: 15 35 | bitfield b: 1 36 | bitfield c: 2 37 | bitfield d: 47 38 | bitfield e: 5 39 | bitfield a: 7 40 | bitfield b: 0 41 | bitfield c: 3 42 | bitfield d: 47 43 | bitfield e: 5 44 | struct: 3 5 45 | n in chain: 3 46 | n in chain: 6 47 | n in chain: 7 48 | option: 12 49 | option A: 0 50 | option B: 1 51 | option C: -5 52 | option D: -4 53 | option E: 10 54 | option F: 11 55 | option G: 12 56 | option 2A: 20 57 | option 3A: 21 58 | enum width matches: true 59 | copied string: foobar 60 | -------------------------------------------------------------------------------- /src/machine/buffer.go: -------------------------------------------------------------------------------- 1 | package machine 2 | 3 | import ( 4 | "runtime/volatile" 5 | ) 6 | 7 | const bufferSize = 128 8 | 9 | // RingBuffer is ring buffer implementation inspired by post at 10 | // https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php 11 | type RingBuffer struct { 12 | rxbuffer [bufferSize]volatile.Register8 13 | head volatile.Register8 14 | tail volatile.Register8 15 | } 16 | 17 | // NewRingBuffer returns a new ring buffer. 18 | func NewRingBuffer() *RingBuffer { 19 | return &RingBuffer{} 20 | } 21 | 22 | // Used returns how many bytes in buffer have been used. 23 | func (rb *RingBuffer) Used() uint8 { 24 | return uint8(rb.head.Get() - rb.tail.Get()) 25 | } 26 | 27 | // Put stores a byte in the buffer. If the buffer is already 28 | // full, the method will return false. 29 | func (rb *RingBuffer) Put(val byte) bool { 30 | if rb.Used() != bufferSize { 31 | rb.head.Set(rb.head.Get() + 1) 32 | rb.rxbuffer[rb.head.Get()%bufferSize].Set(val) 33 | return true 34 | } 35 | return false 36 | } 37 | 38 | // Get returns a byte from the buffer. If the buffer is empty, 39 | // the method will return a false as the second value. 40 | func (rb *RingBuffer) Get() (byte, bool) { 41 | if rb.Used() != 0 { 42 | rb.tail.Set(rb.tail.Get() + 1) 43 | return rb.rxbuffer[rb.tail.Get()%bufferSize].Get(), true 44 | } 45 | return 0, false 46 | } 47 | -------------------------------------------------------------------------------- /src/syscall/syscall_darwin.go: -------------------------------------------------------------------------------- 1 | package syscall 2 | 3 | // This file defines errno and constants to match the darwin libsystem ABI. 4 | // Values have been determined experimentally by compiling some C code on macOS 5 | // with Clang and looking at the resulting LLVM IR. 6 | 7 | // This function returns the error location in the darwin ABI. 8 | // Discovered by compiling the following code using Clang: 9 | // 10 | // #include 11 | // int getErrno() { 12 | // return errno; 13 | // } 14 | // 15 | //export __error 16 | func libc___error() *int32 17 | 18 | // getErrno returns the current C errno. It may not have been caused by the last 19 | // call, so it should only be relied upon when the last call indicates an error 20 | // (for example, by returning -1). 21 | func getErrno() Errno { 22 | errptr := libc___error() 23 | return Errno(uintptr(*errptr)) 24 | } 25 | 26 | const ( 27 | ENOENT Errno = 2 28 | EINTR Errno = 4 29 | EMFILE Errno = 24 30 | EAGAIN Errno = 35 31 | ETIMEDOUT Errno = 60 32 | ENOSYS Errno = 78 33 | EWOULDBLOCK Errno = EAGAIN 34 | ) 35 | 36 | type Signal int 37 | 38 | const ( 39 | SIGCHLD Signal = 20 40 | SIGINT Signal = 2 41 | SIGKILL Signal = 9 42 | SIGTRAP Signal = 5 43 | SIGQUIT Signal = 3 44 | SIGTERM Signal = 15 45 | ) 46 | 47 | const ( 48 | O_RDONLY = 0 49 | O_WRONLY = 1 50 | O_RDWR = 2 51 | ) 52 | -------------------------------------------------------------------------------- /src/runtime/gc_stack_portable.go: -------------------------------------------------------------------------------- 1 | // +build gc.conservative gc.extalloc 2 | // +build !baremetal 3 | 4 | package runtime 5 | 6 | import ( 7 | "unsafe" 8 | ) 9 | 10 | //go:extern runtime.stackChainStart 11 | var stackChainStart *stackChainObject 12 | 13 | type stackChainObject struct { 14 | parent *stackChainObject 15 | numSlots uintptr 16 | } 17 | 18 | // markStack marks all root pointers found on the stack. 19 | // 20 | // This implementation is conservative and relies on the compiler inserting code 21 | // to manually push/pop stack objects that are stored in a linked list starting 22 | // with stackChainStart. Manually keeping track of stack values is _much_ more 23 | // expensive than letting the compiler do it and it inhibits a few important 24 | // optimizations, but it has the big advantage of being portable to basically 25 | // any ISA, including WebAssembly. 26 | func markStack() { 27 | stackObject := stackChainStart 28 | for stackObject != nil { 29 | start := uintptr(unsafe.Pointer(stackObject)) + unsafe.Sizeof(uintptr(0))*2 30 | end := start + stackObject.numSlots*unsafe.Alignof(uintptr(0)) 31 | markRoots(start, end) 32 | stackObject = stackObject.parent 33 | } 34 | } 35 | 36 | // trackPointer is a stub function call inserted by the compiler during IR 37 | // construction. Calls to it are later replaced with regular stack bookkeeping 38 | // code. 39 | func trackPointer(ptr unsafe.Pointer) 40 | -------------------------------------------------------------------------------- /testdata/cgo/main.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | int global = 3; 4 | bool globalBool = 1; 5 | bool globalBool2 = 10; // test narrowing 6 | float globalFloat = 3.1; 7 | double globalDouble = 3.2; 8 | _Complex float globalComplexFloat = 4.1+3.3i; 9 | _Complex double globalComplexDouble = 4.2+3.4i; 10 | _Complex double globalComplexLongDouble = 4.3+3.5i; 11 | char globalChar = 100; 12 | void *globalVoidPtrSet = &global; 13 | void *globalVoidPtrNull; 14 | int64_t globalInt64 = -(2LL << 40); 15 | collection_t globalStruct = {256, -123456, 3.14, 88}; 16 | int globalStructSize = sizeof(globalStruct); 17 | short globalArray[3] = {5, 6, 7}; 18 | joined_t globalUnion; 19 | int globalUnionSize = sizeof(globalUnion); 20 | option_t globalOption = optionG; 21 | bitfield_t globalBitfield = {244, 15, 1, 2, 47, 5}; 22 | 23 | int smallEnumWidth = sizeof(option2_t); 24 | 25 | int fortytwo() { 26 | return 42; 27 | } 28 | 29 | int add(int a, int b) { 30 | return a + b; 31 | } 32 | 33 | int doCallback(int a, int b, binop_t callback) { 34 | return callback(a, b); 35 | } 36 | 37 | void store(int value, int *ptr) { 38 | *ptr = value; 39 | } 40 | 41 | void unionSetShort(short s) { 42 | globalUnion.s = s; 43 | } 44 | 45 | void unionSetFloat(float f) { 46 | globalUnion.f = f; 47 | } 48 | 49 | void unionSetData(short f0, short f1, short f2) { 50 | globalUnion.data[0] = 5; 51 | globalUnion.data[1] = 8; 52 | globalUnion.data[2] = 1; 53 | } 54 | -------------------------------------------------------------------------------- /testdata/map.txt: -------------------------------------------------------------------------------- 1 | map length: 2 2 | map read: answer = 42 3 | answer = 42 4 | foo = 3 5 | map length: 1 6 | map read: data = 3 7 | data = 3 8 | map length: 12 9 | map read: three = 3 10 | one = 1 11 | two = 2 12 | three = 3 13 | four = 4 14 | five = 5 15 | six = 6 16 | seven = 7 17 | eight = 8 18 | nine = 9 19 | ten = 10 20 | eleven = 11 21 | twelve = 12 22 | map length: 12 23 | map read: ten = 10 24 | one = 1 25 | two = 2 26 | three = 3 27 | four = 4 28 | five = 5 29 | six = 6 30 | seven = 7 31 | eight = 8 32 | nine = 9 33 | ten = 10 34 | eleven = 11 35 | twelve = 12 36 | map length: 11 37 | map read: seven = 7 38 | one = 1 39 | two = 2 40 | three = 3 41 | four = 4 42 | five = 5 43 | seven = 7 44 | eight = 8 45 | nine = 9 46 | ten = 10 47 | eleven = 11 48 | twelve = 12 49 | lookup with comma-ok: eight 8 true 50 | lookup with comma-ok: nokey 0 false 51 | false true 2 52 | true false 0 53 | nilmap: 0 54 | 4 55 | 42 56 | 4321 57 | 5555 58 | itfMap[3]: 0 59 | itfMap[3.14]: 3 60 | itfMap[8]: 8 61 | itfMap[uint8(8)]: 80 62 | itfMap["eight"]: 800 63 | itfMap[[2]int{5, 2}]: 52 64 | itfMap[true]: 1 65 | itfMap[8]: 0 66 | floatMap[42]: 84 67 | floatMap[43]: 0 68 | floatMap[42]: 0 69 | structMap[{"tau", 6.28}]: 5 70 | structMap[{"Tau", 6.28}]: 0 71 | structMap[{"tau", 3.14}]: 0 72 | structMap[{"tau", 6.28}]: 0 73 | tested preallocated map 74 | tested growing of a map 75 | -------------------------------------------------------------------------------- /compiler/ircheck/errors.go: -------------------------------------------------------------------------------- 1 | package ircheck 2 | 3 | import ( 4 | "go/scanner" 5 | "go/token" 6 | "path/filepath" 7 | 8 | "tinygo.org/x/go-llvm" 9 | ) 10 | 11 | // errorAt returns an error value at the location of the instruction. 12 | // The location information may not be complete as it depends on debug 13 | // information in the IR. 14 | func errorAt(inst llvm.Value, msg string) scanner.Error { 15 | return scanner.Error{ 16 | Pos: getPosition(inst), 17 | Msg: msg, 18 | } 19 | } 20 | 21 | // getPosition returns the position information for the given value, as far as 22 | // it is available. 23 | func getPosition(val llvm.Value) token.Position { 24 | if !val.IsAInstruction().IsNil() { 25 | loc := val.InstructionDebugLoc() 26 | if loc.IsNil() { 27 | return token.Position{} 28 | } 29 | file := loc.LocationScope().ScopeFile() 30 | return token.Position{ 31 | Filename: filepath.Join(file.FileDirectory(), file.FileFilename()), 32 | Line: int(loc.LocationLine()), 33 | Column: int(loc.LocationColumn()), 34 | } 35 | } else if !val.IsAFunction().IsNil() { 36 | loc := val.Subprogram() 37 | if loc.IsNil() { 38 | return token.Position{} 39 | } 40 | file := loc.ScopeFile() 41 | return token.Position{ 42 | Filename: filepath.Join(file.FileDirectory(), file.FileFilename()), 43 | Line: int(loc.SubprogramLine()), 44 | } 45 | } else { 46 | return token.Position{} 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/machine/i2s.go: -------------------------------------------------------------------------------- 1 | // +build sam 2 | 3 | // This is the definition for I2S bus functions. 4 | // Actual implementations if available for any given hardware 5 | // are to be found in its the board definition. 6 | // 7 | // For more info about I2S, see: https://en.wikipedia.org/wiki/I%C2%B2S 8 | // 9 | 10 | package machine 11 | 12 | type I2SMode uint8 13 | type I2SStandard uint8 14 | type I2SClockSource uint8 15 | type I2SDataFormat uint8 16 | 17 | const ( 18 | I2SModeMaster I2SMode = iota 19 | I2SModeSlave 20 | I2SModePDM 21 | ) 22 | 23 | const ( 24 | I2StandardPhilips I2SStandard = iota 25 | I2SStandardMSB 26 | I2SStandardLSB 27 | ) 28 | 29 | const ( 30 | I2SClockSourceInternal I2SClockSource = iota 31 | I2SClockSourceExternal 32 | ) 33 | 34 | const ( 35 | I2SDataFormatDefault I2SDataFormat = 0 36 | I2SDataFormat8bit = 8 37 | I2SDataFormat16bit = 16 38 | I2SDataFormat24bit = 24 39 | I2SDataFormat32bit = 32 40 | ) 41 | 42 | // All fields are optional and may not be required or used on a particular platform. 43 | type I2SConfig struct { 44 | SCK Pin 45 | WS Pin 46 | SD Pin 47 | Mode I2SMode 48 | Standard I2SStandard 49 | ClockSource I2SClockSource 50 | DataFormat I2SDataFormat 51 | AudioFrequency uint32 52 | MasterClockOutput bool 53 | Stereo bool 54 | } 55 | -------------------------------------------------------------------------------- /src/machine/machine_atmega328p.go: -------------------------------------------------------------------------------- 1 | // +build avr,atmega328p 2 | 3 | package machine 4 | 5 | import ( 6 | "device/avr" 7 | "runtime/volatile" 8 | ) 9 | 10 | const irq_USART0_RX = avr.IRQ_USART_RX 11 | 12 | // Configure sets the pin to input or output. 13 | func (p Pin) Configure(config PinConfig) { 14 | if config.Mode == PinOutput { // set output bit 15 | if p < 8 { 16 | avr.DDRD.SetBits(1 << uint8(p)) 17 | } else if p < 14 { 18 | avr.DDRB.SetBits(1 << uint8(p-8)) 19 | } else { 20 | avr.DDRC.SetBits(1 << uint8(p-14)) 21 | } 22 | } else { // configure input: clear output bit 23 | if p < 8 { 24 | avr.DDRD.ClearBits(1 << uint8(p)) 25 | } else if p < 14 { 26 | avr.DDRB.ClearBits(1 << uint8(p-8)) 27 | } else { 28 | avr.DDRC.ClearBits(1 << uint8(p-14)) 29 | } 30 | } 31 | } 32 | 33 | // Get returns the current value of a GPIO pin. 34 | func (p Pin) Get() bool { 35 | if p < 8 { 36 | val := avr.PIND.Get() & (1 << uint8(p)) 37 | return (val > 0) 38 | } else if p < 14 { 39 | val := avr.PINB.Get() & (1 << uint8(p-8)) 40 | return (val > 0) 41 | } else { 42 | val := avr.PINC.Get() & (1 << uint8(p-14)) 43 | return (val > 0) 44 | } 45 | } 46 | 47 | func (p Pin) getPortMask() (*volatile.Register8, uint8) { 48 | if p < 8 { 49 | return avr.PORTD, 1 << uint8(p) 50 | } else if p < 14 { 51 | return avr.PORTB, 1 << uint8(p-8) 52 | } else { 53 | return avr.PORTC, 1 << uint8(p-14) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /transform/maps.go: -------------------------------------------------------------------------------- 1 | package transform 2 | 3 | import ( 4 | "tinygo.org/x/go-llvm" 5 | ) 6 | 7 | // OptimizeMaps eliminates created but unused maps. 8 | // 9 | // In the future, this should statically allocate created but never modified 10 | // maps. This has not yet been implemented, however. 11 | func OptimizeMaps(mod llvm.Module) { 12 | hashmapMake := mod.NamedFunction("runtime.hashmapMake") 13 | if hashmapMake.IsNil() { 14 | // nothing to optimize 15 | return 16 | } 17 | 18 | hashmapBinarySet := mod.NamedFunction("runtime.hashmapBinarySet") 19 | hashmapStringSet := mod.NamedFunction("runtime.hashmapStringSet") 20 | 21 | for _, makeInst := range getUses(hashmapMake) { 22 | updateInsts := []llvm.Value{} 23 | unknownUses := false // are there any uses other than setting a value? 24 | 25 | for _, use := range getUses(makeInst) { 26 | if use := use.IsACallInst(); !use.IsNil() { 27 | switch use.CalledValue() { 28 | case hashmapBinarySet, hashmapStringSet: 29 | updateInsts = append(updateInsts, use) 30 | default: 31 | unknownUses = true 32 | } 33 | } else { 34 | unknownUses = true 35 | } 36 | } 37 | 38 | if !unknownUses { 39 | // This map can be entirely removed, as it is only created but never 40 | // used. 41 | for _, inst := range updateInsts { 42 | inst.EraseFromParentAsInstruction() 43 | } 44 | makeInst.EraseFromParentAsInstruction() 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /transform/testdata/wasm-abi.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 2 | target triple = "wasm32-unknown-unknown-wasm" 3 | 4 | declare i64 @"externalCall$i64wrap"(i8*, i32, i64) 5 | 6 | define internal i64 @testCall(i8* %ptr, i32 %len, i64 %foo) { 7 | %i64asptr = alloca i64 8 | %i64asptr1 = alloca i64 9 | store i64 %foo, i64* %i64asptr1 10 | call void @externalCall(i64* %i64asptr, i8* %ptr, i32 %len, i64* %i64asptr1) 11 | %retval = load i64, i64* %i64asptr 12 | ret i64 %retval 13 | } 14 | 15 | define internal i64 @testCallNonEntry(i8* %ptr, i32 %len) { 16 | entry: 17 | %i64asptr = alloca i64 18 | %i64asptr1 = alloca i64 19 | br label %bb1 20 | 21 | bb1: ; preds = %entry 22 | store i64 3, i64* %i64asptr1 23 | call void @externalCall(i64* %i64asptr, i8* %ptr, i32 %len, i64* %i64asptr1) 24 | %retval = load i64, i64* %i64asptr 25 | ret i64 %retval 26 | } 27 | 28 | define internal void @"exportedFunction$i64wrap"(i64 %foo) unnamed_addr { 29 | %unused = shl i64 %foo, 1 30 | ret void 31 | } 32 | 33 | define internal void @callExportedFunction(i64 %foo) { 34 | call void @"exportedFunction$i64wrap"(i64 %foo) 35 | ret void 36 | } 37 | 38 | declare void @externalCall(i64*, i8*, i32, i64*) 39 | 40 | define void @exportedFunction(i64* %0) { 41 | entry: 42 | %i64 = load i64, i64* %0 43 | call void @"exportedFunction$i64wrap"(i64 %i64) 44 | ret void 45 | } 46 | -------------------------------------------------------------------------------- /src/machine/machine_atsamd51g19.go: -------------------------------------------------------------------------------- 1 | // +build sam,atsamd51,atsamd51g19 2 | 3 | // Peripheral abstraction layer for the atsamd51. 4 | // 5 | // Datasheet: 6 | // http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf 7 | // 8 | package machine 9 | 10 | import "device/sam" 11 | 12 | const HSRAM_SIZE = 0x00030000 13 | 14 | // InitPWM initializes the PWM interface. 15 | func InitPWM() { 16 | // turn on timer clocks used for PWM 17 | sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_ | sam.MCLK_APBBMASK_TCC1_) 18 | sam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_) 19 | 20 | //use clock generator 0 21 | sam.GCLK.PCHCTRL[25].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | 22 | sam.GCLK_PCHCTRL_CHEN) 23 | sam.GCLK.PCHCTRL[29].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | 24 | sam.GCLK_PCHCTRL_CHEN) 25 | } 26 | 27 | // getTimer returns the timer to be used for PWM on this pin 28 | func (pwm PWM) getTimer() *sam.TCC_Type { 29 | switch pwm.Pin { 30 | case PA16: 31 | return sam.TCC1 32 | case PA17: 33 | return sam.TCC1 34 | case PA14: 35 | return sam.TCC2 36 | case PA15: 37 | return sam.TCC2 38 | case PA18: 39 | return sam.TCC1 40 | case PA19: 41 | return sam.TCC1 42 | case PA20: 43 | return sam.TCC0 44 | case PA21: 45 | return sam.TCC0 46 | case PA23: 47 | return sam.TCC0 48 | case PA22: 49 | return sam.TCC0 50 | default: 51 | return nil // not supported on this pin 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/machine/machine_stm32.go: -------------------------------------------------------------------------------- 1 | // +build stm32 2 | 3 | package machine 4 | 5 | // Peripheral abstraction layer for the stm32. 6 | 7 | type PinMode uint8 8 | 9 | // Peripheral operations sequence: 10 | // 1. Enable the clock to the alternate function. 11 | // 2. Enable clock to corresponding GPIO 12 | // 3. Attach the alternate function. 13 | // 4. Configure the input-output port and pins (of the corresponding GPIOx) to match the AF . 14 | // 5. If desired enable the nested vector interrupt control to generate interrupts. 15 | // 6. Program the AF/peripheral for the required configuration (eg baud rate for a USART) . 16 | 17 | // Given that the stm32 family has the AF and GPIO on different registers based on the chip, 18 | // use the main function here for configuring, and use hooks in the more specific chip 19 | // definition files 20 | // Also, the stm32f1xx series handles things differently from the stm32f0/2/3/4 21 | 22 | // ---------- General pin operations ---------- 23 | 24 | // Set the pin to high or low. 25 | // Warning: only use this on an output pin! 26 | func (p Pin) Set(high bool) { 27 | port := p.getPort() 28 | pin := uint8(p) % 16 29 | if high { 30 | port.BSRR.Set(1 << pin) 31 | } else { 32 | port.BSRR.Set(1 << (pin + 16)) 33 | } 34 | } 35 | 36 | // Get returns the current value of a GPIO pin. 37 | func (p Pin) Get() bool { 38 | port := p.getPort() 39 | pin := uint8(p) % 16 40 | val := port.IDR.Get() & (1 << pin) 41 | return (val > 0) 42 | } 43 | -------------------------------------------------------------------------------- /transform/testdata/gc-globals.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 2 | target triple = "wasm32-unknown-unknown-wasm" 3 | 4 | %runtime._string = type { i8*, i32 } 5 | %runtime._interface = type { i32, i8* } 6 | 7 | @globalInt = global i32 5 8 | @globalString = global %runtime._string zeroinitializer 9 | @globalInterface = global %runtime._interface zeroinitializer 10 | @constString = constant %runtime._string zeroinitializer 11 | @constInterface = constant %runtime._interface zeroinitializer 12 | @runtime.trackedGlobalsLength = external global i32 13 | @runtime.trackedGlobalsBitmap = external global [0 x i8] 14 | @runtime.trackedGlobalsStart = external global i32 15 | 16 | define void @main() { 17 | %1 = load i32, i32* @globalInt 18 | %2 = load %runtime._string, %runtime._string* @globalString 19 | %3 = load %runtime._interface, %runtime._interface* @globalInterface 20 | %4 = load %runtime._string, %runtime._string* @constString 21 | %5 = load %runtime._interface, %runtime._interface* @constInterface 22 | ret void 23 | } 24 | 25 | define void @runtime.markGlobals() { 26 | ; Very small subset of what runtime.markGlobals would really do. 27 | ; Just enough to make sure the transformation is correct. 28 | %1 = load i32, i32* @runtime.trackedGlobalsStart 29 | %2 = load i32, i32* @runtime.trackedGlobalsLength 30 | %3 = getelementptr inbounds [0 x i8], [0 x i8]* @runtime.trackedGlobalsBitmap, i32 0, i32 0 31 | %4 = load i8, i8* %3 32 | ret void 33 | } 34 | -------------------------------------------------------------------------------- /src/machine/machine.go: -------------------------------------------------------------------------------- 1 | package machine 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrInvalidInputPin = errors.New("machine: invalid input pin") 7 | ErrInvalidOutputPin = errors.New("machine: invalid output pin") 8 | ErrInvalidClockPin = errors.New("machine: invalid clock pin") 9 | ErrInvalidDataPin = errors.New("machine: invalid data pin") 10 | ) 11 | 12 | type PinConfig struct { 13 | Mode PinMode 14 | } 15 | 16 | // Pin is a single pin on a chip, which may be connected to other hardware 17 | // devices. It can either be used directly as GPIO pin or it can be used in 18 | // other peripherals like ADC, I2C, etc. 19 | type Pin int8 20 | 21 | // NoPin explicitly indicates "not a pin". Use this pin if you want to leave one 22 | // of the pins in a peripheral unconfigured (if supported by the hardware). 23 | const NoPin = Pin(-1) 24 | 25 | // High sets this GPIO pin to high, assuming it has been configured as an output 26 | // pin. It is hardware dependent (and often undefined) what happens if you set a 27 | // pin to high that is not configured as an output pin. 28 | func (p Pin) High() { 29 | p.Set(true) 30 | } 31 | 32 | // Low sets this GPIO pin to low, assuming it has been configured as an output 33 | // pin. It is hardware dependent (and often undefined) what happens if you set a 34 | // pin to low that is not configured as an output pin. 35 | func (p Pin) Low() { 36 | p.Set(false) 37 | } 38 | 39 | type PWM struct { 40 | Pin Pin 41 | } 42 | 43 | type ADC struct { 44 | Pin Pin 45 | } 46 | -------------------------------------------------------------------------------- /src/machine/usb_nrf52840_reset_uf2.go: -------------------------------------------------------------------------------- 1 | // +build nrf52840,nrf52840_reset_uf2 2 | 3 | package machine 4 | 5 | import ( 6 | "device/arm" 7 | "device/nrf" 8 | ) 9 | 10 | const ( 11 | DFU_MAGIC_SERIAL_ONLY_RESET = 0x4e 12 | DFU_MAGIC_UF2_RESET = 0x57 13 | DFU_MAGIC_OTA_RESET = 0xA8 14 | ) 15 | 16 | // checkShouldReset is called by the USB-CDC implementation to check whether to 17 | // reset into the bootloader/OTA and if so, resets the chip appropriately. 18 | func checkShouldReset() { 19 | if usbLineInfo.dwDTERate == 1200 && usbLineInfo.lineState&usb_CDC_LINESTATE_DTR == 0 { 20 | EnterUF2Bootloader() 21 | } 22 | } 23 | 24 | // EnterSerialBootloader resets the chip into the serial bootloader. After 25 | // reset, it can be flashed using serial/nrfutil. 26 | func EnterSerialBootloader() { 27 | arm.DisableInterrupts() 28 | nrf.POWER.GPREGRET.Set(DFU_MAGIC_SERIAL_ONLY_RESET) 29 | arm.SystemReset() 30 | } 31 | 32 | // EnterUF2Bootloader resets the chip into the UF2 bootloader. After reset, it 33 | // can be flashed via nrfutil or by copying a UF2 file to the mass storage device 34 | func EnterUF2Bootloader() { 35 | arm.DisableInterrupts() 36 | nrf.POWER.GPREGRET.Set(DFU_MAGIC_UF2_RESET) 37 | arm.SystemReset() 38 | } 39 | 40 | // EnterOTABootloader resets the chip into the bootloader so that it can be 41 | // flashed via an OTA update 42 | func EnterOTABootloader() { 43 | arm.DisableInterrupts() 44 | nrf.POWER.GPREGRET.Set(DFU_MAGIC_OTA_RESET) 45 | arm.SystemReset() 46 | } 47 | -------------------------------------------------------------------------------- /src/machine/board_atsamd21.go: -------------------------------------------------------------------------------- 1 | // +build sam,atsamd21 arduino_nano33 circuitplay_express 2 | 3 | package machine 4 | 5 | // Return the current CPU frequency in hertz. 6 | func CPUFrequency() uint32 { 7 | return 48000000 8 | } 9 | 10 | // Hardware pins 11 | const ( 12 | PA00 Pin = 0 13 | PA01 Pin = 1 14 | PA02 Pin = 2 15 | PA03 Pin = 3 16 | PA04 Pin = 4 17 | PA05 Pin = 5 18 | PA06 Pin = 6 19 | PA07 Pin = 7 20 | PA08 Pin = 8 21 | PA09 Pin = 9 22 | PA10 Pin = 10 23 | PA11 Pin = 11 24 | PA12 Pin = 12 25 | PA13 Pin = 13 26 | PA14 Pin = 14 27 | PA15 Pin = 15 28 | PA16 Pin = 16 29 | PA17 Pin = 17 30 | PA18 Pin = 18 31 | PA19 Pin = 19 32 | PA20 Pin = 20 33 | PA21 Pin = 21 34 | PA22 Pin = 22 35 | PA23 Pin = 23 36 | PA24 Pin = 24 37 | PA25 Pin = 25 38 | PA26 Pin = 26 39 | PA27 Pin = 27 40 | PA28 Pin = 28 41 | PA29 Pin = 29 42 | PA30 Pin = 30 43 | PA31 Pin = 31 44 | PB00 Pin = 32 45 | PB01 Pin = 33 46 | PB02 Pin = 34 47 | PB03 Pin = 35 48 | PB04 Pin = 36 49 | PB05 Pin = 37 50 | PB06 Pin = 38 51 | PB07 Pin = 39 52 | PB08 Pin = 40 53 | PB09 Pin = 41 54 | PB10 Pin = 42 55 | PB11 Pin = 43 56 | PB12 Pin = 44 57 | PB13 Pin = 45 58 | PB14 Pin = 46 59 | PB15 Pin = 47 60 | PB16 Pin = 48 61 | PB17 Pin = 49 62 | PB18 Pin = 50 63 | PB19 Pin = 51 64 | PB20 Pin = 52 65 | PB21 Pin = 53 66 | PB22 Pin = 54 67 | PB23 Pin = 55 68 | PB24 Pin = 56 69 | PB25 Pin = 57 70 | PB26 Pin = 58 71 | PB27 Pin = 59 72 | PB28 Pin = 60 73 | PB29 Pin = 61 74 | PB30 Pin = 62 75 | PB31 Pin = 63 76 | ) 77 | -------------------------------------------------------------------------------- /src/runtime/runtime_tinygoriscv_qemu.go: -------------------------------------------------------------------------------- 1 | // +build tinygo.riscv,virt,qemu 2 | 3 | package runtime 4 | 5 | import ( 6 | "device/riscv" 7 | "runtime/volatile" 8 | "unsafe" 9 | ) 10 | 11 | // This file implements the VirtIO RISC-V interface implemented in QEMU, which 12 | // is an interface designed for emulation. 13 | 14 | type timeUnit int64 15 | 16 | const tickMicros = 1 17 | 18 | var timestamp timeUnit 19 | 20 | func postinit() {} 21 | 22 | //export main 23 | func main() { 24 | preinit() 25 | run() 26 | abort() 27 | } 28 | 29 | const asyncScheduler = false 30 | 31 | func sleepTicks(d timeUnit) { 32 | // TODO: actually sleep here for the given time. 33 | timestamp += d 34 | } 35 | 36 | func ticks() timeUnit { 37 | return timestamp 38 | } 39 | 40 | // Memory-mapped I/O as defined by QEMU. 41 | // Source: https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c 42 | // Technically this is an implementation detail but hopefully they won't change 43 | // the memory-mapped I/O registers. 44 | var ( 45 | // UART0 output register. 46 | stdoutWrite = (*volatile.Register8)(unsafe.Pointer(uintptr(0x10000000))) 47 | // SiFive test finisher 48 | testFinisher = (*volatile.Register16)(unsafe.Pointer(uintptr(0x100000))) 49 | ) 50 | 51 | func putchar(c byte) { 52 | stdoutWrite.Set(uint8(c)) 53 | } 54 | 55 | func abort() { 56 | // Make sure the QEMU process exits. 57 | testFinisher.Set(0x5555) // FINISHER_PASS 58 | 59 | // Lock up forever (as a fallback). 60 | for { 61 | riscv.Asm("wfi") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/examples/wasm/main/index.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | Go wasm 12 | 13 | 14 | 15 | 20 | 21 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/runtime/volatile/volatile.go: -------------------------------------------------------------------------------- 1 | // Package volatile provides definitions for volatile loads and stores. These 2 | // are implemented as compiler builtins. 3 | // 4 | // The load operations load a volatile value. The store operations store to a 5 | // volatile value. The compiler will emit exactly one load or store operation 6 | // when possible and will not reorder volatile operations. However, the compiler 7 | // may move other operations across load/store operations, so make sure that all 8 | // relevant loads/stores are done in a volatile way if this is a problem. 9 | // 10 | // These loads and stores are commonly used to read/write values from memory 11 | // mapped peripheral devices. They do not provide atomicity, use the sync/atomic 12 | // package for that. 13 | // 14 | // For more details: https://llvm.org/docs/LangRef.html#volatile-memory-accesses 15 | // and https://blog.regehr.org/archives/28. 16 | package volatile 17 | 18 | // LoadUint8 loads the volatile value *addr. 19 | func LoadUint8(addr *uint8) (val uint8) 20 | 21 | // LoadUint16 loads the volatile value *addr. 22 | func LoadUint16(addr *uint16) (val uint16) 23 | 24 | // LoadUint32 loads the volatile value *addr. 25 | func LoadUint32(addr *uint32) (val uint32) 26 | 27 | // StoreUint8 stores val to the volatile value *addr. 28 | func StoreUint8(addr *uint8, val uint8) 29 | 30 | // StoreUint16 stores val to the volatile value *addr. 31 | func StoreUint16(addr *uint16, val uint16) 32 | 33 | // StoreUint32 stores val to the volatile value *addr. 34 | func StoreUint32(addr *uint32, val uint32) 35 | -------------------------------------------------------------------------------- /transform/testdata/maps.out.ll: -------------------------------------------------------------------------------- 1 | target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" 2 | target triple = "armv7m-none-eabi" 3 | 4 | %runtime.hashmap = type { %runtime.hashmap*, i8*, i32, i8, i8, i8 } 5 | 6 | @answer = constant [6 x i8] c"answer" 7 | 8 | declare nonnull %runtime.hashmap* @runtime.hashmapMake(i8, i8, i32) 9 | 10 | declare void @runtime.hashmapStringSet(%runtime.hashmap* nocapture, i8*, i32, i8* nocapture readonly) 11 | 12 | declare i1 @runtime.hashmapStringGet(%runtime.hashmap* nocapture, i8*, i32, i8* nocapture) 13 | 14 | define void @testUnused() { 15 | ret void 16 | } 17 | 18 | define i32 @testReadonly() { 19 | %map = call %runtime.hashmap* @runtime.hashmapMake(i8 4, i8 4, i32 0) 20 | %hashmap.value = alloca i32 21 | store i32 42, i32* %hashmap.value 22 | %hashmap.value.bitcast = bitcast i32* %hashmap.value to i8* 23 | call void @runtime.hashmapStringSet(%runtime.hashmap* %map, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @answer, i32 0, i32 0), i32 6, i8* %hashmap.value.bitcast) 24 | %hashmap.value2 = alloca i32 25 | %hashmap.value2.bitcast = bitcast i32* %hashmap.value2 to i8* 26 | %commaOk = call i1 @runtime.hashmapStringGet(%runtime.hashmap* %map, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @answer, i32 0, i32 0), i32 6, i8* %hashmap.value2.bitcast) 27 | %loadedValue = load i32, i32* %hashmap.value2 28 | ret i32 %loadedValue 29 | } 30 | 31 | define %runtime.hashmap* @testUsed() { 32 | %1 = call %runtime.hashmap* @runtime.hashmapMake(i8 4, i8 4, i32 0) 33 | ret %runtime.hashmap* %1 34 | } 35 | -------------------------------------------------------------------------------- /src/machine/board_microbit.go: -------------------------------------------------------------------------------- 1 | // +build microbit 2 | 3 | package machine 4 | 5 | // The micro:bit does not have a 32kHz crystal on board. 6 | const HasLowFrequencyCrystal = false 7 | 8 | // Buttons on the micro:bit (A and B) 9 | const ( 10 | BUTTON Pin = BUTTONA 11 | BUTTONA Pin = 17 12 | BUTTONB Pin = 26 13 | ) 14 | 15 | // UART pins 16 | const ( 17 | UART_TX_PIN Pin = 24 18 | UART_RX_PIN Pin = 25 19 | ) 20 | 21 | // ADC pins 22 | const ( 23 | ADC0 Pin = 3 // P0 on the board 24 | ADC1 Pin = 2 // P1 on the board 25 | ADC2 Pin = 1 // P2 on the board 26 | ) 27 | 28 | // I2C pins 29 | const ( 30 | SDA_PIN Pin = 30 // P20 on the board 31 | SCL_PIN Pin = 0 // P19 on the board 32 | ) 33 | 34 | // SPI pins 35 | const ( 36 | SPI0_SCK_PIN Pin = 23 // P13 on the board 37 | SPI0_MOSI_PIN Pin = 21 // P15 on the board 38 | SPI0_MISO_PIN Pin = 22 // P14 on the board 39 | ) 40 | 41 | // GPIO/Analog pins 42 | const ( 43 | P0 Pin = 3 44 | P1 Pin = 2 45 | P2 Pin = 1 46 | P3 Pin = 4 47 | P4 Pin = 5 48 | P5 Pin = 17 49 | P6 Pin = 12 50 | P7 Pin = 11 51 | P8 Pin = 18 52 | P9 Pin = 10 53 | P10 Pin = 6 54 | P11 Pin = 26 55 | P12 Pin = 20 56 | P13 Pin = 23 57 | P14 Pin = 22 58 | P15 Pin = 21 59 | P16 Pin = 16 60 | ) 61 | 62 | // LED matrix pins 63 | const ( 64 | LED_COL_1 Pin = 4 65 | LED_COL_2 Pin = 5 66 | LED_COL_3 Pin = 6 67 | LED_COL_4 Pin = 7 68 | LED_COL_5 Pin = 8 69 | LED_COL_6 Pin = 9 70 | LED_COL_7 Pin = 10 71 | LED_COL_8 Pin = 11 72 | LED_COL_9 Pin = 12 73 | LED_ROW_1 Pin = 13 74 | LED_ROW_2 Pin = 14 75 | LED_ROW_3 Pin = 15 76 | ) 77 | -------------------------------------------------------------------------------- /src/runtime/runtime_atsamd21e18.go: -------------------------------------------------------------------------------- 1 | // +build sam,atsamd21,atsamd21e18 2 | 3 | package runtime 4 | 5 | import ( 6 | "device/sam" 7 | ) 8 | 9 | func initSERCOMClocks() { 10 | // Turn on clock to SERCOM0 for UART0 11 | sam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM0_) 12 | 13 | // Use GCLK0 for SERCOM0 aka UART0 14 | // GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx) 15 | // GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source 16 | // GCLK_CLKCTRL_CLKEN ; 17 | sam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM0_CORE << sam.GCLK_CLKCTRL_ID_Pos) | 18 | (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) | 19 | sam.GCLK_CLKCTRL_CLKEN) 20 | waitForSync() 21 | 22 | // Turn on clock to SERCOM1 23 | sam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM1_) 24 | sam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM1_CORE << sam.GCLK_CLKCTRL_ID_Pos) | 25 | (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) | 26 | sam.GCLK_CLKCTRL_CLKEN) 27 | waitForSync() 28 | 29 | // Turn on clock to SERCOM2 30 | sam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM2_) 31 | sam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM2_CORE << sam.GCLK_CLKCTRL_ID_Pos) | 32 | (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) | 33 | sam.GCLK_CLKCTRL_CLKEN) 34 | waitForSync() 35 | 36 | // Turn on clock to SERCOM3 37 | sam.PM.APBCMASK.SetBits(sam.PM_APBCMASK_SERCOM3_) 38 | sam.GCLK.CLKCTRL.Set((sam.GCLK_CLKCTRL_ID_SERCOM3_CORE << sam.GCLK_CLKCTRL_ID_Pos) | 39 | (sam.GCLK_CLKCTRL_GEN_GCLK0 << sam.GCLK_CLKCTRL_GEN_Pos) | 40 | sam.GCLK_CLKCTRL_CLKEN) 41 | waitForSync() 42 | } 43 | -------------------------------------------------------------------------------- /src/runtime/float.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package runtime 6 | 7 | import "unsafe" 8 | 9 | var inf = float64frombits(0x7FF0000000000000) 10 | 11 | // isNaN reports whether f is an IEEE 754 ``not-a-number'' value. 12 | func isNaN(f float64) (is bool) { 13 | // IEEE 754 says that only NaNs satisfy f != f. 14 | return f != f 15 | } 16 | 17 | // isFinite reports whether f is neither NaN nor an infinity. 18 | func isFinite(f float64) bool { 19 | return !isNaN(f - f) 20 | } 21 | 22 | // isInf reports whether f is an infinity. 23 | func isInf(f float64) bool { 24 | return !isNaN(f) && !isFinite(f) 25 | } 26 | 27 | // Abs returns the absolute value of x. 28 | // 29 | // Special cases are: 30 | // Abs(±Inf) = +Inf 31 | // Abs(NaN) = NaN 32 | func abs(x float64) float64 { 33 | const sign = 1 << 63 34 | return float64frombits(float64bits(x) &^ sign) 35 | } 36 | 37 | // copysign returns a value with the magnitude 38 | // of x and the sign of y. 39 | func copysign(x, y float64) float64 { 40 | const sign = 1 << 63 41 | return float64frombits(float64bits(x)&^sign | float64bits(y)&sign) 42 | } 43 | 44 | // Float64bits returns the IEEE 754 binary representation of f. 45 | func float64bits(f float64) uint64 { 46 | return *(*uint64)(unsafe.Pointer(&f)) 47 | } 48 | 49 | // Float64frombits returns the floating point number corresponding 50 | // the IEEE 754 binary representation b. 51 | func float64frombits(b uint64) float64 { 52 | return *(*float64)(unsafe.Pointer(&b)) 53 | } 54 | -------------------------------------------------------------------------------- /src/runtime/runtime_arm7tdmi.go: -------------------------------------------------------------------------------- 1 | // +build arm7tdmi 2 | 3 | package runtime 4 | 5 | import ( 6 | _ "runtime/interrupt" // make sure the interrupt handler is defined 7 | "unsafe" 8 | ) 9 | 10 | type timeUnit int64 11 | 12 | const tickMicros = 1 13 | 14 | func putchar(c byte) { 15 | // dummy, TODO 16 | } 17 | 18 | //go:extern _sbss 19 | var _sbss [0]byte 20 | 21 | //go:extern _ebss 22 | var _ebss [0]byte 23 | 24 | //go:extern _sdata 25 | var _sdata [0]byte 26 | 27 | //go:extern _sidata 28 | var _sidata [0]byte 29 | 30 | //go:extern _edata 31 | var _edata [0]byte 32 | 33 | func postinit() {} 34 | 35 | // Entry point for Go. Initialize all packages and call main.main(). 36 | //export main 37 | func main() { 38 | // Initialize .data and .bss sections. 39 | preinit() 40 | 41 | // Run program. 42 | run() 43 | } 44 | 45 | func preinit() { 46 | // Initialize .bss: zero-initialized global variables. 47 | ptr := unsafe.Pointer(&_sbss) 48 | for ptr != unsafe.Pointer(&_ebss) { 49 | *(*uint32)(ptr) = 0 50 | ptr = unsafe.Pointer(uintptr(ptr) + 4) 51 | } 52 | 53 | // Initialize .data: global variables initialized from flash. 54 | src := unsafe.Pointer(&_sidata) 55 | dst := unsafe.Pointer(&_sdata) 56 | for dst != unsafe.Pointer(&_edata) { 57 | *(*uint32)(dst) = *(*uint32)(src) 58 | dst = unsafe.Pointer(uintptr(dst) + 4) 59 | src = unsafe.Pointer(uintptr(src) + 4) 60 | } 61 | } 62 | 63 | func ticks() timeUnit { 64 | // TODO 65 | return 0 66 | } 67 | 68 | const asyncScheduler = false 69 | 70 | func sleepTicks(d timeUnit) { 71 | // TODO 72 | } 73 | 74 | func abort() { 75 | // TODO 76 | for { 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/internal/reflectlite/reflect.go: -------------------------------------------------------------------------------- 1 | package reflectlite 2 | 3 | import "reflect" 4 | 5 | func Swapper(slice interface{}) func(i, j int) { 6 | return reflect.Swapper(slice) 7 | } 8 | 9 | type Kind = reflect.Kind 10 | type Type = reflect.Type 11 | type Value = reflect.Value 12 | 13 | const ( 14 | Invalid Kind = reflect.Invalid 15 | Bool Kind = reflect.Bool 16 | Int Kind = reflect.Int 17 | Int8 Kind = reflect.Int8 18 | Int16 Kind = reflect.Int16 19 | Int32 Kind = reflect.Int32 20 | Int64 Kind = reflect.Int64 21 | Uint Kind = reflect.Uint 22 | Uint8 Kind = reflect.Uint8 23 | Uint16 Kind = reflect.Uint16 24 | Uint32 Kind = reflect.Uint32 25 | Uint64 Kind = reflect.Uint64 26 | Uintptr Kind = reflect.Uintptr 27 | Float32 Kind = reflect.Float32 28 | Float64 Kind = reflect.Float64 29 | Complex64 Kind = reflect.Complex64 30 | Complex128 Kind = reflect.Complex128 31 | Array Kind = reflect.Array 32 | Chan Kind = reflect.Chan 33 | Func Kind = reflect.Func 34 | Interface Kind = reflect.Interface 35 | Map Kind = reflect.Map 36 | Ptr Kind = reflect.Ptr 37 | Slice Kind = reflect.Slice 38 | String Kind = reflect.String 39 | Struct Kind = reflect.Struct 40 | UnsafePointer Kind = reflect.UnsafePointer 41 | ) 42 | 43 | func ValueOf(i interface{}) reflect.Value { 44 | return reflect.ValueOf(i) 45 | } 46 | 47 | func TypeOf(i interface{}) reflect.Type { 48 | return reflect.TypeOf(i) 49 | } 50 | 51 | type ValueError = reflect.ValueError 52 | -------------------------------------------------------------------------------- /src/runtime/runtime_atsamd51g19.go: -------------------------------------------------------------------------------- 1 | // +build sam,atsamd51,atsamd51g19 2 | 3 | package runtime 4 | 5 | import ( 6 | "device/sam" 7 | ) 8 | 9 | func initSERCOMClocks() { 10 | // Turn on clock to SERCOM0 for UART0 11 | sam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_) 12 | sam.GCLK.PCHCTRL[7].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 13 | sam.GCLK_PCHCTRL_CHEN) 14 | 15 | // sets the "slow" clock shared by all SERCOM 16 | sam.GCLK.PCHCTRL[3].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 17 | sam.GCLK_PCHCTRL_CHEN) 18 | 19 | // Turn on clock to SERCOM1 20 | sam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_) 21 | sam.GCLK.PCHCTRL[8].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 22 | sam.GCLK_PCHCTRL_CHEN) 23 | 24 | // Turn on clock to SERCOM2 25 | sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_) 26 | sam.GCLK.PCHCTRL[23].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 27 | sam.GCLK_PCHCTRL_CHEN) 28 | 29 | // Turn on clock to SERCOM3 30 | sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_) 31 | sam.GCLK.PCHCTRL[24].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 32 | sam.GCLK_PCHCTRL_CHEN) 33 | 34 | // Turn on clock to SERCOM4 35 | sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_) 36 | sam.GCLK.PCHCTRL[34].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 37 | sam.GCLK_PCHCTRL_CHEN) 38 | 39 | // Turn on clock to SERCOM5 40 | sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_) 41 | sam.GCLK.PCHCTRL[35].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 42 | sam.GCLK_PCHCTRL_CHEN) 43 | } 44 | -------------------------------------------------------------------------------- /src/runtime/runtime_atsamd51j19.go: -------------------------------------------------------------------------------- 1 | // +build sam,atsamd51,atsamd51j19 2 | 3 | package runtime 4 | 5 | import ( 6 | "device/sam" 7 | ) 8 | 9 | func initSERCOMClocks() { 10 | // Turn on clock to SERCOM0 for UART0 11 | sam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM0_) 12 | sam.GCLK.PCHCTRL[7].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 13 | sam.GCLK_PCHCTRL_CHEN) 14 | 15 | // sets the "slow" clock shared by all SERCOM 16 | sam.GCLK.PCHCTRL[3].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 17 | sam.GCLK_PCHCTRL_CHEN) 18 | 19 | // Turn on clock to SERCOM1 20 | sam.MCLK.APBAMASK.SetBits(sam.MCLK_APBAMASK_SERCOM1_) 21 | sam.GCLK.PCHCTRL[8].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 22 | sam.GCLK_PCHCTRL_CHEN) 23 | 24 | // Turn on clock to SERCOM2 25 | sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM2_) 26 | sam.GCLK.PCHCTRL[23].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 27 | sam.GCLK_PCHCTRL_CHEN) 28 | 29 | // Turn on clock to SERCOM3 30 | sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_SERCOM3_) 31 | sam.GCLK.PCHCTRL[24].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 32 | sam.GCLK_PCHCTRL_CHEN) 33 | 34 | // Turn on clock to SERCOM4 35 | sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM4_) 36 | sam.GCLK.PCHCTRL[34].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 37 | sam.GCLK_PCHCTRL_CHEN) 38 | 39 | // Turn on clock to SERCOM5 40 | sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_SERCOM5_) 41 | sam.GCLK.PCHCTRL[35].Set((sam.GCLK_PCHCTRL_GEN_GCLK1 << sam.GCLK_PCHCTRL_GEN_Pos) | 42 | sam.GCLK_PCHCTRL_CHEN) 43 | } 44 | --------------------------------------------------------------------------------