Пример #1
0
        private static void MergePhiVersions(SSAConstructorSparseEx ssa, DirectGraph graph
                                             )
        {
            // collect phi versions
            List <HashSet <VarVersionPair> > lst = new List <HashSet <VarVersionPair> >();

            foreach (KeyValuePair <VarVersionPair, FastSparseSetFactory <int> .FastSparseSet <int> > ent
                     in ssa.GetPhi())
            {
                HashSet <VarVersionPair> set = new HashSet <VarVersionPair>();
                set.Add(ent.Key);
                foreach (int version in ent.Value)
                {
                    set.Add(new VarVersionPair(ent.Key.var, version));
                }
                for (int i = lst.Count - 1; i >= 0; i--)
                {
                    HashSet <VarVersionPair> tset         = lst[i];
                    HashSet <VarVersionPair> intersection = new HashSet <VarVersionPair>(set);
                    intersection.IntersectWith(tset);
                    if (!(intersection.Count == 0))
                    {
                        Sharpen.Collections.AddAll(set, tset);
                        lst.RemoveAtReturningValue(i);
                    }
                }
                lst.Add(set);
            }
            Dictionary <VarVersionPair, int> phiVersions = new Dictionary <VarVersionPair, int
                                                                           >();

            foreach (HashSet <VarVersionPair> set in lst)
            {
                int min = int.MaxValue;
                foreach (VarVersionPair paar in set)
                {
                    if (paar.version < min)
                    {
                        min = paar.version;
                    }
                }
                foreach (VarVersionPair paar in set)
                {
                    Sharpen.Collections.Put(phiVersions, new VarVersionPair(paar.var, paar.version),
                                            min);
                }
            }
            UpdateVersions(graph, phiVersions);
        }
Пример #2
0
        public virtual void SetVarVersions(RootStatement root, VarVersionsProcessor previousVersionsProcessor
                                           )
        {
            SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();

            ssa.SplitVariables(root, method);
            FlattenStatementsHelper flattenHelper = new FlattenStatementsHelper();
            DirectGraph             graph         = flattenHelper.BuildDirectGraph(root);

            MergePhiVersions(ssa, graph);
            typeProcessor.CalculateVarTypes(root, graph);
            SimpleMerge(typeProcessor, graph, method);
            // FIXME: advanced merging
            EliminateNonJavaTypes(typeProcessor);
            SetNewVarIndices(typeProcessor, graph, previousVersionsProcessor);
        }
Пример #3
0
        public virtual bool SimplifyStackVarsStatement(Statement stat, HashSet <int> setReorderedIfs
                                                       , SSAConstructorSparseEx ssa, StructClass cl)
        {
            bool           res         = false;
            List <Exprent> expressions = stat.GetExprents();

            if (expressions == null)
            {
                bool processClass14 = DecompilerContext.GetOption(IFernflowerPreferences.Decompile_Class_1_4
                                                                  );
                while (true)
                {
                    bool changed = false;
                    foreach (Statement st in stat.GetStats())
                    {
                        res    |= SimplifyStackVarsStatement(st, setReorderedIfs, ssa, cl);
                        changed = IfHelper.MergeIfs(st, setReorderedIfs) || BuildIff(st, ssa) || processClass14 &&
                                  CollapseInlinedClass14(st);
                        // collapse composed if's
                        // collapse iff ?: statement
                        // collapse inlined .class property in version 1.4 and before
                        if (changed)
                        {
                            break;
                        }
                    }
                    res |= changed;
                    if (!changed)
                    {
                        break;
                    }
                }
            }
            else
            {
                res = SimplifyStackVarsExprents(expressions, cl);
            }
            return(res);
        }
Пример #4
0
        public virtual void SimplifyStackVars(RootStatement root, StructMethod mt, StructClass
                                              cl)
        {
            HashSet <int>           setReorderedIfs = new HashSet <int>();
            SSAUConstructorSparseEx ssau            = null;

            while (true)
            {
                bool found = false;
                SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();
                ssa.SplitVariables(root, mt);
                SimplifyExprentsHelper sehelper = new SimplifyExprentsHelper(ssau == null);
                while (sehelper.SimplifyStackVarsStatement(root, setReorderedIfs, ssa, cl))
                {
                    found = true;
                }
                SetVersionsToNull(root);
                SequenceHelper.CondenseSequences(root);
                ssau = new SSAUConstructorSparseEx();
                ssau.SplitVariables(root, mt);
                if (IterateStatements(root, ssau))
                {
                    found = true;
                }
                SetVersionsToNull(root);
                if (!found)
                {
                    break;
                }
            }
            // remove unused assignments
            ssau = new SSAUConstructorSparseEx();
            ssau.SplitVariables(root, mt);
            IterateStatements(root, ssau);
            SetVersionsToNull(root);
        }
Пример #5
0
        private static bool BuildIff(Statement stat, SSAConstructorSparseEx ssa)
        {
            if (stat.type == Statement.Type_If && stat.GetExprents() == null)
            {
                IfStatement   statement          = (IfStatement)stat;
                Exprent       ifHeadExpr         = statement.GetHeadexprent();
                HashSet <int> ifHeadExprBytecode = (ifHeadExpr == null ? null : ifHeadExpr.bytecode
                                                    );
                if (statement.iftype == IfStatement.Iftype_Ifelse)
                {
                    Statement ifStatement   = statement.GetIfstat();
                    Statement elseStatement = statement.GetElsestat();
                    if (ifStatement.GetExprents() != null && ifStatement.GetExprents().Count == 1 &&
                        elseStatement.GetExprents() != null && elseStatement.GetExprents().Count == 1 &&
                        ifStatement.GetAllSuccessorEdges().Count == 1 && elseStatement.GetAllSuccessorEdges
                            ().Count == 1 && ifStatement.GetAllSuccessorEdges()[0].GetDestination() == elseStatement
                        .GetAllSuccessorEdges()[0].GetDestination())
                    {
                        Exprent ifExpr   = ifStatement.GetExprents()[0];
                        Exprent elseExpr = elseStatement.GetExprents()[0];
                        if (ifExpr.type == Exprent.Exprent_Assignment && elseExpr.type == Exprent.Exprent_Assignment)
                        {
                            AssignmentExprent ifAssign   = (AssignmentExprent)ifExpr;
                            AssignmentExprent elseAssign = (AssignmentExprent)elseExpr;
                            if (ifAssign.GetLeft().type == Exprent.Exprent_Var && elseAssign.GetLeft().type ==
                                Exprent.Exprent_Var)
                            {
                                VarExprent ifVar   = (VarExprent)ifAssign.GetLeft();
                                VarExprent elseVar = (VarExprent)elseAssign.GetLeft();
                                if (ifVar.GetIndex() == elseVar.GetIndex() && ifVar.IsStack())
                                {
                                    // ifVar.getIndex() >= VarExprent.STACK_BASE) {
                                    bool found = false;
                                    foreach (KeyValuePair <VarVersionPair, FastSparseSetFactory <int> .FastSparseSet <int> > ent
                                             in ssa.GetPhi())
                                    {
                                        if (ent.Key.var == ifVar.GetIndex())
                                        {
                                            if (ent.Value.Contains(ifVar.GetVersion()) && ent.Value.Contains(elseVar.GetVersion
                                                                                                                 ()))
                                            {
                                                found = true;
                                                break;
                                            }
                                        }
                                    }
                                    if (found)
                                    {
                                        List <Exprent> data     = new List <Exprent>(statement.GetFirst().GetExprents());
                                        List <Exprent> operands = Sharpen.Arrays.AsList(statement.GetHeadexprent().GetCondition
                                                                                            (), ifAssign.GetRight(), elseAssign.GetRight());
                                        data.Add(new AssignmentExprent(ifVar, new FunctionExprent(FunctionExprent.Function_Iif
                                                                                                  , operands, ifHeadExprBytecode), ifHeadExprBytecode));
                                        statement.SetExprents(data);
                                        if ((statement.GetAllSuccessorEdges().Count == 0))
                                        {
                                            StatEdge ifEdge = ifStatement.GetAllSuccessorEdges()[0];
                                            StatEdge edge   = new StatEdge(ifEdge.GetType(), statement, ifEdge.GetDestination()
                                                                           );
                                            statement.AddSuccessor(edge);
                                            if (ifEdge.closure != null)
                                            {
                                                ifEdge.closure.AddLabeledEdge(edge);
                                            }
                                        }
                                        SequenceHelper.DestroyAndFlattenStatement(statement);
                                        return(true);
                                    }
                                }
                            }
                        }
                        else if (ifExpr.type == Exprent.Exprent_Exit && elseExpr.type == Exprent.Exprent_Exit)
                        {
                            ExitExprent ifExit   = (ExitExprent)ifExpr;
                            ExitExprent elseExit = (ExitExprent)elseExpr;
                            if (ifExit.GetExitType() == elseExit.GetExitType() && ifExit.GetValue() != null &&
                                elseExit.GetValue() != null && ifExit.GetExitType() == ExitExprent.Exit_Return)
                            {
                                // throw is dangerous, because of implicit casting to a common superclass
                                // e.g. throws IOException and throw true?new RuntimeException():new IOException(); won't work
                                if (ifExit.GetExitType() == ExitExprent.Exit_Throw && !ifExit.GetValue().GetExprType
                                        ().Equals(elseExit.GetValue().GetExprType()))
                                {
                                    // note: getExprType unreliable at this point!
                                    return(false);
                                }
                                // avoid flattening to 'iff' if any of the branches is an 'iff' already
                                if (IsIff(ifExit.GetValue()) || IsIff(elseExit.GetValue()))
                                {
                                    return(false);
                                }
                                List <Exprent> data = new List <Exprent>(statement.GetFirst().GetExprents());
                                data.Add(new ExitExprent(ifExit.GetExitType(), new FunctionExprent(FunctionExprent
                                                                                                   .Function_Iif, Sharpen.Arrays.AsList(statement.GetHeadexprent().GetCondition(),
                                                                                                                                        ifExit.GetValue(), elseExit.GetValue()), ifHeadExprBytecode), ifExit.GetRetType(
                                                             ), ifHeadExprBytecode));
                                statement.SetExprents(data);
                                StatEdge  retEdge = ifStatement.GetAllSuccessorEdges()[0];
                                Statement closure = retEdge.closure == statement?statement.GetParent() : retEdge
                                                        .closure;

                                statement.AddSuccessor(new StatEdge(StatEdge.Type_Break, statement, retEdge.GetDestination
                                                                        (), closure));
                                SequenceHelper.DestroyAndFlattenStatement(statement);
                                return(true);
                            }
                        }
                    }
                }
            }
            return(false);
        }
Пример #6
0
        private FinallyProcessor.Record GetFinallyInformation(StructMethod mt, RootStatement
                                                              root, CatchAllStatement fstat)
        {
            Dictionary <BasicBlock, bool> mapLast             = new Dictionary <BasicBlock, bool>();
            BasicBlockStatement           firstBlockStatement = fstat.GetHandler().GetBasichead();
            BasicBlock  firstBasicBlock = firstBlockStatement.GetBlock();
            Instruction instrFirst      = firstBasicBlock.GetInstruction(0);
            int         firstcode       = 0;

            switch (instrFirst.opcode)
            {
            case ICodeConstants.opc_pop:
            {
                firstcode = 1;
                break;
            }

            case ICodeConstants.opc_astore:
            {
                firstcode = 2;
                break;
            }
            }
            ExprProcessor proc = new ExprProcessor(methodDescriptor, varProcessor);

            proc.ProcessStatement(root, mt.GetClassStruct());
            SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();

            ssa.SplitVariables(root, mt);
            List <Exprent> lstExprents = firstBlockStatement.GetExprents();
            VarVersionPair varpaar     = new VarVersionPair((VarExprent)((AssignmentExprent)lstExprents
                                                                         [firstcode == 2 ? 1 : 0]).GetLeft());
            FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
            DirectGraph             dgraph      = flatthelper.BuildDirectGraph(root);
            LinkedList <DirectNode> stack       = new LinkedList <DirectNode>();

            stack.AddLast(dgraph.first);
            HashSet <DirectNode> setVisited = new HashSet <DirectNode>();

            while (!(stack.Count == 0))
            {
                DirectNode node = Sharpen.Collections.RemoveFirst(stack);
                if (setVisited.Contains(node))
                {
                    continue;
                }
                setVisited.Add(node);
                BasicBlockStatement blockStatement = null;
                if (node.block != null)
                {
                    blockStatement = node.block;
                }
                else if (node.preds.Count == 1)
                {
                    blockStatement = node.preds[0].block;
                }
                bool isTrueExit = true;
                if (firstcode != 1)
                {
                    isTrueExit = false;
                    for (int i = 0; i < node.exprents.Count; i++)
                    {
                        Exprent exprent = node.exprents[i];
                        if (firstcode == 0)
                        {
                            List <Exprent> lst = exprent.GetAllExprents();
                            lst.Add(exprent);
                            bool found = false;
                            foreach (Exprent expr in lst)
                            {
                                if (expr.type == Exprent.Exprent_Var && new VarVersionPair((VarExprent)expr).Equals
                                        (varpaar))
                                {
                                    found = true;
                                    break;
                                }
                            }
                            if (found)
                            {
                                found = false;
                                if (exprent.type == Exprent.Exprent_Exit)
                                {
                                    ExitExprent exexpr = (ExitExprent)exprent;
                                    if (exexpr.GetExitType() == ExitExprent.Exit_Throw && exexpr.GetValue().type == Exprent
                                        .Exprent_Var)
                                    {
                                        found = true;
                                    }
                                }
                                if (!found)
                                {
                                    return(null);
                                }
                                else
                                {
                                    isTrueExit = true;
                                }
                            }
                        }
                        else if (firstcode == 2)
                        {
                            // search for a load instruction
                            if (exprent.type == Exprent.Exprent_Assignment)
                            {
                                AssignmentExprent assexpr = (AssignmentExprent)exprent;
                                if (assexpr.GetRight().type == Exprent.Exprent_Var && new VarVersionPair((VarExprent
                                                                                                          )assexpr.GetRight()).Equals(varpaar))
                                {
                                    Exprent next = null;
                                    if (i == node.exprents.Count - 1)
                                    {
                                        if (node.succs.Count == 1)
                                        {
                                            DirectNode nd = node.succs[0];
                                            if (!(nd.exprents.Count == 0))
                                            {
                                                next = nd.exprents[0];
                                            }
                                        }
                                    }
                                    else
                                    {
                                        next = node.exprents[i + 1];
                                    }
                                    bool found = false;
                                    if (next != null && next.type == Exprent.Exprent_Exit)
                                    {
                                        ExitExprent exexpr = (ExitExprent)next;
                                        if (exexpr.GetExitType() == ExitExprent.Exit_Throw && exexpr.GetValue().type == Exprent
                                            .Exprent_Var && assexpr.GetLeft().Equals(exexpr.GetValue()))
                                        {
                                            found = true;
                                        }
                                    }
                                    if (!found)
                                    {
                                        return(null);
                                    }
                                    else
                                    {
                                        isTrueExit = true;
                                    }
                                }
                            }
                        }
                    }
                }
                // find finally exits
                if (blockStatement != null && blockStatement.GetBlock() != null)
                {
                    Statement handler = fstat.GetHandler();
                    foreach (StatEdge edge in blockStatement.GetSuccessorEdges(Statement.Statedge_Direct_All
                                                                               ))
                    {
                        if (edge.GetType() != StatEdge.Type_Regular && handler.ContainsStatement(blockStatement
                                                                                                 ) && !handler.ContainsStatement(edge.GetDestination()))
                        {
                            bool?existingFlag = mapLast.GetOrNullable(blockStatement.GetBlock());
                            // note: the dummy node is also processed!
                            if (existingFlag == null || !existingFlag.Value)
                            {
                                Sharpen.Collections.Put(mapLast, blockStatement.GetBlock(), isTrueExit);
                                break;
                            }
                        }
                    }
                }
                Sharpen.Collections.AddAll(stack, node.succs);
            }
            // empty finally block?
            if (fstat.GetHandler().type == Statement.Type_Basicblock)
            {
                bool isEmpty            = false;
                bool isFirstLast        = mapLast.ContainsKey(firstBasicBlock);
                InstructionSequence seq = firstBasicBlock.GetSeq();
                switch (firstcode)
                {
                case 0:
                {
                    isEmpty = isFirstLast && seq.Length() == 1;
                    break;
                }

                case 1:
                {
                    isEmpty = seq.Length() == 1;
                    break;
                }

                case 2:
                {
                    isEmpty = isFirstLast ? seq.Length() == 3 : seq.Length() == 1;
                    break;
                }
                }
                if (isEmpty)
                {
                    firstcode = 3;
                }
            }
            return(new FinallyProcessor.Record(firstcode, mapLast));
        }