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 Exprent IsReplaceableVar(Exprent exprent, Dictionary <VarVersionPair , Exprent> mapVarValues) { Exprent dest = null; if (exprent.type == Exprent.Exprent_Var) { VarExprent var = (VarExprent)exprent; dest = mapVarValues.GetOrNull(new VarVersionPair(var)); } return(dest); }
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 HashSet <VarVersionPair> GetAllVersions(Exprent exprent) { HashSet <VarVersionPair> res = new HashSet <VarVersionPair>(); List <Exprent> listTemp = new List <Exprent>(exprent.GetAllExprents(true)); listTemp.Add(exprent); foreach (Exprent expr in listTemp) { if (expr.type == Exprent.Exprent_Var) { VarExprent var = (VarExprent)expr; res.Add(new VarVersionPair(var)); } } return(res); }
private static void ReplaceSingleVar(Exprent parent, VarExprent var, Exprent dest , SSAUConstructorSparseEx ssau) { parent.ReplaceExprent(var, dest); // live sets SFormsFastMapDirect livemap = ssau.GetLiveVarVersionsMap(new VarVersionPair(var)); HashSet <VarVersionPair> setVars = GetAllVersions(dest); foreach (VarVersionPair varpaar in setVars) { VarVersionNode node = ssau.GetSsuversions().nodes.GetWithKey(varpaar); var toRemove = new List <KeyValuePair <int, FastSparseSetFactory <int> .FastSparseSet <int> > >(); var entryList = node.live.EntryList(); for (var index = 0; index < entryList.Count; index++) { var itent = entryList[index]; KeyValuePair <int, FastSparseSetFactory <int> .FastSparseSet <int> > ent = entryList.ElementAtOrDefault(index + 1); if (ent.Value == null) { break; } int key = ent.Key; if (!livemap.ContainsKey(key)) { toRemove.Add(itent); } else { FastSparseSetFactory <int> .FastSparseSet <int> set = ent.Value; set.Complement(livemap.Get(key)); if (set.IsEmpty()) { toRemove.Add(itent); } } } foreach (var keyValuePair in toRemove) { node.live.PutInternal(keyValuePair.Key, keyValuePair.Value, true); // entryList.RemoveAll(c => c.Key == keyValuePair.Key); } } }
private static bool SetDefinition(Exprent expr, int index) { if (expr.type == Exprent.Exprent_Assignment) { Exprent left = ((AssignmentExprent)expr).GetLeft(); if (left.type == Exprent.Exprent_Var) { VarExprent var = (VarExprent)left; if (var.GetIndex() == index) { var.SetDefinition(true); return(true); } } } return(false); }
public static bool IsInvocationInitConstructor(InvocationExprent inv, MethodWrapper method, ClassWrapper wrapper, bool withThis) { if (inv.GetFunctype() == InvocationExprent.Typ_Init && inv.GetInstance().type == Exprent.Exprent_Var) { VarExprent instVar = (VarExprent)inv.GetInstance(); VarVersionPair varPair = new VarVersionPair(instVar); string className = method.varproc.GetThisVars().GetOrNull(varPair); if (className != null) { // any this instance. TODO: Restrict to current class? return(withThis || !wrapper.GetClassStruct().qualifiedName.Equals(inv.GetClassname ())); } } return(false); }
private static void UpdateVersions(DirectGraph graph, Dictionary <VarVersionPair, int> versions) { 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 var = (VarExprent)expr; int?version = versions.GetOrNullable(new VarVersionPair(var)); if (version != null) { var.SetVersion(version.Value); } } } return(0); } ); }
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 bool FindAndRemoveParameterCheck(Statement stat, StructMethod mt) { Statement st = stat.GetFirst(); while (st.type == Statement.Type_Sequence) { st = st.GetFirst(); } if (st.type == Statement.Type_If) { IfStatement ifstat = (IfStatement)st; Statement ifbranch = ifstat.GetIfstat(); Exprent if_condition = ifstat.GetHeadexprent().GetCondition(); bool is_notnull_check = false; // TODO: FUNCTION_NE also possible if reversed order (in theory) if (ifbranch != null && if_condition.type == Exprent.Exprent_Function && ((FunctionExprent )if_condition).GetFuncType() == FunctionExprent.Function_Eq && ifbranch.type == Statement.Type_Basicblock && ifbranch.GetExprents().Count == 1 && ifbranch.GetExprents ()[0].type == Exprent.Exprent_Exit) { FunctionExprent func = (FunctionExprent)if_condition; Exprent first_param = func.GetLstOperands()[0]; Exprent second_param = func.GetLstOperands()[1]; if (second_param.type == Exprent.Exprent_Const && second_param.GetExprType().type == ICodeConstants.Type_Null) { // TODO: reversed parameter order if (first_param.type == Exprent.Exprent_Var) { VarExprent var = (VarExprent)first_param; bool thisvar = !mt.HasModifier(ICodeConstants.Acc_Static); MethodDescriptor md = MethodDescriptor.ParseDescriptor(mt.GetDescriptor()); // parameter annotations StructAnnotationParameterAttribute param_annotations = mt.GetAttribute(StructGeneralAttribute .Attribute_Runtime_Invisible_Parameter_Annotations); if (param_annotations != null) { List <List <AnnotationExprent> > param_annotations_lists = param_annotations.GetParamAnnotations (); int method_param_number = [email protected]; int index = thisvar ? 1 : 0; for (int i = 0; i < method_param_number; i++) { if (index == var.GetIndex()) { if (param_annotations_lists.Count >= method_param_number - i) { int shift = method_param_number - param_annotations_lists.Count; // NOTE: workaround for compiler bug, count annotations starting with the last parameter List <AnnotationExprent> annotations = param_annotations_lists[i - shift]; foreach (AnnotationExprent ann in annotations) { if (ann.GetClassName().Equals("org/jetbrains/annotations/NotNull")) { is_notnull_check = true; break; } } } break; } index += md.@params[i].stackSize; } } } } } if (!is_notnull_check) { return(false); } RemoveParameterCheck(stat); return(true); } return(false); }
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 Exprent ReplaceAccessExprent(ClassesProcessor.ClassNode caller, MethodWrapper methdest, InvocationExprent invexpr) { ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(invexpr.GetClassname()); MethodWrapper methsource = null; if (node != null && node.GetWrapper() != null) { methsource = node.GetWrapper().GetMethodWrapper(invexpr.GetName(), invexpr.GetStringDescriptor ()); } if (methsource == null || !mapMethodType.ContainsKey(methsource)) { return(null); } // if same method, return if (node.classStruct.qualifiedName.Equals(caller.classStruct.qualifiedName) && methsource .methodStruct.GetName().Equals(methdest.methodStruct.GetName()) && methsource.methodStruct .GetDescriptor().Equals(methdest.methodStruct.GetDescriptor())) { // no recursive invocations permitted! return(null); } NestedMemberAccess.MethodAccess type = mapMethodType.GetOrNull(methsource); // // FIXME: impossible case. MethodAccess.NORMAL is not saved in the map // if(type == MethodAccess.NORMAL) { // return null; // } if (!SameTree(caller, node)) { return(null); } DirectGraph graph = methsource.GetOrBuildGraph(); Exprent source = graph.first.exprents[0]; Exprent retexprent = null; switch (type.ordinal()) { case 1: { ExitExprent exsource = (ExitExprent)source; if (exsource.GetValue().type == Exprent.Exprent_Var) { // qualified this VarExprent var = (VarExprent)exsource.GetValue(); string varname = methsource.varproc.GetVarName(new VarVersionPair(var)); if (!methdest.setOuterVarNames.Contains(varname)) { VarNamesCollector vnc = new VarNamesCollector(); vnc.AddName(varname); methdest.varproc.RefreshVarNames(vnc); methdest.setOuterVarNames.Add(varname); } int index = methdest.counter.GetCounterAndIncrement(CounterContainer.Var_Counter); VarExprent ret = new VarExprent(index, var.GetVarType(), methdest.varproc); methdest.varproc.SetVarName(new VarVersionPair(index, 0), varname); retexprent = ret; } else { // field FieldExprent ret = (FieldExprent)exsource.GetValue().Copy(); if (!ret.IsStatic()) { ret.ReplaceExprent(ret.GetInstance(), invexpr.GetLstParameters()[0]); } retexprent = ret; } break; } case 2: { AssignmentExprent ret_1; if (source.type == Exprent.Exprent_Exit) { ExitExprent extex = (ExitExprent)source; ret_1 = (AssignmentExprent)extex.GetValue().Copy(); } else { ret_1 = (AssignmentExprent)source.Copy(); } FieldExprent fexpr = (FieldExprent)ret_1.GetLeft(); if (fexpr.IsStatic()) { ret_1.ReplaceExprent(ret_1.GetRight(), invexpr.GetLstParameters()[0]); } else { ret_1.ReplaceExprent(ret_1.GetRight(), invexpr.GetLstParameters()[1]); fexpr.ReplaceExprent(fexpr.GetInstance(), invexpr.GetLstParameters()[0]); } // do not use copied bytecodes ret_1.GetLeft().bytecode = null; ret_1.GetRight().bytecode = null; retexprent = ret_1; break; } case 4: { retexprent = ReplaceFunction(invexpr, source); break; } case 3: { if (source.type == Exprent.Exprent_Exit) { source = ((ExitExprent)source).GetValue(); } InvocationExprent invret = (InvocationExprent)source.Copy(); int index_1 = 0; if (!invret.IsStatic()) { invret.ReplaceExprent(invret.GetInstance(), invexpr.GetLstParameters()[0]); index_1 = 1; } for (int i = 0; i < invret.GetLstParameters().Count; i++) { invret.ReplaceExprent(invret.GetLstParameters()[i], invexpr.GetLstParameters()[i + index_1]); } retexprent = invret; break; } } if (retexprent != null) { // preserve original bytecodes retexprent.bytecode = null; retexprent.AddBytecodeOffsets(invexpr.bytecode); // hide synthetic access method bool hide = true; if (node.type == ClassesProcessor.ClassNode.Class_Root || (node.access & ICodeConstants .Acc_Static) != 0) { StructMethod mt = methsource.methodStruct; if (!mt.IsSynthetic()) { hide = false; } } if (hide) { node.GetWrapper().GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(invexpr.GetName (), invexpr.GetStringDescriptor())); } } return(retexprent); }
private void SetNewVarIndices(VarTypeProcessor typeProcessor, DirectGraph graph, VarVersionsProcessor previousVersionsProcessor) { Dictionary <VarVersionPair, VarType> mapExprentMaxTypes = typeProcessor.GetMapExprentMaxTypes (); Dictionary <VarVersionPair, VarType> mapExprentMinTypes = typeProcessor.GetMapExprentMinTypes (); Dictionary <VarVersionPair, int> mapFinalVars = typeProcessor.GetMapFinalVars(); CounterContainer counters = DecompilerContext.GetCounterContainer(); Dictionary <VarVersionPair, int> mapVarPaar = new Dictionary <VarVersionPair, int> (); Dictionary <int, int> mapOriginalVarIndices = new Dictionary <int, int>(); // map var-version pairs on new var indexes foreach (VarVersionPair pair in new List <VarVersionPair>(mapExprentMinTypes.Keys)) { if (pair.version >= 0) { int newIndex = pair.version == 1 ? pair.var : counters.GetCounterAndIncrement(CounterContainer .Var_Counter); VarVersionPair newVar = new VarVersionPair(newIndex, 0); Sharpen.Collections.Put(mapExprentMinTypes, newVar, mapExprentMinTypes.GetOrNull( pair)); Sharpen.Collections.Put(mapExprentMaxTypes, newVar, mapExprentMaxTypes.GetOrNull( pair)); if (mapFinalVars.ContainsKey(pair)) { Sharpen.Collections.Put(mapFinalVars, newVar, Sharpen.Collections.Remove(mapFinalVars , pair)); } Sharpen.Collections.Put(mapVarPaar, pair, newIndex); Sharpen.Collections.Put(mapOriginalVarIndices, newIndex, pair.var); } } // set new vars 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 newVar = (VarExprent)expr; int?newVarIndex = mapVarPaar.GetOrNullable(new VarVersionPair(newVar)); if (newVarIndex != null) { newVar.SetIndex(newVarIndex.Value); newVar.SetVersion(0); } } else if (expr.type == Exprent.Exprent_Const) { VarType maxType = mapExprentMaxTypes.GetOrNull(new VarVersionPair(expr.id, -1)); if (maxType != null && maxType.Equals(VarType.Vartype_Char)) { ((ConstExprent)expr).SetConstType(maxType); } } } return(0); } ); if (previousVersionsProcessor != null) { Dictionary <int, int> oldIndices = previousVersionsProcessor.GetMapOriginalVarIndices (); this.mapOriginalVarIndices = new Dictionary <int, int>(mapOriginalVarIndices.Count ); foreach (KeyValuePair <int, int> entry in mapOriginalVarIndices) { int value = entry.Value; int?oldValue = oldIndices.GetOrNullable(value); value = oldValue != null ? oldValue.Value : value; Sharpen.Collections.Put(this.mapOriginalVarIndices, entry.Key, value); } } else { this.mapOriginalVarIndices = mapOriginalVarIndices; } }
public virtual void Init() { DecompilerContext.SetProperty(DecompilerContext.Current_Class, classStruct); DecompilerContext.SetProperty(DecompilerContext.Current_Class_Wrapper, this); DecompilerContext.GetLogger().StartClass(classStruct.qualifiedName); int maxSec = System.Convert.ToInt32(DecompilerContext.GetProperty(IFernflowerPreferences .Max_Processing_Method).ToString()); bool testMode = DecompilerContext.GetOption(IFernflowerPreferences.Unit_Test_Mode ); foreach (StructMethod mt in classStruct.GetMethods()) { DecompilerContext.GetLogger().StartMethod(mt.GetName() + " " + mt.GetDescriptor() ); MethodDescriptor md = MethodDescriptor.ParseDescriptor(mt.GetDescriptor()); VarProcessor varProc = new VarProcessor(mt, md); DecompilerContext.StartMethod(varProc); VarNamesCollector vc = varProc.GetVarNamesCollector(); CounterContainer counter = DecompilerContext.GetCounterContainer(); RootStatement root = null; bool isError = false; try { if (mt.ContainsCode()) { if (maxSec == 0 || testMode) { root = MethodProcessorRunnable.CodeToJava(mt, md, varProc); } else { MethodProcessorRunnable mtProc = new MethodProcessorRunnable(mt, md, varProc, DecompilerContext .GetCurrentContext()); Thread mtThread = new Thread(o => mtProc.Run()) { Name = "Java decompiler" }; long stopAt = Runtime.CurrentTimeMillis() + maxSec * 1000L; mtThread.Start(); while (!mtProc.IsFinished()) { try { lock (mtProc.Lock) { Thread.Sleep(200); } } catch (Exception e) { KillThread(mtThread); throw; } if (Runtime.CurrentTimeMillis() >= stopAt) { string message = "Processing time limit exceeded for method " + mt.GetName() + ", execution interrupted."; DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Error ); KillThread(mtThread); isError = true; break; } } if (!isError) { root = mtProc.GetResult(); } } } else { bool thisVar = !mt.HasModifier(ICodeConstants.Acc_Static); int paramCount = 0; if (thisVar) { Sharpen.Collections.Put(varProc.GetThisVars(), new VarVersionPair(0, 0), classStruct .qualifiedName); paramCount = 1; } paramCount += [email protected]; int varIndex = 0; for (int i = 0; i < paramCount; i++) { varProc.SetVarName(new VarVersionPair(varIndex, 0), vc.GetFreeName(varIndex)); if (thisVar) { if (i == 0) { varIndex++; } else { varIndex += md.@params[i - 1].stackSize; } } else { varIndex += md.@params[i].stackSize; } } } } catch (Exception t) { string message = "Method " + mt.GetName() + " " + mt.GetDescriptor() + " couldn't be decompiled."; DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn , t); isError = true; } MethodWrapper methodWrapper = new MethodWrapper(root, varProc, mt, counter); methodWrapper.decompiledWithErrors = isError; methods.AddWithKey(methodWrapper, InterpreterUtil.MakeUniqueKey(mt.GetName(), mt. GetDescriptor())); if (!isError) { // rename vars so that no one has the same name as a field VarNamesCollector namesCollector = new VarNamesCollector(); classStruct.GetFields().ForEach((StructField f) => namesCollector.AddName(f.GetName ())); varProc.RefreshVarNames(namesCollector); // if debug information present and should be used if (DecompilerContext.GetOption(IFernflowerPreferences.Use_Debug_Var_Names)) { StructLocalVariableTableAttribute attr = mt.GetLocalVariableAttr(); if (attr != null) { // only param names here varProc.SetDebugVarNames(attr.GetMapParamNames()); // the rest is here methodWrapper.GetOrBuildGraph().IterateExprents((Exprent exprent) => { List <Exprent> lst = exprent.GetAllExprents(true); lst.Add(exprent); lst.Where(e => e.type == Exprent.Exprent_Var).ToList().ForEach((Exprent e) => { VarExprent varExprent = (VarExprent)e; string name = varExprent.GetDebugName(mt); if (name != null) { varProc.SetVarName(varExprent.GetVarVersionPair(), name); } } ); return(0); } ); } } } DecompilerContext.GetLogger().EndMethod(); } DecompilerContext.GetLogger().EndClass(); }
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); }
public virtual void SetVarDefinitions() { VarNamesCollector vc = varproc.GetVarNamesCollector(); foreach (KeyValuePair <int, Statement> en in mapVarDefStatements) { Statement stat = en.Value; int index = en.Key; if (implDefVars.Contains(index)) { // already implicitly defined continue; } varproc.SetVarName(new VarVersionPair(index, 0), vc.GetFreeName(index)); // special case for if (stat.type == Statement.Type_Do) { DoStatement dstat = (DoStatement)stat; if (dstat.GetLooptype() == DoStatement.Loop_For) { if (dstat.GetInitExprent() != null && SetDefinition(dstat.GetInitExprent(), index )) { continue; } else { List <Exprent> lstSpecial = Sharpen.Arrays.AsList(dstat.GetConditionExprent(), dstat .GetIncExprent()); foreach (VarExprent var in GetAllVars(lstSpecial)) { if (var.GetIndex() == index) { stat = stat.GetParent(); break; } } } } } Statement first = FindFirstBlock(stat, index); List <Exprent> lst; if (first == null) { lst = stat.GetVarDefinitions(); } else if (first.GetExprents() == null) { lst = first.GetVarDefinitions(); } else { lst = first.GetExprents(); } bool defset = false; // search for the first assignment to var [index] int addindex = 0; foreach (Exprent expr in lst) { if (SetDefinition(expr, index)) { defset = true; break; } else { bool foundvar = false; foreach (Exprent exp in expr.GetAllExprents(true)) { if (exp.type == Exprent.Exprent_Var && ((VarExprent)exp).GetIndex() == index) { foundvar = true; break; } } if (foundvar) { break; } } addindex++; } if (!defset) { VarExprent var = new VarExprent(index, varproc.GetVarType(new VarVersionPair(index , 0)), varproc); var.SetDefinition(true); lst.Add(addindex, var); } } }
public VarVersionPair(VarExprent var) { this.var = var.GetIndex(); this.version = var.GetVersion(); }
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 virtual void SetMonitor(VarExprent monitor) { this.monitor = monitor; }
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 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); }