/// <summary> /// Gets a string representation of the instruction block offset that this CFG block logical construct node represents. /// </summary> /// <remarks> /// If the <paramref name="node"/> is partial CFG block logical construct then the string representing its offset is: /// "{offset of the instruction block}_{partial construct index}" /// Where the partial construct index is the index of the partial construct in the <paramref name="context"/>.CFGBlockToLogicalConstructMap. /// </remarks> /// <param name="context"></param> /// <param name="node"></param> /// <returns></returns> protected string NodeILOffset(LogicalFlowBuilderContext context, CFGBlockLogicalConstruct node) { if (node == null) { return("null"); } //If the CFG construct is a partial block, the offset is: "blockOffset_indexOfPartialBlock" PartialCFGBlockLogicalConstruct partialNode = node as PartialCFGBlockLogicalConstruct; if (partialNode != null) { int indexOfPartialConstruct = Array.IndexOf(context.CFGBlockToLogicalConstructMap[partialNode.TheBlock], partialNode); if (indexOfPartialConstruct == -1) { //sanity check throw new Exception("Invalid partial block data."); } return(string.Format("IL_{0}_{1}", partialNode.TheBlock.First.Offset.ToString("x4"), indexOfPartialConstruct)); } else { return(string.Format("IL_{0}", node.TheBlock.First.Offset.ToString("x4"))); } }
public YieldGuardedBlocksBuilder(LogicalFlowBuilderContext logicalContext, DecompilationContext decompilationContext) { this.orderedCFGNodes = new List <CFGBlockLogicalConstruct>(); this.createdConstructsToIntervalMap = new Dictionary <TryFinallyLogicalConstruct, YieldExceptionHandlerInfo>(); base(); this.logicalContext = logicalContext; this.methodContext = decompilationContext.get_MethodContext(); return; }
internal MethodSpecificContext(DecompilationAnalysisResults analysisResults, YieldData yieldData, AsyncData asyncData, bool isMethodBodyChanged, Dictionary<string, Statement> gotoLabels, List<GotoStatement> gotoStatements, StackUsageData stackData, bool isBaseConstructorInvokingConstructor, bool enableEventAnalysis, MethodBody body, Collection<VariableDefinition> variables, ControlFlowGraph controlFlowGraph, ExpressionDecompilerData expressions, BlockLogicalConstruct logicalConstructsTree, LogicalFlowBuilderContext logicalConstructsContext, MethodInvocationExpression ctorInvokeExpression, Dictionary<Statement, ILogicalConstruct> statementToLogicalConstruct, Dictionary<ILogicalConstruct, List<Statement>> logicalConstructToStatements, Dictionary<VariableDefinition, string> variableDefinitionToNameMap, HashSet<string> variableNamesCollection, Dictionary<ParameterDefinition, string> parameterDefinitionToNameMap, HashSet<VariableDefinition> variablesToRename, Dictionary<FieldDefinition, Expression> fieldToExpression, int lambdaVariablesCount, Dictionary<VariableDefinition, AssignmentType> variableAssignmentData, List<ParameterDefinition> outParametersToAssign, bool isDestructor, BlockStatement destructorStatements, HashSet<VariableDefinition> undeclaredLinqVariables, Dictionary<VariableReference, Dictionary<FieldDefinition, Expression>> closureVariableToFieldValue, HashSet<VariableDefinition> variablesToNotDeclare) { this.AnalysisResults = analysisResults; this.YieldData = yieldData; this.AsyncData = asyncData; this.IsMethodBodyChanged = isMethodBodyChanged; this.GotoLabels = gotoLabels; this.GotoStatements = gotoStatements; this.StackData = stackData; this.IsBaseConstructorInvokingConstructor = isBaseConstructorInvokingConstructor; this.EnableEventAnalysis = enableEventAnalysis; this.Body = body; this.Variables = variables; this.ControlFlowGraph = controlFlowGraph; this.Expressions = expressions; this.LogicalConstructsTree = logicalConstructsTree; this.LogicalConstructsContext = logicalConstructsContext; this.CtorInvokeExpression = ctorInvokeExpression; this.StatementToLogicalConstruct = statementToLogicalConstruct; this.LogicalConstructToStatements = logicalConstructToStatements; this.VariableDefinitionToNameMap = variableDefinitionToNameMap; this.VariableNamesCollection = variableNamesCollection; this.ParameterDefinitionToNameMap = parameterDefinitionToNameMap; this.VariablesToRename = variablesToRename; this.FieldToExpression = fieldToExpression; this.LambdaVariablesCount = lambdaVariablesCount; this.VariableAssignmentData = variableAssignmentData; this.OutParametersToAssign = outParametersToAssign; this.IsDestructor = isDestructor; this.DestructorStatements = destructorStatements; this.UndeclaredLinqVariables = undeclaredLinqVariables; this.ClosureVariableToFieldValue = closureVariableToFieldValue; this.VariablesToNotDeclare = variablesToNotDeclare; }
public BlockStatement Process(DecompilationContext context, BlockStatement body) { this.methodContext = context.get_MethodContext(); V_0 = context.get_MethodContext().get_Method().get_Module().get_TypeSystem(); this.logicalBuilderContext = new LogicalFlowBuilderContext(context.get_MethodContext().get_ControlFlowGraph()); this.cfgBlockSplitter = new CFGBlockSplitter(this.logicalBuilderContext); this.conditionBuilder = new ConditionBuilder(this.logicalBuilderContext, V_0); this.loopBuilder = new LoopBuilder(this.logicalBuilderContext, V_0); this.switchBuilder = new SwitchBuilder(this.logicalBuilderContext); this.ifBuilder = new IfBuilder(this.logicalBuilderContext, this.methodContext.get_Method().get_Module().get_TypeSystem()); this.followNodeDeterminator = new FollowNodeDeterminator(V_0); this.yieldGuardedBlocksBuilder = new YieldGuardedBlocksBuilder(this.logicalBuilderContext, context); this.GetMaxIndexOfBlock(); this.InitializeTheBlock(); this.guardedBlocksBuilder = new GuardedBlocksBuilder(this.logicalBuilderContext); context.get_MethodContext().set_LogicalConstructsTree(this.BuildLogicalConstructTree()); context.get_MethodContext().set_LogicalConstructsContext(this.logicalBuilderContext); return(body); }
protected string NodeILOffset(LogicalFlowBuilderContext context, CFGBlockLogicalConstruct node) { if (node == null) { return("null"); } V_0 = node as PartialCFGBlockLogicalConstruct; if (V_0 == null) { V_2 = node.get_TheBlock().get_First().get_Offset(); return(String.Format("IL_{0}", V_2.ToString("x4"))); } V_1 = Array.IndexOf <CFGBlockLogicalConstruct>(context.get_CFGBlockToLogicalConstructMap().get_Item(V_0.get_TheBlock()), V_0); if (V_1 == -1) { throw new Exception("Invalid partial block data."); } V_2 = V_0.get_TheBlock().get_First().get_Offset(); return(String.Format("IL_{0}_{1}", V_2.ToString("x4"), V_1)); }
public BlockStatement Process(DecompilationContext context, BlockStatement body) { this.methodContext = context.MethodContext; TypeSystem typeSystem = context.MethodContext.Method.Module.TypeSystem; logicalBuilderContext = new LogicalFlowBuilderContext(context.MethodContext.ControlFlowGraph); cfgBlockSplitter = new CFGBlockSplitter(logicalBuilderContext); conditionBuilder = new ConditionBuilder(logicalBuilderContext, typeSystem); loopBuilder = new LoopBuilder(logicalBuilderContext, typeSystem); switchBuilder = new SwitchBuilder(logicalBuilderContext); ifBuilder = new IfBuilder(logicalBuilderContext, methodContext.Method.Module.TypeSystem); followNodeDeterminator = new FollowNodeDeterminator(typeSystem); yieldGuardedBlocksBuilder = new YieldGuardedBlocksBuilder(logicalBuilderContext, context); GetMaxIndexOfBlock(); InitializeTheBlock(); guardedBlocksBuilder = new GuardedBlocksBuilder(logicalBuilderContext); context.MethodContext.LogicalConstructsTree = BuildLogicalConstructTree(); context.MethodContext.LogicalConstructsContext = logicalBuilderContext; return(body); }
public BlockStatement Process(DecompilationContext context, BlockStatement body) { this.methodContext = context.MethodContext; TypeSystem typeSystem = context.MethodContext.Method.Module.TypeSystem; logicalBuilderContext = new LogicalFlowBuilderContext(context.MethodContext.ControlFlowGraph); cfgBlockSplitter = new CFGBlockSplitter(logicalBuilderContext); conditionBuilder = new ConditionBuilder(logicalBuilderContext, typeSystem); loopBuilder = new LoopBuilder(logicalBuilderContext, typeSystem); switchBuilder = new SwitchBuilder(logicalBuilderContext); ifBuilder = new IfBuilder(logicalBuilderContext, methodContext.Method.Module.TypeSystem); followNodeDeterminator = new FollowNodeDeterminator(typeSystem); yieldGuardedBlocksBuilder = new YieldGuardedBlocksBuilder(logicalBuilderContext, context); GetMaxIndexOfBlock(); InitializeTheBlock(); guardedBlocksBuilder = new GuardedBlocksBuilder(logicalBuilderContext); context.MethodContext.LogicalConstructsTree = BuildLogicalConstructTree(); context.MethodContext.LogicalConstructsContext = logicalBuilderContext; return body; }
protected override string ToString(string constructName, HashSet<CFGBlockLogicalConstruct> printedBlocks, LogicalFlowBuilderContext context) { StringBuilder sb = new StringBuilder(); sb.AppendLine("PartialCFGConstruct"); sb.AppendLine("{"); sb.AppendLine(string.Format("\t{0}:", NodeILOffset(context, this))); foreach (Telerik.JustDecompiler.Ast.Expressions.Expression expression in LogicalConstructExpressions) { sb.Append("\t"); sb.AppendLine(expression.ToCodeString()); } string followNodeString = string.Format("\tFollowNode: {0}", NodeILOffset(context, CFGFollowNode)); sb.AppendLine(followNodeString); sb.AppendLine("}"); printedBlocks.Add(this); return sb.ToString(); }
protected override string ToString(string constructName, HashSet <CFGBlockLogicalConstruct> printedBlocks, LogicalFlowBuilderContext context) { V_0 = new StringBuilder(); dummyVar0 = V_0.AppendLine(this.GetType().get_Name()); dummyVar1 = V_0.AppendLine("{"); V_1 = this.get_TheBlock().get_First(); while ((object)V_1 != (object)this.get_TheBlock().get_Last()) { dummyVar2 = V_0.AppendLine(String.Format("\t{0}", V_1.ToString())); V_1 = V_1.get_Next(); } dummyVar3 = V_0.AppendLine(String.Format("\t{0}", V_1.ToString())); V_2 = String.Format("\tFollowNode: {0}", this.NodeILOffset(context, this.get_CFGFollowNode())); dummyVar4 = V_0.AppendLine(V_2); dummyVar5 = V_0.AppendLine("}"); dummyVar6 = printedBlocks.Add(this); return(V_0.ToString()); }
protected DominatorTreeDependentStep(LogicalFlowBuilderContext context) { this.logicalContext = context; }
public CFGBlockSplitter(LogicalFlowBuilderContext logicalContext) { base(); this.logicalContext = logicalContext; return; }
public CFGBlockSplitter(LogicalFlowBuilderContext logicalContext) { this.logicalContext = logicalContext; }
public YieldGuardedBlocksBuilder(LogicalFlowBuilderContext logicalContext, DecompilationContext decompilationContext) { this.logicalContext = logicalContext; this.methodContext = decompilationContext.MethodContext; }
public static KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> SplitCFGBlockAt(LogicalFlowBuilderContext logicalContext, CFGBlockLogicalConstruct cfgBlock, int expressionIndex) { V_0 = cfgBlock.get_LogicalConstructExpressions(); if (V_0 == null) { throw new ArgumentNullException("blockExpressions"); } if (expressionIndex <= 0 || expressionIndex >= V_0.get_Count()) { throw new ArgumentOutOfRangeException("expressionIndex"); } V_1 = logicalContext.get_CFGBlockToLogicalConstructMap().get_Item(cfgBlock.get_TheBlock()); V_2 = (int)V_1.Length; V_3 = 0; while (V_3 < V_2 && cfgBlock != V_1[V_3]) { V_3 = V_3 + 1; } if (V_3 == V_2) { throw new ArgumentException("cfgBlock"); } V_4 = cfgBlock.get_LogicalConstructExpressions().GetRange(0, expressionIndex); V_5 = new PartialCFGBlockLogicalConstruct(cfgBlock, V_4); V_5.RedirectPredecessors(); V_6 = cfgBlock.get_LogicalConstructExpressions().GetRange(expressionIndex, V_0.get_Count() - expressionIndex); V_7 = new PartialCFGBlockLogicalConstruct(cfgBlock, V_6); V_7.RedirectSuccessors(); V_5.AddToSuccessors(V_7); V_7.AddToPredecessors(V_5); V_8 = new CFGBlockLogicalConstruct[V_2 + 1]; V_9 = 0; V_10 = 0; while (V_9 < V_2) { if (V_9 == V_3) { V_8[V_10] = V_5; stackVariable68 = V_10 + 1; V_10 = stackVariable68; V_8[stackVariable68] = V_7; } else { V_8[V_10] = V_1[V_9]; } V_9 = V_9 + 1; V_10 = V_10 + 1; } logicalContext.get_CFGBlockToLogicalConstructMap().set_Item(cfgBlock.get_TheBlock(), V_8); return(new KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct>(V_5, V_7)); }
public virtual string ToString(LogicalFlowBuilderContext context) { return(this.ToString(this.GetType().get_Name(), new HashSet <CFGBlockLogicalConstruct>(), context)); }
protected override string ToString(string constructName, HashSet <CFGBlockLogicalConstruct> printedBlocks, LogicalFlowBuilderContext context) { StringBuilder sb = new StringBuilder(); sb.AppendLine("PartialCFGConstruct"); sb.AppendLine("{"); sb.AppendLine(string.Format("\t{0}:", NodeILOffset(context, this))); foreach (Telerik.JustDecompiler.Ast.Expressions.Expression expression in LogicalConstructExpressions) { sb.Append("\t"); sb.AppendLine(expression.ToCodeString()); } string followNodeString = string.Format("\tFollowNode: {0}", NodeILOffset(context, CFGFollowNode)); sb.AppendLine(followNodeString); sb.AppendLine("}"); printedBlocks.Add(this); return(sb.ToString()); }
protected override string ToString(string constructName, HashSet <CFGBlockLogicalConstruct> printedBlocks, LogicalFlowBuilderContext context) { V_0 = new StringBuilder(); dummyVar0 = V_0.AppendLine("PartialCFGConstruct"); dummyVar1 = V_0.AppendLine("{"); dummyVar2 = V_0.AppendLine(String.Format("\t{0}:", this.NodeILOffset(context, this))); V_2 = this.get_LogicalConstructExpressions().GetEnumerator(); try { while (V_2.MoveNext()) { V_3 = V_2.get_Current(); dummyVar3 = V_0.Append("\t"); dummyVar4 = V_0.AppendLine(V_3.ToCodeString()); } } finally { ((IDisposable)V_2).Dispose(); } V_1 = String.Format("\tFollowNode: {0}", this.NodeILOffset(context, this.get_CFGFollowNode())); dummyVar5 = V_0.AppendLine(V_1); dummyVar6 = V_0.AppendLine("}"); dummyVar7 = printedBlocks.Add(this); return(V_0.ToString()); }
/// <summary> /// Splits the given CFG construct into two partial constructs. The first containing the expressions with indices 0 to expressionIndex - 1, the second - /// expressionIndex to end. This method modifies the logicalContext.CFGBlockToLogicalConstructMap /// </summary> /// <param name="logicalContext"></param> /// <param name="cfgBlock"></param> /// <param name="expressionIndex"></param> /// <returns>A key value pair containing the first partial construct as key and the second as value.</returns> public static KeyValuePair<CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> SplitCFGBlockAt(LogicalFlowBuilderContext logicalContext, CFGBlockLogicalConstruct cfgBlock, int expressionIndex) { List<Expression> blockExpressions = cfgBlock.LogicalConstructExpressions; if(blockExpressions == null) { throw new ArgumentNullException("blockExpressions"); } if(expressionIndex <= 0 || expressionIndex >= blockExpressions.Count) { throw new ArgumentOutOfRangeException("expressionIndex"); } CFGBlockLogicalConstruct[] instructionBlockConstructs = logicalContext.CFGBlockToLogicalConstructMap[cfgBlock.TheBlock]; int cfgBlockArrayLength = instructionBlockConstructs.Length; int cfgBlockIndex; for (cfgBlockIndex = 0; cfgBlockIndex < cfgBlockArrayLength; cfgBlockIndex++) { if(cfgBlock == instructionBlockConstructs[cfgBlockIndex]) { break; } } if(cfgBlockIndex == cfgBlockArrayLength) { throw new ArgumentException("cfgBlock"); } List<Expression> firstExpressionsList = cfgBlock.LogicalConstructExpressions.GetRange(0, expressionIndex); PartialCFGBlockLogicalConstruct firstPartial = new PartialCFGBlockLogicalConstruct(cfgBlock, firstExpressionsList); firstPartial.RedirectPredecessors(); List<Expression> secondExpressionsList = cfgBlock.LogicalConstructExpressions.GetRange(expressionIndex, blockExpressions.Count - expressionIndex); PartialCFGBlockLogicalConstruct secondPartial = new PartialCFGBlockLogicalConstruct(cfgBlock, secondExpressionsList); secondPartial.RedirectSuccessors(); firstPartial.AddToSuccessors(secondPartial); secondPartial.AddToPredecessors(firstPartial); CFGBlockLogicalConstruct[] updatedCollection = new CFGBlockLogicalConstruct[cfgBlockArrayLength + 1]; for (int i = 0, j = 0; i < cfgBlockArrayLength; i++, j++) { if (i != cfgBlockIndex) { updatedCollection[j] = instructionBlockConstructs[i]; } else { updatedCollection[j] = firstPartial; updatedCollection[++j] = secondPartial; } } logicalContext.CFGBlockToLogicalConstructMap[cfgBlock.TheBlock] = updatedCollection; return new KeyValuePair<CFGBlockLogicalConstruct, CFGBlockLogicalConstruct>(firstPartial, secondPartial); }
/// <summary> /// Splits the given CFG construct into two partial constructs. The first containing the expressions with indices 0 to expressionIndex - 1, the second - /// expressionIndex to end. This method modifies the logicalContext.CFGBlockToLogicalConstructMap /// </summary> /// <param name="logicalContext"></param> /// <param name="cfgBlock"></param> /// <param name="expressionIndex"></param> /// <returns>A key value pair containing the first partial construct as key and the second as value.</returns> public static KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> SplitCFGBlockAt(LogicalFlowBuilderContext logicalContext, CFGBlockLogicalConstruct cfgBlock, int expressionIndex) { List <Expression> blockExpressions = cfgBlock.LogicalConstructExpressions; if (blockExpressions == null) { throw new ArgumentNullException("blockExpressions"); } if (expressionIndex <= 0 || expressionIndex >= blockExpressions.Count) { throw new ArgumentOutOfRangeException("expressionIndex"); } CFGBlockLogicalConstruct[] instructionBlockConstructs = logicalContext.CFGBlockToLogicalConstructMap[cfgBlock.TheBlock]; int cfgBlockArrayLength = instructionBlockConstructs.Length; int cfgBlockIndex; for (cfgBlockIndex = 0; cfgBlockIndex < cfgBlockArrayLength; cfgBlockIndex++) { if (cfgBlock == instructionBlockConstructs[cfgBlockIndex]) { break; } } if (cfgBlockIndex == cfgBlockArrayLength) { throw new ArgumentException("cfgBlock"); } List <Expression> firstExpressionsList = cfgBlock.LogicalConstructExpressions.GetRange(0, expressionIndex); PartialCFGBlockLogicalConstruct firstPartial = new PartialCFGBlockLogicalConstruct(cfgBlock, firstExpressionsList); firstPartial.RedirectPredecessors(); List <Expression> secondExpressionsList = cfgBlock.LogicalConstructExpressions.GetRange(expressionIndex, blockExpressions.Count - expressionIndex); PartialCFGBlockLogicalConstruct secondPartial = new PartialCFGBlockLogicalConstruct(cfgBlock, secondExpressionsList); secondPartial.RedirectSuccessors(); firstPartial.AddToSuccessors(secondPartial); secondPartial.AddToPredecessors(firstPartial); CFGBlockLogicalConstruct[] updatedCollection = new CFGBlockLogicalConstruct[cfgBlockArrayLength + 1]; for (int i = 0, j = 0; i < cfgBlockArrayLength; i++, j++) { if (i != cfgBlockIndex) { updatedCollection[j] = instructionBlockConstructs[i]; } else { updatedCollection[j] = firstPartial; updatedCollection[++j] = secondPartial; } } logicalContext.CFGBlockToLogicalConstructMap[cfgBlock.TheBlock] = updatedCollection; return(new KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct>(firstPartial, secondPartial)); }
protected DominatorTreeDependentStep(LogicalFlowBuilderContext context) { base(); this.logicalContext = context; return; }
protected virtual string ToString(string constructName, HashSet <CFGBlockLogicalConstruct> printedCFGBlocks, LogicalFlowBuilderContext context) { V_0 = new StringBuilder(); dummyVar0 = V_0.AppendLine(constructName); dummyVar1 = V_0.AppendLine("{"); V_1 = this.GetSortedArrayFromCollection <CFGBlockLogicalConstruct>(this.get_CFGBlocks()); V_2 = new Stack <CFGBlockLogicalConstruct>(); V_4 = 0; while (V_4 < (int)V_1.Length) { V_5 = V_1[V_4] as CFGBlockLogicalConstruct; if (!printedCFGBlocks.Contains(V_5)) { V_2.Push(V_5); while (V_2.get_Count() > 0) { V_6 = V_2.Pop(); if (printedCFGBlocks.Contains(V_6) || !LogicalFlowUtilities.TryGetParentConstructWithGivenParent(V_6, this, out V_7)) { continue; } stackVariable48 = ((LogicalConstructBase)V_7).ToString(V_7.GetType().get_Name(), printedCFGBlocks, context); stackVariable50 = new String[1]; stackVariable50[0] = Environment.get_NewLine(); V_9 = stackVariable48.Split(stackVariable50, 1); V_10 = 0; while (V_10 < (int)V_9.Length) { V_11 = V_9[V_10]; dummyVar2 = V_0.AppendLine(String.Format("\t{0}", V_11)); V_10 = V_10 + 1; } V_8 = this.GetSortedArrayFromCollection <ISingleEntrySubGraph>(V_7.get_SameParentSuccessors()); V_12 = (int)V_8.Length - 1; while (V_12 >= 0) { if (!printedCFGBlocks.Contains(V_8[V_12].get_FirstBlock())) { V_2.Push(V_8[V_12].get_FirstBlock()); } V_12 = V_12 - 1; } } } V_4 = V_4 + 1; } V_3 = String.Format("\tFollowNode: {0}", this.NodeILOffset(context, this.get_CFGFollowNode())); dummyVar3 = V_0.AppendLine(V_3); dummyVar4 = V_0.AppendLine("}"); return(V_0.ToString()); }
/// <summary> /// Gets a string representation of this logical construct. /// </summary> /// <remarks> /// Used for testing purposes. /// </remarks> /// <param name="constructName">The name of the construct.</param> /// <param name="printedCFGBlocks">A set containing all of the CFG block logical constructs that are already traversed.</param> /// <param name="context">The current logical flow builder context.</param> /// <returns></returns> protected virtual string ToString(string constructName, HashSet <CFGBlockLogicalConstruct> printedCFGBlocks, LogicalFlowBuilderContext context) { StringBuilder sb = new StringBuilder(); sb.AppendLine(constructName); sb.AppendLine("{"); ILogicalConstruct[] cfgBlocksArray = GetSortedArrayFromCollection(this.CFGBlocks); Stack <CFGBlockLogicalConstruct> printingStack = new Stack <CFGBlockLogicalConstruct>(); for (int i = 0; i < cfgBlocksArray.Length; i++) { CFGBlockLogicalConstruct currentCFGBlock = cfgBlocksArray[i] as CFGBlockLogicalConstruct; //If the current node is already printed we skip it. if (printedCFGBlocks.Contains(currentCFGBlock)) { continue; } //We use a stack to print the constructs in preorder. printingStack.Push(currentCFGBlock); while (printingStack.Count > 0) { CFGBlockLogicalConstruct blockToPrint = printingStack.Pop(); if (printedCFGBlocks.Contains(blockToPrint)) { continue; } //Foreach CFG construct that is not printed we get the parent (not necessarily direct) logical construct that is child of this construct //(i.e. childConstructToPrint is the child of this construct that contains the blockToPrint). ILogicalConstruct childConstructToPrint; if (!LogicalFlowUtilities.TryGetParentConstructWithGivenParent(blockToPrint, this, out childConstructToPrint)) { continue; } string childString = ((LogicalConstructBase)childConstructToPrint).ToString(childConstructToPrint.GetType().Name, printedCFGBlocks, context); //Indent each line of child's strings by one tab, so that they appear visually better string[] childStringLines = childString.Split(new String[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in childStringLines) { sb.AppendLine(string.Format("\t{0}", line)); } //We get a sorted array ot the child's same parent successors and we push their CFG logical construct entries in reverse order on the //printing stack, so that the closest successor is going to be printed next. ILogicalConstruct[] sameParentSuccessors = GetSortedArrayFromCollection(childConstructToPrint.SameParentSuccessors); for (int j = sameParentSuccessors.Length - 1; j >= 0; j--) { if (!printedCFGBlocks.Contains(sameParentSuccessors[j].FirstBlock)) { printingStack.Push(sameParentSuccessors[j].FirstBlock); } } } } string followNodeString = string.Format("\tFollowNode: {0}", NodeILOffset(context, CFGFollowNode)); sb.AppendLine(followNodeString); sb.AppendLine("}"); return(sb.ToString()); }
protected override string ToString(string constructName, HashSet <CFGBlockLogicalConstruct> printedBlocks, LogicalFlowBuilderContext context) { StringBuilder sb = new StringBuilder(); sb.AppendLine(this.GetType().Name); sb.AppendLine("{"); Instruction currentInstruction = TheBlock.First; while (currentInstruction != TheBlock.Last) { sb.AppendLine(string.Format("\t{0}", currentInstruction.ToString())); currentInstruction = currentInstruction.Next; } sb.AppendLine(string.Format("\t{0}", currentInstruction.ToString())); string followNodeString = string.Format("\tFollowNode: {0}", NodeILOffset(context, CFGFollowNode)); sb.AppendLine(followNodeString); sb.AppendLine("}"); printedBlocks.Add(this); return(sb.ToString()); }