/// <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"); }
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; }
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"); }
/// <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 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; }