public void SplitConditionalCFGBlocks() { V_0 = (new List <KeyValuePair <InstructionBlock, CFGBlockLogicalConstruct[]> >(this.logicalContext.get_CFGBlockToLogicalConstructMap())).GetEnumerator(); try { while (V_0.MoveNext()) { V_1 = V_0.get_Current(); if ((int)V_1.get_Key().get_Successors().Length <= 1) { continue; } V_2 = V_1.get_Value()[(int)V_1.get_Value().Length - 1]; if (V_2.get_LogicalConstructExpressions().get_Count() <= 1) { continue; } dummyVar0 = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_2, V_2.get_LogicalConstructExpressions().get_Count() - 1); } } finally { ((IDisposable)V_0).Dispose(); } return; }
/// <summary> /// Gets the first found entry CFGBlockLogicalConstruct for a state from the tryStates. /// </summary> /// <remarks> /// We try to get the first CFGBlockLC, that is going to be reached by the control flow, in which the state field is assigned to a state of the /// <paramref name="tryStates"/>. If the assignment is not at the begining of the CFGConstruct then we need to split it, since the try begins /// at the assignment. /// </remarks> /// <param name="tryStates"></param> /// <returns></returns> private CFGBlockLogicalConstruct GetStateBeginBlockConstruct(HashSet <int> tryStates) { for (int i = 0; i < this.orderedCFGNodes.Count; i++) { CFGBlockLogicalConstruct currentCFGConstruct = this.orderedCFGNodes[i]; List <Expression> blockExpressions = currentCFGConstruct.LogicalConstructExpressions; for (int j = 0; j < blockExpressions.Count; j++) { int value; if (TryGetStateAssignValue(blockExpressions[j], out value) && tryStates.Contains(value)) { if (j != 0) { KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> newCFGConstructsPair = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, currentCFGConstruct, j); this.orderedCFGNodes[i] = newCFGConstructsPair.Key; this.orderedCFGNodes.Insert(i + 1, newCFGConstructsPair.Value); return(newCFGConstructsPair.Value); } else { return(currentCFGConstruct); } } } } throw new Exception("Invalid state value"); }
private CFGBlockLogicalConstruct GetStateBeginBlockConstruct(HashSet <int> tryStates) { V_0 = 0; while (V_0 < this.orderedCFGNodes.get_Count()) { V_1 = this.orderedCFGNodes.get_Item(V_0); V_2 = V_1.get_LogicalConstructExpressions(); V_3 = 0; while (V_3 < V_2.get_Count()) { if (this.TryGetStateAssignValue(V_2.get_Item(V_3), out V_4) && tryStates.Contains(V_4)) { if (V_3 == 0) { return(V_1); } V_5 = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_1, V_3); this.orderedCFGNodes.set_Item(V_0, V_5.get_Key()); this.orderedCFGNodes.Insert(V_0 + 1, V_5.get_Value()); return(V_5.get_Value()); } V_3 = V_3 + 1; } V_0 = V_0 + 1; } throw new Exception("Invalid state value"); }
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> /// Splits each CFG construct that has more than one successor (i.e. condition block) and holds more than one expression. /// </summary> public void SplitConditionalCFGBlocks() { //We need to copy the dictionary, since the LogicalFlowUtilities.SplitCFGBlockAt method modifies it (and the enumerator explodes). //Also we copy it in a list, since we don't need the functionality of the dictionary. List <KeyValuePair <InstructionBlock, CFGBlockLogicalConstruct[]> > blockToConstructsPairList = new List <KeyValuePair <InstructionBlock, CFGBlockLogicalConstruct[]> >(logicalContext.CFGBlockToLogicalConstructMap); foreach (KeyValuePair <InstructionBlock, CFGBlockLogicalConstruct[]> blockToConstructsPair in blockToConstructsPairList) { if (blockToConstructsPair.Key.Successors.Length > 1) { //For each instruction block there can be more than one partial CFG LC, so we take the last one, since it will hold the condition expression. CFGBlockLogicalConstruct cfgConstruct = blockToConstructsPair.Value[blockToConstructsPair.Value.Length - 1]; if (cfgConstruct.LogicalConstructExpressions.Count > 1) { //If the last construct for this block holds more than one expression we split it at the last expression. LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, cfgConstruct, cfgConstruct.LogicalConstructExpressions.Count - 1); } } } }
/// <summary> /// Checks each a node before adding its successors to the <paramref name="bfsQueue"/>. /// </summary> /// <remarks> /// If the node is a CFGBlockLC and it contains the invocation of the finally method, or the entry of the finally block, /// then we should not continue the traversal. /// </remarks> /// <param name="handlerInfo"></param> /// <param name="bfsQueue"></param> /// <param name="currentNode"></param> private void ProcessCurrentNode(YieldExceptionHandlerInfo handlerInfo, Queue <ILogicalConstruct> bfsQueue, ILogicalConstruct currentNode) { if (currentNode is CFGBlockLogicalConstruct) { CFGBlockLogicalConstruct currentCFGNode = currentNode as CFGBlockLogicalConstruct; for (int i = 0; i < currentCFGNode.LogicalConstructExpressions.Count; i++) { Expression currentExpression = currentCFGNode.LogicalConstructExpressions[i]; int value; if (TryGetStateAssignValue(currentExpression, out value)) { if (!handlerInfo.TryStates.Contains(value)) //sanity check { if (handlerInfo.HandlerType != YieldExceptionHandlerType.Method && TryProcessConditionalDisposeHandler(handlerInfo, currentCFGNode)) { return; } throw new Exception("Invalid state value"); } } else if (handlerInfo.HandlerType == YieldExceptionHandlerType.Method && currentExpression.CodeNodeType == CodeNodeType.MethodInvocationExpression && (currentExpression as MethodInvocationExpression).MethodExpression.MethodDefinition == handlerInfo.FinallyMethodDefinition) { //For the finally block we need the CFGBlockLC that contains only the invocation of the finally method. //That's why we need to split the CFGBlockLC, if there are other expressions besides the invocation. CFGBlockLogicalConstruct currentFinallyBlock; if (currentCFGNode.LogicalConstructExpressions.Count == 1) { if (newFinallyBody == null) { newFinallyBody = currentCFGNode; } finallyBlocks.Add(newFinallyBody); orderedCFGNodes.Remove(currentCFGNode); return; } if (i == 0) { KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> newConstructsPair = LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i + 1); currentFinallyBlock = newConstructsPair.Key; orderedCFGNodes[orderedCFGNodes.IndexOf(currentCFGNode)] = newConstructsPair.Value; } else if (i < currentCFGNode.LogicalConstructExpressions.Count - 1) { KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> endOfTryPair = LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i); newTryBody.Add(endOfTryPair.Key); KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> finallyRestOfBlockPair = LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, endOfTryPair.Value, 1); currentFinallyBlock = finallyRestOfBlockPair.Key; orderedCFGNodes[orderedCFGNodes.IndexOf(currentCFGNode)] = finallyRestOfBlockPair.Value; } else // i == count - 1 { KeyValuePair <CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> tryFinallyPair = LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i); newTryBody.Add(tryFinallyPair.Key); currentFinallyBlock = tryFinallyPair.Value; orderedCFGNodes.Remove(currentCFGNode); } if (newFinallyBody == null) { newFinallyBody = currentFinallyBlock; } finallyBlocks.Add(currentFinallyBlock); return; } } } else if (currentNode is TryFinallyLogicalConstruct) { TryFinallyLogicalConstruct tryFinallyConstruct = currentNode as TryFinallyLogicalConstruct; YieldExceptionHandlerInfo oldHandlerInfo; if (createdConstructsToIntervalMap.TryGetValue(tryFinallyConstruct, out oldHandlerInfo) && oldHandlerInfo.TryStates.IsProperSupersetOf(handlerInfo.TryStates)) { throw new Exception("This try/finally construct cannot be nested in the current construct"); } } newTryBody.Add(currentNode); foreach (ILogicalConstruct successor in currentNode.SameParentSuccessors) { bfsQueue.Enqueue(successor); } }
private bool HasForParent(ILogicalConstruct supposedParent) { return(LogicalFlowUtilities.TryGetParentConstructWithGivenParent(this, supposedParent, out V_0)); }
/// <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()); }
private void ProcessCurrentNode(YieldExceptionHandlerInfo handlerInfo, Queue <ILogicalConstruct> bfsQueue, ILogicalConstruct currentNode) { if (currentNode as CFGBlockLogicalConstruct == null) { if (currentNode as TryFinallyLogicalConstruct != null && this.createdConstructsToIntervalMap.TryGetValue(currentNode as TryFinallyLogicalConstruct, out V_10) && V_10.get_TryStates().IsProperSupersetOf(handlerInfo.get_TryStates())) { throw new Exception("This try/finally construct cannot be nested in the current construct"); } } else { V_0 = currentNode as CFGBlockLogicalConstruct; V_1 = 0; while (V_1 < V_0.get_LogicalConstructExpressions().get_Count()) { V_2 = V_0.get_LogicalConstructExpressions().get_Item(V_1); if (!this.TryGetStateAssignValue(V_2, out V_3)) { if (handlerInfo.get_HandlerType() == YieldExceptionHandlerType.Method && V_2.get_CodeNodeType() == 19 && (object)(V_2 as MethodInvocationExpression).get_MethodExpression().get_MethodDefinition() == (object)handlerInfo.get_FinallyMethodDefinition()) { if (V_0.get_LogicalConstructExpressions().get_Count() == 1) { if (this.newFinallyBody == null) { this.newFinallyBody = V_0; } dummyVar0 = this.finallyBlocks.Add(this.newFinallyBody); dummyVar1 = this.orderedCFGNodes.Remove(V_0); return; } if (V_1 != 0) { if (V_1 >= V_0.get_LogicalConstructExpressions().get_Count() - 1) { V_8 = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_0, V_1); dummyVar3 = this.newTryBody.Add(V_8.get_Key()); V_4 = V_8.get_Value(); dummyVar4 = this.orderedCFGNodes.Remove(V_0); } else { V_6 = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_0, V_1); dummyVar2 = this.newTryBody.Add(V_6.get_Key()); V_7 = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_6.get_Value(), 1); V_4 = V_7.get_Key(); this.orderedCFGNodes.set_Item(this.orderedCFGNodes.IndexOf(V_0), V_7.get_Value()); } } else { V_5 = LogicalFlowUtilities.SplitCFGBlockAt(this.logicalContext, V_0, V_1 + 1); V_4 = V_5.get_Key(); this.orderedCFGNodes.set_Item(this.orderedCFGNodes.IndexOf(V_0), V_5.get_Value()); } if (this.newFinallyBody == null) { this.newFinallyBody = V_4; } dummyVar5 = this.finallyBlocks.Add(V_4); return; } } else { if (!handlerInfo.get_TryStates().Contains(V_3)) { if (handlerInfo.get_HandlerType() == YieldExceptionHandlerType.Method || !this.TryProcessConditionalDisposeHandler(handlerInfo, V_0)) { throw new Exception("Invalid state value"); } return; } } V_1 = V_1 + 1; } } dummyVar6 = this.newTryBody.Add(currentNode); V_11 = currentNode.get_SameParentSuccessors().GetEnumerator(); try { while (V_11.MoveNext()) { V_12 = (ILogicalConstruct)V_11.get_Current(); bfsQueue.Enqueue(V_12); } } finally { ((IDisposable)V_11).Dispose(); } return; }