Example #1
0
        void VisitLogicNot(Comp inst, ILInstruction arg)
        {
            ILInstruction lhs, rhs;

            if (arg is Comp comp)
            {
                if ((comp.InputType != StackType.F && !comp.IsLifted) || comp.Kind.IsEqualityOrInequality())
                {
                    context.Step("push negation into comparison", inst);
                    comp.Kind = comp.Kind.Negate();
                    comp.AddILRange(inst.ILRange);
                    inst.ReplaceWith(comp);
                }
                comp.AcceptVisitor(this);
            }
            else if (arg.MatchLogicAnd(out lhs, out rhs))
            {
                // logic.not(if (lhs) rhs else ldc.i4 0)
                // ==> if (logic.not(lhs)) ldc.i4 1 else logic.not(rhs)
                context.Step("push negation into logic.and", inst);
                IfInstruction ifInst = (IfInstruction)arg;
                var           ldc0   = ifInst.FalseInst;
                Debug.Assert(ldc0.MatchLdcI4(0));
                ifInst.Condition = Comp.LogicNot(lhs, inst.ILRange);
                ifInst.TrueInst  = new LdcI4(1)
                {
                    ILRange = ldc0.ILRange
                };
                ifInst.FalseInst = Comp.LogicNot(rhs, inst.ILRange);
                inst.ReplaceWith(ifInst);
                ifInst.AcceptVisitor(this);
            }
            else if (arg.MatchLogicOr(out lhs, out rhs))
            {
                // logic.not(if (lhs) ldc.i4 1 else rhs)
                // ==> if (logic.not(lhs)) logic.not(rhs) else ldc.i4 0)
                context.Step("push negation into logic.or", inst);
                IfInstruction ifInst = (IfInstruction)arg;
                var           ldc1   = ifInst.TrueInst;
                Debug.Assert(ldc1.MatchLdcI4(1));
                ifInst.Condition = Comp.LogicNot(lhs, inst.ILRange);
                ifInst.TrueInst  = Comp.LogicNot(rhs, inst.ILRange);
                ifInst.FalseInst = new LdcI4(0)
                {
                    ILRange = ldc1.ILRange
                };
                inst.ReplaceWith(ifInst);
                ifInst.AcceptVisitor(this);
            }
            else
            {
                arg.AcceptVisitor(this);
            }
        }