Этот коммит содержится в:
Ayke van Laethem 2019-02-09 23:18:17 +01:00 коммит произвёл Ron Evans
родитель 2d5bc836f5
коммит 0b212cf2f6
11 изменённых файлов: 119 добавлений и 52 удалений

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

@ -4,6 +4,9 @@ matrix:
include: include:
- dist: xenial - dist: xenial
go: "1.11" go: "1.11"
- os: osx
go: "1.11"
env: PATH="/usr/local/opt/llvm/bin:$PATH"
addons: addons:
apt: apt:
@ -24,8 +27,16 @@ addons:
- qemu-user - qemu-user
- gcc-avr - gcc-avr
- avr-libc - avr-libc
homebrew:
update: true
taps: ArmMbed/homebrew-formulae
packages:
- llvm@7
- qemu
- arm-none-eabi-gcc
install: install:
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then mkdir -p /Users/travis/gopath/bin; fi
- curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
- dep ensure --vendor-only - dep ensure --vendor-only
@ -35,14 +46,14 @@ script:
- make gen-device - make gen-device
- tinygo build -size short -o blinky1.nrf.elf -target=pca10040 examples/blinky1 - tinygo build -size short -o blinky1.nrf.elf -target=pca10040 examples/blinky1
- tinygo build -size short -o blinky2.nrf.elf -target=pca10040 examples/blinky2 - tinygo build -size short -o blinky2.nrf.elf -target=pca10040 examples/blinky2
- tinygo build -size short -o blinky2 examples/blinky2 - tinygo build -o blinky2 examples/blinky2 # TODO: re-enable -size flag with MachO support
- tinygo build -size short -o test.nrf.elf -target=pca10040 examples/test - tinygo build -size short -o test.nrf.elf -target=pca10040 examples/test
- tinygo build -size short -o blinky1.nrf51.elf -target=microbit examples/echo - tinygo build -size short -o blinky1.nrf51.elf -target=microbit examples/echo
- tinygo build -size short -o test.nrf.elf -target=nrf52840-mdk examples/blinky1 - tinygo build -size short -o test.nrf.elf -target=nrf52840-mdk examples/blinky1
- tinygo build -size short -o blinky1.nrf51d.elf -target=pca10031 examples/blinky1 - tinygo build -size short -o blinky1.nrf51d.elf -target=pca10031 examples/blinky1
- tinygo build -size short -o blinky1.stm32.elf -target=bluepill examples/blinky1 - tinygo build -size short -o blinky1.stm32.elf -target=bluepill examples/blinky1
- tinygo build -size short -o blinky1.avr.elf -target=arduino examples/blinky1 - if [ "$TRAVIS_OS_NAME" == "linux" ]; then tinygo build -size short -o blinky1.avr.elf -target=arduino examples/blinky1; fi
- tinygo build -size short -o blinky1.avr.elf -target=digispark examples/blinky1 - if [ "$TRAVIS_OS_NAME" == "linux" ]; then tinygo build -size short -o blinky1.avr.elf -target=digispark examples/blinky1; fi
- tinygo build -size short -o blinky1.reel.elf -target=reelboard examples/blinky1 - tinygo build -size short -o blinky1.reel.elf -target=reelboard examples/blinky1
- tinygo build -size short -o blinky2.reel.elf -target=reelboard examples/blinky2 - tinygo build -size short -o blinky2.reel.elf -target=reelboard examples/blinky2
- tinygo build -size short -o blinky1.pca10056.elf -target=pca10056 examples/blinky1 - tinygo build -size short -o blinky1.pca10056.elf -target=pca10056 examples/blinky1

6
Gopkg.lock сгенерированный
Просмотреть файл

@ -11,15 +11,15 @@
"go/types/typeutil", "go/types/typeutil",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "40960b6deb8ecdb8bcde6a8f44722731939b8ddc" revision = "3744606dbb67b99c60d3f11cb10bd3f9e6dad472"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:3611159788efdd4e0cfae18b6ebcccbad25a2815968b0e4323b42647d201031a" digest = "1:a6a25fd8906c74978f1ed811bc9fd3422da8093be863b458874b02a782b6ae3e"
name = "tinygo.org/x/go-llvm" name = "tinygo.org/x/go-llvm"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "f420620d1a0f54417a5712260153fe861780d030" revision = "d5f730401f5069618b275a5241c6417eb0c38a65"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"

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

@ -1353,7 +1353,7 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
} }
switch fn.RelString(nil) { switch fn.RelString(nil) {
case "syscall.Syscall", "syscall.Syscall6": case "syscall.Syscall", "syscall.Syscall6", "syscall.Syscall9":
return c.emitSyscall(frame, instr) return c.emitSyscall(frame, instr)
} }

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

@ -17,7 +17,20 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
num, _ := constant.Uint64Val(call.Args[0].(*ssa.Const).Value) num, _ := constant.Uint64Val(call.Args[0].(*ssa.Const).Value)
var syscallResult llvm.Value var syscallResult llvm.Value
switch { switch {
case c.GOARCH == "amd64" && c.GOOS == "linux": case c.GOARCH == "amd64":
if c.GOOS == "darwin" {
// Darwin adds this magic number to system call numbers:
//
// > Syscall classes for 64-bit system call entry.
// > For 64-bit users, the 32-bit syscall number is partitioned
// > with the high-order bits representing the class and low-order
// > bits being the syscall number within that class.
// > The high-order 32-bits of the 64-bit syscall number are unused.
// > All system classes enter the kernel via the syscall instruction.
//
// Source: https://opensource.apple.com/source/xnu/xnu-792.13.8/osfmk/mach/i386/syscall_sw.h
num += 0x2000000
}
// Sources: // Sources:
// https://stackoverflow.com/a/2538212 // https://stackoverflow.com/a/2538212
// https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#syscall // https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#syscall
@ -34,6 +47,9 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
"{r10}", "{r10}",
"{r8}", "{r8}",
"{r9}", "{r9}",
"{r11}",
"{r12}",
"{r13}",
}[i] }[i]
llvmValue, err := c.parseExpr(frame, arg) llvmValue, err := c.parseExpr(frame, arg)
if err != nil { if err != nil {
@ -119,21 +135,42 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
default: default:
return llvm.Value{}, c.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+c.GOOS+"/"+c.GOARCH) return llvm.Value{}, c.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+c.GOOS+"/"+c.GOARCH)
} }
// Return values: r0, r1, err uintptr switch c.GOOS {
// Pseudocode: case "linux":
// var err uintptr // Return values: r0, r1 uintptr, err Errno
// if syscallResult < 0 && syscallResult > -4096 { // Pseudocode:
// err = -syscallResult // var err uintptr
// } // if syscallResult < 0 && syscallResult > -4096 {
// return syscallResult, 0, err // err = -syscallResult
zero := llvm.ConstInt(c.uintptrType, 0, false) // }
inrange1 := c.builder.CreateICmp(llvm.IntSLT, syscallResult, llvm.ConstInt(c.uintptrType, 0, false), "") // return syscallResult, 0, err
inrange2 := c.builder.CreateICmp(llvm.IntSGT, syscallResult, llvm.ConstInt(c.uintptrType, 0xfffffffffffff000, true), "") // -4096 zero := llvm.ConstInt(c.uintptrType, 0, false)
hasError := c.builder.CreateAnd(inrange1, inrange2, "") inrange1 := c.builder.CreateICmp(llvm.IntSLT, syscallResult, llvm.ConstInt(c.uintptrType, 0, false), "")
errResult := c.builder.CreateSelect(hasError, c.builder.CreateNot(syscallResult, ""), zero, "syscallError") inrange2 := c.builder.CreateICmp(llvm.IntSGT, syscallResult, llvm.ConstInt(c.uintptrType, 0xfffffffffffff000, true), "") // -4096
retval := llvm.Undef(llvm.StructType([]llvm.Type{c.uintptrType, c.uintptrType, c.uintptrType}, false)) hasError := c.builder.CreateAnd(inrange1, inrange2, "")
retval = c.builder.CreateInsertValue(retval, syscallResult, 0, "") errResult := c.builder.CreateSelect(hasError, c.builder.CreateSub(zero, syscallResult, ""), zero, "syscallError")
retval = c.builder.CreateInsertValue(retval, zero, 1, "") retval := llvm.Undef(llvm.StructType([]llvm.Type{c.uintptrType, c.uintptrType, c.uintptrType}, false))
retval = c.builder.CreateInsertValue(retval, errResult, 2, "") retval = c.builder.CreateInsertValue(retval, syscallResult, 0, "")
return retval, nil retval = c.builder.CreateInsertValue(retval, zero, 1, "")
retval = c.builder.CreateInsertValue(retval, errResult, 2, "")
return retval, nil
case "darwin":
// Return values: r0, r1 uintptr, err Errno
// Pseudocode:
// var err uintptr
// if syscallResult != 0 {
// err = syscallResult
// }
// return syscallResult, 0, err
zero := llvm.ConstInt(c.uintptrType, 0, false)
hasError := c.builder.CreateICmp(llvm.IntNE, syscallResult, llvm.ConstInt(c.uintptrType, 0, false), "")
errResult := c.builder.CreateSelect(hasError, syscallResult, zero, "syscallError")
retval := llvm.Undef(llvm.StructType([]llvm.Type{c.uintptrType, c.uintptrType, c.uintptrType}, false))
retval = c.builder.CreateInsertValue(retval, syscallResult, 0, "")
retval = c.builder.CreateInsertValue(retval, zero, 1, "")
retval = c.builder.CreateInsertValue(retval, errResult, 2, "")
return retval, nil
default:
return llvm.Value{}, c.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+c.GOOS+"/"+c.GOARCH)
}
} }

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

@ -3,7 +3,9 @@
package loader package loader
/* /*
#cgo CFLAGS: -I/usr/lib/llvm-7/include #cgo linux CFLAGS: -I/usr/lib/llvm-7/include
#cgo LDFLAGS: -L/usr/lib/llvm-7/lib -lclang #cgo darwin CFLAGS: -I/usr/local/opt/llvm/include
#cgo linux LDFLAGS: -L/usr/lib/llvm-7/lib -lclang
#cgo darwin LDFLAGS: -L/usr/local/opt/llvm/lib -lclang -lffi
*/ */
import "C" import "C"

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

@ -22,7 +22,7 @@ import (
) )
var commands = map[string]string{ var commands = map[string]string{
"ar": "ar", "ar": "llvm-ar",
"clang": "clang-7", "clang": "clang-7",
"ld.lld": "ld.lld-7", "ld.lld": "ld.lld-7",
"wasm-ld": "wasm-ld-7", "wasm-ld": "wasm-ld-7",
@ -102,7 +102,9 @@ func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, act
return errors.New("verification error after interpreting runtime.initAll") return errors.New("verification error after interpreting runtime.initAll")
} }
c.ApplyFunctionSections() // -ffunction-sections if spec.GOOS != "darwin" {
c.ApplyFunctionSections() // -ffunction-sections
}
if err := c.Verify(); err != nil { if err := c.Verify(); err != nil {
return errors.New("verification error after applying function sections") return errors.New("verification error after applying function sections")
} }

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

@ -10,6 +10,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime"
"sort" "sort"
"testing" "testing"
) )
@ -53,32 +54,34 @@ func TestCompiler(t *testing.T) {
return return
} }
t.Log("running tests for linux/arm...")
for _, path := range matches {
if path == "testdata/cgo/" {
continue // TODO: improve CGo
}
t.Run(path, func(t *testing.T) {
runTest(path, tmpdir, "arm--linux-gnueabi", t)
})
}
t.Log("running tests for linux/arm64...")
for _, path := range matches {
if path == "testdata/cgo/" {
continue // TODO: improve CGo
}
t.Run(path, func(t *testing.T) {
runTest(path, tmpdir, "aarch64--linux-gnueabi", t)
})
}
t.Log("running tests for emulated cortex-m3...") t.Log("running tests for emulated cortex-m3...")
for _, path := range matches { for _, path := range matches {
t.Run(path, func(t *testing.T) { t.Run(path, func(t *testing.T) {
runTest(path, tmpdir, "qemu", t) runTest(path, tmpdir, "qemu", t)
}) })
} }
if runtime.GOOS == "linux" {
t.Log("running tests for linux/arm...")
for _, path := range matches {
if path == "testdata/cgo/" {
continue // TODO: improve CGo
}
t.Run(path, func(t *testing.T) {
runTest(path, tmpdir, "arm--linux-gnueabi", t)
})
}
t.Log("running tests for linux/arm64...")
for _, path := range matches {
if path == "testdata/cgo/" {
continue // TODO: improve CGo
}
t.Run(path, func(t *testing.T) {
runTest(path, tmpdir, "aarch64--linux-gnueabi", t)
})
}
}
} }
func runTest(path, tmpdir string, target string, t *testing.T) { func runTest(path, tmpdir string, target string, t *testing.T) {

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

@ -1,4 +1,4 @@
// +build linux // +build darwin linux
package os package os

5
src/runtime/os_darwin.go Обычный файл
Просмотреть файл

@ -0,0 +1,5 @@
// +build darwin
package runtime
const GOOS = "darwin"

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

@ -1,4 +1,4 @@
// +build linux // +build darwin linux
package runtime package runtime

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

@ -189,6 +189,9 @@ func LoadTarget(target string) (*TargetSpec, error) {
return nil, errors.New("expected a full LLVM target or a custom target in -target flag") return nil, errors.New("expected a full LLVM target or a custom target in -target flag")
} }
goos := tripleSplit[2] goos := tripleSplit[2]
if strings.HasPrefix(goos, "darwin") {
goos = "darwin"
}
goarch := map[string]string{ // map from LLVM arch to Go arch goarch := map[string]string{ // map from LLVM arch to Go arch
"i386": "386", "i386": "386",
"x86_64": "amd64", "x86_64": "amd64",
@ -211,11 +214,15 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
BuildTags: []string{goos, goarch}, BuildTags: []string{goos, goarch},
Compiler: commands["clang"], Compiler: commands["clang"],
Linker: "cc", Linker: "cc",
LDFlags: []string{"-no-pie", "-Wl,--gc-sections"}, // WARNING: clang < 5.0 requires -nopie
Objcopy: "objcopy", Objcopy: "objcopy",
GDB: "gdb", GDB: "gdb",
GDBCmds: []string{"run"}, GDBCmds: []string{"run"},
} }
if goos == "darwin" {
spec.LDFlags = append(spec.LDFlags, "-Wl,-dead_strip")
} else {
spec.LDFlags = append(spec.LDFlags, "-no-pie", "-Wl,--gc-sections") // WARNING: clang < 5.0 requires -nopie
}
if goarch != runtime.GOARCH { if goarch != runtime.GOARCH {
// Some educated guesses as to how to invoke helper programs. // Some educated guesses as to how to invoke helper programs.
if goarch == "arm" && goos == "linux" { if goarch == "arm" && goos == "linux" {