public ICompiledMethod JIT(AccCIL.IR.MethodEntry method) { //First we execute all IR/CIL optimizations, except the register allocator IRegisterAllocator allocator = null; foreach (IOptimizer o in m_optimizers) { if (this.OptimizationLevel >= o.IncludeLevel) { if (o is IRegisterAllocator) { allocator = (IRegisterAllocator)o; continue; } else { o.Optimize(method, this.OptimizationLevel); } } } CompiledMethod state = new CompiledMethod(method); SPEOpCodeMapper mapper = new SPEOpCodeMapper(state); state.StartFunction(); //We store the local variables in the permanent registers followed by the function arguments int locals = method.Method.Body.Variables.Count; int args = method.Method.Parameters.Count; int permRegs = locals + args; //TODO: Handle this case by storing the extra data on the stack if (permRegs > MAX_LV_REGISTERS) { throw new Exception("Too many locals+arguments"); } //Make sure the register usage is clean method.ResetVirtualRegisters(); //TODO: should be able to re-use registers used by the arguments, which frees appx 70 extra registers List <int> usedRegs = this.OptimizationLevel > AccCIL.OptimizationLevel.None ? new RegisterAllocator().AllocateRegisters(_LV0 + permRegs, allocator, method) : new List <int>(); //new AccCILVisualizer.Visualizer(new AccCIL.IR.MethodEntry[] { method }).ShowDialog(); //If we need to store locals, we must preserve the local variable registers for (int i = 0; i < permRegs; i++) { mapper.PushStack(new TemporaryRegister((uint)(_LV0 + i))); usedRegs.Remove(_LV0 + i); } //All remaining used registers must also be preserved foreach (int i in usedRegs.Reverse <int>()) { if (i > _LV0) { mapper.PushStack(new TemporaryRegister((uint)(i))); } } //Clear as required if (method.Method.Body.InitLocals) { for (int i = 0; i < locals; i++) { mapper.ClearRegister((uint)(_LV0 + i)); } } //Now copy over the arguments for (int i = 0; i < args; i++) { mapper.CopyRegister((uint)(_ARG0 + i), (uint)(_LV0 + locals + i)); } int requiredStackDepth = state.StackDepth; //Now add each parsed subtree foreach (AccCIL.IR.InstructionElement el in method.Childnodes) { System.Diagnostics.Debug.Assert(state.VirtualStackDepth == requiredStackDepth); RecursiveTranslate(state, mapper, el, new Dictionary <AccCIL.IR.InstructionElement, string>()); System.Diagnostics.Debug.Assert(state.VirtualStackDepth == requiredStackDepth); System.Diagnostics.Trace.Assert(state.StackDepth >= requiredStackDepth); } state.EndFunction(); System.Diagnostics.Trace.Assert(state.StackDepth == requiredStackDepth); //All used registers must be preserved foreach (int i in usedRegs) { if (i > _LV0) { mapper.PopStack((uint)(i), true); } } //If we had to store locals, we must restore the local variable registers for (int i = 0; i < permRegs; i++) { mapper.PopStack((uint)(_LV0 + (permRegs - i - 1)), true); } System.Diagnostics.Trace.Assert(state.StackDepth == 0); return(state); }
private void AssignFixedRegisters(List <int> usedRegisters, AccCIL.IR.MethodEntry method) { foreach (var i in method.FlatInstructionList) { switch (i.Instruction.OpCode.Code) { case Mono.Cecil.Cil.Code.Ret: AssignRegister(i, ABI_RETURN_REGISTER, usedRegisters, true); break; case Mono.Cecil.Cil.Code.Call: case Mono.Cecil.Cil.Code.Calli: case Mono.Cecil.Cil.Code.Callvirt: AssignRegister(i, ABI_RETURN_REGISTER, usedRegisters, true); //TODO: Add spill limit for arguments for (int j = 0; j < i.Childnodes.Length; j++) { AssignRegister(i.Childnodes[j], ABI_FUNCTION_PARAMETER_REGISTER_START + j, usedRegisters, true); } break; case Mono.Cecil.Cil.Code.Stloc_0: AssignRegister(i.Childnodes[0], SPEJITCompiler._LV0, usedRegisters, true); break; case Mono.Cecil.Cil.Code.Stloc_1: AssignRegister(i.Childnodes[0], SPEJITCompiler._LV0 + 1, usedRegisters, true); break; case Mono.Cecil.Cil.Code.Stloc_2: AssignRegister(i.Childnodes[0], SPEJITCompiler._LV0 + 2, usedRegisters, true); break; case Mono.Cecil.Cil.Code.Stloc_3: AssignRegister(i.Childnodes[0], SPEJITCompiler._LV0 + 3, usedRegisters, true); break; case Mono.Cecil.Cil.Code.Stloc_S: AssignRegister(i.Childnodes[0], SPEJITCompiler._LV0 + ((Mono.Cecil.Cil.VariableReference)i.Instruction.Operand).Index, usedRegisters, true); break; case Mono.Cecil.Cil.Code.Ldloc_0: AssignRegister(i, SPEJITCompiler._LV0, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldloc_1: AssignRegister(i, SPEJITCompiler._LV0 + 1, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldloc_2: AssignRegister(i, SPEJITCompiler._LV0 + 2, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldloc_3: AssignRegister(i, SPEJITCompiler._LV0 + 3, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldloc_S: AssignRegister(i, SPEJITCompiler._LV0 + ((Mono.Cecil.Cil.VariableReference)i.Instruction.Operand).Index, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldarg_0: AssignRegister(i, SPEJITCompiler._LV0 + method.Method.Body.Variables.Count, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldarg_1: AssignRegister(i, SPEJITCompiler._LV0 + method.Method.Body.Variables.Count + 1, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldarg_2: AssignRegister(i, SPEJITCompiler._LV0 + method.Method.Body.Variables.Count + 2, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldarg_3: AssignRegister(i, SPEJITCompiler._LV0 + method.Method.Body.Variables.Count + 3, usedRegisters, false); break; case Mono.Cecil.Cil.Code.Ldarg_S: case Mono.Cecil.Cil.Code.Ldarg: AssignRegister(i, SPEJITCompiler._LV0 + method.Method.Body.Variables.Count + method.Method.Parameters.IndexOf(((Mono.Cecil.ParameterDefinition)i.Instruction.Operand)), usedRegisters, false); break; } } }
public ICompiledMethod JIT(AccCIL.IR.MethodEntry method) { throw new NotImplementedException(); }
public List <int> AllocateRegisters(int extraRegisters, AccCIL.IRegisterAllocator allocator, AccCIL.IR.MethodEntry method) { List <int> usedRegisters = new List <int>(); AssignFixedRegisters(usedRegisters, method); if (allocator != null) { Stack <int> registers = new Stack <int>(Enumerable.Range(extraRegisters, 128 - extraRegisters)); usedRegisters.AddRange(allocator.AllocateRegisters(registers, method)); } return(usedRegisters.Distinct().ToList()); }