private static void ResetExprentTypes(DirectGraph graph) { graph.IterateExprents((Exprent exprent) => { List <Exprent> lst = exprent.GetAllExprents(true); lst.Add(exprent); foreach (Exprent expr in lst) { if (expr.type == Exprent.Exprent_Var) { ((VarExprent)expr).SetVarType(VarType.Vartype_Unknown); } else if (expr.type == Exprent.Exprent_Const) { ConstExprent constExpr = (ConstExprent)expr; if (constExpr.GetConstType().typeFamily == ICodeConstants.Type_Family_Integer) { constExpr.SetConstType(new ConstExprent(constExpr.GetIntValue(), constExpr.IsBoolPermitted (), null).GetConstType()); } } } return(0); } ); }
private static StructField FindAssertionField(ClassesProcessor.ClassNode node) { ClassWrapper wrapper = node.GetWrapper(); bool noSynthFlag = DecompilerContext.GetOption(IFernflowerPreferences.Synthetic_Not_Set ); foreach (StructField fd in wrapper.GetClassStruct().GetFields()) { string keyField = InterpreterUtil.MakeUniqueKey(fd.GetName(), fd.GetDescriptor()); // initializer exists if (wrapper.GetStaticFieldInitializers().ContainsKey(keyField)) { // access flags set if (fd.HasModifier(ICodeConstants.Acc_Static) && fd.HasModifier(ICodeConstants.Acc_Final ) && (noSynthFlag || fd.IsSynthetic())) { // field type boolean FieldDescriptor fdescr = FieldDescriptor.ParseDescriptor(fd.GetDescriptor()); if (VarType.Vartype_Boolean.Equals(fdescr.type)) { Exprent initializer = wrapper.GetStaticFieldInitializers().GetWithKey(keyField); if (initializer.type == Exprent.Exprent_Function) { FunctionExprent fexpr = (FunctionExprent)initializer; if (fexpr.GetFuncType() == FunctionExprent.Function_Bool_Not && fexpr.GetLstOperands ()[0].type == Exprent.Exprent_Invocation) { InvocationExprent invexpr = (InvocationExprent)fexpr.GetLstOperands()[0]; if (invexpr.GetInstance() != null && invexpr.GetInstance().type == Exprent.Exprent_Const && "desiredAssertionStatus".Equals(invexpr.GetName()) && "java/lang/Class".Equals (invexpr.GetClassname()) && (invexpr.GetLstParameters().Count == 0)) { ConstExprent cexpr = (ConstExprent)invexpr.GetInstance(); if (VarType.Vartype_Class.Equals(cexpr.GetConstType())) { ClassesProcessor.ClassNode nd = node; while (nd != null) { if (nd.GetWrapper().GetClassStruct().qualifiedName.Equals(cexpr.GetValue())) { break; } nd = nd.parent; } if (nd != null) { // found enclosing class with the same name return(fd); } } } } } } } } } return(null); }
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 ProcessClassRec(ClassesProcessor.ClassNode node, IDictionary <ClassWrapper, MethodWrapper> mapClassMeths, HashSet <ClassWrapper> setFound) { ClassWrapper wrapper = node.GetWrapper(); // search code foreach (MethodWrapper meth in wrapper.GetMethods()) { RootStatement root = meth.root; if (root != null) { DirectGraph graph = meth.GetOrBuildGraph(); graph.IterateExprents((Exprent exprent) => { foreach (KeyValuePair <ClassWrapper, MethodWrapper> ent in mapClassMeths) { if (ReplaceInvocations(exprent, ent.Key, ent.Value)) { setFound.Add(ent.Key); } } return(0); } ); } } // search initializers for (int j = 0; j < 2; j++) { VBStyleCollection <Exprent, string> initializers = j == 0 ? wrapper.GetStaticFieldInitializers () : wrapper.GetDynamicFieldInitializers(); for (int i = 0; i < initializers.Count; i++) { foreach (KeyValuePair <ClassWrapper, MethodWrapper> ent in mapClassMeths) { Exprent exprent = initializers[i]; if (ReplaceInvocations(exprent, ent.Key, ent.Value)) { setFound.Add(ent.Key); } string cl = IsClass14Invocation(exprent, ent.Key, ent.Value); if (cl != null) { initializers[i] = new ConstExprent(VarType.Vartype_Class, cl.Replace('.', '/'), exprent .bytecode); setFound.Add(ent.Key); } } } } // iterate nested classes foreach (ClassesProcessor.ClassNode nd in node.nested) { ProcessClassRec(nd, mapClassMeths, setFound); } }
private bool CheckTypeExprent(Exprent exprent) { foreach (Exprent expr in exprent.GetAllExprents()) { if (!CheckTypeExprent(expr)) { return(false); } } if (exprent.type == Exprent.Exprent_Const) { ConstExprent constExpr = (ConstExprent)exprent; if (constExpr.GetConstType().typeFamily <= ICodeConstants.Type_Family_Integer) { // boolean or integer VarVersionPair pair = new VarVersionPair(constExpr.id, -1); if (!mapExprentMinTypes.ContainsKey(pair)) { Sharpen.Collections.Put(mapExprentMinTypes, pair, constExpr.GetConstType()); } } } CheckTypesResult result = exprent.CheckExprTypeBounds(); bool res = true; if (result != null) { foreach (CheckTypesResult.ExprentTypePair entry in result.GetLstMaxTypeExprents()) { if (entry.type.typeFamily != ICodeConstants.Type_Family_Object) { ChangeExprentType(entry.exprent, entry.type, 1); } } foreach (CheckTypesResult.ExprentTypePair entry in result.GetLstMinTypeExprents()) { res &= ChangeExprentType(entry.exprent, entry.type, 0); } } return(res); }
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 bool ChangeExprentType(Exprent exprent, VarType newType, int minMax) { bool res = true; switch (exprent.type) { case Exprent.Exprent_Const: { ConstExprent constExpr = (ConstExprent)exprent; VarType constType = constExpr.GetConstType(); if (newType.typeFamily > ICodeConstants.Type_Family_Integer || constType.typeFamily > ICodeConstants.Type_Family_Integer) { return(true); } else if (newType.typeFamily == ICodeConstants.Type_Family_Integer) { VarType minInteger = new ConstExprent((int)constExpr.GetValue(), false, null).GetConstType (); if (minInteger.IsStrictSuperset(newType)) { newType = minInteger; } } goto case Exprent.Exprent_Var; } case Exprent.Exprent_Var: { VarVersionPair pair = null; if (exprent.type == Exprent.Exprent_Const) { pair = new VarVersionPair(((ConstExprent)exprent).id, -1); } else if (exprent.type == Exprent.Exprent_Var) { pair = new VarVersionPair((VarExprent)exprent); } if (minMax == 0) { // min VarType currentMinType = mapExprentMinTypes.GetOrNull(pair); VarType newMinType; if (currentMinType == null || newType.typeFamily > currentMinType.typeFamily) { newMinType = newType; } else if (newType.typeFamily < currentMinType.typeFamily) { return(true); } else { newMinType = VarType.GetCommonSupertype(currentMinType, newType); } Sharpen.Collections.Put(mapExprentMinTypes, pair, newMinType); if (exprent.type == Exprent.Exprent_Const) { ((ConstExprent)exprent).SetConstType(newMinType); } if (currentMinType != null && (newMinType.typeFamily > currentMinType.typeFamily || newMinType.IsStrictSuperset(currentMinType))) { return(false); } } else { // max VarType currentMaxType = mapExprentMaxTypes.GetOrNull(pair); VarType newMaxType; if (currentMaxType == null || newType.typeFamily < currentMaxType.typeFamily) { newMaxType = newType; } else if (newType.typeFamily > currentMaxType.typeFamily) { return(true); } else { newMaxType = VarType.GetCommonMinType(currentMaxType, newType); } Sharpen.Collections.Put(mapExprentMaxTypes, pair, newMaxType); } break; } case Exprent.Exprent_Assignment: { return(ChangeExprentType(((AssignmentExprent)exprent).GetRight(), newType, minMax )); } case Exprent.Exprent_Function: { FunctionExprent func = (FunctionExprent)exprent; switch (func.GetFuncType()) { case FunctionExprent.Function_Iif: { // FIXME: res = ChangeExprentType(func.GetLstOperands()[1], newType, minMax) & ChangeExprentType (func.GetLstOperands()[2], newType, minMax); break; } case FunctionExprent.Function_And: case FunctionExprent.Function_Or: case FunctionExprent.Function_Xor: { res = ChangeExprentType(func.GetLstOperands()[0], newType, minMax) & ChangeExprentType (func.GetLstOperands()[1], newType, minMax); break; } } break; } } return(res); }
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); }