/// <summary> /// Handles the given function call argument /// </summary> /// <param name="compilationData">The compilation data</param> /// <param name="argumentIndex">The index of the argument</param> /// <param name="argumentType">The type of the argument</param> /// <param name="argumentRegisters">The virtual registers for the arguments</param> /// <param name="aliveRegistersStack">The alive registers stack</param> /// <param name="toCall">The function to call</param> public void CallFunctionArgument( CompilationData compilationData, int argumentIndex, VMType argumentType, IReadOnlyList<VirtualRegister> argumentRegisters, IDictionary<HardwareRegister, int> aliveRegistersStack, FunctionDefinition toCall) { var virtualAssembler = compilationData.VirtualAssembler; var regAlloc = compilationData.RegisterAllocation; var generatedCode = compilationData.Function.GeneratedCode; int thisNumArgs = compilationData.Function.Definition.Parameters.Count; int numArgs = toCall.Parameters.Count; int argsStart = 1 + compilationData.StackSize / Assembler.RegisterSize; if (virtualAssembler.NeedSpillRegister) { argsStart += 1; } int alignment = this.CalculateStackAlignment(compilationData, toCall.Parameters, aliveRegistersStack.Count); var virtualReg = argumentRegisters[numArgs - 1 - argumentIndex]; var virtualRegStack = regAlloc.GetStackIndex(virtualReg); //Check if to pass argument by via the stack if (argumentIndex >= numRegisterArguments) { //Move arguments to the stack HardwareRegister spillReg; int stackOffset = 0; if (argumentType.IsPrimitiveType(PrimitiveTypes.Float)) { spillReg = virtualAssembler.GetFloatSpillRegister(); if (!virtualRegStack.HasValue) { stackOffset = aliveRegistersStack[virtualAssembler.GetFloatRegisterForVirtual(virtualReg).Value]; } } else { spillReg = virtualAssembler.GetIntSpillRegister(); if (!virtualRegStack.HasValue) { stackOffset = aliveRegistersStack[virtualAssembler.GetIntRegisterForVirtual(virtualReg).Value]; } } var argMemory = new MemoryOperand(); if (virtualRegStack.HasValue) { argMemory = new MemoryOperand( Register.BP, virtualAssembler.CalculateStackOffset(virtualRegStack.Value)); } else { argMemory = new MemoryOperand( Register.BP, -(argsStart + stackOffset) * Assembler.RegisterSize); } Assembler.Move(generatedCode, spillReg, argMemory); Assembler.Push(generatedCode, spillReg); } else { HardwareRegister argReg; int stackOffset = 0; if (argumentType.IsPrimitiveType(PrimitiveTypes.Float)) { argReg = floatArgumentRegisters[argumentIndex]; if (!virtualRegStack.HasValue) { stackOffset = aliveRegistersStack[virtualAssembler.GetFloatRegisterForVirtual(virtualReg).Value]; } } else { argReg = intArgumentRegisters[argumentIndex]; if (!virtualRegStack.HasValue) { stackOffset = aliveRegistersStack[virtualAssembler.GetIntRegisterForVirtual(virtualReg).Value]; } } var argMemory = new MemoryOperand(); if (virtualRegStack.HasValue) { argMemory = new MemoryOperand( Register.BP, virtualAssembler.CalculateStackOffset(virtualRegStack.Value)); } else { argMemory = new MemoryOperand( Register.BP, -(argsStart + stackOffset) * Assembler.RegisterSize); } Assembler.Move(generatedCode, argReg, argMemory); } }
/// <summary> /// Moves an argument to the stack /// </summary> /// <param name="compilationData">The compilation data</param> /// <param name="argumentIndex">The argument index</param> /// <param name="argumentType">The type of the argument</param> private void MoveArgumentToStack(CompilationData compilationData, int argumentIndex, VMType argumentType) { var generatedCode = compilationData.Function.GeneratedCode; int argStackOffset = -(1 + argumentIndex) * Assembler.RegisterSize; if (argumentIndex >= numRegisterArguments) { int stackArgumentIndex = this.GetStackArgumentIndex(compilationData, argumentIndex); var argStackSource = new MemoryOperand( Register.BP, Assembler.RegisterSize * (6 + stackArgumentIndex)); HardwareRegister tmpReg; if (argumentType.IsPrimitiveType(PrimitiveTypes.Float)) { tmpReg = compilationData.VirtualAssembler.GetFloatSpillRegister(); } else { tmpReg = new IntRegister(Register.AX); } Assembler.Move(generatedCode, tmpReg, argStackSource); Assembler.Move(generatedCode, new MemoryOperand(Register.BP, argStackOffset), tmpReg); } else { //var argReg = floatArgumentRegisters[argumentIndex]; HardwareRegister argReg; if (argumentType.IsPrimitiveType(PrimitiveTypes.Float)) { argReg = floatArgumentRegisters[argumentIndex]; } else { argReg = intArgumentRegisters[argumentIndex]; } Assembler.Move(generatedCode, new MemoryOperand(Register.BP, argStackOffset), argReg); } }