private static bool IsStackAssignment(Exprent first, Exprent second) { if (first.type == Exprent.Exprent_Assignment && second.type == Exprent.Exprent_Assignment) { AssignmentExprent asf = (AssignmentExprent)first; AssignmentExprent ass = (AssignmentExprent)second; while (true) { if (asf.GetRight().Equals(ass.GetRight())) { if ((asf.GetLeft().type == Exprent.Exprent_Var && ((VarExprent)asf.GetLeft()).IsStack ()) && (ass.GetLeft().type != Exprent.Exprent_Var || !((VarExprent)ass.GetLeft() ).IsStack())) { if (!ass.GetLeft().ContainsExprent(asf.GetLeft())) { asf.SetRight(ass); return(true); } } } if (asf.GetRight().type == Exprent.Exprent_Assignment) { asf = (AssignmentExprent)asf.GetRight(); } else { break; } } } return(false); }
private static bool AddArrayInitializer(Exprent first, Exprent second) { if (first.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)first; if (@as.GetRight().type == Exprent.Exprent_New && @as.GetLeft().type == Exprent.Exprent_Var) { NewExprent newExpr = (NewExprent)@as.GetRight(); if (!(newExpr.GetLstArrayElements().Count == 0)) { VarExprent arrVar = (VarExprent)@as.GetLeft(); if (second.type == Exprent.Exprent_Assignment) { AssignmentExprent aas = (AssignmentExprent)second; if (aas.GetLeft().type == Exprent.Exprent_Array) { ArrayExprent arrExpr = (ArrayExprent)aas.GetLeft(); if (arrExpr.GetArray().type == Exprent.Exprent_Var && arrVar.Equals(arrExpr.GetArray ()) && arrExpr.GetIndex().type == Exprent.Exprent_Const) { int constValue = ((ConstExprent)arrExpr.GetIndex()).GetIntValue(); if (constValue < newExpr.GetLstArrayElements().Count) { Exprent init = newExpr.GetLstArrayElements()[constValue]; if (init.type == Exprent.Exprent_Const) { ConstExprent cinit = (ConstExprent)init; VarType arrType = newExpr.GetNewType().DecreaseArrayDim(); ConstExprent defaultVal = ExprProcessor.GetDefaultArrayValue(arrType); if (cinit.Equals(defaultVal)) { Exprent tempExpr = aas.GetRight(); if (!tempExpr.ContainsExprent(arrVar)) { newExpr.GetLstArrayElements()[constValue] = tempExpr; if (tempExpr.type == Exprent.Exprent_New) { NewExprent tempNewExpr = (NewExprent)tempExpr; int dims = newExpr.GetNewType().arrayDim; if (dims > 1 && !(tempNewExpr.GetLstArrayElements().Count == 0)) { tempNewExpr.SetDirectArrayInit(true); } } return(true); } } } } } } } } } } return(false); }
private static void LiftConstructor(ClassWrapper wrapper) { foreach (MethodWrapper method in wrapper.GetMethods()) { if (ICodeConstants.Init_Name.Equals(method.methodStruct.GetName()) && method.root != null) { Statement firstData = Statements.FindFirstData(method.root); if (firstData == null) { return; } int index = 0; List <Exprent> lstExprents = firstData.GetExprents(); foreach (Exprent exprent in lstExprents) { int action = 0; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent assignExpr = (AssignmentExprent)exprent; if (assignExpr.GetLeft().type == Exprent.Exprent_Field && assignExpr.GetRight().type == Exprent.Exprent_Var) { FieldExprent fExpr = (FieldExprent)assignExpr.GetLeft(); if (fExpr.GetClassname().Equals(wrapper.GetClassStruct().qualifiedName)) { StructField structField = wrapper.GetClassStruct().GetField(fExpr.GetName(), fExpr .GetDescriptor().descriptorString); if (structField != null && structField.HasModifier(ICodeConstants.Acc_Final)) { action = 1; } } } } else if (index > 0 && exprent.type == Exprent.Exprent_Invocation && Statements.IsInvocationInitConstructor ((InvocationExprent)exprent, method, wrapper, true)) { // this() or super() lstExprents.Add(0, lstExprents.RemoveAtReturningValue(index)); action = 2; } if (action != 1) { break; } index++; } } } }
private static bool IsTrivialStackAssignment(Exprent first) { if (first.type == Exprent.Exprent_Assignment) { AssignmentExprent asf = (AssignmentExprent)first; if (asf.GetLeft().type == Exprent.Exprent_Var && asf.GetRight().type == Exprent.Exprent_Var) { VarExprent left = (VarExprent)asf.GetLeft(); VarExprent right = (VarExprent)asf.GetRight(); return(left.GetIndex() == right.GetIndex() && left.IsStack() && right.IsStack()); } } return(false); }
private static string IsClass14Invocation(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) { if (exprent.type == Exprent.Exprent_Function) { FunctionExprent fexpr = (FunctionExprent)exprent; if (fexpr.GetFuncType() == FunctionExprent.Function_Iif) { if (fexpr.GetLstOperands()[0].type == Exprent.Exprent_Function) { FunctionExprent headexpr = (FunctionExprent)fexpr.GetLstOperands()[0]; if (headexpr.GetFuncType() == FunctionExprent.Function_Eq) { if (headexpr.GetLstOperands()[0].type == Exprent.Exprent_Field && headexpr.GetLstOperands ()[1].type == Exprent.Exprent_Const && ((ConstExprent)headexpr.GetLstOperands()[ 1]).GetConstType().Equals(VarType.Vartype_Null)) { FieldExprent field = (FieldExprent)headexpr.GetLstOperands()[0]; ClassesProcessor.ClassNode fieldnode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(field.GetClassname()); if (fieldnode != null && fieldnode.classStruct.qualifiedName.Equals(wrapper.GetClassStruct ().qualifiedName)) { // source class StructField fd = wrapper.GetClassStruct().GetField(field.GetName(), field.GetDescriptor ().descriptorString); // FIXME: can be null! why?? if (fd != null && fd.HasModifier(ICodeConstants.Acc_Static) && (fd.IsSynthetic() || DecompilerContext.GetOption(IFernflowerPreferences.Synthetic_Not_Set))) { if (fexpr.GetLstOperands()[1].type == Exprent.Exprent_Assignment && fexpr.GetLstOperands ()[2].Equals(field)) { AssignmentExprent asexpr = (AssignmentExprent)fexpr.GetLstOperands()[1]; if (asexpr.GetLeft().Equals(field) && asexpr.GetRight().type == Exprent.Exprent_Invocation) { InvocationExprent invexpr = (InvocationExprent)asexpr.GetRight(); if (invexpr.GetClassname().Equals(wrapper.GetClassStruct().qualifiedName) && invexpr .GetName().Equals(meth.methodStruct.GetName()) && invexpr.GetStringDescriptor(). Equals(meth.methodStruct.GetDescriptor())) { if (invexpr.GetLstParameters()[0].type == Exprent.Exprent_Const) { wrapper.GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(fd.GetName(), fd.GetDescriptor ())); // hide synthetic field return(((ConstExprent)invexpr.GetLstParameters()[0]).GetValue().ToString()); } } } } } } } } } } } return(null); }
private static void ExtractStaticInitializers(ClassWrapper wrapper, MethodWrapper method) { RootStatement root = method.root; StructClass cl = wrapper.GetClassStruct(); Statement firstData = Statements.FindFirstData(root); if (firstData != null) { bool inlineInitializers = cl.HasModifier(ICodeConstants.Acc_Interface) || cl.HasModifier (ICodeConstants.Acc_Enum); while (!(firstData.GetExprents().Count == 0)) { Exprent exprent = firstData.GetExprents()[0]; bool found = false; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent assignExpr = (AssignmentExprent)exprent; if (assignExpr.GetLeft().type == Exprent.Exprent_Field) { FieldExprent fExpr = (FieldExprent)assignExpr.GetLeft(); if (fExpr.IsStatic() && fExpr.GetClassname().Equals(cl.qualifiedName) && cl.HasField (fExpr.GetName(), fExpr.GetDescriptor().descriptorString)) { // interfaces fields should always be initialized inline if (inlineInitializers || IsExprentIndependent(assignExpr.GetRight(), method)) { string keyField = InterpreterUtil.MakeUniqueKey(fExpr.GetName(), fExpr.GetDescriptor ().descriptorString); if (!wrapper.GetStaticFieldInitializers().ContainsKey(keyField)) { wrapper.GetStaticFieldInitializers().AddWithKey(assignExpr.GetRight(), keyField); firstData.GetExprents().RemoveAtReturningValue(0); found = true; } } } } } if (!found) { break; } } } }
// propagate (var = new X) forward to the <init> invocation private static bool IsConstructorInvocationRemote(List <Exprent> list, int index) { Exprent current = list[index]; if (current.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)current; if (@as.GetLeft().type == Exprent.Exprent_Var && @as.GetRight().type == Exprent.Exprent_New) { NewExprent newExpr = (NewExprent)@as.GetRight(); VarType newType = newExpr.GetNewType(); VarVersionPair leftPair = new VarVersionPair((VarExprent)@as.GetLeft()); if (newType.type == ICodeConstants.Type_Object && newType.arrayDim == 0 && newExpr .GetConstructor() == null) { for (int i = index + 1; i < list.Count; i++) { Exprent remote = list[i]; // <init> invocation if (remote.type == Exprent.Exprent_Invocation) { InvocationExprent @in = (InvocationExprent)remote; if (@in.GetFunctype() == InvocationExprent.Typ_Init && @in.GetInstance().type == Exprent.Exprent_Var && @as.GetLeft().Equals(@in.GetInstance())) { newExpr.SetConstructor(@in); @in.SetInstance(null); list[i] = @as.Copy(); return(true); } } // check for variable in use HashSet <VarVersionPair> setVars = remote.GetAllVariables(); if (setVars.Contains(leftPair)) { // variable used somewhere in between -> exit, need a better reduced code return(false); } } } } } return(false); }
private static bool IsStackAssignment2(Exprent first, Exprent second) { // e.g. 1.4-style class invocation if (first.type == Exprent.Exprent_Assignment && second.type == Exprent.Exprent_Assignment) { AssignmentExprent asf = (AssignmentExprent)first; AssignmentExprent ass = (AssignmentExprent)second; if (asf.GetLeft().type == Exprent.Exprent_Var && ass.GetRight().type == Exprent.Exprent_Var && asf.GetLeft().Equals(ass.GetRight()) && ((VarExprent)asf.GetLeft()).IsStack( )) { if (ass.GetLeft().type != Exprent.Exprent_Var || !((VarExprent)ass.GetLeft()).IsStack ()) { asf.SetRight(new AssignmentExprent(ass.GetLeft(), asf.GetRight(), ass.bytecode)); return(true); } } } return(false); }
private static bool IsIPPorIMM2(Exprent first, Exprent second) { if (first.type != Exprent.Exprent_Assignment || second.type != Exprent.Exprent_Assignment) { return(false); } AssignmentExprent af = (AssignmentExprent)first; AssignmentExprent @as = (AssignmentExprent)second; if (@as.GetRight().type != Exprent.Exprent_Function) { return(false); } FunctionExprent func = (FunctionExprent)@as.GetRight(); if (func.GetFuncType() != FunctionExprent.Function_Add && func.GetFuncType() != FunctionExprent .Function_Sub) { return(false); } Exprent econd = func.GetLstOperands()[0]; Exprent econst = func.GetLstOperands()[1]; if (econst.type != Exprent.Exprent_Const && econd.type == Exprent.Exprent_Const && func.GetFuncType() == FunctionExprent.Function_Add) { econd = econst; econst = func.GetLstOperands()[0]; } if (econst.type == Exprent.Exprent_Const && ((ConstExprent)econst).HasValueOne() && af.GetLeft().Equals(econd) && af.GetRight().Equals(@as.GetLeft()) && (af.GetLeft ().GetExprentUse() & Exprent.Multiple_Uses) != 0) { int type = func.GetFuncType() == FunctionExprent.Function_Add ? FunctionExprent.Function_Ipp : FunctionExprent.Function_Imm; FunctionExprent ret = new FunctionExprent(type, af.GetRight(), func.bytecode); ret.SetImplicitType(VarType.Vartype_Int); af.SetRight(ret); return(true); } return(false); }
private static Exprent IsPPIorMMI(Exprent first) { if (first.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)first; if (@as.GetRight().type == Exprent.Exprent_Function) { FunctionExprent func = (FunctionExprent)@as.GetRight(); if (func.GetFuncType() == FunctionExprent.Function_Add || func.GetFuncType() == FunctionExprent .Function_Sub) { Exprent econd = func.GetLstOperands()[0]; Exprent econst = func.GetLstOperands()[1]; if (econst.type != Exprent.Exprent_Const && econd.type == Exprent.Exprent_Const && func.GetFuncType() == FunctionExprent.Function_Add) { econd = econst; econst = func.GetLstOperands()[0]; } if (econst.type == Exprent.Exprent_Const && ((ConstExprent)econst).HasValueOne()) { Exprent left = @as.GetLeft(); if (left.type != Exprent.Exprent_Var && left.Equals(econd)) { int type = func.GetFuncType() == FunctionExprent.Function_Add ? FunctionExprent.Function_Ppi : FunctionExprent.Function_Mmi; FunctionExprent ret = new FunctionExprent(type, econd, func.bytecode); ret.SetImplicitType(VarType.Vartype_Int); return(ret); } } } } } return(null); }
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); }
private void ComputeMethodType(ClassesProcessor.ClassNode node, MethodWrapper method ) { NestedMemberAccess.MethodAccess type = NestedMemberAccess.MethodAccess.Normal; if (method.root != null) { DirectGraph graph = method.GetOrBuildGraph(); StructMethod mt = method.methodStruct; if ((noSynthFlag || mt.IsSynthetic()) && mt.HasModifier(ICodeConstants.Acc_Static )) { if (graph.nodes.Count == 2) { // incl. dummy exit node if (graph.first.exprents.Count == 1) { Exprent exprent = graph.first.exprents[0]; MethodDescriptor mtdesc = MethodDescriptor.ParseDescriptor(mt.GetDescriptor()); int parcount = [email protected]; Exprent exprCore = exprent; if (exprent.type == Exprent.Exprent_Exit) { ExitExprent exexpr = (ExitExprent)exprent; if (exexpr.GetExitType() == ExitExprent.Exit_Return && exexpr.GetValue() != null) { exprCore = exexpr.GetValue(); } } switch (exprCore.type) { case Exprent.Exprent_Field: { FieldExprent fexpr = (FieldExprent)exprCore; if ((parcount == 1 && !fexpr.IsStatic()) || (parcount == 0 && fexpr.IsStatic())) { if (fexpr.GetClassname().Equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field if (fexpr.IsStatic() || (fexpr.GetInstance().type == Exprent.Exprent_Var && ((VarExprent )fexpr.GetInstance()).GetIndex() == 0)) { type = NestedMemberAccess.MethodAccess.Field_Get; } } } break; } case Exprent.Exprent_Var: { // qualified this if (parcount == 1) { // this or final variable if (((VarExprent)exprCore).GetIndex() != 0) { type = NestedMemberAccess.MethodAccess.Field_Get; } } break; } case Exprent.Exprent_Function: { // for now detect only increment/decrement FunctionExprent functionExprent = (FunctionExprent)exprCore; if (functionExprent.GetFuncType() >= FunctionExprent.Function_Imm && functionExprent .GetFuncType() <= FunctionExprent.Function_Ppi) { if (functionExprent.GetLstOperands()[0].type == Exprent.Exprent_Field) { type = NestedMemberAccess.MethodAccess.Function; } } break; } case Exprent.Exprent_Invocation: { type = NestedMemberAccess.MethodAccess.Method; break; } case Exprent.Exprent_Assignment: { AssignmentExprent asexpr = (AssignmentExprent)exprCore; if (asexpr.GetLeft().type == Exprent.Exprent_Field && asexpr.GetRight().type == Exprent .Exprent_Var) { FieldExprent fexpras = (FieldExprent)asexpr.GetLeft(); if ((parcount == 2 && !fexpras.IsStatic()) || (parcount == 1 && fexpras.IsStatic( ))) { if (fexpras.GetClassname().Equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field if (fexpras.IsStatic() || (fexpras.GetInstance().type == Exprent.Exprent_Var && ( (VarExprent)fexpras.GetInstance()).GetIndex() == 0)) { if (((VarExprent)asexpr.GetRight()).GetIndex() == parcount - 1) { type = NestedMemberAccess.MethodAccess.Field_Set; } } } } } break; } } if (type == NestedMemberAccess.MethodAccess.Method) { // FIXME: check for private flag of the method type = NestedMemberAccess.MethodAccess.Normal; InvocationExprent invexpr = (InvocationExprent)exprCore; bool isStatic = invexpr.IsStatic(); if ((isStatic && invexpr.GetLstParameters().Count == parcount) || (!isStatic && invexpr .GetInstance().type == Exprent.Exprent_Var && ((VarExprent)invexpr.GetInstance() ).GetIndex() == 0 && invexpr.GetLstParameters().Count == parcount - 1)) { bool equalpars = true; int index = isStatic ? 0 : 1; for (int i = 0; i < invexpr.GetLstParameters().Count; i++) { Exprent parexpr = invexpr.GetLstParameters()[i]; if (parexpr.type != Exprent.Exprent_Var || ((VarExprent)parexpr).GetIndex() != index) { equalpars = false; break; } index += mtdesc.@params[i + (isStatic ? 0 : 1)].stackSize; } if (equalpars) { type = NestedMemberAccess.MethodAccess.Method; } } } } else if (graph.first.exprents.Count == 2) { Exprent exprentFirst = graph.first.exprents[0]; Exprent exprentSecond = graph.first.exprents[1]; if (exprentFirst.type == Exprent.Exprent_Assignment && exprentSecond.type == Exprent .Exprent_Exit) { MethodDescriptor mtdesc = MethodDescriptor.ParseDescriptor(mt.GetDescriptor()); int parcount = [email protected]; AssignmentExprent asexpr = (AssignmentExprent)exprentFirst; if (asexpr.GetLeft().type == Exprent.Exprent_Field && asexpr.GetRight().type == Exprent .Exprent_Var) { FieldExprent fexpras = (FieldExprent)asexpr.GetLeft(); if ((parcount == 2 && !fexpras.IsStatic()) || (parcount == 1 && fexpras.IsStatic( ))) { if (fexpras.GetClassname().Equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field if (fexpras.IsStatic() || (fexpras.GetInstance().type == Exprent.Exprent_Var && ( (VarExprent)fexpras.GetInstance()).GetIndex() == 0)) { if (((VarExprent)asexpr.GetRight()).GetIndex() == parcount - 1) { ExitExprent exexpr = (ExitExprent)exprentSecond; if (exexpr.GetExitType() == ExitExprent.Exit_Return && exexpr.GetValue() != null) { if (exexpr.GetValue().type == Exprent.Exprent_Var && ((VarExprent)asexpr.GetRight ()).GetIndex() == parcount - 1) { type = NestedMemberAccess.MethodAccess.Field_Set; } } } } } } } } } } } } if (type != NestedMemberAccess.MethodAccess.Normal) { Sharpen.Collections.Put(mapMethodType, method, type); } else { Sharpen.Collections.Remove(mapMethodType, method); } }
private Exprent ProcessExprentRecursive(Exprent exprent) { bool replaced = true; while (replaced) { replaced = false; foreach (Exprent expr in exprent.GetAllExprents()) { Exprent retexpr = ProcessExprentRecursive(expr); if (retexpr != null) { exprent.ReplaceExprent(expr, retexpr); replaced = true; exprentReplaced = true; break; } } } if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)exprent; if (@as.GetRight().type == Exprent.Exprent_Function) { FunctionExprent func = (FunctionExprent)@as.GetRight(); VarType midlayer = null; if (func.GetFuncType() >= FunctionExprent.Function_I2l && func.GetFuncType() <= FunctionExprent .Function_I2s) { midlayer = func.GetSimpleCastType(); if (func.GetLstOperands()[0].type == Exprent.Exprent_Function) { func = (FunctionExprent)func.GetLstOperands()[0]; } else { return(null); } } if (func.GetFuncType() == FunctionExprent.Function_Add || func.GetFuncType() == FunctionExprent .Function_Sub) { Exprent econd = func.GetLstOperands()[0]; Exprent econst = func.GetLstOperands()[1]; if (econst.type != Exprent.Exprent_Const && econd.type == Exprent.Exprent_Const && func.GetFuncType() == FunctionExprent.Function_Add) { econd = econst; econst = func.GetLstOperands()[0]; } if (econst.type == Exprent.Exprent_Const && ((ConstExprent)econst).HasValueOne()) { Exprent left = @as.GetLeft(); VarType condtype = econd.GetExprType(); if (left.Equals(econd) && (midlayer == null || midlayer.Equals(condtype))) { FunctionExprent ret = new FunctionExprent(func.GetFuncType() == FunctionExprent.Function_Add ? FunctionExprent.Function_Ppi : FunctionExprent.Function_Mmi, econd, func.bytecode ); ret.SetImplicitType(condtype); exprentReplaced = true; return(ret); } } } } } return(null); }
private int[] IterateExprent(List <Exprent> lstExprents, int index, Exprent next, Dictionary <VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau) { Exprent exprent = lstExprents[index]; int changed = 0; foreach (Exprent expr in exprent.GetAllExprents()) { var oldExpr = expr; while (true) { object[] arr = IterateChildExprent(oldExpr, exprent, next, mapVarValues, ssau); Exprent retexpr = (Exprent)arr[0]; changed |= (bool)arr[1] ? 1 : 0; bool isReplaceable = (bool)arr[2]; if (retexpr != null) { if (isReplaceable) { ReplaceSingleVar(exprent, (VarExprent)oldExpr, retexpr, ssau); oldExpr = retexpr; } else { exprent.ReplaceExprent(oldExpr, retexpr); } changed = 1; } if (!isReplaceable) { break; } } } // no var on the highest level, so no replacing VarExprent left = null; Exprent right = null; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)exprent; if (@as.GetLeft().type == Exprent.Exprent_Var) { left = (VarExprent)@as.GetLeft(); right = @as.GetRight(); } } if (left == null) { return(new int[] { -1, changed }); } VarVersionPair leftpaar = new VarVersionPair(left); List <VarVersionNode> usedVers = new List <VarVersionNode>(); bool notdom = GetUsedVersions(ssau, leftpaar, usedVers); if (!notdom && (usedVers.Count == 0)) { if (left.IsStack() && (right.type == Exprent.Exprent_Invocation || right.type == Exprent.Exprent_Assignment || right.type == Exprent.Exprent_New)) { if (right.type == Exprent.Exprent_New) { // new Object(); permitted NewExprent nexpr = (NewExprent)right; if (nexpr.IsAnonymous() || nexpr.GetNewType().arrayDim > 0 || nexpr.GetNewType(). type != ICodeConstants.Type_Object) { return(new int[] { -1, changed }); } } lstExprents[index] = right; return(new int[] { index + 1, 1 }); } else if (right.type == Exprent.Exprent_Var) { lstExprents.RemoveAtReturningValue(index); return(new int[] { index, 1 }); } else { return(new int[] { -1, changed }); } } int useflags = right.GetExprentUse(); // stack variables only if (!left.IsStack() && (right.type != Exprent.Exprent_Var || ((VarExprent)right). IsStack())) { // special case catch(... ex) return(new int[] { -1, changed }); } if ((useflags & Exprent.Multiple_Uses) == 0 && (notdom || usedVers.Count > 1)) { return(new int[] { -1, changed }); } Dictionary <int, HashSet <VarVersionPair> > mapVars = GetAllVarVersions(leftpaar, right , ssau); bool isSelfReference = mapVars.ContainsKey(leftpaar.var); if (isSelfReference && notdom) { return(new int[] { -1, changed }); } HashSet <VarVersionPair> setNextVars = next == null ? null : GetAllVersions(next); // FIXME: fix the entire method! if (right.type != Exprent.Exprent_Const && right.type != Exprent.Exprent_Var && setNextVars != null && mapVars.ContainsKey(leftpaar.var)) { foreach (VarVersionNode usedvar in usedVers) { if (!setNextVars.Contains(new VarVersionPair(usedvar.var, usedvar.version))) { return(new int[] { -1, changed }); } } } Sharpen.Collections.Remove(mapVars, leftpaar.var); bool vernotreplaced = false; bool verreplaced = false; HashSet <VarVersionPair> setTempUsedVers = new HashSet <VarVersionPair>(); foreach (VarVersionNode usedvar in usedVers) { VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version); if (IsVersionToBeReplaced(usedver, mapVars, ssau, leftpaar) && (right.type == Exprent .Exprent_Const || right.type == Exprent.Exprent_Var || right.type == Exprent.Exprent_Field || setNextVars == null || setNextVars.Contains(usedver))) { setTempUsedVers.Add(usedver); verreplaced = true; } else { vernotreplaced = true; } } if (isSelfReference && vernotreplaced) { return(new int[] { -1, changed }); } else { foreach (VarVersionPair usedver in setTempUsedVers) { Exprent copy = right.Copy(); if (right.type == Exprent.Exprent_Field && ssau.GetMapFieldVars().ContainsKey(right .id)) { Sharpen.Collections.Put(ssau.GetMapFieldVars(), copy.id, ssau.GetMapFieldVars().GetOrNullable (right.id)); } Sharpen.Collections.Put(mapVarValues, usedver, copy); } } if (!notdom && !vernotreplaced) { // remove assignment lstExprents.RemoveAtReturningValue(index); return(new int[] { index, 1 }); } else if (verreplaced) { return(new int[] { index + 1, changed }); } else { return(new int[] { -1, changed }); } }
private void ProcessExprent(Exprent expr, SFormsFastMapDirect[] varmaparr) { if (expr == null) { return; } VarExprent varassign = null; bool finished = false; switch (expr.type) { case Exprent.Exprent_Assignment: { AssignmentExprent assexpr = (AssignmentExprent)expr; if (assexpr.GetCondType() == AssignmentExprent.Condition_None) { Exprent dest = assexpr.GetLeft(); if (dest.type == Exprent.Exprent_Var) { varassign = (VarExprent)dest; } } break; } case Exprent.Exprent_Function: { FunctionExprent func = (FunctionExprent)expr; switch (func.GetFuncType()) { case FunctionExprent.Function_Iif: { ProcessExprent(func.GetLstOperands()[0], varmaparr); SFormsFastMapDirect varmapFalse; if (varmaparr[1] == null) { varmapFalse = new SFormsFastMapDirect(varmaparr[0]); } else { varmapFalse = varmaparr[1]; varmaparr[1] = null; } ProcessExprent(func.GetLstOperands()[1], varmaparr); SFormsFastMapDirect[] varmaparrNeg = new SFormsFastMapDirect[] { varmapFalse, null }; ProcessExprent(func.GetLstOperands()[2], varmaparrNeg); MergeMaps(varmaparr[0], varmaparrNeg[0]); varmaparr[1] = null; finished = true; break; } case FunctionExprent.Function_Cadd: { ProcessExprent(func.GetLstOperands()[0], varmaparr); SFormsFastMapDirect[] varmaparrAnd = new SFormsFastMapDirect[] { new SFormsFastMapDirect (varmaparr[0]), null }; ProcessExprent(func.GetLstOperands()[1], varmaparrAnd); // false map varmaparr[1] = MergeMaps(varmaparr[varmaparr[1] == null ? 0 : 1], varmaparrAnd[varmaparrAnd [1] == null ? 0 : 1]); // true map varmaparr[0] = varmaparrAnd[0]; finished = true; break; } case FunctionExprent.Function_Cor: { ProcessExprent(func.GetLstOperands()[0], varmaparr); SFormsFastMapDirect[] varmaparrOr = new SFormsFastMapDirect[] { new SFormsFastMapDirect (varmaparr[varmaparr[1] == null ? 0 : 1]), null }; ProcessExprent(func.GetLstOperands()[1], varmaparrOr); // false map varmaparr[1] = varmaparrOr[varmaparrOr[1] == null ? 0 : 1]; // true map varmaparr[0] = MergeMaps(varmaparr[0], varmaparrOr[0]); finished = true; break; } } break; } } if (finished) { return; } List <Exprent> lst = expr.GetAllExprents(); lst.Remove(varassign); foreach (Exprent ex in lst) { ProcessExprent(ex, varmaparr); } SFormsFastMapDirect varmap = varmaparr[0]; if (varassign != null) { int varindex = varassign.GetIndex(); if (varassign.GetVersion() == 0) { // get next version int nextver = GetNextFreeVersion(varindex); // set version varassign.SetVersion(nextver); SetCurrentVar(varmap, varindex, nextver); } else { SetCurrentVar(varmap, varindex, varassign.GetVersion()); } } else if (expr.type == Exprent.Exprent_Var) { VarExprent vardest = (VarExprent)expr; int varindex = vardest.GetIndex(); FastSparseSetFactory <int> .FastSparseSet <int> vers = varmap.Get(varindex); int cardinality = vers.GetCardinality(); if (cardinality == 1) { // == 1 // set version int it = new Sharpen.EnumeratorAdapter <int>(vers.GetEnumerator()).Next(); vardest.SetVersion(it); } else if (cardinality == 2) { // size > 1 int current_vers = vardest.GetVersion(); VarVersionPair currpaar = new VarVersionPair(varindex, current_vers); if (current_vers != 0 && phi.ContainsKey(currpaar)) { SetCurrentVar(varmap, varindex, current_vers); // update phi node phi.GetOrNull(currpaar).Union(vers); } else { // increase version int nextver = GetNextFreeVersion(varindex); // set version vardest.SetVersion(nextver); SetCurrentVar(varmap, varindex, nextver); // create new phi node Sharpen.Collections.Put(phi, new VarVersionPair(varindex, nextver), vers); } } } }
public static void Simplify(SwitchStatement switchStatement) { SwitchExprent switchExprent = (SwitchExprent)switchStatement.GetHeadexprent(); Exprent value = switchExprent.GetValue(); if (IsEnumArray(value)) { List <List <Exprent> > caseValues = switchStatement.GetCaseValues(); Dictionary <Exprent, Exprent> mapping = new Dictionary <Exprent, Exprent>(caseValues .Count); ArrayExprent array = (ArrayExprent)value; FieldExprent arrayField = (FieldExprent)array.GetArray(); ClassesProcessor.ClassNode classNode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(arrayField.GetClassname()); if (classNode != null) { MethodWrapper wrapper = classNode.GetWrapper().GetMethodWrapper(ICodeConstants.Clinit_Name , "()V"); if (wrapper != null && wrapper.root != null) { wrapper.GetOrBuildGraph().IterateExprents((Exprent exprent) => { if (exprent is AssignmentExprent) { AssignmentExprent assignment = (AssignmentExprent)exprent; Exprent left = assignment.GetLeft(); if (left.type == Exprent.Exprent_Array && ((ArrayExprent)left).GetArray().Equals( arrayField)) { Sharpen.Collections.Put(mapping, assignment.GetRight(), ((InvocationExprent)((ArrayExprent )left).GetIndex()).GetInstance()); } } return(0); } ); } } List <List <Exprent> > realCaseValues = new List <List <Exprent> >(caseValues.Count); foreach (List <Exprent> caseValue in caseValues) { List <Exprent> values = new List <Exprent>(caseValue.Count); realCaseValues.Add(values); foreach (Exprent exprent in caseValue) { if (exprent == null) { values.Add(null); } else { Exprent realConst = mapping.GetOrNull(exprent); if (realConst == null) { DecompilerContext.GetLogger().WriteMessage("Unable to simplify switch on enum: " + exprent + " not found, available: " + mapping, IFernflowerLogger.Severity.Error ); return; } values.Add(realConst.Copy()); } } } caseValues.Clear(); Sharpen.Collections.AddAll(caseValues, realCaseValues); switchExprent.ReplaceExprent(value, ((InvocationExprent)array.GetIndex()).GetInstance ().Copy()); } }
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)); }
private static void ExtractDynamicInitializers(ClassWrapper wrapper) { StructClass cl = wrapper.GetClassStruct(); bool isAnonymous = DecompilerContext.GetClassProcessor().GetMapRootClasses().GetOrNull (cl.qualifiedName).type == ClassesProcessor.ClassNode.Class_Anonymous; List <List <Exprent> > lstFirst = new List <List <Exprent> >(); List <MethodWrapper> lstMethodWrappers = new List <MethodWrapper>(); foreach (MethodWrapper method in wrapper.GetMethods()) { if (ICodeConstants.Init_Name.Equals(method.methodStruct.GetName()) && method.root != null) { // successfully decompiled constructor Statement firstData = Statements.FindFirstData(method.root); if (firstData == null || (firstData.GetExprents().Count == 0)) { return; } lstFirst.Add(firstData.GetExprents()); lstMethodWrappers.Add(method); Exprent exprent = firstData.GetExprents()[0]; if (!isAnonymous) { // FIXME: doesn't make sense if (exprent.type != Exprent.Exprent_Invocation || !Statements.IsInvocationInitConstructor ((InvocationExprent)exprent, method, wrapper, false)) { return; } } } } if ((lstFirst.Count == 0)) { return; } while (true) { string fieldWithDescr = null; Exprent value = null; for (int i = 0; i < lstFirst.Count; i++) { List <Exprent> lst = lstFirst[i]; if (lst.Count < (isAnonymous ? 1 : 2)) { return; } Exprent exprent = lst[isAnonymous ? 0 : 1]; bool found = false; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent assignExpr = (AssignmentExprent)exprent; if (assignExpr.GetLeft().type == Exprent.Exprent_Field) { FieldExprent fExpr = (FieldExprent)assignExpr.GetLeft(); if (!fExpr.IsStatic() && fExpr.GetClassname().Equals(cl.qualifiedName) && cl.HasField (fExpr.GetName(), fExpr.GetDescriptor().descriptorString)) { // check for the physical existence of the field. Could be defined in a superclass. if (IsExprentIndependent(assignExpr.GetRight(), lstMethodWrappers[i])) { string fieldKey = InterpreterUtil.MakeUniqueKey(fExpr.GetName(), fExpr.GetDescriptor ().descriptorString); if (fieldWithDescr == null) { fieldWithDescr = fieldKey; value = assignExpr.GetRight(); } else if (!fieldWithDescr.Equals(fieldKey) || !value.Equals(assignExpr.GetRight())) { return; } found = true; } } } } if (!found) { return; } } if (!wrapper.GetDynamicFieldInitializers().ContainsKey(fieldWithDescr)) { wrapper.GetDynamicFieldInitializers().AddWithKey(value, fieldWithDescr); foreach (List <Exprent> lst in lstFirst) { lst.RemoveAtReturningValue(isAnonymous ? 0 : 1); } } else { return; } } }
private static object[] IterateChildExprent(Exprent exprent, Exprent parent, Exprent next, Dictionary <VarVersionPair, Exprent> mapVarValues, SSAUConstructorSparseEx ssau) { bool changed = false; foreach (Exprent expr in exprent.GetAllExprents()) { var oldExpr = expr; while (true) { object[] arr = IterateChildExprent(oldExpr, parent, next, mapVarValues, ssau); Exprent retexpr = (Exprent)arr[0]; changed |= (bool)arr[1]; bool isReplaceable = (bool)arr[2]; if (retexpr != null) { if (isReplaceable) { ReplaceSingleVar(exprent, (VarExprent)oldExpr, retexpr, ssau); oldExpr = retexpr; } else { exprent.ReplaceExprent(oldExpr, retexpr); } changed = true; } if (!isReplaceable) { break; } } } Exprent dest = IsReplaceableVar(exprent, mapVarValues); if (dest != null) { return(new object[] { dest, true, true }); } VarExprent left = null; Exprent right = null; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)exprent; if (@as.GetLeft().type == Exprent.Exprent_Var) { left = (VarExprent)@as.GetLeft(); right = @as.GetRight(); } } if (left == null) { return(new object[] { null, changed, false }); } bool isHeadSynchronized = false; if (next == null && parent.type == Exprent.Exprent_Monitor) { MonitorExprent monexpr = (MonitorExprent)parent; if (monexpr.GetMonType() == MonitorExprent.Monitor_Enter && exprent.Equals(monexpr .GetValue())) { isHeadSynchronized = true; } } // stack variable or synchronized head exprent if (!left.IsStack() && !isHeadSynchronized) { return(new object[] { null, changed, false }); } VarVersionPair leftpaar = new VarVersionPair(left); List <VarVersionNode> usedVers = new List <VarVersionNode>(); bool notdom = GetUsedVersions(ssau, leftpaar, usedVers); if (!notdom && (usedVers.Count == 0)) { return(new object[] { right, changed, false }); } // stack variables only if (!left.IsStack()) { return(new object[] { null, changed, false }); } int useflags = right.GetExprentUse(); if ((useflags & Exprent.Both_Flags) != Exprent.Both_Flags) { return(new object[] { null, changed, false }); } Dictionary <int, HashSet <VarVersionPair> > mapVars = GetAllVarVersions(leftpaar, right , ssau); if (mapVars.ContainsKey(leftpaar.var) && notdom) { return(new object[] { null, changed, false }); } Sharpen.Collections.Remove(mapVars, leftpaar.var); HashSet <VarVersionPair> setAllowedVars = GetAllVersions(parent); if (next != null) { Sharpen.Collections.AddAll(setAllowedVars, GetAllVersions(next)); } bool vernotreplaced = false; HashSet <VarVersionPair> setTempUsedVers = new HashSet <VarVersionPair>(); foreach (VarVersionNode usedvar in usedVers) { VarVersionPair usedver = new VarVersionPair(usedvar.var, usedvar.version); if (IsVersionToBeReplaced(usedver, mapVars, ssau, leftpaar) && (right.type == Exprent .Exprent_Var || setAllowedVars.Contains(usedver))) { setTempUsedVers.Add(usedver); } else { vernotreplaced = true; } } if (!notdom && !vernotreplaced) { foreach (VarVersionPair usedver in setTempUsedVers) { Exprent copy = right.Copy(); if (right.type == Exprent.Exprent_Field && ssau.GetMapFieldVars().ContainsKey(right .id)) { Sharpen.Collections.Put(ssau.GetMapFieldVars(), copy.id, ssau.GetMapFieldVars().GetOrNullable (right.id)); } Sharpen.Collections.Put(mapVarValues, usedver, copy); } // remove assignment return(new object[] { right, changed, false }); } return(new object[] { null, changed, false }); }
private static int IsArrayInitializer(List <Exprent> list, int index) { Exprent current = list[index]; if (current.type == Exprent.Exprent_Assignment) { AssignmentExprent @as = (AssignmentExprent)current; if (@as.GetRight().type == Exprent.Exprent_New && @as.GetLeft().type == Exprent.Exprent_Var) { NewExprent newExpr = (NewExprent)@as.GetRight(); if (newExpr.GetExprType().arrayDim > 0 && newExpr.GetLstDims().Count == 1 && (newExpr .GetLstArrayElements().Count == 0) && newExpr.GetLstDims()[0].type == Exprent.Exprent_Const) { int size = (int)((ConstExprent)newExpr.GetLstDims()[0]).GetValue(); if (size == 0) { return(0); } VarExprent arrVar = (VarExprent)@as.GetLeft(); Dictionary <int, Exprent> mapInit = new Dictionary <int, Exprent>(); int i = 1; while (index + i < list.Count && i <= size) { bool found = false; Exprent expr = list[index + i]; if (expr.type == Exprent.Exprent_Assignment) { AssignmentExprent aas = (AssignmentExprent)expr; if (aas.GetLeft().type == Exprent.Exprent_Array) { ArrayExprent arrExpr = (ArrayExprent)aas.GetLeft(); if (arrExpr.GetArray().type == Exprent.Exprent_Var && arrVar.Equals(arrExpr.GetArray ()) && arrExpr.GetIndex().type == Exprent.Exprent_Const) { // TODO: check for a number type. Failure extremely improbable, but nevertheless... int constValue = ((ConstExprent)arrExpr.GetIndex()).GetIntValue(); if (constValue < size && !mapInit.ContainsKey(constValue)) { if (!aas.GetRight().ContainsExprent(arrVar)) { Sharpen.Collections.Put(mapInit, constValue, aas.GetRight()); found = true; } } } } } if (!found) { break; } i++; } double fraction = ((double)mapInit.Count) / size; if ((arrVar.IsStack() && fraction > 0) || (size <= 7 && fraction >= 0.3) || (size > 7 && fraction >= 0.7)) { List <Exprent> lstRet = new List <Exprent>(); VarType arrayType = newExpr.GetNewType().DecreaseArrayDim(); ConstExprent defaultVal = ExprProcessor.GetDefaultArrayValue(arrayType); for (int j = 0; j < size; j++) { lstRet.Add(defaultVal.Copy()); } int dims = newExpr.GetNewType().arrayDim; foreach (KeyValuePair <int, Exprent> ent in mapInit) { Exprent tempExpr = ent.Value; lstRet[ent.Key] = tempExpr; if (tempExpr.type == Exprent.Exprent_New) { NewExprent tempNewExpr = (NewExprent)tempExpr; if (dims > 1 && !(tempNewExpr.GetLstArrayElements().Count == 0)) { tempNewExpr.SetDirectArrayInit(true); } } } newExpr.SetLstArrayElements(lstRet); return(mapInit.Count); } } } } return(0); }
private void ProcessExprent(Exprent expr, SFormsFastMapDirect[] varmaparr, Statement stat, bool calcLiveVars) { if (expr == null) { return; } VarExprent varassign = null; bool finished = false; switch (expr.type) { case Exprent.Exprent_Assignment: { AssignmentExprent assexpr = (AssignmentExprent)expr; if (assexpr.GetCondType() == AssignmentExprent.Condition_None) { Exprent dest = assexpr.GetLeft(); if (dest.type == Exprent.Exprent_Var) { varassign = (VarExprent)dest; } } break; } case Exprent.Exprent_Function: { FunctionExprent func = (FunctionExprent)expr; switch (func.GetFuncType()) { case FunctionExprent.Function_Iif: { ProcessExprent(func.GetLstOperands()[0], varmaparr, stat, calcLiveVars); SFormsFastMapDirect varmapFalse; if (varmaparr[1] == null) { varmapFalse = new SFormsFastMapDirect(varmaparr[0]); } else { varmapFalse = varmaparr[1]; varmaparr[1] = null; } ProcessExprent(func.GetLstOperands()[1], varmaparr, stat, calcLiveVars); SFormsFastMapDirect[] varmaparrNeg = new SFormsFastMapDirect[] { varmapFalse, null }; ProcessExprent(func.GetLstOperands()[2], varmaparrNeg, stat, calcLiveVars); MergeMaps(varmaparr[0], varmaparrNeg[0]); varmaparr[1] = null; finished = true; break; } case FunctionExprent.Function_Cadd: { ProcessExprent(func.GetLstOperands()[0], varmaparr, stat, calcLiveVars); SFormsFastMapDirect[] varmaparrAnd = new SFormsFastMapDirect[] { new SFormsFastMapDirect (varmaparr[0]), null }; ProcessExprent(func.GetLstOperands()[1], varmaparrAnd, stat, calcLiveVars); // false map varmaparr[1] = MergeMaps(varmaparr[varmaparr[1] == null ? 0 : 1], varmaparrAnd[varmaparrAnd [1] == null ? 0 : 1]); // true map varmaparr[0] = varmaparrAnd[0]; finished = true; break; } case FunctionExprent.Function_Cor: { ProcessExprent(func.GetLstOperands()[0], varmaparr, stat, calcLiveVars); SFormsFastMapDirect[] varmaparrOr = new SFormsFastMapDirect[] { new SFormsFastMapDirect (varmaparr[varmaparr[1] == null ? 0 : 1]), null }; ProcessExprent(func.GetLstOperands()[1], varmaparrOr, stat, calcLiveVars); // false map varmaparr[1] = varmaparrOr[varmaparrOr[1] == null ? 0 : 1]; // true map varmaparr[0] = MergeMaps(varmaparr[0], varmaparrOr[0]); finished = true; break; } } break; } } if (!finished) { List <Exprent> lst = expr.GetAllExprents(); lst.Remove(varassign); foreach (Exprent ex in lst) { ProcessExprent(ex, varmaparr, stat, calcLiveVars); } } SFormsFastMapDirect varmap = varmaparr[0]; // field access if (expr.type == Exprent.Exprent_Field) { int?index; if (mapFieldVars.ContainsKey(expr.id)) { index = mapFieldVars.GetOrNullable(expr.id); } else { index = fieldvarcounter--; Sharpen.Collections.Put(mapFieldVars, expr.id, index); // ssu graph ssuversions.CreateNode(new VarVersionPair(index, 1)); } SetCurrentVar(varmap, index, 1); } else if (expr.type == Exprent.Exprent_Invocation || (expr.type == Exprent.Exprent_Assignment && ((AssignmentExprent)expr).GetLeft().type == Exprent.Exprent_Field) || (expr. type == Exprent.Exprent_New && ((NewExprent)expr).GetNewType().type == ICodeConstants .Type_Object) || expr.type == Exprent.Exprent_Function) { bool ismmpp = true; if (expr.type == Exprent.Exprent_Function) { ismmpp = false; FunctionExprent fexpr = (FunctionExprent)expr; if (fexpr.GetFuncType() >= FunctionExprent.Function_Imm && fexpr.GetFuncType() <= FunctionExprent.Function_Ppi) { if (fexpr.GetLstOperands()[0].type == Exprent.Exprent_Field) { ismmpp = true; } } } if (ismmpp) { varmap.RemoveAllFields(); } } if (varassign != null) { int varindex = varassign.GetIndex(); if (varassign.GetVersion() == 0) { // get next version int nextver = GetNextFreeVersion(varindex, stat); // set version varassign.SetVersion(nextver); // ssu graph ssuversions.CreateNode(new VarVersionPair(varindex, nextver)); SetCurrentVar(varmap, varindex, nextver); } else { if (calcLiveVars) { VarMapToGraph(new VarVersionPair(varindex, varassign.GetVersion()), varmap); } SetCurrentVar(varmap, varindex, varassign.GetVersion()); } } else if (expr.type == Exprent.Exprent_Function) { // MM or PP function FunctionExprent func_1 = (FunctionExprent)expr; switch (func_1.GetFuncType()) { case FunctionExprent.Function_Imm: case FunctionExprent.Function_Mmi: case FunctionExprent.Function_Ipp: case FunctionExprent.Function_Ppi: { if (func_1.GetLstOperands()[0].type == Exprent.Exprent_Var) { VarExprent var = (VarExprent)func_1.GetLstOperands()[0]; int varindex = var.GetIndex(); VarVersionPair varpaar = new VarVersionPair(varindex, var.GetVersion()); // ssu graph VarVersionPair phantomver = phantomppnodes.GetOrNull(varpaar); if (phantomver == null) { // get next version int nextver = GetNextFreeVersion(varindex, null); phantomver = new VarVersionPair(varindex, nextver); //ssuversions.createOrGetNode(phantomver); ssuversions.CreateNode(phantomver); VarVersionNode vernode = ssuversions.nodes.GetWithKey(varpaar); FastSparseSetFactory <int> .FastSparseSet <int> vers = factory.SpawnEmptySet(); if (vernode.preds.Count == 1) { vers.Add(new Sharpen.EnumeratorAdapter <VarVersionEdge>(vernode.preds.GetEnumerator()).Next().source.version); } else { foreach (VarVersionEdge edge in vernode.preds) { vers.Add(new Sharpen.EnumeratorAdapter <VarVersionEdge>(edge.source.preds.GetEnumerator()).Next().source.version); } } vers.Add(nextver); CreateOrUpdatePhiNode(varpaar, vers, stat); Sharpen.Collections.Put(phantomppnodes, varpaar, phantomver); } if (calcLiveVars) { VarMapToGraph(varpaar, varmap); } SetCurrentVar(varmap, varindex, var.GetVersion()); } break; } } } else if (expr.type == Exprent.Exprent_Var) { VarExprent vardest = (VarExprent)expr; int varindex = vardest.GetIndex(); int current_vers = vardest.GetVersion(); FastSparseSetFactory <int> .FastSparseSet <int> vers = varmap.Get(varindex); int cardinality = vers.GetCardinality(); if (cardinality == 1) { // size == 1 if (current_vers != 0) { if (calcLiveVars) { VarMapToGraph(new VarVersionPair(varindex, current_vers), varmap); } SetCurrentVar(varmap, varindex, current_vers); } else { // split last version int usever = GetNextFreeVersion(varindex, stat); // set version vardest.SetVersion(usever); SetCurrentVar(varmap, varindex, usever); // ssu graph int lastver = new Sharpen.EnumeratorAdapter <int>(vers.GetEnumerator()).Next(); VarVersionNode prenode = ssuversions.nodes.GetWithKey(new VarVersionPair(varindex , lastver)); VarVersionNode usenode = ssuversions.CreateNode(new VarVersionPair(varindex, usever )); VarVersionEdge edge = new VarVersionEdge(VarVersionEdge.Edge_General, prenode, usenode ); prenode.AddSuccessor(edge); usenode.AddPredecessor(edge); } } else if (cardinality == 2) { // size > 1 if (current_vers != 0) { if (calcLiveVars) { VarMapToGraph(new VarVersionPair(varindex, current_vers), varmap); } SetCurrentVar(varmap, varindex, current_vers); } else { // split version int usever = GetNextFreeVersion(varindex, stat); // set version vardest.SetVersion(usever); // ssu node ssuversions.CreateNode(new VarVersionPair(varindex, usever)); SetCurrentVar(varmap, varindex, usever); current_vers = usever; } CreateOrUpdatePhiNode(new VarVersionPair(varindex, current_vers), vers, stat); } } }
private static Exprent IdentifySecondaryFunctions(Exprent exprent, bool statement_level , VarProcessor varProc) { if (exprent.type == Exprent.Exprent_Function) { FunctionExprent fexpr = (FunctionExprent)exprent; switch (fexpr.GetFuncType()) { case FunctionExprent.Function_Bool_Not: { Exprent retparam = PropagateBoolNot(fexpr); if (retparam != null) { return(retparam); } break; } case FunctionExprent.Function_Eq: case FunctionExprent.Function_Ne: case FunctionExprent.Function_Gt: case FunctionExprent.Function_Ge: case FunctionExprent.Function_Lt: case FunctionExprent.Function_Le: { Exprent expr1 = fexpr.GetLstOperands()[0]; Exprent expr2 = fexpr.GetLstOperands()[1]; if (expr1.type == Exprent.Exprent_Const) { expr2 = expr1; expr1 = fexpr.GetLstOperands()[1]; } if (expr1.type == Exprent.Exprent_Function && expr2.type == Exprent.Exprent_Const) { FunctionExprent funcexpr = (FunctionExprent)expr1; ConstExprent cexpr = (ConstExprent)expr2; int functype = funcexpr.GetFuncType(); if (functype == FunctionExprent.Function_Lcmp || functype == FunctionExprent.Function_Fcmpg || functype == FunctionExprent.Function_Fcmpl || functype == FunctionExprent.Function_Dcmpg || functype == FunctionExprent.Function_Dcmpl) { int desttype = -1; int?[] destcons = mapNumComparisons.GetOrNull(fexpr.GetFuncType()); if (destcons != null) { int index = cexpr.GetIntValue() + 1; if (index >= 0 && index <= 2) { int?destcon = destcons[index]; if (destcon != null) { desttype = destcon.Value; } } } if (desttype >= 0) { return(new FunctionExprent(desttype, funcexpr.GetLstOperands(), funcexpr.bytecode )); } } } break; } } } bool replaced = true; while (replaced) { replaced = false; foreach (Exprent expr in exprent.GetAllExprents()) { Exprent retexpr = IdentifySecondaryFunctions(expr, false, varProc); if (retexpr != null) { exprent.ReplaceExprent(expr, retexpr); replaced = true; break; } } } switch (exprent.type) { case Exprent.Exprent_Function: { FunctionExprent fexpr_1 = (FunctionExprent)exprent; List <Exprent> lstOperands = fexpr_1.GetLstOperands(); switch (fexpr_1.GetFuncType()) { case FunctionExprent.Function_Xor: { for (int i = 0; i < 2; i++) { Exprent operand = lstOperands[i]; VarType operandtype = operand.GetExprType(); if (operand.type == Exprent.Exprent_Const && operandtype.type != ICodeConstants.Type_Boolean) { ConstExprent cexpr = (ConstExprent)operand; long val; if (operandtype.type == ICodeConstants.Type_Long) { val = (long)cexpr.GetValue(); } else { val = (int)cexpr.GetValue(); } if (val == -1) { List <Exprent> lstBitNotOperand = new List <Exprent>(); lstBitNotOperand.Add(lstOperands[1 - i]); return(new FunctionExprent(FunctionExprent.Function_Bit_Not, lstBitNotOperand, fexpr_1 .bytecode)); } } } break; } case FunctionExprent.Function_Eq: case FunctionExprent.Function_Ne: { if (lstOperands[0].GetExprType().type == ICodeConstants.Type_Boolean && lstOperands [1].GetExprType().type == ICodeConstants.Type_Boolean) { for (int i = 0; i < 2; i++) { if (lstOperands[i].type == Exprent.Exprent_Const) { ConstExprent cexpr = (ConstExprent)lstOperands[i]; int val = (int)cexpr.GetValue(); if ((fexpr_1.GetFuncType() == FunctionExprent.Function_Eq && val == 1) || (fexpr_1 .GetFuncType() == FunctionExprent.Function_Ne && val == 0)) { return(lstOperands[1 - i]); } else { List <Exprent> lstNotOperand = new List <Exprent>(); lstNotOperand.Add(lstOperands[1 - i]); return(new FunctionExprent(FunctionExprent.Function_Bool_Not, lstNotOperand, fexpr_1 .bytecode)); } } } } break; } case FunctionExprent.Function_Bool_Not: { if (lstOperands[0].type == Exprent.Exprent_Const) { int val = ((ConstExprent)lstOperands[0]).GetIntValue(); if (val == 0) { return(new ConstExprent(VarType.Vartype_Boolean, 1, fexpr_1.bytecode)); } else { return(new ConstExprent(VarType.Vartype_Boolean, 0, fexpr_1.bytecode)); } } break; } case FunctionExprent.Function_Iif: { Exprent expr1_1 = lstOperands[1]; Exprent expr2_1 = lstOperands[2]; if (expr1_1.type == Exprent.Exprent_Const && expr2_1.type == Exprent.Exprent_Const) { ConstExprent cexpr1 = (ConstExprent)expr1_1; ConstExprent cexpr2 = (ConstExprent)expr2_1; if (cexpr1.GetExprType().type == ICodeConstants.Type_Boolean && cexpr2.GetExprType ().type == ICodeConstants.Type_Boolean) { if (cexpr1.GetIntValue() == 0 && cexpr2.GetIntValue() != 0) { return(new FunctionExprent(FunctionExprent.Function_Bool_Not, lstOperands[0], fexpr_1 .bytecode)); } else if (cexpr1.GetIntValue() != 0 && cexpr2.GetIntValue() == 0) { return(lstOperands[0]); } } } break; } case FunctionExprent.Function_Lcmp: case FunctionExprent.Function_Fcmpl: case FunctionExprent.Function_Fcmpg: case FunctionExprent.Function_Dcmpl: case FunctionExprent.Function_Dcmpg: { int var = DecompilerContext.GetCounterContainer().GetCounterAndIncrement(CounterContainer .Var_Counter); VarType type = lstOperands[0].GetExprType(); FunctionExprent iff = new FunctionExprent(FunctionExprent.Function_Iif, Sharpen.Arrays.AsList <Exprent> (new FunctionExprent(FunctionExprent.Function_Lt, Sharpen.Arrays.AsList <Exprent>(new VarExprent (var, type, varProc), ConstExprent.GetZeroConstant(type.type)), null), new ConstExprent (VarType.Vartype_Int, -1, null), new ConstExprent(VarType.Vartype_Int, 1, null)) , null); FunctionExprent head = new FunctionExprent(FunctionExprent.Function_Eq, Sharpen.Arrays.AsList <Exprent> (new AssignmentExprent(new VarExprent(var, type, varProc), new FunctionExprent(FunctionExprent .Function_Sub, Sharpen.Arrays.AsList(lstOperands[0], lstOperands[1]), null), null ), ConstExprent.GetZeroConstant(type.type)), null); varProc.SetVarType(new VarVersionPair(var, 0), type); return(new FunctionExprent(FunctionExprent.Function_Iif, Sharpen.Arrays.AsList <Exprent>(head , new ConstExprent(VarType.Vartype_Int, 0, null), iff), fexpr_1.bytecode)); } } break; } case Exprent.Exprent_Assignment: { // check for conditional assignment AssignmentExprent asexpr = (AssignmentExprent)exprent; Exprent right = asexpr.GetRight(); Exprent left = asexpr.GetLeft(); if (right.type == Exprent.Exprent_Function) { FunctionExprent func = (FunctionExprent)right; VarType midlayer = null; if (func.GetFuncType() >= FunctionExprent.Function_I2l && func.GetFuncType() <= FunctionExprent .Function_I2s) { right = func.GetLstOperands()[0]; midlayer = func.GetSimpleCastType(); if (right.type == Exprent.Exprent_Function) { func = (FunctionExprent)right; } else { return(null); } } List <Exprent> lstFuncOperands = func.GetLstOperands(); Exprent cond = null; switch (func.GetFuncType()) { case FunctionExprent.Function_Add: case FunctionExprent.Function_And: case FunctionExprent.Function_Or: case FunctionExprent.Function_Xor: { if (left.Equals(lstFuncOperands[1])) { cond = lstFuncOperands[0]; break; } goto case FunctionExprent.Function_Sub; } case FunctionExprent.Function_Sub: case FunctionExprent.Function_Mul: case FunctionExprent.Function_Div: case FunctionExprent.Function_Rem: case FunctionExprent.Function_Shl: case FunctionExprent.Function_Shr: case FunctionExprent.Function_Ushr: { if (left.Equals(lstFuncOperands[0])) { cond = lstFuncOperands[1]; } break; } } if (cond != null && (midlayer == null || midlayer.Equals(cond.GetExprType()))) { asexpr.SetRight(cond); asexpr.SetCondType(func.GetFuncType()); } } break; } case Exprent.Exprent_Invocation: { if (!statement_level) { // simplify if exprent is a real expression. The opposite case is pretty absurd, can still happen however (and happened at least once). Exprent retexpr = ConcatenationHelper.ContractStringConcat(exprent); if (!exprent.Equals(retexpr)) { return(retexpr); } } break; } } return(null); }