Beispiel #1
0
 protected internal override void VisitStObj(StObj inst)
 {
     base.VisitStObj(inst);
     if (EarlyExpressionTransforms.StObjToStLoc(inst, context))
     {
         context.RequestRerun();
         return;
     }
     TransformAssignment.HandleCompoundAssign(inst, context);
 }
Beispiel #2
0
        protected internal override void VisitCall(Call inst)
        {
            var expr = EarlyExpressionTransforms.HandleCall(inst, context);

            if (expr != null)
            {
                // The resulting expression may trigger further rules, so continue visiting the replacement:
                expr.AcceptVisitor(this);
            }
            else
            {
                base.VisitCall(inst);
                TransformAssignment.HandleCompoundAssign(inst, context);
            }
        }
Beispiel #3
0
 protected internal override void VisitLdObj(LdObj inst)
 {
     base.VisitLdObj(inst);
     EarlyExpressionTransforms.AddressOfLdLocToLdLoca(inst, context);
     if (EarlyExpressionTransforms.LdObjToLdLoc(inst, context))
     {
         return;
     }
     if (TransformDecimalFieldToConstant(inst, out LdcDecimal decimalConstant))
     {
         context.Step("TransformDecimalFieldToConstant", inst);
         inst.ReplaceWith(decimalConstant);
         return;
     }
 }
 protected internal override void VisitStObj(StObj inst)
 {
     if (IsDisplayClassFieldAccess(inst.Target, out var v, out var displayClass, out var field)) {
         VariableToDeclare vd = displayClass.VariablesToDeclare[(IField)field.MemberDefinition];
         if (vd.CanPropagate && vd.Initializers.Contains(inst)) {
             if (inst.Parent is Block containingBlock) {
                 context.Step($"Remove initializer of {v.Name}.{vd.Name} due to propagation", inst);
                 containingBlock.Instructions.Remove(inst);
                 return;
             }
         }
     }
     base.VisitStObj(inst);
     EarlyExpressionTransforms.StObjToStLoc(inst, context);
 }
Beispiel #5
0
        protected internal override void VisitStObj(StObj inst)
        {
            base.VisitStObj(inst);
            if (EarlyExpressionTransforms.StObjToStLoc(inst, context))
            {
                context.RequestRerun();
                return;
            }

            if (inst.Value is BinaryNumericInstruction binary &&
                binary.Left.MatchLdObj(out ILInstruction target, out IType t) &&
                inst.Target.Match(target).Success &&
                SemanticHelper.IsPure(target.Flags) &&
                CompoundAssignmentInstruction.IsBinaryCompatibleWithType(binary, t))
            {
                context.Step("compound assignment", inst);
                // stobj(target, binary.op(ldobj(target), ...))
                // => compound.op(target, ...)
                inst.ReplaceWith(new CompoundAssignmentInstruction(
                                     binary, binary.Left, binary.Right,
                                     t, CompoundAssignmentType.EvaluatesToNewValue));
            }
        }
Beispiel #6
0
 protected internal override void VisitStObj(StObj inst)
 {
     inst.Value.AcceptVisitor(this);
     if (inst.Parent is Block)
     {
         if (IsParameterAssignment(inst, out var displayClass, out var field, out var parameter))
         {
             context.Step($"Detected parameter assignment {parameter.Name}", inst);
             displayClass.Variables.Add((IField)field.MemberDefinition, parameter);
             instructionsToRemove.Add(inst);
             return;
         }
         if (IsDisplayClassAssignment(inst, out displayClass, out field, out var variable))
         {
             context.Step($"Detected display-class assignment {variable.Name}", inst);
             displayClass.Variables.Add((IField)field.MemberDefinition, variable);
             instructionsToRemove.Add(inst);
             return;
         }
     }
     inst.Target.AcceptVisitor(this);
     EarlyExpressionTransforms.StObjToStLoc(inst, context);
 }
Beispiel #7
0
 protected internal override void VisitLdObj(LdObj inst)
 {
     base.VisitLdObj(inst);
     EarlyExpressionTransforms.LdObjToLdLoc(inst, context);
 }
Beispiel #8
0
        protected internal override void VisitComp(Comp inst)
        {
            // "logic.not(arg)" is sugar for "comp(arg != ldc.i4 0)"
            if (inst.MatchLogicNot(out var arg))
            {
                VisitLogicNot(inst, arg);
                return;
            }
            else if (inst.Kind == ComparisonKind.Inequality && inst.LiftingKind == ComparisonLiftingKind.None &&
                     inst.Right.MatchLdcI4(0) && (IfInstruction.IsInConditionSlot(inst) || inst.Left is Comp)
                     )
            {
                // if (comp(x != 0)) ==> if (x)
                // comp(comp(...) != 0) => comp(...)
                context.Step("Remove redundant comp(... != 0)", inst);
                inst.Left.AddILRange(inst);
                inst.ReplaceWith(inst.Left);
                inst.Left.AcceptVisitor(this);
                return;
            }

            base.VisitComp(inst);
            if (inst.IsLifted)
            {
                return;
            }
            EarlyExpressionTransforms.FixComparisonKindLdNull(inst, context);

            var rightWithoutConv = inst.Right.UnwrapConv(ConversionKind.SignExtend).UnwrapConv(ConversionKind.ZeroExtend);

            if (rightWithoutConv.MatchLdcI4(0) &&
                inst.Sign == Sign.Unsigned &&
                (inst.Kind == ComparisonKind.GreaterThan || inst.Kind == ComparisonKind.LessThanOrEqual))
            {
                if (inst.Kind == ComparisonKind.GreaterThan)
                {
                    context.Step("comp.unsigned(left > ldc.i4 0) => comp(left != ldc.i4 0)", inst);
                    inst.Kind = ComparisonKind.Inequality;
                    VisitComp(inst);
                    return;
                }
                else if (inst.Kind == ComparisonKind.LessThanOrEqual)
                {
                    context.Step("comp.unsigned(left <= ldc.i4 0) => comp(left == ldc.i4 0)", inst);
                    inst.Kind = ComparisonKind.Equality;
                    VisitComp(inst);
                    return;
                }
            }
            else if (rightWithoutConv.MatchLdcI4(0) && inst.Kind.IsEqualityOrInequality())
            {
                if (inst.Left.MatchLdLen(StackType.I, out ILInstruction array))
                {
                    // comp.unsigned(ldlen array == conv i4->i(ldc.i4 0))
                    // => comp(ldlen.i4 array == ldc.i4 0)
                    // This is a special case where the C# compiler doesn't generate conv.i4 after ldlen.
                    context.Step("comp(ldlen.i4 array == ldc.i4 0)", inst);
                    inst.InputType = StackType.I4;
                    inst.Left.ReplaceWith(new LdLen(StackType.I4, array).WithILRange(inst.Left));
                    inst.Right = rightWithoutConv;
                }
                else if (inst.Left is Conv conv && conv.TargetType == PrimitiveType.I && conv.Argument.ResultType == StackType.O)
                {
                    // C++/CLI sometimes uses this weird comparison with null:
                    context.Step("comp(conv o->i (ldloc obj) == conv i4->i <sign extend>(ldc.i4 0))", inst);
                    // -> comp(ldloc obj == ldnull)
                    inst.InputType = StackType.O;
                    inst.Left      = conv.Argument;
                    inst.Right     = new LdNull().WithILRange(inst.Right);
                    inst.Right.AddILRange(rightWithoutConv);
                }
            }
        }