예제 #1
0
 /// <summary>
 /// Save the state in the low register back to the original register when a save is needed.
 /// The save code is inserted directly before the given target instruction.
 /// </summary>
 public void SaveToOriginalAndClear(Instruction target, BasicBlock block, MethodBody body, RegisterSpillingMap map)
 {
     if (wideStart != null)
     {
         wideStart.SaveToOriginalAndClear(target, block, body, map);
     }
     else
     {
         if (SaveToOriginalNeeded)
         {
             var original = OriginalRegister;
             // Fix target to insert before
             if (target.OpCode.IsMoveResult())
             {
                 do
                 {
                     target = target.GetPrevious(body.Instructions);
                 } while (target.OpCode == OpCodes.Nop);
             }
             // Insert save code
             var move = CreateMove(LowRegister, original, type);
             block.InsertBefore(target, move);
             // Save end in mapping
             Mapping.LastInstruction = move;
             // Record mapping
             map.Add(Mapping);
         }
         Clear();
     }
 }
예제 #2
0
            /// <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);
            }