compiler: add syscalls for 64-bit arm

Этот коммит содержится в:
Ayke van Laethem 2019-02-05 20:13:39 +01:00 коммит произвёл Ron Evans
родитель 93d5269fef
коммит 3cba36f2ba
4 изменённых файлов: 49 добавлений и 1 удалений

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

@ -18,6 +18,8 @@ addons:
- gcc-arm-linux-gnueabi
- binutils-arm-none-eabi
- libc6-dev-armel-cross
- gcc-aarch64-linux-gnu
- libc6-dev-arm64-cross
- qemu-system-arm
- qemu-user
- gcc-avr

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

@ -81,6 +81,41 @@ func (c *Compiler) emitSyscall(frame *Frame, call *ssa.CallCommon) (llvm.Value,
fnType := llvm.FunctionType(c.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0)
syscallResult = c.builder.CreateCall(target, args, "")
case c.GOARCH == "arm64" && c.GOOS == "linux":
// Source: syscall(2) man page.
args := []llvm.Value{}
argTypes := []llvm.Type{}
// Constraints will look something like:
// ={x0},0,{x1},{x2},{x8},~{x3},~{x4},~{x5},~{x6},~{x7},~{x16},~{x17}
constraints := "={x0}"
for i, arg := range call.Args[1:] {
constraints += "," + [...]string{
"0", // tie to output
"{x1}",
"{x2}",
"{x3}",
"{x4}",
"{x5}",
}[i]
llvmValue, err := c.parseExpr(frame, arg)
if err != nil {
return llvm.Value{}, err
}
args = append(args, llvmValue)
argTypes = append(argTypes, llvmValue.Type())
}
args = append(args, llvm.ConstInt(c.uintptrType, num, false))
argTypes = append(argTypes, c.uintptrType)
constraints += ",{x8}" // syscall number
for i := len(call.Args) - 1; i < 8; i++ {
// x0-x7 may get clobbered during the syscall following the aarch64
// calling convention.
constraints += ",~{x" + strconv.Itoa(i) + "}"
}
constraints += ",~{x16},~{x17}" // scratch registers
fnType := llvm.FunctionType(c.uintptrType, argTypes, false)
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0)
syscallResult = c.builder.CreateCall(target, args, "")
default:
return llvm.Value{}, c.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+c.GOOS+"/"+c.GOARCH)
}

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

@ -63,6 +63,16 @@ func TestCompiler(t *testing.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...")
for _, path := range matches {
t.Run(path, func(t *testing.T) {

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

@ -224,10 +224,11 @@ func defaultTarget(goos, goarch, triple string) (*TargetSpec, error) {
spec.GDB = "arm-linux-gnueabi-gdb"
spec.Emulator = []string{"qemu-arm", "-L", "/usr/arm-linux-gnueabi"}
}
if goarch == "arm64" {
if goarch == "arm64" && goos == "linux" {
spec.Linker = "aarch64-linux-gnu-gcc"
spec.Objcopy = "aarch64-linux-gnu-objcopy"
spec.GDB = "aarch64-linux-gnu-gdb"
spec.Emulator = []string{"qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"}
}
if goarch == "386" {
spec.CFlags = []string{"-m32"}