/// <summary> /// Connect outgoing condition less edges from parentBlock with belonging children point blocks /// </summary> /// <param name="parentBlock">Parent point block which children point blocks will be connected</param> /// <param name="pendingBlocks">Point blocks which children hasn't been processed yet</param> private void connectConditionLessEdges(PointsBlock parentBlock, Queue <PointsBlock> pendingBlocks) { foreach (var child in parentBlock.OutgoingBlocks) { connectConditionLessEdge(parentBlock, child, pendingBlocks); } }
/// <summary> /// Creates non-contractable points block for single program point /// </summary> /// <param name="createdPoint">Program points which block is created</param> /// <param name="outgoingBlocks">Outgoing edges from current block</param> /// <returns>Created block</returns> internal static PointsBlock ForPoint(ProgramPointBase createdPoint, IEnumerable <BasicBlock> outgoingBlocks) { var pointsBlock = new PointsBlock(outgoingBlocks, new BasicBlockEdge[0], null); pointsBlock._containedPoints.Add(createdPoint); pointsBlock._needsContraction = false; return(pointsBlock); }
/// <summary> /// Creates uncontractable points block from expression points /// </summary> /// <param name="expressionPoints">Points representing expression</param> /// <returns>Created block</returns> internal static PointsBlock ForExpression(IEnumerable <ProgramPointBase> expressionPoints) { //for expression there are no outgoing edges var pointsBlock = new PointsBlock(new BasicBlock[0], new BasicBlockEdge[0], null); pointsBlock._containedPoints.AddRange(expressionPoints); return(pointsBlock); }
/// <summary> /// Creates points block containing just given program point. /// <remarks>Created points block is not contractable</remarks> /// </summary> /// <param name="createdPoint">Program point that will be contained in created block.</param> /// <param name="outgoingBlocks">Blocks used as outcomming edges</param> /// <returns>Created points block</returns> private PointsBlock CreateBlockFromProgramPoint(ProgramPointBase newPoint, params BasicBlock[] outgoingBlocks) { reportCreation(newPoint); var createdBlock = PointsBlock.ForPoint(newPoint, outgoingBlocks); _createdBlocks.Add(createdBlock); return(createdBlock); }
/// <summary> /// Creates points block from statement points belonging to given block /// </summary> /// <param name="statementPoints">Statement points belonging to given block</param> /// <param name="block">Block which points block is created</param> /// <param name="needsContraction">Determine that given block will be contractable</param> /// <returns>Created block</returns> internal static PointsBlock ForBlock(IEnumerable <ProgramPointBase> statementPoints, BasicBlock block, bool needsContraction) { var defaultBlock = block.DefaultBranch == null ? null : block.DefaultBranch.To; var pointsBlock = new PointsBlock(new BasicBlock[0], block.OutgoingEdges, defaultBlock); pointsBlock._containedPoints.AddRange(statementPoints); pointsBlock._needsContraction = needsContraction; return(pointsBlock); }
/// <summary> /// Creates points block from given condition /// Points block will have single outgoing block as outcomming edge /// </summary> /// <param name="condition">Condition which points block is created</param> /// <param name="outgoingBlock">Block used as outcomming edge</param> /// <param name="expressionValues">Expression parts of assumed condition</param> /// <returns>Created points block</returns> internal PointsBlock CreateAssumeBlock(AssumptionCondition condition, BasicBlock outgoingBlock, params ValuePoint[] expressionValues) { var point = new AssumePoint(condition, expressionValues); reportCreation(point); var createdBlock = PointsBlock.ForPoint(point, new[] { outgoingBlock }); _createdBlocks.Add(createdBlock); return(createdBlock); }
/// <summary> /// Build graph from given starting block /// <remarks>Uses _context graph build</remarks> /// </summary> /// <param name="startBlock">Block containing graph Start point</param> private void buildGraph(PointsBlock startBlock) { //blocks that needs to handle children var pendingBlocks = new Queue <PointsBlock>(); pendingBlocks.Enqueue(startBlock); while (pendingBlocks.Count > 0) { var parentBlock = pendingBlocks.Dequeue(); //connect all its outgoing blocks (not condition edges) connectConditionLessEdges(parentBlock, pendingBlocks); //connect conditional edges (also with default branch) connectConditionEdges(parentBlock, pendingBlocks); } _context.ConnectBlocks(); }
/// <summary> /// Creates points block directly from basic block. It is checked that /// block is not empty, otherwise contractable block will be created /// </summary> /// <param name="block">Block witch statements fill created block</param> /// <returns>Created points block</returns> internal PointsBlock CreateFromBlock(BasicBlock block) { PointsBlock createdBlock; var points = expandStatements(block.Statements); if (points.Count > 0) { createdBlock = PointsBlock.ForBlock(points, block, false); } else { var empty = new EmptyProgramPoint(); reportCreation(empty); createdBlock = PointsBlock.ForBlock(new[] { empty }, block, true); } _createdBlocks.Add(createdBlock); _createdBasicBlocks.Add(block, createdBlock); return(createdBlock); }
/// <summary> /// Creates points block from given expression /// <remarks>It's supposed to be used as parent for assume block</remarks> /// </summary> /// <param name="expression">Expression which points block will be created</param> /// <returns>Created points block</returns> internal PointsBlock CreateFromExpression(Expression expression) { PointsBlock createdBlock; if (_creadtedExpressionBlocks.TryGetValue(expression, out createdBlock)) { return(createdBlock); } var points = ElementExpander.ExpandStatement(expression, reportCreation); if (points.Any()) { createdBlock = PointsBlock.ForExpression(points); _creadtedExpressionBlocks.Add(expression, createdBlock); _createdBlocks.Add(createdBlock); return(createdBlock); } else { throw new NotSupportedException("Empty expression is not supported"); } }
/// <summary> /// Connect outgoing condition edges from parentBlock with belonging children point blocks via assume blocks /// </summary> /// <param name="parentBlock">Parent point block which children point blocks will be connected</param> /// <param name="pendingBlocks">Point blocks which children hasn't been processed yet</param> private void connectConditionEdges(PointsBlock parentBlock, Queue <PointsBlock> pendingBlocks) { //collected expression values - because of sharing with default branch var expressionValues = new List <ValuePoint>(); //collected expression parts - because of default assumption condition creation var expressionParts = new List <Expression>(); //collected expression blocks - because of connecting default assumption var expressionBlocks = new List <PointsBlock>(); //process all outgoing conditional edges // For each conditional edge, create block and append it as a child of parrent block // TODO: in current CFG, there should be always at most one conditional edge foreach (var edge in parentBlock.ConditionalEdges) { Expression expression; if (edge.EdgeType == BasicBlockEdgeTypes.CONDITIONAL) { expression = edge.Condition; } else if (edge.EdgeType == BasicBlockEdgeTypes.FOREACH) { //now is foreach handled without condition processing (edge is added as non conditional) connectConditionLessEdge(parentBlock, edge.To, pendingBlocks); continue; } else { throw new NotSupportedException("Not supported CFG edge of type: " + edge.GetType()); } var conditionExpressionBlock = _context.CreateFromExpression(expression); var expressionValue = conditionExpressionBlock.LastPoint as ValuePoint; //collect info for default branch expressionValues.Add(expressionValue); expressionParts.Add(expression); expressionBlocks.Add(conditionExpressionBlock); var condition = new AssumptionCondition(ConditionForm.All, expression); parentBlock.AddChild(conditionExpressionBlock); //connect edge.To through assume block var assumeBlock = _context.CreateAssumeBlock(condition, edge.To, expressionValue); conditionExpressionBlock.AddChild(assumeBlock); //assume block needs processing of its children pendingBlocks.Enqueue(assumeBlock); } //if there is default branch if (parentBlock.Default != null) { if (expressionValues.Count == 0) { //there is default branch without any condition - connect without assume block // connect default branch to parent var defaultBlock = getChildBlock(parentBlock.Default, pendingBlocks); //default block needs processing of its children parentBlock.AddChild(defaultBlock); } else { //there has to be assumption condition on default branch // connect default branch to conditional blocks var values = expressionValues.ToArray(); var condition = new AssumptionCondition(ConditionForm.None, expressionParts.ToArray()); var defaultAssumeBlock = _context.CreateAssumeBlock(condition, parentBlock.Default, values); //default Assume has to be added as child of all expression blocks foreach (var conditionExpression in expressionBlocks) { conditionExpression.AddChild(defaultAssumeBlock); } pendingBlocks.Enqueue(defaultAssumeBlock); } } }
/// <summary> /// Connect outgoing condition less edge from parentBlock with given child /// </summary> /// <param name="parentBlock">Parent point block which child block will be connected</param> /// <param name="child">Block connected as child of parent block</param> /// <param name="pendingBlocks">Point blocks which children hasn't been processed yet</param> private void connectConditionLessEdge(PointsBlock parentBlock, BasicBlock child, Queue <PointsBlock> pendingBlocks) { var childBlock = getChildBlock(child, pendingBlocks); parentBlock.AddChild(childBlock); }
/// <summary> /// Add child points block for current points block /// <remarks>Program points contained in point blocks are connected with flow edge after connect is called</remarks> /// </summary> /// <param name="childBlock">Added child points block</param> internal void AddChild(PointsBlock childBlock) { childBlock._parentBlocks.Add(this); _childrenBlocks.Add(childBlock); }