GotoNext() public méthode

Goes to the next instruction.
public GotoNext ( ) : void
Résultat void
Exemple #1
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand v0 = context.Operand1;
            Operand v1 = context.Operand2;
            Operand v2 = context.Operand3;
            Operand v3 = context.GetOperand(3);

            Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP);
            Operand ebp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP);

            Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
            Operand ebx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX);
            Operand ecx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX);

            Operand exceptionRegister = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Object, methodCompiler.Architecture.ExceptionRegister);

            // Move all virtual registers into physical registers - necessary since stack frame pointer will change
            context.SetInstruction(X86.Mov, eax, v0);
            context.AppendInstruction(X86.Mov, ebx, v1);
            context.AppendInstruction(X86.Mov, ecx, v2);
            context.AppendInstruction(X86.Mov, exceptionRegister, v3);

            // Update the frame and stack registers
            context.AppendInstruction(X86.Mov, ebp, ecx);
            context.AppendInstruction(X86.Mov, esp, ebx);
            context.AppendInstruction(X86.Jmp, null, eax);

            // future - common code (refactor opportunity)
            context.GotoNext();

            // Remove all remaining instructions in block and clear next block list
            while (!context.IsBlockEndInstruction)
            {
                if (!context.IsEmpty)
                {
                    context.SetInstruction(X86.Nop);
                }
                context.GotoNext();
            }

            var nextBlocks = context.Block.NextBlocks;

            foreach (var next in nextBlocks)
            {
                next.PreviousBlocks.Remove(context.Block);
            }

            nextBlocks.Clear();
        }
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        void IMethodCompilerStage.Run()
        {
            Dictionary<Operand, int> list = new Dictionary<Operand, int>();

            foreach (var block in this.basicBlocks)
            {
                for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext())
                {
                    context.Marked = false;

                    if (context.Result == null)
                        continue;

                    int index = 0;

                    if (list.TryGetValue(context.Result, out index))
                    {
                        instructionSet.Data[index].Marked = true;
                        context.Marked = true;
                    }
                    else
                    {
                        list.Add(context.Result, context.Index);
                    }

                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        void IMethodCompilerStage.Run()
        {
            if (AreExceptions)
                return;

            foreach (var block in this.basicBlocks)
            {
                if (block.Label == Int32.MaxValue)
                    continue;

                for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext())
                {
                    if (context.Instruction is PhiInstruction)
                        this.ProcessPhiInstruction(block, context);

                    for (var i = 0; i < context.OperandCount; ++i)
                    {
                        var op = context.GetOperand(i);
                        if (op is SsaOperand)
                            context.SetOperand(i, (op as SsaOperand).Operand);
                    }

                    for (var i = 0; i < context.ResultCount; ++i)
                    {
                        var op = context.GetResult(i);
                        if (op is SsaOperand)
                            context.SetResult(i, (op as SsaOperand).Operand);
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Inserts the copy statement.
        /// </summary>
        /// <param name="predecessor">The predecessor.</param>
        /// <param name="result">The result.</param>
        /// <param name="operand">The operand.</param>
        private void InsertCopyStatement(BasicBlock predecessor, Operand result, Operand operand)
        {
            var context = new Context(this.instructionSet, predecessor);
            while (!context.EndOfInstruction && IsBranchInstruction(context))
                context.GotoNext();

            if (context.Index != -1)
                context = context.InsertBefore();

            var source = operand is SsaOperand ? (operand as SsaOperand).Operand : operand;
            var destination = result is SsaOperand ? (result as SsaOperand).Operand : result;

            Debug.Assert(!(source is SsaOperand));
            Debug.Assert(!(destination is SsaOperand));

            context.SetInstruction(IR.Instruction.MoveInstruction, destination, source);
        }
        protected override void Run()
        {
            foreach (var block in BasicBlocks)
            {
                for (var context = new Context(this.InstructionSet, block); !context.IsBlockEndInstruction; context.GotoNext())
                {
                    if (!(context.Instruction is X86Instruction))
                        continue;

                    if (context.OperandCount != context.Instruction.DefaultOperandCount ||
                        context.ResultCount != context.Instruction.DefaultResultCount)
                    {
                        context.Marked = true;
                    }
                }
            }
        }
        protected override void Run()
        {
            foreach (var block in BasicBlocks)
            {
                for (var context = new Context(this.InstructionSet, block); !context.IsBlockEndInstruction; context.GotoNext())
                {
                    if (context.IsEmpty || !(context.Instruction is X86Instruction))
                        continue;

                    if (context.Instruction == X86.Jmp || context.Instruction == X86.FarJmp)
                        continue;

                    // Convert any floating point constants into labels
                    EmitFloatingPointConstants(context);

                    // No floating point opcode allows both the result and operand to be a memory location
                    // if necessary, load into register first
                    if (context.OperandCount == 1
                        && context.ResultCount == 1
                        && context.Operand1.IsMemoryAddress
                        && context.Result.IsMemoryAddress
                        && (context.Result.IsR || context.Operand1.IsR))
                    {
                        LoadFirstOperandIntoRegister(context);
                    }
                    else
                        // No two-operand floating point opcode allows the first operand to a memory operand
                        if (context.OperandCount == 2 && context.Operand1.IsMemoryAddress && context.Operand1.IsR)
                        {
                            if (IsCommutative(context.Instruction))
                            {
                                // swap operands
                                var t = context.Operand2;
                                context.Operand2 = context.Operand1;
                                context.Operand1 = t;
                            }
                            else
                            {
                                LoadFirstOperandIntoRegister(context);
                            }
                        }
                }
            }
        }
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        void IMethodCompilerStage.Run()
        {
            if (AreExceptions)
                return;

            foreach (var block in this.basicBlocks)
                if (block.NextBlocks.Count == 0 && block.PreviousBlocks.Count == 0)
                    return;

            foreach (var block in this.basicBlocks)
            {
                for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext())
                {
                    if (!this.IsFoldableInstruction(context))
                        continue;
                    if (!this.HasFoldableArguments(context))
                        continue;
                    this.FoldInstruction(context);
                }
            }
        }
        /// <summary>
        /// Enumerates all instructions and eliminates floating point constants from them.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="ctxEpilogue">The context of the epilogue.</param>
        private void ProcessInstructions(Context ctx, Context ctxEpilogue)
        {
            // Current constant operand
            ConstantOperand co = null;

            for (; !ctx.EndOfInstruction; ctx.GotoNext())
            {
                // A constant may only appear on the right side of an expression, so we ignore constants in
                // result - there should never be one there.
                foreach (Operand op in ctx.Operands)
                {
                    co = op as ConstantOperand;
                    if (co != null && IsLargeConstant(co))
                    {
                        // Move the constant out of the code stream and place it right after the code.
                        ctxEpilogue.AppendInstruction(Instruction.LiteralInstruction);
                        ctxEpilogue.LiteralData = new IR.LiteralData(ctx.Label, co.Type, co.Value);

                        op.Replace(((ctxEpilogue.Instruction) as Instructions.LiteralInstruction).CreateOperand(ctxEpilogue), instructionSet);

                        _constantRemoved = true;
                    }

                }
            }
        }
Exemple #9
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="block"></param>
        private void RenameVariables(BasicBlock block)
        {
            for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext())
            {
                if (!(context.Instruction is PhiInstruction))
                {
                    for (var i = 0; i < context.OperandCount; ++i)
                    {
                        var op = context.GetOperand(i);
                        if (!(op is StackOperand))
                            continue;
                        var name = NameForOperand(context.GetOperand(i));
                        if (!this.variableInformation.ContainsKey(name))
                            throw new Exception(name + " is not in dictionary [block = " + block + "]");
                        var index = this.variableInformation[name].Stack.Peek();
                        context.SetOperand(i, new SsaOperand(context.GetOperand(i), index));
                    }
                }

                if (PhiPlacementStage.IsAssignmentToStackVariable(context))
                {
                    var name = NameForOperand(context.Result);
                    var index = this.variableInformation[name].Count;
                    context.SetResult(new SsaOperand(context.Result, index));
                    this.variableInformation[name].Stack.Push(index);
                    ++this.variableInformation[name].Count;
                }
            }

            foreach (var s in block.NextBlocks)
            {
                var j = this.WhichPredecessor(s, block);
                for (var context = new Context(this.instructionSet, s); !context.EndOfInstruction; context.GotoNext())
                {
                    if (!(context.Instruction is PhiInstruction))
                        continue;
                    var name = NameForOperand(context.GetOperand(j));
                    if (this.variableInformation[name].Stack.Count > 0)
                    {
                        var index = this.variableInformation[name].Stack.Peek();
                        context.SetOperand(j, new SsaOperand(context.GetOperand(j), index));
                    }
                }
            }

            foreach (var s in this.dominanceCalculationStage.GetChildren(block))
            {
                this.RenameVariables(s);
            }

            for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext())
            {
                if (PhiPlacementStage.IsAssignmentToStackVariable(context))
                {
                    var instName = context.Label + "." + context.Index;
                    var op = this.oldLefHandSide[instName];
                    var name = NameForOperand(op);
                    this.variableInformation[name].Stack.Pop();
                }
            }
        }
        /// <summary>
        /// Determines whether [is empty block with single jump] [the specified block].
        /// </summary>
        /// <param name="block">The block.</param>
        /// <returns>
        ///   <c>true</c> if [is empty block with single jump] [the specified block]; otherwise, <c>false</c>.
        /// </returns>
        protected bool IsEmptyBlockWithSingleJump(BasicBlock block)
        {
            if (block.NextBlocks.Count != 1)
                return false;

            var ctx = new Context(InstructionSet, block);

            Debug.Assert(ctx.IsBlockStartInstruction);
            ctx.GotoNext();

            while (!ctx.IsBlockEndInstruction)
            {
                if (!ctx.IsEmpty)
                {
                    if (ctx.Instruction.FlowControl != FlowControl.UnconditionalBranch)
                        return false;
                }

                ctx.GotoNext();
            }

            return true;
        }
        /// <summary>
        /// Called to emit a list of instructions offered by the instruction provider.
        /// </summary>
        protected virtual void EmitInstructions()
        {
            foreach (BasicBlock block in basicBlocks)
            {
                BlockStart(block);

                for (Context context = new Context(instructionSet, block); !context.EndOfInstruction; context.GotoNext())
                    if (context.Instruction != null)
                        if (!context.Ignore)
                        {
                            IPlatformInstruction instruction = context.Instruction as IPlatformInstruction;
                            if (instruction != null)
                                instruction.Emit(context, codeEmitter);
                            else
                                Trace(InternalTrace.CompilerEvent.Error, "Missing Code Transformation: " + context.ToString());
                        }

                BlockEnd(block);
            }
        }
Exemple #12
0
        /// <summary>
        /// Eliminates the common subexpressions.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private static void EliminateCommonSubexpressions(Context ctx)
        {
            List<AEBinExp> AEB = new List<AEBinExp>();
            List<AEBinExp> tmp;

            AEBinExp aeb;

            for (; !ctx.EndOfInstruction; ctx.GotoNext())
            {
                IInstruction instruction = ctx.Instruction; // block.Instructions[i];
                RegisterOperand temp = null;
                bool found = false;

                if ((instruction is CIL.ArithmeticInstruction) && (instruction is CIL.BinaryInstruction))
                {
                    tmp = new List<AEBinExp>(AEB);

                    while (tmp.Count > 0)
                    {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        // Match current instruction's expression against those
                        // in AEB, including commutativity
                        if (IsCommutative(instruction))
                        {
                            //int position = aeb.Position;
                            found = true;

                            // If no variable in tuple, create a new temporary and
                            // insert an instruction evaluating the expression
                            // and assigning it to the temporary
                            if (aeb.Var == null)
                            {
                                // new_tmp()
                                AEB.Remove(aeb);
                                AEB.Add(new AEBinExp(aeb.Position, aeb.Operand1, aeb.Operator, aeb.Operand2, temp));

                                // Insert new assignment to instruction stream in block
                                Context inserted = ctx.InsertBefore();

                                switch (aeb.Operator)
                                {
                                    case Operation.Add:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Add), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Mul:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Mul), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Or:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Or), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    case Operation.Xor:
                                        inserted.SetInstruction(CIL.Instruction.Get(CIL.OpCode.Xor), temp, aeb.Operand1, aeb.Operand2);
                                        break;
                                    default:
                                        break;
                                }

                                //block.Instructions.Insert(position, inst);

                                //++position;
                                //++i;

                                // Replace current instruction by one that copies
                                // the temporary instruction
                                // FIXME PG:
                                // block.Instructions[position] = new IR.MoveInstruction(block.Instructions[position].Results[0], temp);
                                // ctx.SetInstruction(IR.MoveInstruction); // FIXME PG
                                // ctx.Result = block.Instructions[position].Results[0]; // FIXME PG
                                ctx.Operand1 = temp;
                            }
                            else
                            {
                                temp = (RegisterOperand)aeb.Var;
                            }

                            // FIXME PG
                            // block.Instructions[i] = new IR.MoveInstruction(instruction.Results[0], temp);
                        }
                    }

                    if (!found)
                    {
                        Operation opr = Operation.None;

                        if (instruction is CIL.AddInstruction)
                            opr = Operation.Add;
                        else if (instruction is CIL.MulInstruction)
                            opr = Operation.Mul;
                        else if (instruction is IR.LogicalAndInstruction)
                            opr = Operation.And;
                        // Insert new tuple
                        AEB.Add(new AEBinExp(ctx.Index, ctx.Operand1, opr, ctx.Operand2, null));
                    }

                    // Remove all tuples that use the variable assigned to by
                    // the current instruction
                    tmp = new List<AEBinExp>(AEB);

                    while (tmp.Count > 0)
                    {
                        aeb = tmp[0];
                        tmp.RemoveAt(0);

                        if (ctx.Operand1 == aeb.Operand1 || ctx.Operand2 == aeb.Operand2)
                            AEB.Remove(aeb);
                    }
                }
            }
        }
        /// <summary>
        /// Empties the block of all instructions.
        /// </summary>
        /// <param name="block">The block.</param>
        protected void EmptyBlockOfAllInstructions(BasicBlock block)
        {
            var ctx = new Context(InstructionSet, block);
            Debug.Assert(ctx.IsBlockStartInstruction);
            ctx.GotoNext();

            while (!ctx.IsBlockEndInstruction)
            {
                if (!ctx.IsEmpty)
                {
                    ctx.Remove();
                }

                ctx.GotoNext();
            }
        }
        /// <summary>
        /// Logs the instructions in the given enumerable to the trace.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private static void LogInstructions(StringBuilder text, Context ctx)
        {
            for (; !ctx.EndOfInstruction; ctx.GotoNext())
            {
                if (ctx.Instruction == null)
                    continue;

                if (ctx.Ignore)
                    text.Append("; ");

                if (ctx.Marked)
                    text.AppendFormat("L_{0:X4}* {1}", ctx.Label, ctx.Instruction.ToString(ctx));
                else
                    text.AppendFormat("L_{0:X4}: {1}", ctx.Label, ctx.Instruction.ToString(ctx));

                text.AppendLine();
            }
        }
Exemple #15
0
 private void NumberInstructions()
 {
     int index = 2;
     foreach (BasicBlock block in basicBlocks)
     {
         for (Context context = new Context(methodCompiler.InstructionSet, block); !context.EndOfInstruction; context.GotoNext())
         {
             if (!context.IsEmpty)
             {
                 instructionNumbering[context.Index] = index;
                 index = index + 2;
             }
         }
     }
 }
        private IEnumerable<Context> ScanForOperatorNew()
        {
            foreach (BasicBlock block in this.basicBlocks)
            {
                Context context = new Context(instructionSet, block);
                while (!context.EndOfInstruction)
                {
                    if (context.Instruction is NewobjInstruction || context.Instruction is NewarrInstruction)
                    {
                        Debug.WriteLine(@"StaticAllocationResolutionStage: Found a newobj or newarr instruction.");
                        yield return context.Clone();
                    }

                    context.GotoNext();
                }
            }
        }
Exemple #17
0
        /// <summary>
        /// Updates the prologue.
        /// </summary>
        private void UpdatePrologue()
        {
            // Update prologue Block
            var prologueBlock = this.BasicBlocks.PrologueBlock;

            if (prologueBlock != null)
            {
                Context prologueContext = new Context(InstructionSet, prologueBlock);

                prologueContext.GotoNext();

                Debug.Assert(prologueContext.Instruction is Prologue);

                AddPrologueInstructions(prologueContext);
            }
        }
Exemple #18
0
        /// <summary>
        /// Updates the epilogue.
        /// </summary>
        private void UpdateEpilogue()
        {
            // Update epilogue Block
            var epilogueBlock = this.BasicBlocks.EpilogueBlock;

            if (epilogueBlock != null)
            {
                Context epilogueContext = new Context(InstructionSet, epilogueBlock);

                epilogueContext.GotoNext();

                while (epilogueContext.IsEmpty)
                {
                    epilogueContext.GotoNext();
                }

                Debug.Assert(epilogueContext.Instruction is Epilogue);

                AddEpilogueInstructions(epilogueContext);
            }
        }
 /// <summary>
 /// Collects all local variables assignments into a list.
 /// </summary>
 /// <param name="locals">Holds all locals found by the stage.</param>
 /// <param name="block">The block.</param>
 private void CollectLocalVariables(List<StackOperand> locals, BasicBlock block)
 {
     for (Context ctx = new Context(instructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
     {
         // Does this instruction define a new stack variable?
         foreach (Operand op in ctx.Results)
         {
             // The instruction list may not be in SSA form, so we have to check existence again here unfortunately.
             // FIXME: Allow us to detect the state of blocks
             LocalVariableOperand lvop = op as LocalVariableOperand;
             if (lvop != null && !locals.Contains(lvop))
                 locals.Add(lvop);
         }
     }
 }
Exemple #20
0
        /// <summary>
        /// Logs the instructions in the given enumerable to the trace.
        /// </summary>
        /// <param name="ctx">The context.</param>
        private static void LogInstructions(StringBuilder text, Context ctx)
        {
            for (; ctx.Index >= 0; ctx.GotoNext())
            {
                if (ctx.IsEmpty)
                    continue;

                text.AppendFormat("L_{0:X4}", ctx.Label);

                if (ctx.Marked)
                    text.AppendFormat("*");
                else
                    text.AppendFormat(" ");

                //if (ctx.SlotNumber != 0)
                //	text.AppendFormat("/{0}", ctx.SlotNumber.ToString());

                text.AppendFormat("{0}", ctx.Instruction.ToString(ctx));
                text.AppendLine();

                if (ctx.IsBlockEndInstruction)
                    return;
            }
        }
        /// <summary>
        /// Dumps this instance.
        /// </summary>
        protected void Dump(bool before)
        {
            Debug.WriteLine(string.Empty);

            Debug.WriteLine("METHOD: " + MethodCompiler.Method.FullName);
            Debug.WriteLine("STAGE : " + (before ? "[BEFORE] " : "[AFTER] ") + GetType().Name);
            Debug.WriteLine(string.Empty);

            for (int index = 0; index < BasicBlocks.Count; index++)
                for (Context ctx = new Context(BasicBlocks[index]); !ctx.IsBlockEndInstruction; ctx.GotoNext())
                    if (!ctx.IsEmpty)
                        Debug.WriteLine(ctx.ToString());
        }
        /// <summary>
        /// Assigns the operands.
        /// </summary>
        /// <param name="block">The block.</param>
        /// <param name="operandStack">The operand stack.</param>
        private void AssignOperands(BasicBlock block, Stack<Operand> operandStack)
        {
            for (var ctx = new Context(instructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                if (ctx.Instruction == null)
                    continue;

                if (ctx.Instruction is IR.JmpInstruction)
                    continue;

                if (!(ctx.Instruction is IBranchInstruction) && !(ctx.Instruction is ICILInstruction) && !(ctx.Instruction is IR.ExceptionPrologueInstruction))
                    continue;

                if (ctx.Instruction is IR.ExceptionPrologueInstruction)
                {
                    AssignOperandsFromCILStack(ctx, operandStack);
                    PushResultOperands(ctx, operandStack);
                }
                else //if (!(ctx.Instruction is IR.JmpInstruction))
                {
                    AssignOperandsFromCILStack(ctx, operandStack);
                    (ctx.Instruction as ICILInstruction).Validate(ctx, methodCompiler);
                    PushResultOperands(ctx, operandStack);
                }
            }
        }
        /// <summary>
        /// Dumps this instance.
        /// </summary>
        protected void Dump(bool before)
        {
            Debug.WriteLine(string.Empty);

            Debug.WriteLine("METHOD: " + MethodCompiler.Method.FullName);
            Debug.WriteLine("STAGE : " + (before ? "[BEFORE] " : "[AFTER] ") + GetType().Name);
            Debug.WriteLine(string.Empty);

            for (int index = 0; index < BasicBlocks.Count; index++)
            {
                for (Context ctx = new Context(BasicBlocks[index]); !ctx.IsBlockEndInstruction; ctx.GotoNext())
                {
                    if (!ctx.IsEmpty)
                    {
                        Debug.WriteLine(ctx.ToString());
                    }
                }
            }
        }
        /// <summary>
        /// Creates the outgoing moves.
        /// </summary>
        /// <param name="block">The block.</param>
        /// <param name="operandStack">The operand stack.</param>
        /// <param name="joinStack">The join stack.</param>
        private void CreateOutgoingMoves(BasicBlock block, Stack<Operand> operandStack, Stack<Operand> joinStack)
        {
            var context = new Context(instructionSet, block);

            while (!context.EndOfInstruction && !(context.Instruction is IBranchInstruction))
            {
                context.GotoNext();
            }

            while (operandStack.Count > 0)
            {
                var operand = operandStack.Pop();
                var destination = joinStack.Pop();
                context.InsertBefore().SetInstruction(IR.Instruction.MoveInstruction, destination, operand);
            }
        }