/// <summary> /// Convert the given instruction into 1 or more dex instructions. /// </summary> internal static IEnumerable<Instruction> Convert(RL.Instruction source, RegisterMapper regMapper) { var dexIns = new Instruction(source.Code.ToDex(), source.Operand) { SequencePoint = source.SequencePoint }; var dexRegisters = dexIns.Registers; dexRegisters.AddRange(source.Registers.Select(x => regMapper[x])); if (!AllRegistersFit(dexIns) || dexIns.RequiresInvokeRange()) { // At least 1 register does not fit. // Insert a NOP first so we do not have to re-route when we insert spilling code. yield return new Instruction(OpCodes.Nop); } yield return dexIns; }
/// <summary> /// Convert the given instruction into 1 or more dex instructions. /// </summary> internal static IEnumerable <Instruction> Convert(RL.Instruction source, RegisterMapper regMapper) { var dexIns = new Instruction(source.Code.ToDex(), source.Operand) { SequencePoint = source.SequencePoint }; var dexRegisters = dexIns.Registers; dexRegisters.AddRange(source.Registers.Select(x => regMapper[x])); if (!AllRegistersFit(dexIns) || dexIns.RequiresInvokeRange()) { // At least 1 register does not fit. // Insert a NOP first so we do not have to re-route when we insert spilling code. yield return(new Instruction(OpCodes.Nop)); } yield return(dexIns); }
/// <summary> /// Convert a normal invoke_x to invoke_x_range. /// </summary> private void ConvertInvoke(Instruction ins) { var registers = ins.Registers; var count = registers.Count; if (count == 0) { return; } // Replace all registers with their "spill" variant (if any) for (var i = 0; i < count; i++) { Register sReg; LowRegisterState state; if (TryGetLowRegister(registers[i], out sReg, out state)) { ReplaceRegister(ins, registers[i], sReg); } } // By replacing the registers, it it possible to avoid the invoke_x_range opcodes? if (!ins.RequiresInvokeRange()) { return; } if (!IsValidInvokeRange(registers)) { // Use invoke frame for (var i = 0; i < count; i++) { var type = GetType(registers[i]); block.InsertBefore(ins, CreateMove(registers[i], invokeFrame[i], type)); registers[i] = invokeFrame[i]; } } // Change opcode ins.OpCode = ins.OpCode.InvokeToRange(); }
/// <summary> /// Convert a normal invoke_x to invoke_x_range. /// </summary> private void ConvertInvoke(Instruction ins) { var registers = ins.Registers; var count = registers.Count; if (count == 0) return; // Replace all registers with their "spill" variant (if any) for (var i = 0; i < count; i++) { Register sReg; LowRegisterState state; if (TryGetLowRegister(registers[i], out sReg, out state)) { ReplaceRegister(ins, registers[i], sReg); } } // By replacing the registers, it it possible to avoid the invoke_x_range opcodes? if (!ins.RequiresInvokeRange()) return; if (!IsValidInvokeRange(registers)) { // Use invoke frame for (var i = 0; i < count; i++) { var type = GetType(registers[i]); block.InsertBefore(ins, CreateMove(registers[i], invokeFrame[i], type)); registers[i] = invokeFrame[i]; } } // Change opcode ins.OpCode = ins.OpCode.InvokeToRange(); }