func PreserveRegisters(ctx *IR_Context, argTypes []Type, returnType Type) (lib.Instructions, map[lib.Operand]lib.Operand, []lib.Operand) {
	clobbered := []lib.Operand{}
	result := []lib.Instruction{}
	mapping := map[lib.Operand]lib.Operand{}
	returnOp := ctx.ABI.ReturnTypeToOperand(returnType)
	push := x86_64.PUSH(returnOp)
	result = append(result, push)
	clobbered = append(clobbered, returnOp)
	ctx.AddInstruction(push)
	allocator := ctx.Allocator.(*X86_64_Allocator)
	regs := ctx.ABI.GetRegistersForArgs(argTypes)
	var inUse bool
	for i, arg := range argTypes {
		reg := regs[i]
		if arg.Type() == T_Float64 {
			inUse = allocator.FloatRegisters[reg.Register]
		} else {
			inUse = allocator.Registers[reg.Register]
		}
		if inUse {
			result = append(result, x86_64.PUSH(reg))
			ctx.AddInstruction(x86_64.PUSH(reg))
			clobbered = append(clobbered, reg)
		}
	}
	mappedClobbered := 1  
	for i, arg := range argTypes {
		reg := regs[i]
		if arg.Type() == T_Float64 {
			inUse = allocator.FloatRegisters[reg.Register]
		} else {
			inUse = allocator.Registers[reg.Register]
		}
		if inUse {
			offset := (len(clobbered) - mappedClobbered) * int(arg.Width())
			mapping[reg] = &encoding.DisplacedRegister{encoding.Rsp, uint8(offset)}
			mappedClobbered += 1
		}
	}
	return result, mapping, clobbered
}
returns instructions and clobbered registers
package x86_64
import (
	"fmt"
	"github.com/bspaans/jit-compiler/asm/x86_64"
	"github.com/bspaans/jit-compiler/asm/x86_64/encoding"
	. "github.com/bspaans/jit-compiler/ir/shared"
	"github.com/bspaans/jit-compiler/lib"
)
type ABI_AMDSystemV struct {
	intTargets   []*encoding.Register
	floatTargets []*encoding.Register
}
func NewABI_AMDSystemV() *ABI_AMDSystemV {
	return &ABI_AMDSystemV{
		intTargets:   []*encoding.Register{encoding.Rdi, encoding.Rsi, encoding.Rdx, encoding.Rcx, encoding.R10, encoding.R8, encoding.R9},
		floatTargets: []*encoding.Register{encoding.Xmm0, encoding.Xmm1, encoding.Xmm2, encoding.Xmm3, encoding.Xmm4, encoding.Xmm5},
	}
}
func (a *ABI_AMDSystemV) GetRegistersForArgs(args []Type) []*encoding.Register {
	intRegisterIx := 0
	floatRegisterIx := 0
	result := []*encoding.Register{}
	var reg *encoding.Register
	for _, arg := range args {
		if arg.Type() == T_Float64 {
			reg = a.floatTargets[floatRegisterIx]
			floatRegisterIx += 1
		} else {
			reg = a.intTargets[intRegisterIx]
			intRegisterIx += 1
		}
		result = append(result, reg)
	}
	return result
}
func (a *ABI_AMDSystemV) ReturnTypeToOperand(arg Type) lib.Operand {
	if arg.Type() == T_Float64 {
		return encoding.Xmm0
	}
	return encoding.Rax
}