diff --git a/src/core/CallExtern.go b/src/core/CallExtern.go index 8d3f358..abb1a7a 100644 --- a/src/core/CallExtern.go +++ b/src/core/CallExtern.go @@ -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 } diff --git a/src/x86/Registers.go b/src/x86/Registers.go index 0ed7c5f..090a678 100644 --- a/src/x86/Registers.go +++ b/src/x86/Registers.go @@ -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} )