public static void StartMethod(VarProcessor varProcessor) { DecompilerContext context = GetCurrentContext(); context.varProcessor = varProcessor; context.counterContainer = new CounterContainer(); }
public MethodWrapper(RootStatement root, VarProcessor varproc, StructMethod methodStruct , CounterContainer counter) { this.root = root; this.varproc = varproc; this.methodStruct = methodStruct; this.counter = counter; }
public MethodProcessorRunnable(StructMethod method, MethodDescriptor methodDescriptor , VarProcessor varProc, DecompilerContext parentContext) { this.method = method; this.methodDescriptor = methodDescriptor; this.varProc = varProc; this.parentContext = parentContext; }
public VarExprent(int index, VarType varType, VarProcessor processor, int visibleOffset ) : base(Exprent_Var) { this.index = index; this.varType = varType; this.processor = processor; this.visibleOffset = visibleOffset; }
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(); }
public VarExprent(int index, VarType varType, VarProcessor processor) : this(index, varType, processor, -1) { }
public FinallyProcessor(MethodDescriptor md, VarProcessor varProc) { methodDescriptor = md; varProcessor = varProc; }
public static bool IdentifySecondaryFunctions(Statement stat, VarProcessor varProc ) { if (stat.GetExprents() == null) { // if(){;}else{...} -> if(!){...} if (stat.type == Statement.Type_If) { IfStatement ifelsestat = (IfStatement)stat; Statement ifstat = ifelsestat.GetIfstat(); if (ifelsestat.iftype == IfStatement.Iftype_Ifelse && ifstat.GetExprents() != null && (ifstat.GetExprents().Count == 0) && ((ifstat.GetAllSuccessorEdges().Count == 0) || !ifstat.GetAllSuccessorEdges()[0].@explicit)) { // move else to the if position ifelsestat.GetStats().RemoveWithKey(ifstat.id); ifelsestat.iftype = IfStatement.Iftype_If; ifelsestat.SetIfstat(ifelsestat.GetElsestat()); ifelsestat.SetElsestat(null); if ((ifelsestat.GetAllSuccessorEdges().Count == 0) && !(ifstat.GetAllSuccessorEdges ().Count == 0)) { StatEdge endedge = ifstat.GetAllSuccessorEdges()[0]; ifstat.RemoveSuccessor(endedge); endedge.SetSource(ifelsestat); if (endedge.closure != null) { ifelsestat.GetParent().AddLabeledEdge(endedge); } ifelsestat.AddSuccessor(endedge); } ifelsestat.GetFirst().RemoveSuccessor(ifelsestat.GetIfEdge()); ifelsestat.SetIfEdge(ifelsestat.GetElseEdge()); ifelsestat.SetElseEdge(null); // negate head expression ifelsestat.SetNegated(!ifelsestat.IsNegated()); ifelsestat.GetHeadexprentList()[0] = ((IfExprent)ifelsestat.GetHeadexprent().Copy ()).NegateIf(); return(true); } } } bool replaced = true; while (replaced) { replaced = false; List <object> lstObjects = new List <object>(stat.GetExprents() == null ? (IEnumerable <object>)stat.GetSequentialObjects () : stat.GetExprents()); for (int i = 0; i < lstObjects.Count; i++) { object obj = lstObjects[i]; if (obj is Statement) { if (IdentifySecondaryFunctions((Statement)obj, varProc)) { replaced = true; break; } } else if (obj is Exprent) { Exprent retexpr = IdentifySecondaryFunctions((Exprent)obj, true, varProc); if (retexpr != null) { if (stat.GetExprents() == null) { // only head expressions can be replaced! stat.ReplaceExprent((Exprent)obj, retexpr); } else { stat.GetExprents()[i] = retexpr; } replaced = true; break; } } } } return(false); }
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); }
public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); string super_qualifier = null; bool isInstanceThis = false; tracer.AddMapping(bytecode); if (instance is InvocationExprent) { ((InvocationExprent)instance).MarkUsingBoxingResult(); } if (isStatic__) { if (IsBoxingCall() && canIgnoreBoxing) { // process general "boxing" calls, e.g. 'Object[] data = { true }' or 'Byte b = 123' // here 'byte' and 'short' values do not need an explicit narrowing type cast ExprProcessor.GetCastedExprent(lstParameters[0], descriptor.@params[0], buf, indent , false, false, false, false, tracer); return(buf); } ClassesProcessor.ClassNode node = (ClassesProcessor.ClassNode)DecompilerContext.GetProperty (DecompilerContext.Current_Class_Node); if (node == null || !classname.Equals(node.classStruct.qualifiedName)) { buf.Append(DecompilerContext.GetImportCollector().GetShortNameInClassContext(ExprProcessor .BuildJavaClassName(classname))); } } else { if (instance != null && instance.type == Exprent.Exprent_Var) { VarExprent instVar = (VarExprent)instance; VarVersionPair varPair = new VarVersionPair(instVar); VarProcessor varProc = instVar.GetProcessor(); if (varProc == null) { MethodWrapper currentMethod = (MethodWrapper)DecompilerContext.GetProperty(DecompilerContext .Current_Method_Wrapper); if (currentMethod != null) { varProc = currentMethod.varproc; } } string this_classname = null; if (varProc != null) { this_classname = varProc.GetThisVars().GetOrNull(varPair); } if (this_classname != null) { isInstanceThis = true; if (invocationTyp == Invoke_Special) { if (!classname.Equals(this_classname)) { // TODO: direct comparison to the super class? StructClass cl = DecompilerContext.GetStructContext().GetClass(classname); bool isInterface = cl != null && cl.HasModifier(ICodeConstants.Acc_Interface); super_qualifier = !isInterface ? this_classname : classname; } } } } if (functype == Typ_General) { if (super_qualifier != null) { TextUtil.WriteQualifiedSuper(buf, super_qualifier); } else if (instance != null) { TextBuffer res = instance.ToJava(indent, tracer); if (IsUnboxingCall()) { // we don't print the unboxing call - no need to bother with the instance wrapping / casting buf.Append(res); return(buf); } VarType rightType = instance.GetExprType(); VarType leftType = new VarType(ICodeConstants.Type_Object, 0, classname); if (rightType.Equals(VarType.Vartype_Object) && !leftType.Equals(rightType)) { buf.Append("((").Append(ExprProcessor.GetCastTypeName(leftType)).Append(")"); if (instance.GetPrecedence() >= FunctionExprent.GetPrecedence(FunctionExprent.Function_Cast )) { res.Enclose("(", ")"); } buf.Append(res).Append(")"); } else if (instance.GetPrecedence() > GetPrecedence()) { buf.Append("(").Append(res).Append(")"); } else { buf.Append(res); } } } } switch (functype) { case Typ_General: { if (VarExprent.Var_Nameless_Enclosure.Equals(buf.ToString())) { buf = new TextBuffer(); } if (buf.Length() > 0) { buf.Append("."); } buf.Append(name); if (invocationTyp == Invoke_Dynamic) { buf.Append("<invokedynamic>"); } buf.Append("("); break; } case Typ_Clinit: { throw new Exception("Explicit invocation of " + ICodeConstants.Clinit_Name); } case Typ_Init: { if (super_qualifier != null) { buf.Append("super("); } else if (isInstanceThis) { buf.Append("this("); } else if (instance != null) { buf.Append(instance.ToJava(indent, tracer)).Append(".<init>("); } else { throw new Exception("Unrecognized invocation of " + ICodeConstants.Init_Name); } break; } } List <VarVersionPair> mask = null; bool isEnum = false; if (functype == Typ_Init) { ClassesProcessor.ClassNode newNode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(classname); if (newNode != null) { mask = ExprUtil.GetSyntheticParametersMask(newNode, stringDescriptor, lstParameters .Count); isEnum = newNode.classStruct.HasModifier(ICodeConstants.Acc_Enum) && DecompilerContext .GetOption(IFernflowerPreferences.Decompile_Enum); } } BitSet setAmbiguousParameters = GetAmbiguousParameters(); // omit 'new Type[] {}' for the last parameter of a vararg method call if (lstParameters.Count == [email protected] && IsVarArgCall()) { Exprent lastParam = lstParameters[lstParameters.Count - 1]; if (lastParam.type == Exprent_New && lastParam.GetExprType().arrayDim >= 1) { ((NewExprent)lastParam).SetVarArgParam(true); } } bool firstParameter = true; int start = isEnum ? 2 : 0; for (int i = start; i < lstParameters.Count; i++) { if (mask == null || mask[i] == null) { TextBuffer buff = new TextBuffer(); bool ambiguous = setAmbiguousParameters.Get(i); // 'byte' and 'short' literals need an explicit narrowing type cast when used as a parameter ExprProcessor.GetCastedExprent(lstParameters[i], descriptor.@params[i], buff, indent , true, ambiguous, true, true, tracer); // the last "new Object[0]" in the vararg call is not printed if (buff.Length() > 0) { if (!firstParameter) { buf.Append(", "); } buf.Append(buff); } firstParameter = false; } } buf.Append(')'); return(buf); }
/// <exception cref="System.IO.IOException"/> public static RootStatement CodeToJava(StructMethod mt, MethodDescriptor md, VarProcessor varProc) { StructClass cl = mt.GetClassStruct(); bool isInitializer = ICodeConstants.Clinit_Name.Equals(mt.GetName()); // for now static initializer only mt.ExpandData(); InstructionSequence seq = mt.GetInstructionSequence(); ControlFlowGraph graph = new ControlFlowGraph(seq); DeadCodeHelper.RemoveDeadBlocks(graph); graph.InlineJsr(mt); // TODO: move to the start, before jsr inlining DeadCodeHelper.ConnectDummyExitBlock(graph); DeadCodeHelper.RemoveGotos(graph); ExceptionDeobfuscator.RemoveCircularRanges(graph); ExceptionDeobfuscator.RestorePopRanges(graph); if (DecompilerContext.GetOption(IFernflowerPreferences.Remove_Empty_Ranges)) { ExceptionDeobfuscator.RemoveEmptyRanges(graph); } if (DecompilerContext.GetOption(IFernflowerPreferences.Ensure_Synchronized_Monitor )) { // special case: search for 'synchronized' ranges w/o monitorexit instruction (as generated by Kotlin and Scala) DeadCodeHelper.ExtendSynchronizedRangeToMonitorexit(graph); } if (DecompilerContext.GetOption(IFernflowerPreferences.No_Exceptions_Return)) { // special case: single return instruction outside of a protected range DeadCodeHelper.IncorporateValueReturns(graph); } // ExceptionDeobfuscator.restorePopRanges(graph); ExceptionDeobfuscator.InsertEmptyExceptionHandlerBlocks(graph); DeadCodeHelper.MergeBasicBlocks(graph); DecompilerContext.GetCounterContainer().SetCounter(CounterContainer.Var_Counter, mt.GetLocalVariables()); if (ExceptionDeobfuscator.HasObfuscatedExceptions(graph)) { DecompilerContext.GetLogger().WriteMessage("Heavily obfuscated exception ranges found!" , IFernflowerLogger.Severity.Warn); if (!ExceptionDeobfuscator.HandleMultipleEntryExceptionRanges(graph)) { DecompilerContext.GetLogger().WriteMessage("Found multiple entry exception ranges which could not be splitted" , IFernflowerLogger.Severity.Warn); } ExceptionDeobfuscator.InsertDummyExceptionHandlerBlocks(graph, cl.GetBytecodeVersion ()); } RootStatement root = DomHelper.ParseGraph(graph); FinallyProcessor fProc = new FinallyProcessor(md, varProc); while (fProc.IterateGraph(mt, root, graph)) { root = DomHelper.ParseGraph(graph); } // remove synchronized exception handler // not until now because of comparison between synchronized statements in the finally cycle DomHelper.RemoveSynchronizedHandler(root); // LabelHelper.lowContinueLabels(root, new HashSet<StatEdge>()); SequenceHelper.CondenseSequences(root); ClearStructHelper.ClearStatements(root); ExprProcessor proc = new ExprProcessor(md, varProc); proc.ProcessStatement(root, cl); SequenceHelper.CondenseSequences(root); StackVarsProcessor stackProc = new StackVarsProcessor(); do { stackProc.SimplifyStackVars(root, mt, cl); varProc.SetVarVersions(root); }while (new PPandMMHelper().FindPPandMM(root)); while (true) { LabelHelper.CleanUpEdges(root); do { MergeHelper.EnhanceLoops(root); }while (LoopExtractHelper.ExtractLoops(root) || IfHelper.MergeAllIfs(root)); if (DecompilerContext.GetOption(IFernflowerPreferences.Idea_Not_Null_Annotation)) { if (IdeaNotNullHelper.RemoveHardcodedChecks(root, mt)) { SequenceHelper.CondenseSequences(root); stackProc.SimplifyStackVars(root, mt, cl); varProc.SetVarVersions(root); } } LabelHelper.IdentifyLabels(root); if (InlineSingleBlockHelper.InlineSingleBlocks(root)) { continue; } // initializer may have at most one return point, so no transformation of method exits permitted if (isInitializer || !ExitHelper.CondenseExits(root)) { break; } } // FIXME: !! //if(!EliminateLoopsHelper.eliminateLoops(root)) { // break; //} ExitHelper.RemoveRedundantReturns(root); SecondaryFunctionsHelper.IdentifySecondaryFunctions(root, varProc); varProc.SetVarDefinitions(root); // must be the last invocation, because it makes the statement structure inconsistent // FIXME: new edge type needed LabelHelper.ReplaceContinueWithBreak(root); mt.ReleaseResources(); return(root); }