private static void RecursiveTranslate(CompiledMethod state, SPEOpCodeMapper mapper, AccCIL.IR.InstructionElement el, Dictionary <AccCIL.IR.InstructionElement, string> compiled) { if (compiled.ContainsKey(el)) { System.Diagnostics.Debug.Assert(el.Instruction.OpCode.Code == Mono.Cecil.Cil.Code.Dup); return; } compiled.Add(el, null); foreach (AccCIL.IR.InstructionElement els in el.Childnodes) { RecursiveTranslate(state, mapper, els, compiled); } int stackdepth = state.VirtualStackDepth; System.Reflection.MethodInfo translator; if (!_opTranslations.TryGetValue(el.Instruction.OpCode.Code, out translator)) { throw new Exception(string.Format("Missing a translator for CIL code {0}", el.Instruction.OpCode.Code)); } state.StartInstruction(el.Instruction); translator.Invoke(mapper, new object[] { el }); state.EndInstruction(); //Verify that the instruction handler managed to handle the stack System.Diagnostics.Debug.Assert(state.VirtualStackDepth == stackdepth + AccCIL.AccCIL.StackChangeCount(el)); }
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); }