Example #1
0
        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));
        }
Example #2
0
        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;
        }