mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-10 05:53:39 +00:00
compiler, runtime: fix SyscallN handling for Windows on Go 1.26+
Go 1.26 changed all Windows syscall wrappers in zsyscall_windows.go to use SyscallN instead of fixed-argument Syscall/Syscall6/etc. The SyscallN function now has a body that calls an unexported syscalln function (provided by runtime via //go:linkname). TinyGo's existing createSyscall compiler builtin used call.Args[2:] to extract syscall arguments, but for variadic SyscallN the SSA representation passes args as a slice value (not individual args), causing call.Args[2:] to be empty -- resulting in zero arguments being passed to Windows API calls and 0xc0000005 access violations. Fix this by: 1. Excluding syscall.SyscallN from builtin interception, letting Go 1.26's function body compile normally (it calls syscalln) 2. Adding a new createSyscalln compiler builtin that intercepts syscall.syscalln and correctly handles the variadic slice: - Generates a switch on the arg count n (0-18 cases) - Each case loads args from the slice via GEP/Load - Wraps calls with SetLastError(0)/GetLastError() as before - Handles i386 stdcall conventions 3. Adding runtime stubs for both Go versions: - go1.26: syscall.syscalln stub (body intercepted by compiler) - pre-go1.26: syscall.SyscallN stub (linker satisfaction)
This commit is contained in:
@@ -1980,10 +1980,14 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
|
||||
return b.emitSV64Call(instr.Args, getPos(instr))
|
||||
case strings.HasPrefix(name, "(device/riscv.CSR)."):
|
||||
return b.emitCSROperation(instr)
|
||||
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.Syscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscall"):
|
||||
case (strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.Syscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscall")) && name != "syscall.SyscallN":
|
||||
if b.GOOS != "darwin" {
|
||||
return b.createSyscall(instr)
|
||||
}
|
||||
case name == "syscall.syscalln":
|
||||
if b.GOOS == "windows" {
|
||||
return b.createSyscalln(instr)
|
||||
}
|
||||
case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"):
|
||||
return b.createRawSyscallNoError(instr)
|
||||
case name == "runtime.supportsRecover":
|
||||
|
||||
Reference in New Issue
Block a user