/// <summary> /// Allocate a low register and map it to the given original register. /// </summary> private LowRegisterState AllocateLowRegister(Instruction ins, Register register, MethodBody body) { // Prepare var type = GetType(register); var isWide = (type == RType.Wide); var regsNeeded = isWide ? 2 : 1; LowRegisterState regState = null; HashSet <Register> allRegistersUsedInIns = null; while (true) { // Try to allocate free spilling register regState = lowRegisters.FirstOrDefault(x => x.IsFreeFor(type)); if (regState != null) { break; // Found a free low register } // No spilling register is available. // Free another register first // If wide, free 2 registers if (nextSpillIndex + regsNeeded > lowRegisters.Length) { nextSpillIndex = 0; } regState = lowRegisters[nextSpillIndex]; var regStateNext = isWide ? lowRegisters[nextSpillIndex + 1] : null; // Update index so we take another the next time nextSpillIndex = (nextSpillIndex + regsNeeded) % (lowRegisters.Length - 1); // Do not allocate registers already used in the current instruction allRegistersUsedInIns = allRegistersUsedInIns ?? GetAllUsedRegisters(ins); if (allRegistersUsedInIns.Contains(regState.LowRegister)) { continue; } if ((regStateNext != null) && allRegistersUsedInIns.Contains(regStateNext.LowRegister)) { continue; } // Save sReg back to original register var map = mapper.RegisterSpillingMap; regState.SaveToOriginalAndClear(ins, block, body, map); if (regStateNext != null) { regStateNext.SaveToOriginalAndClear(ins, block, body, map); } } // Add mapping regState.SetInUseBy(register, type); return(regState); }
/// <summary> /// Mark this low register state as no longer in use. /// </summary> private void Clear() { if (isWide) { next.Clear(); } OriginalRegister = null; SaveToOriginalNeeded = false; isWide = false; type = RType.Value; wideStart = null; Mapping = null; }
/// <summary> /// Default ctor. /// </summary> internal BlockSpillCodeGenerator(BasicBlock block, RegisterMapper mapper, List <Register> lowRegisters, List <Register> invokeFrame, List <Register> allRegisters) { this.block = block; this.mapper = mapper; this.lowRegisters = new LowRegisterState[lowRegisters.Count]; LowRegisterState next = null; for (var i = lowRegisters.Count - 1; i >= 0; i--) { this.lowRegisters[i] = new LowRegisterState(lowRegisters[i], next); next = this.lowRegisters[i]; } this.invokeFrame = invokeFrame; this.allRegisters = allRegisters; }
/// <summary> /// Default ctor /// </summary> public LowRegisterState(Register lowRegister, LowRegisterState next) { LowRegister = lowRegister; this.next = next; }
/// <summary> /// Try to get the low register that the given original register is mapped onto. /// </summary> private bool TryGetLowRegister(Register originalRegister, out Register lowRegister, out LowRegisterState lowRegisterState) { lowRegisterState = lowRegisters.FirstOrDefault(x => x.OriginalRegister == originalRegister); lowRegister = (lowRegisterState != null) ? lowRegisterState.LowRegister : null; return(lowRegister != null); }
/// <summary> /// Mark this low register state as no longer in use. /// </summary> private void Clear() { if (isWide) next.Clear(); OriginalRegister = null; SaveToOriginalNeeded = false; isWide = false; type = RType.Value; wideStart = null; Mapping = null; }
/// <summary> /// Try to get the low register that the given original register is mapped onto. /// </summary> private bool TryGetLowRegister(Register originalRegister, out Register lowRegister, out LowRegisterState lowRegisterState) { lowRegisterState = lowRegisters.FirstOrDefault(x => x.OriginalRegister == originalRegister); lowRegister = (lowRegisterState != null) ? lowRegisterState.LowRegister : null; return (lowRegister != null); }