Fixed volatile registers on external calls

This commit is contained in:
Eduard Urbach 2025-02-12 12:47:08 +01:00
parent 49afa5d800
commit c10395eddc
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
2 changed files with 32 additions and 8 deletions

View File

@ -2,7 +2,10 @@ package core
import (
"fmt"
"slices"
"git.akyoto.dev/cli/q/src/asm"
"git.akyoto.dev/cli/q/src/cpu"
"git.akyoto.dev/cli/q/src/expression"
"git.akyoto.dev/cli/q/src/types"
"git.akyoto.dev/cli/q/src/x86"
@ -11,6 +14,17 @@ import (
// CallExtern calls an external function.
func (f *Function) CallExtern(fn *Function, parameters []*expression.Expression) ([]types.Type, error) {
f.DLLs = f.DLLs.Append(fn.Package, fn.Name)
var pushedRegisters []cpu.Register
for _, register := range x86.WindowsVolatileRegisters {
if f.RegisterIsUsed(register) {
f.Register(asm.PUSH, register)
f.FreeRegister(register)
pushedRegisters = append(pushedRegisters, register)
}
}
registers := x86.WindowsInputRegisters[:len(parameters)]
err := f.BeforeCall(fn, parameters, registers)
@ -19,5 +33,14 @@ func (f *Function) CallExtern(fn *Function, parameters []*expression.Expression)
}
f.DLLCall(fmt.Sprintf("%s.%s", fn.Package, fn.Name))
for _, register := range registers {
f.FreeRegister(register)
}
for _, register := range slices.Backward(pushedRegisters) {
f.Register(asm.POP, register)
}
return fn.OutputTypes, nil
}

View File

@ -22,12 +22,13 @@ const (
)
var (
AllRegisters = []cpu.Register{RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15}
SyscallInputRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9}
SyscallOutputRegisters = []cpu.Register{RAX, RCX, R11}
GeneralRegisters = []cpu.Register{RCX, RBX, R11, R12, R13, R14, R15, RBP}
InputRegisters = SyscallInputRegisters
OutputRegisters = SyscallInputRegisters
WindowsInputRegisters = []cpu.Register{RCX, RDX, R8, R9}
WindowsOutputRegisters = []cpu.Register{RAX}
AllRegisters = []cpu.Register{RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15}
SyscallInputRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9}
SyscallOutputRegisters = []cpu.Register{RAX, RCX, R11}
GeneralRegisters = []cpu.Register{RBX, R12, R13, R14, R15, RCX, R11, RBP}
InputRegisters = SyscallInputRegisters
OutputRegisters = SyscallInputRegisters
WindowsInputRegisters = []cpu.Register{RCX, RDX, R8, R9}
WindowsOutputRegisters = []cpu.Register{RAX}
WindowsVolatileRegisters = []cpu.Register{RCX, RDX, R8, R9, R10, R11}
)