Skip to content

Commit e655925

Browse files
aykevldeadprogram
authored andcommitted
compiler: implement syscall.rawSyscallNoError in inline assembly
This makes it possible to call syscall.Getpid() on Linux, for example. These syscalls never return an error so don't need any error checking.
1 parent e02f308 commit e655925

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

compiler/compiler.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
// Version of the compiler pacakge. Must be incremented each time the compiler
2424
// package changes in a way that affects the generated LLVM module.
2525
// This version is independent of the TinyGo version number.
26-
const Version = 11 // last change: change method name globals
26+
const Version = 12 // last change: implement syscall.rawSyscallNoError
2727

2828
func init() {
2929
llvm.InitializeAllTargets()
@@ -1310,6 +1310,8 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
13101310
return b.emitCSROperation(instr)
13111311
case strings.HasPrefix(name, "syscall.Syscall"):
13121312
return b.createSyscall(instr)
1313+
case strings.HasPrefix(name, "syscall.rawSyscallNoError"):
1314+
return b.createRawSyscallNoError(instr)
13131315
case strings.HasPrefix(name, "runtime/volatile.Load"):
13141316
return b.createVolatileLoad(instr)
13151317
case strings.HasPrefix(name, "runtime/volatile.Store"):

compiler/syscall.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import (
1010
"tinygo.org/x/go-llvm"
1111
)
1212

13-
// createSyscall emits an inline system call instruction, depending on the
14-
// target OS/arch.
15-
func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
13+
// createRawSyscall creates a system call with the provided system call number
14+
// and returns the result as a single integer (the system call result). The
15+
// result is not further interpreted.
16+
func (b *builder) createRawSyscall(call *ssa.CallCommon) (llvm.Value, error) {
1617
num := b.getValue(call.Args[0])
17-
var syscallResult llvm.Value
1818
switch {
1919
case b.GOARCH == "amd64":
2020
if b.GOOS == "darwin" {
@@ -57,7 +57,7 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
5757
constraints += ",~{rcx},~{r11}"
5858
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
5959
target := llvm.InlineAsm(fnType, "syscall", constraints, true, false, llvm.InlineAsmDialectIntel)
60-
syscallResult = b.CreateCall(target, args, "")
60+
return b.CreateCall(target, args, ""), nil
6161
case b.GOARCH == "386" && b.GOOS == "linux":
6262
// Sources:
6363
// syscall(2) man page
@@ -83,7 +83,7 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
8383
}
8484
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
8585
target := llvm.InlineAsm(fnType, "int 0x80", constraints, true, false, llvm.InlineAsmDialectIntel)
86-
syscallResult = b.CreateCall(target, args, "")
86+
return b.CreateCall(target, args, ""), nil
8787
case b.GOARCH == "arm" && b.GOOS == "linux":
8888
// Implement the EABI system call convention for Linux.
8989
// Source: syscall(2) man page.
@@ -115,7 +115,7 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
115115
}
116116
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
117117
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0)
118-
syscallResult = b.CreateCall(target, args, "")
118+
return b.CreateCall(target, args, ""), nil
119119
case b.GOARCH == "arm64" && b.GOOS == "linux":
120120
// Source: syscall(2) man page.
121121
args := []llvm.Value{}
@@ -147,10 +147,19 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
147147
constraints += ",~{x16},~{x17}" // scratch registers
148148
fnType := llvm.FunctionType(b.uintptrType, argTypes, false)
149149
target := llvm.InlineAsm(fnType, "svc #0", constraints, true, false, 0)
150-
syscallResult = b.CreateCall(target, args, "")
150+
return b.CreateCall(target, args, ""), nil
151151
default:
152152
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
153153
}
154+
}
155+
156+
// createSyscall emits instructions for the syscall.Syscall* family of
157+
// functions, depending on the target OS/arch.
158+
func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
159+
syscallResult, err := b.createRawSyscall(call)
160+
if err != nil {
161+
return syscallResult, err
162+
}
154163
switch b.GOOS {
155164
case "linux", "freebsd":
156165
// Return values: r0, r1 uintptr, err Errno
@@ -190,3 +199,16 @@ func (b *builder) createSyscall(call *ssa.CallCommon) (llvm.Value, error) {
190199
return llvm.Value{}, b.makeError(call.Pos(), "unknown GOOS/GOARCH for syscall: "+b.GOOS+"/"+b.GOARCH)
191200
}
192201
}
202+
203+
// createRawSyscallNoError emits instructions for the Linux-specific
204+
// syscall.rawSyscallNoError function.
205+
func (b *builder) createRawSyscallNoError(call *ssa.CallCommon) (llvm.Value, error) {
206+
syscallResult, err := b.createRawSyscall(call)
207+
if err != nil {
208+
return syscallResult, err
209+
}
210+
retval := llvm.ConstNull(b.ctx.StructType([]llvm.Type{b.uintptrType, b.uintptrType}, false))
211+
retval = b.CreateInsertValue(retval, syscallResult, 0, "")
212+
retval = b.CreateInsertValue(retval, llvm.ConstInt(b.uintptrType, 0, false), 1, "")
213+
return retval, nil
214+
}

0 commit comments

Comments
 (0)