Beispiel #1
0
        public static void DoEvictUnreachableCode(ControlFlowGraph cfg)
        {
            // todo. this still doesn't completely fix code like "while(false)"
            var unreachable = cfg.Vertices.Except(cfg.Cflow());

            unreachable.Contains(cfg.Finish).AssertFalse();
            cfg.RemoveVertices(unreachable);
        }
        public static void DoDecompileComplexConditions(ControlFlowGraph cfg)
        {
            var flow = cfg.Cflow(cfg.Start);

            while (true)
            {
                var vs = flow.FirstOrDefault(v =>
                                             v.Residue.Count() == 1 &&
                                             cfg.Vedges(v, null).Count() == 2 &&
                                             cfg.Vedges(v, null).All(e => e.Target.BalancedCode.IsEmpty() && e.Target.Residue.Count() == 1));
                if (vs == null)
                {
                    break;
                }

                var conv = cfg.ConvStrict(vs);
                var ass  = conv.BalancedCode.AssertFirst().AssertCast <Assign>();
                (ass.Lhs is Ref && ass.Rhs is Loophole).AssertTrue();

                var parts      = cfg.Cflow(vs, conv);
                var innerEdges = cfg.Edges(parts, parts).ToList();
                cfg.Edges(null, parts).Except(innerEdges).AssertEach(e => e.Target == vs);
                cfg.Edges(parts, null).Except(innerEdges).AssertEach(e => e.Source == vs || e.Source == conv);

                while (true)
                {
                    var somethingWasChanged = false;
                    foreach (var pivot in parts)
                    {
                        var pivot_inEdges = cfg.Vedges(null, pivot);
                        if (pivot_inEdges.Count() != 1)
                        {
                            continue;
                        }

                        var e_pred2pivot  = pivot_inEdges.AssertSingle();
                        var pred          = e_pred2pivot.Source;
                        var pred_outEdges = cfg.Vedges(pred, null);
                        if (pred_outEdges.Count() != 2)
                        {
                            continue;
                        }

                        var e_pred2target1  = pred_outEdges.AssertSingle(e => e.Target != pivot);
                        var target1         = e_pred2target1.Target;
                        var e_pivot2target1 = cfg.Vedge(pivot, target1);
                        if (e_pivot2target1 == null)
                        {
                            continue;
                        }

                        var pivot_outEdges = cfg.Vedges(pivot, null);
                        if (pivot_outEdges.Count() != 2)
                        {
                            continue;
                        }
                        var e_pivot2target2 = pivot_outEdges.AssertSingle(e => e.Target != target1);
                        var target2         = e_pivot2target2.Target;

                        var @operator = e_pred2target1.Condition == PredicateType.IsTrue ? OperatorType.OrElse :
                                        e_pred2target1.Condition == PredicateType.IsFalse ? OperatorType.AndAlso :
                                        ((Func <OperatorType>)(() => { throw AssertionHelper.Fail(); }))();
                        var clause_left  = pred.Residue.AssertSingle();
                        var clause_right = pivot.Residue.AssertSingle();
                        var negate_rhs   = e_pred2target1.Condition != e_pivot2target1.Condition;
                        if (negate_rhs)
                        {
                            clause_right = Operator.Not(clause_right);
                        }
                        var junction = Operator.Create(@operator, clause_left, clause_right);

                        cfg.RemoveVertex(pivot);
                        cfg.AddEdge(new ControlFlowEdge(pred, target2, e_pred2target1.Condition.Negate()));
                        pred.Residue.SetElements(junction);
                        somethingWasChanged |= true;
                    }

                    if (!somethingWasChanged)
                    {
                        break;
                    }
                }

                parts = cfg.Cflow(vs, conv);
                (parts.Count() == 4).AssertTrue();
                var @const = parts.Except(vs, conv).AssertSingle(v => v.Residue.AssertSingle() is Const);
                var vnext  = parts.Except(vs, conv, @const).AssertSingle();
                (cfg.Vedge(@const, vnext) == null && cfg.Vedge(vnext, @const) == null).AssertTrue();
                cfg.Vedge(vs, vnext).IsConditional.AssertTrue();
                cfg.Vedge(vs, @const).IsConditional.AssertTrue();
                cfg.Vedge(vnext, conv).IsUnconditional.AssertTrue();
                cfg.Vedge(@const, conv).IsUnconditional.AssertTrue();

                var estart     = vs.Residue.AssertSingle();
                var enext      = vnext.Residue.AssertSingle();
                var cond_const = @const.Residue.AssertSingle().AssertCast <Const>().Value.AssertCast <int>();
                var cond_edge  = cfg.Vedge(vs, @const).Condition;
                var val_const  = cond_const == 1 ? true :
                                 cond_const == 0 ? false :
                                 ((Func <bool>)(() => { throw AssertionHelper.Fail(); }))();
                var val_edge = cond_edge == PredicateType.IsTrue ? true :
                               cond_edge == PredicateType.IsFalse ? false :
                               ((Func <bool>)(() => { throw AssertionHelper.Fail(); }))();

                var operator1     = val_const ? OperatorType.OrElse : OperatorType.AndAlso;
                var clause_left1  = val_edge && val_const ? estart : Operator.Not(estart);
                var clause_right1 = !val_edge && !val_const?Operator.Not(enext) : enext;

                var junction1 = Operator.Create(operator1, clause_left1, clause_right1);

                var conv_outEdges = cfg.Vedges(conv, null);
                var conv_inEdges  = cfg.Vedges(null, conv).Except(cfg.Vedges(parts, conv));
                cfg.RemoveVertices(@const, vnext, conv);
                conv_outEdges.ForEach(e => cfg.AddEdge(new ControlFlowEdge(vs, e.Target, e.Tag)));
                conv_inEdges.ForEach(e => cfg.AddEdge(new ControlFlowEdge(e.Source, vs, e.Tag)));

                vs.BalancedCode.Add(new Assign(ass.Lhs, junction1));
                vs.BalancedCode.AddElements(conv.BalancedCode.Skip(1));
                vs.Residue.SetElements(conv.Residue);
            }

            cfg.Edges().AssertEach(e => e.Tag.Arity() <= 1);
            cfg.Vertices.Where(v => v.Residue.IsNotEmpty()).AssertEach(v => v.Residue.Count() == 1);
            cfg.Vertices.AssertNone(v => v.Residue.IsNotEmpty() &&
                                    cfg.Vedges(v, null).Any(e => e.IsUnconditional && e.Target != cfg.Finish));
        }