Fixed volatile registers on external calls
This commit is contained in:
parent
49afa5d800
commit
c10395eddc
@ -2,7 +2,10 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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/expression"
|
||||||
"git.akyoto.dev/cli/q/src/types"
|
"git.akyoto.dev/cli/q/src/types"
|
||||||
"git.akyoto.dev/cli/q/src/x86"
|
"git.akyoto.dev/cli/q/src/x86"
|
||||||
@ -11,6 +14,17 @@ import (
|
|||||||
// CallExtern calls an external function.
|
// CallExtern calls an external function.
|
||||||
func (f *Function) CallExtern(fn *Function, parameters []*expression.Expression) ([]types.Type, error) {
|
func (f *Function) CallExtern(fn *Function, parameters []*expression.Expression) ([]types.Type, error) {
|
||||||
f.DLLs = f.DLLs.Append(fn.Package, fn.Name)
|
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)]
|
registers := x86.WindowsInputRegisters[:len(parameters)]
|
||||||
err := f.BeforeCall(fn, parameters, registers)
|
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))
|
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
|
return fn.OutputTypes, nil
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,10 @@ var (
|
|||||||
AllRegisters = []cpu.Register{RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15}
|
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}
|
SyscallInputRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9}
|
||||||
SyscallOutputRegisters = []cpu.Register{RAX, RCX, R11}
|
SyscallOutputRegisters = []cpu.Register{RAX, RCX, R11}
|
||||||
GeneralRegisters = []cpu.Register{RCX, RBX, R11, R12, R13, R14, R15, RBP}
|
GeneralRegisters = []cpu.Register{RBX, R12, R13, R14, R15, RCX, R11, RBP}
|
||||||
InputRegisters = SyscallInputRegisters
|
InputRegisters = SyscallInputRegisters
|
||||||
OutputRegisters = SyscallInputRegisters
|
OutputRegisters = SyscallInputRegisters
|
||||||
WindowsInputRegisters = []cpu.Register{RCX, RDX, R8, R9}
|
WindowsInputRegisters = []cpu.Register{RCX, RDX, R8, R9}
|
||||||
WindowsOutputRegisters = []cpu.Register{RAX}
|
WindowsOutputRegisters = []cpu.Register{RAX}
|
||||||
|
WindowsVolatileRegisters = []cpu.Register{RCX, RDX, R8, R9, R10, R11}
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user