// TODO:
        // 1. If first branch is to the next basic block,
        //       then swap branch condition, replace branch target with jump target, and remove jump instruction.
        //           part of code: ConditionCode = GetOppositeConditionCode(ConditionCode);
        // 2. If the basic block contains only a single jump instruction, rewrite all jumps to avoid it.
        protected override void Run()
        {
            var trace = CreateTrace();

            for (int f = 0; f < BasicBlocks.Count - 1; f++)
            {
                var from = BasicBlocks[f];
                var next = BasicBlocks[f + 1];

                Context context = new Context(InstructionSet, from, from.EndIndex);
                context.GotoPrevious();

                while (context.IsEmpty)
                {
                    context.GotoPrevious();
                }

                if (context.Instruction.FlowControl != FlowControl.UnconditionalBranch)
                    continue;

                Debug.Assert(context.Instruction.FlowControl == FlowControl.UnconditionalBranch);
                Debug.Assert(context.BranchTargets.Length == 1);

                var target = context.BranchTargets[0];

                if (next.Label != target)
                    continue;

                context.Remove();
            }
        }
Exemple #2
0
 /// <summary>
 /// Replaces the intrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="typeSystem">The type system.</param>
 void IIntrinsicMethod.ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem, IList<RuntimeParameter> parameters)
 {
     // TODO
     context.Remove();
 }
        /// <summary>
        /// Visitation function for SwitchInstruction.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.Switch(Context context)
        {
            int[] targets = context.BranchTargets;
            Operand operand = context.Operand1;

            context.Remove();

            for (int i = 0; i < targets.Length - 1; ++i)
            {
                context.AppendInstruction(X86.Cmp, null, operand, Operand.CreateConstant(BuiltInSigType.IntPtr, i));
                context.AppendInstruction(X86.Branch, ConditionCode.Equal);
                context.SetBranch(targets[i]);
            }
        }
        /// <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>
        /// Visitation function for Return.
        /// </summary>
        /// <param name="context">The context.</param>
        void IIRVisitor.Return(Context context)
        {
            Debug.Assert(context.BranchTargets != null);

            if (context.Operand1 != null)
            {
                // HACK - to support test suit on windows
                //if (context.Operand1.IsR)
                //{
                //	Operand stack = methodCompiler.StackLayout.AddStackLocal(context.Operand1.Type);
                //	Context before = context.InsertBefore();
                //	architecture.InsertMoveInstruction(before, stack, context.Operand1);
                //	before.AppendInstruction(X86.Fld, null, stack);
                //}

                var returnOperand = context.Operand1;

                context.Remove();

                CallingConvention.SetReturnValue(TypeLayout, context, returnOperand);

                context.AppendInstruction(X86.Jmp);
                context.SetBranch(Int32.MaxValue);
            }
            else
            {
                context.SetInstruction(X86.Jmp);
                context.SetBranch(Int32.MaxValue);
            }
        }
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Movzx"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void IX86Visitor.Movzx(Context context)
        {
            // Movsx can not use ESI or EDI registers
            if (context.Operand1.IsCPURegister && (context.Operand1.Register == GeneralPurposeRegister.ESI || context.Operand1.Register == GeneralPurposeRegister.EDI))
            {
                Debug.Assert(context.Result.IsCPURegister);

                Operand dest = context.Result;
                Operand source = context.Operand1;

                if (source.Register != dest.Register)
                {
                    context.SetInstruction(X86.Mov, dest, source);
                }
                else
                {
                    context.Remove();
                }

                if (dest.IsShort || dest.IsChar)
                {
                    context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstantUnsignedInt(TypeSystem, (uint)0xffff));
                }
                else if (dest.IsByte || dest.IsBoolean)
                {
                    context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstantUnsignedInt(TypeSystem, (uint)0xff));
                }
            }
        }
        /// <summary>
        /// Visitation function for <see cref="IX86Visitor.Movsx"/> instructions.
        /// </summary>
        /// <param name="context">The context.</param>
        void IX86Visitor.Movsx(Context context)
        {
            // Movsx can not use ESI or EDI registers
            if (context.Operand1.IsCPURegister && (context.Operand1.Register == GeneralPurposeRegister.ESI || context.Operand1.Register == GeneralPurposeRegister.EDI))
            {
                Operand dest = context.Result;
                Operand source = context.Operand1;

                if (source.Register != dest.Register)
                {
                    context.SetInstruction(X86.Mov, dest, source);
                }
                else
                {
                    context.Remove();
                }

                if (source.IsShort || source.IsChar)
                {
                    context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstantUnsignedInt(MethodCompiler.TypeSystem, (uint)0x0000ffff));
                    context.AppendInstruction(X86.Xor, dest, dest, Operand.CreateConstantUnsignedInt(MethodCompiler.TypeSystem, (uint)0x00010000));
                    context.AppendInstruction(X86.Sub, dest, dest, Operand.CreateConstantUnsignedInt(MethodCompiler.TypeSystem, (uint)0x00010000));
                }
                else if (source.IsByte || source.IsBoolean)
                {
                    context.AppendInstruction(X86.And, dest, dest, Operand.CreateConstantUnsignedInt(MethodCompiler.TypeSystem, (uint)0x000000ff));
                    context.AppendInstruction(X86.Xor, dest, dest, Operand.CreateConstantUnsignedInt(MethodCompiler.TypeSystem, (uint)0x00000100));
                    context.AppendInstruction(X86.Sub, dest, dest, Operand.CreateConstantUnsignedInt(MethodCompiler.TypeSystem, (uint)0x00000100));
                }
            }
        }
        /// <summary>
        /// Visitation function for SwitchInstruction.
        /// </summary>
        /// <param name="context">The context.</param>
        void IR.IIRVisitor.SwitchInstruction(Context context)
        {
            IBranch branch = context.Branch;
            Operand operand = context.Operand1;

            context.Remove();

            for (int i = 0; i < branch.Targets.Length - 1; ++i)
            {
                context.AppendInstruction(Instruction.CmpInstruction, operand, new ConstantOperand(BuiltInSigType.IntPtr, i));
                context.AppendInstruction(Instruction.BranchInstruction, IR.ConditionCode.Equal);
                context.SetBranch(branch.Targets[i]);
            }
        }
Exemple #9
0
        /// <summary>
        /// Processes the phi instruction.
        /// </summary>
        /// <param name="block">The block.</param>
        /// <param name="context">The context.</param>
        private void ProcessPhiInstruction(BasicBlock block, Context context)
        {
            for (var predecessorIndex = 0; predecessorIndex < block.PreviousBlocks.Count; ++predecessorIndex)
            {
                var predecessor = block.PreviousBlocks[predecessorIndex];
                var operand = context.GetOperand(predecessorIndex);

                this.InsertCopyStatement(predecessor, context.Result, operand);
            }
            context.Remove();
        }