protected internal override void VisitStObj(StObj inst)
 {
     base.VisitStObj(inst);
     if (EarlyExpressionTransforms.StObjToStLoc(inst, context))
     {
         context.RequestRerun();
         return;
     }
     TransformAssignment.HandleCompoundAssign(inst, context);
 }
Exemple #2
0
        bool LegacyPattern(Block block, int pos, StatementTransformContext context)
        {
            // Legacy csc pattern:
            //   stloc s(lhsInst)
            //   if (logic.not(call op_False(ldloc s))) Block {
            //     stloc s(call op_BitwiseAnd(ldloc s, rhsInst))
            //   }
            // ->
            //   stloc s(user.logic op_BitwiseAnd(lhsInst, rhsInst))
            if (!block.Instructions[pos].MatchStLoc(out var s, out var lhsInst))
            {
                return(false);
            }
            if (!(s.Kind == VariableKind.StackSlot))
            {
                return(false);
            }
            if (!(block.Instructions[pos + 1] is IfInstruction ifInst))
            {
                return(false);
            }
            if (!ifInst.Condition.MatchLogicNot(out var condition))
            {
                return(false);
            }
            if (!(MatchCondition(condition, out var s2, out string conditionMethodName) && s2 == s))
            {
                return(false);
            }
            if (ifInst.FalseInst.OpCode != OpCode.Nop)
            {
                return(false);
            }
            var trueInst = Block.Unwrap(ifInst.TrueInst);

            if (!trueInst.MatchStLoc(s, out var storeValue))
            {
                return(false);
            }
            if (storeValue is Call call)
            {
                if (!MatchBitwiseCall(call, s, conditionMethodName))
                {
                    return(false);
                }
                if (s.IsUsedWithin(call.Arguments[1]))
                {
                    return(false);
                }
                context.Step("User-defined short-circuiting logic operator (legacy pattern)", condition);
                ((StLoc)block.Instructions[pos]).Value = new UserDefinedLogicOperator(call.Method, lhsInst, call.Arguments[1])
                                                         .WithILRange(call);
                block.Instructions.RemoveAt(pos + 1);
                context.RequestRerun();                 // the 'stloc s' may now be eligible for inlining
                return(true);
            }
            return(false);
        }
Exemple #3
0
        public void Run(Block block, BlockTransformContext context)
        {
            var ctx = new StatementTransformContext(context);
            int pos = 0;

            ctx.rerunPosition = block.Instructions.Count - 1;
            while (pos >= 0)
            {
                if (ctx.rerunPosition != null)
                {
                    Debug.Assert(ctx.rerunPosition >= pos);
#if DEBUG
                    for (; pos < ctx.rerunPosition; ++pos)
                    {
                        block.Instructions[pos].ResetDirty();
                    }
#else
                    pos = ctx.rerunPosition.Value;
#endif
                    Debug.Assert(pos == ctx.rerunPosition);
                    ctx.rerunPosition = null;
                }
                foreach (var transform in children)
                {
                    transform.Run(block, pos, ctx);
#if DEBUG
                    block.Instructions[pos].CheckInvariant(ILPhase.Normal);
                    for (int i = Math.Max(0, pos - 100); i < pos; ++i)
                    {
                        if (block.Instructions[i].IsDirty)
                        {
                            Debug.Fail($"{transform.GetType().Name} modified an instruction before pos");
                        }
                    }
#endif
                    if (ctx.rerunCurrentPosition)
                    {
                        ctx.rerunCurrentPosition = false;
                        ctx.RequestRerun(pos);
                    }
                    if (ctx.rerunPosition != null)
                    {
                        break;
                    }
                }
                if (ctx.rerunPosition == null)
                {
                    pos--;
                }
            }
        }
Exemple #4
0
 void IStatementTransform.Run(Block block, int pos, StatementTransformContext context)
 {
     this.context = context;
     if (context.Settings.MakeAssignmentExpressions)
     {
         if (TransformInlineAssignmentStObjOrCall(block, pos) || TransformInlineAssignmentLocal(block, pos))
         {
             // both inline assignments create a top-level stloc which might affect inlining
             context.RequestRerun();
             return;
         }
     }
     if (context.Settings.IntroduceIncrementAndDecrement)
     {
         if (TransformPostIncDecOperatorWithInlineStore(block, pos) ||
             TransformPostIncDecOperator(block, pos) ||
             TransformPostIncDecOperatorLocal(block, pos))
         {
             // again, new top-level stloc might need inlining:
             context.RequestRerun();
             return;
         }
     }
 }