package core import ( "git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/expression" ) // CompileCall executes a function call. // All call registers must hold the correct parameter values before the function invocation. // Registers that are in use must be saved if they are modified by the function. // After the function call, they must be restored in reverse order. func (f *Function) CompileCall(root *expression.Expression) error { funcName := root.Children[0].Token.Text() parameters := root.Children[1:] registers := f.cpu.Input[:len(parameters)] isSyscall := funcName == "syscall" if isSyscall { registers = f.cpu.Syscall[:len(parameters)] } err := f.ExpressionsToRegisters(parameters, registers) if err != nil { return err } // Push for _, register := range f.cpu.General { if !f.cpu.IsFree(register) { f.assembler.Register(asm.PUSH, register) } } // Call if isSyscall { f.assembler.Syscall() } else { f.assembler.Call(funcName) } // Pop for i := len(f.cpu.General) - 1; i >= 0; i-- { register := f.cpu.General[i] if !f.cpu.IsFree(register) { f.assembler.Register(asm.POP, register) } } return nil }