Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        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;
                }
            }
        }
Ejemplo n.º 3
0
 public ICompiledMethod JIT(AccCIL.IR.MethodEntry method)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 4
0
        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());
        }