/// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            // Create the prologue block
            Context ctx = new Context(InstructionSet, -1);
            // Add a jump instruction to the first block from the prologue
            ctx.AppendInstruction(IR.Instruction.JmpInstruction);
            //ctx.AppendInstruction(CIL.Instruction.Get(CIL.OpCode.Br));
            ctx.SetBranch(0);
            ctx.Label = -1;
            _prologue = CreateBlock(-1, ctx.Index);

            SplitIntoBlocks(0);

            // Create the epilogue block
            ctx = new Context(InstructionSet, -1);
            // Add null instruction, necessary to generate a block index
            ctx.AppendInstruction(null);
            ctx.Ignore = true;
            ctx.Label = Int32.MaxValue;
            _epilogue = CreateBlock(Int32.MaxValue, ctx.Index);

            // Link all the blocks together
            BuildBlockLinks(_prologue);

            // Link Exception Header Clauses
            LinkExceptionHeaderClauses();
        }
示例#2
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            // Create the prologue block
            Context ctx = new Context(InstructionSet, -1);

            // Add a jump instruction to the first block from the prologue
            //ctx.InsertInstructionAfter(IR.Instruction.JmpInstruction);
            ctx.AppendInstruction(CIL.Instruction.Get(CIL.OpCode.Br));
            ctx.SetBranch(0);
            ctx.Label = -1;
            _prologue = CreateBlock(-1, ctx.Index);

            SplitIntoBlocks(0);

            // Create the epilogue block
            ctx = new Context(InstructionSet, -1);
            // Add null instruction, necessary to generate a block index
            ctx.AppendInstruction(null);
            ctx.Ignore = true;
            ctx.Label  = Int32.MaxValue;
            _epilogue  = CreateBlock(Int32.MaxValue, ctx.Index);

            // Link all the blocks together
            BuildBlockLinks(_prologue);
        }
        /// <summary>
        /// Visitation function for <see cref="CIL.ICILVisitor.BinaryBranch"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void CIL.ICILVisitor.BinaryBranch(Context ctx)
        {
            bool swap = ctx.Operand1 is ConstantOperand;
            IBranch branch = ctx.Branch;
            IR.ConditionCode conditionCode = ConvertCondition((ctx.Instruction as CIL.BinaryBranchInstruction).OpCode);

            if (swap) {
                ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Operand2, ctx.Operand1);
                ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, GetOppositeConditionCode(conditionCode));
            }
            else {
                ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Operand1, ctx.Operand2);
                ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, conditionCode);
            }

            ctx.SetBranch(branch.Targets[0]);
        }
        /// <summary>
        /// Visitation function for <see cref="CIL.ICILVisitor.UnaryBranch"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void CIL.ICILVisitor.UnaryBranch(Context ctx)
        {
            IBranch branch = ctx.Branch;
            CIL.OpCode opcode = (ctx.Instruction as CIL.ICILInstruction).OpCode;
            Operand op = ctx.Operand1;

            ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Operand1, new ConstantOperand(new SigType(CilElementType.I4), 0));

            if (opcode == CIL.OpCode.Brtrue || opcode == CIL.OpCode.Brtrue_s)
                ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual);
            else
                if (opcode == CIL.OpCode.Brfalse || opcode == CIL.OpCode.Brfalse_s)
                    ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal);
                else
                    throw new NotImplementedException();

            ctx.SetBranch(branch.Targets[0]);
        }
        /// <summary>
        /// Visitation function for <see cref="CIL.ICILVisitor.Switch"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void CIL.ICILVisitor.Switch(Context ctx)
        {
            IBranch branch = ctx.Branch;
            Operand operand = ctx.Operand1;

            ctx.Remove();

            for (int i = 0; i < branch.Targets.Length - 1; ++i) {
                ctx.AppendInstruction(CPUx86.Instruction.CmpInstruction, operand, new ConstantOperand(new SigType(CilElementType.I), i));
                ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal);
                ctx.SetBranch(branch.Targets[i]);
            }
        }
示例#6
0
        /// <summary>
        /// Visitation function for <see cref="IR.IIRVisitor.ReturnInstruction"/> instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void IR.IIRVisitor.ReturnInstruction(Context ctx)
        {
            Operand op = ctx.Operand1;

            if (op != null)
            {
                ICallingConvention cc = Architecture.GetCallingConvention (MethodCompiler.Method.Signature.CallingConvention);
                cc.MoveReturnValue (ctx, op);
                ctx.AppendInstruction (CPUx86.Instruction.JmpInstruction);
                ctx.SetBranch (Int32.MaxValue);
            }

            else
            {
                ctx.SetInstruction (CPUx86.Instruction.JmpInstruction);
                ctx.SetBranch (Int32.MaxValue);
            }
        }
示例#7
0
        /// <summary>
        /// Finds all targets.
        /// </summary>
        /// <param name="index">The index.</param>
        private void SplitIntoBlocks(int index)
        {
            Dictionary <int, int> targets = new Dictionary <int, int>();

            targets.Add(index, -1);

            // Find out all targets labels
            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                switch (ctx.Instruction.FlowControl)
                {
                case FlowControl.Next: continue;

                case FlowControl.Call: continue;

                case FlowControl.Break:
                    goto case FlowControl.Branch;

                case FlowControl.Return:
                    continue;

                case FlowControl.Throw:
                    goto case FlowControl.Branch;

                case FlowControl.Branch:
                    // Unconditional branch
                    Debug.Assert(ctx.Branch.Targets.Length == 1);
                    if (!targets.ContainsKey(ctx.Branch.Targets[0]))
                    {
                        targets.Add(ctx.Branch.Targets[0], -1);
                    }
                    continue;

                case FlowControl.Switch: goto case FlowControl.ConditionalBranch;

                case FlowControl.ConditionalBranch:
                    // Conditional branch with multiple targets
                    foreach (int target in ctx.Branch.Targets)
                    {
                        if (!targets.ContainsKey(target))
                        {
                            targets.Add(target, -1);
                        }
                    }
                    int next = ctx.Next.Label;
                    if (!targets.ContainsKey(next))
                    {
                        targets.Add(next, -1);
                    }
                    continue;

                default:
                    Debug.Assert(false);
                    break;
                }
            }

            bool slice = false;

            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                FlowControl flow;

                if (targets.ContainsKey(ctx.Label))
                {
                    CreateBlock(ctx.Label, ctx.Index);

                    if (!ctx.IsFirstInstruction)
                    {
                        Context prev = ctx.Previous;
                        flow = prev.Instruction.FlowControl;
                        if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch)
                        {
                            prev.AppendInstruction(IR.Instruction.JmpInstruction);
                            prev.SetBranch(ctx.Label);
                            prev.SliceAfter();
                        }
                    }

                    targets.Remove(ctx.Label);
                }

                if (slice)
                {
                    ctx.SliceBefore();
                }

                flow = ctx.Instruction.FlowControl;

                slice = (flow == FlowControl.Return || flow == FlowControl.Branch || flow == FlowControl.ConditionalBranch || flow == FlowControl.Break || flow == FlowControl.Throw);
            }

            Debug.Assert(targets.Count <= 1);

            if (FindBlock(0) == null)
            {
                CreateBlock(0, index);
            }
        }
        /// <summary>
        /// Visitation function for ReturnInstruction.
        /// </summary>
        /// <param name="context">The context.</param>
        void IR.IIRVisitor.ReturnInstruction(Context context)
        {
            Operand op = context.Operand1;

            if (op != null)
            {
                callingConvention.MoveReturnValue(context, op);
                context.AppendInstruction(CPUx86.Instruction.JmpInstruction);
                context.SetBranch(Int32.MaxValue);
            }
            else
            {
                context.SetInstruction(CPUx86.Instruction.JmpInstruction);
                context.SetBranch(Int32.MaxValue);
            }
        }
        /// <summary>
        /// Visitation function for <see cref="CIL.ICILVisitor.BinaryBranch"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        void CIL.ICILVisitor.BinaryBranch(Context ctx)
        {
            bool swap = ctx.Operand1 is ConstantOperand;
            IBranch branch = ctx.Branch;
            CIL.OpCode opcode = (ctx.Instruction as CIL.BinaryBranchInstruction).OpCode;
            IR.ConditionCode conditionCode;

            if (swap)
            {
                int tmp = branch.Targets[0];
                branch.Targets[0] = branch.Targets[1];
                branch.Targets[1] = tmp;

                ctx.SetInstruction (CPUx86.Instruction.CmpInstruction, ctx.Operand2, ctx.Operand1);

                switch (opcode) {
                // Signed
                case CIL.OpCode.Beq_s:
                    conditionCode = IR.ConditionCode.NotEqual;
                    break;
                case CIL.OpCode.Bge_s:
                    conditionCode = IR.ConditionCode.LessThan;
                    break;
                case CIL.OpCode.Bgt_s:
                    conditionCode = IR.ConditionCode.LessOrEqual;
                    break;
                case CIL.OpCode.Ble_s:
                    conditionCode = IR.ConditionCode.GreaterThan;
                    break;
                case CIL.OpCode.Blt_s:
                    conditionCode = IR.ConditionCode.GreaterOrEqual;
                    break;

                // Unsigned
                case CIL.OpCode.Bne_un_s:
                    conditionCode = IR.ConditionCode.Equal;
                    break;
                case CIL.OpCode.Bge_un_s:
                    conditionCode = IR.ConditionCode.UnsignedLessThan;
                    break;
                case CIL.OpCode.Bgt_un_s:
                    conditionCode = IR.ConditionCode.UnsignedLessOrEqual;
                    break;
                case CIL.OpCode.Ble_un_s:
                    conditionCode = IR.ConditionCode.UnsignedGreaterThan;
                    break;
                case CIL.OpCode.Blt_un_s:
                    conditionCode = IR.ConditionCode.UnsignedGreaterOrEqual;
                    break;

                // Long form signed
                case CIL.OpCode.Beq:
                    goto case CIL.OpCode.Beq_s;
                case CIL.OpCode.Bge:
                    goto case CIL.OpCode.Bge_s;
                case CIL.OpCode.Bgt:
                    goto case CIL.OpCode.Bgt_s;
                case CIL.OpCode.Ble:
                    goto case CIL.OpCode.Ble_s;
                case CIL.OpCode.Blt:
                    goto case CIL.OpCode.Blt_s;

                // Long form unsigned
                case CIL.OpCode.Bne_un:
                    goto case CIL.OpCode.Bne_un_s;
                case CIL.OpCode.Bge_un:
                    goto case CIL.OpCode.Bge_un_s;
                case CIL.OpCode.Bgt_un:
                    goto case CIL.OpCode.Bgt_un_s;
                case CIL.OpCode.Ble_un:
                    goto case CIL.OpCode.Ble_un_s;
                case CIL.OpCode.Blt_un:
                    goto case CIL.OpCode.Blt_un_s;
                default:

                    throw new NotImplementedException ();
                }
                ctx.AppendInstruction (CPUx86.Instruction.BranchInstruction, conditionCode);
                ctx.SetBranch (branch.Targets[0]);
            }

            else
            {
                ctx.SetInstruction (CPUx86.Instruction.CmpInstruction, ctx.Operand1, ctx.Operand2);

                switch (opcode) {
                // Signed
                case CIL.OpCode.Beq_s:
                    conditionCode = IR.ConditionCode.Equal;
                    break;
                case CIL.OpCode.Bge_s:
                    conditionCode = IR.ConditionCode.GreaterOrEqual;
                    break;
                case CIL.OpCode.Bgt_s:
                    conditionCode = IR.ConditionCode.GreaterThan;
                    break;
                case CIL.OpCode.Ble_s:
                    conditionCode = IR.ConditionCode.LessOrEqual;
                    break;
                case CIL.OpCode.Blt_s:
                    conditionCode = IR.ConditionCode.LessThan;
                    break;

                // Unsigned
                case CIL.OpCode.Bne_un_s:
                    conditionCode = IR.ConditionCode.NotEqual;
                    break;
                case CIL.OpCode.Bge_un_s:
                    conditionCode = IR.ConditionCode.UnsignedGreaterOrEqual;
                    break;
                case CIL.OpCode.Bgt_un_s:
                    conditionCode = IR.ConditionCode.UnsignedGreaterThan;
                    break;
                case CIL.OpCode.Ble_un_s:
                    conditionCode = IR.ConditionCode.UnsignedLessOrEqual;
                    break;
                case CIL.OpCode.Blt_un_s:
                    conditionCode = IR.ConditionCode.UnsignedLessThan;
                    break;

                // Long form signed
                case CIL.OpCode.Beq:
                    goto case CIL.OpCode.Beq_s;
                case CIL.OpCode.Bge:
                    goto case CIL.OpCode.Bge_s;
                case CIL.OpCode.Bgt:
                    goto case CIL.OpCode.Bgt_s;
                case CIL.OpCode.Ble:
                    goto case CIL.OpCode.Ble_s;
                case CIL.OpCode.Blt:
                    goto case CIL.OpCode.Blt_s;

                // Long form unsigned
                case CIL.OpCode.Bne_un:
                    goto case CIL.OpCode.Bne_un_s;
                case CIL.OpCode.Bge_un:
                    goto case CIL.OpCode.Bge_un_s;
                case CIL.OpCode.Bgt_un:
                    goto case CIL.OpCode.Bgt_un_s;
                case CIL.OpCode.Ble_un:
                    goto case CIL.OpCode.Ble_un_s;
                case CIL.OpCode.Blt_un:
                    goto case CIL.OpCode.Blt_un_s;
                default:

                    throw new NotImplementedException ();
                }
                ctx.AppendInstruction (CPUx86.Instruction.BranchInstruction, conditionCode);
                ctx.SetBranch (branch.Targets[0]);
            }

            ctx.AppendInstruction (CPUx86.Instruction.JmpInstruction);
            ctx.SetBranch (branch.Targets[1]);
        }
        /// <summary>
        /// Visitation function for <see cref="ICILVisitor.BinaryBranch"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        public void BinaryBranch(Context ctx)
        {
            IBranch branch = ctx.Branch;

            ConditionCode cc = ConvertCondition(((ICILInstruction)ctx.Instruction).OpCode);
            Operand first = ctx.Operand1;
            Operand second = ctx.Operand2;

            IInstruction comparisonInstruction = Instruction.IntegerCompareInstruction;
            if (first.StackType == StackTypeCode.F)
            {
                comparisonInstruction = Instruction.FloatingPointCompareInstruction;
            }

            Operand comparisonResult = this.MethodCompiler.CreateTemporary(BuiltInSigType.Int32);
            ctx.SetInstruction(comparisonInstruction, comparisonResult, first, second);
            ctx.ConditionCode = cc;

            ctx.AppendInstruction(Instruction.BranchInstruction, comparisonResult);
            ctx.ConditionCode = cc;
            ctx.SetBranch(branch.Targets[0]);
        }
        /// <summary>
        /// Visitation function for <see cref="ICILVisitor.UnaryBranch"/>.
        /// </summary>
        /// <param name="ctx">The context.</param>
        public void UnaryBranch(Context ctx)
        {
            IBranch branch = ctx.Branch;

            ConditionCode cc;
            Operand first = ctx.Operand1;
            Operand second = new ConstantOperand(BuiltInSigType.Int32, 0UL);

            OpCode opcode = ((ICILInstruction)ctx.Instruction).OpCode;
            if (opcode == OpCode.Brtrue || opcode == OpCode.Brtrue_s)
            {
                cc = ConditionCode.NotEqual;
            }
            else if (opcode == OpCode.Brfalse || opcode == OpCode.Brfalse_s)
            {
                cc = ConditionCode.Equal;
            }
            else
            {
                throw new NotSupportedException(@"CILTransformationStage.UnaryBranch doesn't support CIL opcode " + opcode);
            }

            Operand comparisonResult = this.MethodCompiler.CreateTemporary(BuiltInSigType.Int32);
            ctx.SetInstruction(Instruction.IntegerCompareInstruction, comparisonResult, first, second);
            ctx.ConditionCode = cc;

            ctx.AppendInstruction(Instruction.BranchInstruction, comparisonResult);
            ctx.ConditionCode = cc;
            ctx.SetBranch(branch.Targets[0]);
        }
        /// <summary>
        /// Visitation function for BinaryBranch instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void BinaryBranch(Context context)
        {
            IBranch branch = context.Branch;

            ConditionCode cc = ConvertCondition(((CIL.ICILInstruction)context.Instruction).OpCode);
            Operand first = context.Operand1;
            Operand second = context.Operand2;

            IInstruction comparisonInstruction = Instruction.IntegerCompareInstruction;
            if (first.StackType == StackTypeCode.F)
            {
                comparisonInstruction = Instruction.FloatingPointCompareInstruction;
                Operand comparisonResult = this.methodCompiler.CreateTemporary(BuiltInSigType.Int32);
                context.SetInstruction(comparisonInstruction, comparisonResult, first, second);
                context.ConditionCode = cc;

                context.AppendInstruction(Instruction.IntegerCompareInstruction, comparisonResult, comparisonResult, new ConstantOperand(new SigType(CilElementType.I), 1));
                context.ConditionCode = ConditionCode.Equal;
                context.AppendInstruction(Instruction.BranchInstruction, comparisonResult);
                context.ConditionCode = ConditionCode.Equal;
                context.SetBranch(branch.Targets[0]);
                context.AppendInstruction(Instruction.JmpInstruction);
                context.SetBranch(context.Next.Label);
            }
            else
            {
                Operand comparisonResult = this.methodCompiler.CreateTemporary(BuiltInSigType.Int32);
                context.SetInstruction(comparisonInstruction, comparisonResult, first, second);
                context.ConditionCode = cc;

                context.AppendInstruction(Instruction.BranchInstruction, comparisonResult);
                context.ConditionCode = cc;
                context.SetBranch(branch.Targets[0]);
            }
        }
        public void 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(CPUx86.Instruction.CmpInstruction, operand, new ConstantOperand(new SigType(CilElementType.I), i));
                context.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal);
                context.SetBranch(branch.Targets[i]);
            }
        }
        /// <summary>
        /// Visitation function for <see cref="IR.IIRVisitor.ReturnInstruction"/> instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        public void ReturnInstruction(Context ctx)
        {
            Operand op = ctx.Operand1;

            if (op != null) {
                ICallingConvention cc = Architecture.GetCallingConvention();
                cc.MoveReturnValue(ctx, op);
                ctx.AppendInstruction(CPUx86.Instruction.JmpInstruction);
                ctx.SetBranch(Int32.MaxValue);
            }
            else {
                ctx.SetInstruction(CPUx86.Instruction.JmpInstruction);
                ctx.SetBranch(Int32.MaxValue);
            }
        }