internal static bool IsInstrumentationCode(CfgBlock block) { if (block.ExceptionHandler != null) { for (CfgBlock handler = block.ExceptionHandler; handler != null; handler = handler.ExceptionHandler) { Catch catchStmt = handler[0] as Catch; if (catchStmt == null) { continue; } TypeNode exnType = catchStmt.Type; if (exnType == null) { continue; } if (Equals(exnType.FullName, "Microsoft.Contracts.ContractMarkerException")) { return(true); } } } return(false); }
/// <summary> /// Merge the new pending state with the old pending states. /// </summary> /// <returns>merged pending state</returns> private IDataFlowState JoinWithPendingState(CfgBlock prev, CfgBlock block, IDataFlowState newState) { if (Tracing) { Console.WriteLine("JoinWithPendingState: block {0} -> {1}", (prev).UniqueKey, (block).UniqueKey); } IDataFlowState pending = PendingState(block); // note, we call Merge even if old is null. bool changed; bool precise; if (Tracing) { SourceContext sc = (block).SourceContext; if (sc.Document == null && block.Length > 0) { sc = ((Statement)block[0]).SourceContext; } Console.WriteLine("Join with pending state at line {0}", sc.StartLine); } IDataFlowState merged = this.Merge(prev, block, pending, newState, out changed, out precise); if (Tracing) { Console.WriteLine("Join changed {0}", changed); } return(merged); }
/// <summary> /// It visits an individual statement. It is called from VisitBlock. /// /// It calls NonNullInstructionVisitor /// </summary> /// <param name="block"></param> /// <param name="statement"></param> /// <param name="dfstate"></param> /// <returns></returns> protected override IDataFlowState VisitStatement(CfgBlock block, Statement statement, IDataFlowState dfstate) { // For debug purpose if (Analyzer.Debug) { try{ Analyzer.WriteLine("\n:::" + new SampleInstructionVisitor().Visit(statement, null) + " ::: " + statement.SourceContext.SourceText); }catch (Exception e) { Analyzer.WriteLine("Print error: " + statement + ": " + e.Message); } } IDataFlowState result = null; try{ result = (IDataFlowState)(iVisitor.Visit(statement, dfstate)); }catch (Exception e) { typeSystem.HandleError(statement, Cci.Error.InternalCompilerError, ":NonNull:" + e.Message); Console.WriteLine(e.StackTrace); } if (result != null && Analyzer.Debug) { result.Dump(); } return(result); }
/// <summary> /// It split exceptions for current handler and the next chained handler. /// /// It will: /// /// If the exception is completely intercepted by current handler, the /// exception will be consumed. /// /// If the exception caught but not completely, both current handler and /// the next handler will take the states. /// /// If the exception is irrelevant to current caught, the next handler /// will take over the state. Current handler is then bypassed. /// </summary> /// <param name="handler"></param> /// <param name="currentHandlerState"></param> /// <param name="nextHandlerState"></param> protected override void SplitExceptions(CfgBlock handler, ref IDataFlowState currentHandlerState, out IDataFlowState nextHandlerState) { Debug.Assert(currentHandlerState != null, "Internal error in NonNull Analysis"); ExposureState state = (ExposureState)currentHandlerState; if (handler == null || handler.Length == 0) { nextHandlerState = null; return; } if (handler[0] is Unwind) { nextHandlerState = null; currentHandlerState = null; return; } Debug.Assert(handler[0] is Catch, "Exception Handler does not starts with Catch"); Debug.Assert(state.currentException != null, "No current exception to handle"); Catch c = (Catch)handler[0]; if (handler.ExceptionHandler != null && !state.currentException.IsAssignableTo(c.Type)) { nextHandlerState = state;; } else { nextHandlerState = null; } // Compute what trickles through to the next handler // and what sticks to this handler. if (state.currentException.IsAssignableTo(c.Type)) { // everything sticks nextHandlerState = null; } else if (c.Type.IsAssignableTo(state.currentException)) { // c sticks, rest goes to next handler nextHandlerState = state; // copy state to modify the currentException state = new ExposureState(state); state.currentException = c.Type; currentHandlerState = state; } else { // nothing stick all goes to next handler nextHandlerState = state; currentHandlerState = null; } return; }
public IEGraph Join(IEGraph g2, CfgBlock joinPoint, out bool resultIsomorphicToThis) { IMergeInfo minfo; IEGraph result = Join(g2, joinPoint, out minfo); resultIsomorphicToThis = !minfo.Changed; return(result); }
public void Dump() { for (int i = 0; i < array.Count; i++) { CfgBlock block = (CfgBlock)array[i]; Console.WriteLine("{0}: b{1} ({2})", i, block.Index, block.UniqueKey); } }
/// <summary> /// Compute the join of two data flow states at the given block. /// </summary> /// <param name="previous">Predecessor block for this new state</param> /// <param name="joinPoint">Block at which join is computed</param> /// <param name="atMerge">Old state at this block. Can be null, in which case the incoming state /// is the first non-bottom state. In this case, the method must set changed /// <c>resultDiffersFromPreviousMerge</c> to true.</param> /// <param name="incoming">New data flow state flowing to this block.</param> /// <param name="resultDiffersFromPreviousMerge">Boolean for fix point. If the state after /// the merge is equal to the old <c>atMerge</c> state, set to false, otherwise set to true.</param> /// <param name="mergeIsPrecise">can be set to true if the merged result state strictly contains only /// information representing either the atMerge or the incoming state, but no extra approximation. If /// this information cannot be determined by the merge, it must return false. True can only be returned /// if result is truly precise.</param> /// <returns>The new merged state.</returns> protected abstract IDataFlowState Merge( CfgBlock previous, CfgBlock joinPoint, IDataFlowState atMerge, IDataFlowState incoming, out bool resultDiffersFromPreviousMerge, out bool mergeIsPrecise );
private void SetPendingState(CfgBlock block, IDataFlowState pending) { pendingStates[block.Index] = pending; if (Tracing) { Console.WriteLine("SetPendingState: block {0}", (block).UniqueKey); } }
private void PushDepth(CfgBlock succ, int depth) { int olddepth = block2depth[succ.Index]; if (visited[succ.Index]) { //System.Diagnostics.Debug.Assert( olddepth == depth, "Stack depth differs" ); return; } visited[succ.Index] = true; block2depth[succ.Index] = depth; }
private int InitialDepthOfBlock(CfgBlock block, ControlFlowGraph cfg) { int sd = block2depth[block.Index]; if (this.visited[block.Index]) { return(sd); } this.visited[block.Index] = true; int depth; ExceptionHandler eh = cfg.HandlerThatStartsAtBlock(block); if (eh == null) { // if we haven't seen this block and it is not the entry block // nor the Exception Exit of the method // it is unreachable if (block == cfg.Entry) { depth = 0; } else if (block == cfg.ExceptionExit) { depth = 0; } else { depth = -1; } } else { switch (eh.HandlerType) { case NodeType.Catch: case NodeType.FaultHandler: case NodeType.Filter: depth = 1; break; case NodeType.Finally: depth = 0; break; default: throw new ApplicationException("unknown handler type"); } } block2depth[block.Index] = depth; return(depth); }
/// <summary> /// Like PendingState returns the pending state for the given block, but /// it also sets the pending state for this block to null. /// </summary> /// <returns>old pending state</returns> private IDataFlowState PopPendingState(CfgBlock block) { IDataFlowState pending = pendingStates[block.Index]; pendingStates[block.Index] = null; if (Tracing) { Console.WriteLine("PopPendingState: block {0}", (block).UniqueKey); } return(pending); }
protected override IDataFlowState Merge(CfgBlock previous, CfgBlock joinPoint, IDataFlowState atMerge, IDataFlowState incoming, out bool resultDiffersFromPreviousMerge, out bool mergeIsPrecise) { if (nonNullInfo != null) { INonNullState nns = nonNullInfo.OnEdge(previous, joinPoint); if (nns == null && atMerge != null) { incoming = null; } } return(base.Merge(previous, joinPoint, atMerge, incoming, out resultDiffersFromPreviousMerge, out mergeIsPrecise)); }
protected override IDataFlowState Merge(CfgBlock previous, CfgBlock joinPoint, IDataFlowState atMerge, IDataFlowState incoming, out bool resultDiffersFromPreviousMerge, out bool mergeIsPrecise) { resultDiffersFromPreviousMerge = false; mergeIsPrecise = true; if (atMerge == null) { resultDiffersFromPreviousMerge = true; } atMerge = incoming; return(atMerge); }
public IEGraph Join(IEGraph g2, CfgBlock joinPoint, out IMergeInfo mergeInfo) { EGraph eg1 = this; EGraph eg2 = (EGraph)g2; int updateSize; EGraph common = ComputeCommonTail(eg1, eg2, out updateSize); EGraph result; bool doReplay = true; if (common == null) { doReplay = false; result = new EGraph(eg1.elementLattice); result.Block = joinPoint; } else { result = new EGraph(common, joinPoint); } if (Analyzer.Debug) { Console.WriteLine("Last common symbol: {0}", common.idCounter); } if (Analyzer.Statistics) { Console.WriteLine("G1:{0} G2:{1} Tail:{2} UpdateSize:{3}", eg1.historySize, eg2.historySize, result.historySize, updateSize); } MergeState ms = new MergeState(result, eg1, eg2); // Heuristic for using Replay vs. full update doReplay &= (common != eg1.root); doReplay &= (eg1.historySize > 3); doReplay &= (eg2.historySize > 3); if (doReplay) { ms.Replay(common); } else { ms.AddMapping(eg1.constRoot, eg2.constRoot, result.constRoot); ms.JoinSymbolicValue(eg1.constRoot, eg2.constRoot, result.constRoot); } mergeInfo = ms; return(result); }
/// <summary> /// Add the given state to the pending states of the target block. If /// the block is enabled (by the pending edge count optimization), add the /// block to the worklist. /// /// Inv: DoneState => PendingState /\ PendingState != null => InQueue /// /// Cases: /// 1. Done => new, nothing to do /// 2. Done |_| new is precise. Pend' = Pend |_| new, Done' = Done |_| new /// 3. Done |_| new is imprecise. Pend' = Done |_| new, Done' = Done |_| new /// </summary> public void PushState( CfgBlock currentBlock, CfgBlock nextBlock, IDataFlowState state ) { if (Tracing) { Console.WriteLine("PushState: block {0} -> {1}", (currentBlock).UniqueKey, (nextBlock).UniqueKey); } // state == null signals that branch is infeasible if (state == null) { return; } bool precise; // Add state to done state IDataFlowState stillPending = this.StateToReanalyzeBlock(currentBlock, nextBlock, state, out precise); if (stillPending == null) { if (Tracing) { Console.WriteLine("PushState: block {0} no new information for pending state.", (nextBlock).UniqueKey); } return; } if (precise) { // join stillPending to old pending. stillPending = this.JoinWithPendingState(currentBlock, nextBlock, stillPending); } this.SetPendingState(nextBlock, stillPending); // when dequeued, the pending state is what the block needs to be analyzed under. // joinWorkItems.Enqueue(nextBlock); if (Tracing) { Console.WriteLine("PushState: block {0} put on work queue.", (nextBlock).UniqueKey); } }
/// <summary> /// Merge the two states for current block. /// </summary> /// <param name="previous"></param> /// <param name="joinPoint"></param> /// <param name="atMerge"></param> /// <param name="incoming"></param> /// <param name="resultDiffersFromPreviousMerge"></param> /// <param name="mergeIsPrecise"></param> /// <returns></returns> protected override IDataFlowState Merge(CfgBlock previous, CfgBlock joinPoint, IDataFlowState atMerge, IDataFlowState incoming, out bool resultDiffersFromPreviousMerge, out bool mergeIsPrecise) { mergeIsPrecise = false; // No new states; if (incoming == null) { resultDiffersFromPreviousMerge = false; return(atMerge); } // Initialize states if (atMerge == null) { resultDiffersFromPreviousMerge = true; return(incoming); } if (Analyzer.Debug) { Console.WriteLine("Merge at Block {0}-----------------", (joinPoint).UniqueKey); Console.WriteLine(" State at merge"); atMerge.Dump(); Console.WriteLine(" Incoming"); incoming.Dump(); } // Merge the two. ExposureState newState = ExposureState.Join((ExposureState)atMerge, (ExposureState)incoming, joinPoint); if (newState != null) { if (Analyzer.Debug) { Console.WriteLine("\n Merged State"); newState.Dump(); } resultDiffersFromPreviousMerge = true; return(newState); } if (Analyzer.Debug) { Console.WriteLine("Merged state same as old."); } resultDiffersFromPreviousMerge = false; return(atMerge); }
public IStronglyConnectedComponent SccForBlock(CfgBlock block) { if (this.sccMap == null) { this.sccMap = new Hashtable(); foreach (StronglyConnectedComponent /*<CfgBlock>*/ scc in this.sccs) { foreach (CfgBlock iblock in scc.Nodes) { this.sccMap[iblock] = scc; } } } return((StronglyConnectedComponent)this.sccMap[(block)]); }
/// <summary> /// Default per statement visitor called from the default VisitBlock. /// Does identity transformation. Subclasses either override this method /// if the default block handling is sufficient, or they override the Visit method for blocks. /// /// The result of this method is used as the state for all normal control flow successors. /// To push state onto an exception handler, use the PushExceptionState method. Furthermore, for /// conditional branches, different states can be pushed onto the true and false branches directly /// by calling PushPending. In that case, null should be returned from the method in order to avoid pushing /// the returned state onto both true and false targets again. /// </summary> protected virtual IDataFlowState VisitStatement(CfgBlock block, Statement statement, IDataFlowState dfstate) { // simple case analysis to distinguish throws switch (statement.NodeType) { case NodeType.Throw: case NodeType.Rethrow: { PushExceptionState(block, dfstate); return(null); } default: return(dfstate); } }
/// <summary> /// Default per block visitor. Called from Run. /// /// It calls VisitStatement on each statement in a block. /// /// The result of this method is used as the state for all normal control flow successors. /// To push state onto an exception handler, use the PushExceptionState method. Furthermore, for /// conditional branches, different states can be pushed onto the true and false branches directly /// by calling PushPending. In that case, null should be returned from the method in order to avoid pushing /// the returned state onto both true and false targets again. /// </summary> protected virtual IDataFlowState VisitBlock(CfgBlock block, IDataFlowState stateOnEntry) { IDataFlowState currentState = stateOnEntry; for (int i = 0; i < block.Length; i++) { if (currentState == null) { return(null); } currentState = this.VisitStatement(block, (Statement)block[i], currentState); } return(currentState); }
/// <summary> /// Copy constructor /// </summary> /// <param name="from"></param> private EGraph(EGraph from, CfgBlock at) { this.constRoot = from.constRoot; this.termMap = from.termMap; this.idCounter = from.idCounter; this.absMap = from.absMap; this.elementLattice = from.elementLattice; this.forwMap = from.forwMap; this.eqTermMap = from.eqTermMap; // keep history this.updates = from.updates; this.parent = from; this.root = from.root; this.historySize = from.historySize + 1; this.Block = at; // set from to constant from.constant = true; }
protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState stateOnEntry) { IDataFlowState resultState = stateOnEntry; IDataFlowState newState = new MyState(); if (block.ExceptionHandler != null) { this.PushExceptionState(block, newState); } resultState = base.VisitBlock(block, newState); if (block.UniqueId == cfg.NormalExit.UniqueId) { } if (block.UniqueId == cfg.ExceptionExit.UniqueId) { } return(resultState); }
/// <summary> /// Push the given state onto the handler of the block. /// This causes call-backs to SplitException in order to correctly distribute /// the exception state among different nested handlers. /// </summary> /// <param name="currentBlock">Block from which exception escapes</param> /// <param name="state">state on exception flow</param> public void PushExceptionState( CfgBlock currentBlock, IDataFlowState state ) { IDataFlowState currentHandlerState = state; CfgBlock currentHandler = currentBlock; IDataFlowState nextHandlerState; while (currentHandlerState != null) { Debug.Assert(currentHandler.ExceptionHandler != null, String.Format("block {0} does not have an exception handler", (currentHandler).UniqueKey)); currentHandler = currentHandler.ExceptionHandler; if (Tracing) { Console.WriteLine("PushExceptionState (in loop): block {0} -> {1}", (currentBlock).UniqueKey, (currentHandler).UniqueKey); } SplitExceptions(currentHandler, ref currentHandlerState, out nextHandlerState); /// We allow SplitExceptions to make decisions about not propagating any exceptions /// Debug.Assert(currentHandlerState != null || nextHandlerState != null); if (currentHandlerState != null) { PushState(currentBlock, currentHandler, currentHandlerState); } currentHandlerState = nextHandlerState; } }
/// <summary> /// Starts the analysis at the first instruction of the given block /// </summary> protected virtual void Run(ControlFlowGraph cfg, CfgBlock startBlock, IDataFlowState startState) { this.Reinitialize(cfg); pendingStates[startBlock.Index] = startState; joinWorkItems.Enqueue(startBlock); while (joinWorkItems.Count > 0) { //joinWorkItems.Dump(); CfgBlock currentBlock = joinWorkItems.Dequeue(); if (Analyzer.Debug) { Console.WriteLine("\n*** Working on block {0} [{1} statements, line {2}]\n", ((currentBlock).UniqueKey), currentBlock.Length, (currentBlock.Length == 0)? -1 : ((Statement)currentBlock[0]).SourceContext.StartLine); } // Flow the current state through the block. IDataFlowState currentState = PopPendingState(currentBlock); currentState = VisitBlock(currentBlock, currentState); // NOTE: VisitBlock may have explicitly pushed states onto some successors. In that case // it should return null to avoid this code pushing the same state onto all successors. if (currentState != null) { foreach (CfgBlock succ in currentBlock.NormalSuccessors) { PushState(currentBlock, succ, currentState); } } } //while }
/// <summary> /// Implementation of visit Block. It is called from run. /// /// It calls VisitStatement. /// </summary> /// <param name="block"></param> /// <param name="stateOnEntry"></param> /// <returns></returns> protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState stateOnEntry) { Debug.Assert(block != null); currBlock = block; Analyzer.Write("---------block: " + block.UniqueId + ";"); Analyzer.Write(" Exit:"); foreach (CfgBlock b in block.NormalSuccessors) { Analyzer.Write(b.UniqueId + ";"); } if (block.UniqueSuccessor != null) { Analyzer.Write(" FallThrough: " + block.UniqueSuccessor + ";"); } if (block.ExceptionHandler != null) { Analyzer.Write(" ExHandler: " + block.ExceptionHandler.UniqueId + ";"); } Analyzer.WriteLine(""); ExposureState newState; if (stateOnEntry == null) { newState = new ExposureState(typeSystem); } else { newState = new ExposureState((ExposureState)stateOnEntry); } // if (block.ExceptionHandler!=null) // this.PushExceptionState(block,newState); return(base.VisitBlock(block, newState)); }
/// <summary> /// merge the two state atMerge and incoming. /// </summary> /// <param name="previous"></param> /// <param name="joinPoint"></param> /// <param name="atMerge"></param> /// <param name="incoming"></param> /// <param name="resultDiffersFromPreviousMerge"></param> /// <param name="mergeIsPrecise"></param> /// <returns></returns> protected override IDataFlowState Merge(CfgBlock previous, CfgBlock joinPoint, IDataFlowState atMerge, IDataFlowState incoming, out bool resultDiffersFromPreviousMerge, out bool mergeIsPrecise) { resultDiffersFromPreviousMerge = false; mergeIsPrecise = false; // No new states; if (incoming == null) return atMerge; // Initialize states if (atMerge == null) { resultDiffersFromPreviousMerge = true; // //((NNArrayStatus)incoming).FilterStackAndTemporaryLocals(joinPoint.StackDepth); return incoming; } if (Analyzer.Debug ) { Console.WriteLine("Array Reachable Def merge at block {0}", (joinPoint).UniqueKey); Console.WriteLine("atMerge:\n---------"); atMerge.Dump(); Console.WriteLine("incoming:\n---------"); incoming.Dump(); } // Merge the two. NNArrayStatus newState = NNArrayStatus.Merge((NNArrayStatus)atMerge, (NNArrayStatus)incoming, joinPoint); if (newState == null) { if (Analyzer.Debug) { Console.WriteLine("result UNchanged"); } return atMerge; } resultDiffersFromPreviousMerge = true; if (Analyzer.Debug) { Console.WriteLine("Result of merge\n---------"); newState.Dump(); } return newState; }
public static InitializedVariables Merge(InitializedVariables atMerge, InitializedVariables incoming, CfgBlock joinPoint) { bool unchanged; IEGraph result = atMerge.egraph.Join(incoming.egraph, joinPoint, out unchanged); if (unchanged) return null; return new InitializedVariables(incoming.analyzer, result, atMerge.referenceStatus); }
protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState stateOnEntry) { //if (IsInstrumentationCode(block)) // return stateOnEntry; return base.VisitBlock(block, stateOnEntry); }
protected override IDataFlowState Merge(CfgBlock previous, CfgBlock joinPoint, IDataFlowState atMerge, IDataFlowState incoming, out bool resultDiffersFromPreviousMerge, out bool mergeIsPrecise) { if (nonNullInfo != null) { INonNullState nns = nonNullInfo.OnEdge(previous, joinPoint); if (nns == null && atMerge!=null) incoming = null; } return base.Merge(previous, joinPoint, atMerge, incoming, out resultDiffersFromPreviousMerge, out mergeIsPrecise); }
public IEGraph Join(IEGraph g2, CfgBlock joinPoint, out IMergeInfo mergeInfo) { EGraph eg1 = this; EGraph eg2 = (EGraph)g2; int updateSize; EGraph common = ComputeCommonTail(eg1, eg2, out updateSize); EGraph result; bool doReplay = true; if (common == null) { doReplay = false; result = new EGraph(eg1.elementLattice); result.Block = joinPoint; } else { result = new EGraph(common, joinPoint); } if (Analyzer.Debug) { Console.WriteLine("Last common symbol: {0}", common.idCounter); } if (Analyzer.Statistics) { Console.WriteLine("G1:{0} G2:{1} Tail:{2} UpdateSize:{3}", eg1.historySize, eg2.historySize, result.historySize, updateSize); } MergeState ms = new MergeState(result, eg1, eg2); // Heuristic for using Replay vs. full update doReplay &= (common != eg1.root); doReplay &= (eg1.historySize > 3); doReplay &= (eg2.historySize > 3); if (doReplay) { ms.Replay(common); } else { ms.AddMapping(eg1.constRoot, eg2.constRoot, result.constRoot); ms.JoinSymbolicValue(eg1.constRoot, eg2.constRoot, result.constRoot); } mergeInfo = ms; return result; }
/// <summary> /// Exception management /// Need Checking! /// </summary> /// <param name="handler"></param> /// <param name="currentHandlerState"></param> /// <param name="nextHandlerState"></param> protected override void SplitExceptions(CfgBlock handler, ref IDataFlowState currentHandlerState, out IDataFlowState nextHandlerState) { System.Diagnostics.Debug.Assert(currentHandlerState != null, "Internal error in Purity Analysis"); PointsToState state = (PointsToState)currentHandlerState; if (handler == null || handler.Length == 0) { nextHandlerState = null; return; } if (handler[0] is Unwind) { nextHandlerState = null; currentHandlerState = null; return; } // This is if (!(handler[0] is Catch)) { // everything sticks nextHandlerState = null; return; } System.Diagnostics.Debug.Assert(handler[0] is Catch, "Exception Handler does not starts with Catch"); if (state.currentException == null) { nextHandlerState = null; return; } System.Diagnostics.Debug.Assert(state.currentException != null, "No current exception to handle"); Catch c = (Catch)handler[0]; if (handler.ExceptionHandler != null && !state.currentException.IsAssignableTo(c.Type)) { nextHandlerState = state; ; } else { nextHandlerState = null; } // Compute what trickles through to the next handler // and what sticks to this handler. if (state.currentException.IsAssignableTo(c.Type)) { // everything sticks nextHandlerState = null; } else if (c.Type.IsAssignableTo(state.currentException)) { // c sticks, rest goes to next handler nextHandlerState = state; // copy state to modify the currentException state = (state).Copy(); state.currentException = c.Type; currentHandlerState = state; } else { // nothing stick all goes to next handler nextHandlerState = state; currentHandlerState = null; } return; }
/// <summary> /// Copy constructor /// </summary> /// <param name="from"></param> private EGraph(EGraph from, CfgBlock at) { this.constRoot = from.constRoot; this.termMap = from.termMap; this.idCounter = from.idCounter; this.absMap = from.absMap; this.elementLattice = from.elementLattice; this.forwMap = from.forwMap; this.eqTermMap = from.eqTermMap; // keep history this.updates = from.updates; this.parent = from; this.root = from.root; this.historySize = from.historySize+1; this.Block = at; // set from to constant from.constant = true; }
public IEGraph Clone(CfgBlock at) { return new EGraph(this, at); }
protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState state) { Debug.Assert(block != null); NNArrayStatus onEntry = (NNArrayStatus)state; currBlock = block; if (Analyzer.Debug) { Analyzer.Write("---------block: " + block.UniqueId + ";"); Analyzer.Write(" Exit:"); foreach (CfgBlock b in block.NormalSuccessors) Analyzer.Write(b.UniqueId + ";"); if (block.UniqueSuccessor != null) Analyzer.Write(" FallThrough: " + block.UniqueSuccessor + ";"); if (block.ExceptionHandler != null) Analyzer.Write(" ExHandler: " + block.ExceptionHandler.UniqueId + ";"); Analyzer.WriteLine(""); state.Dump(); } if (block.ExceptionHandler != null) { NNArrayStatus exnState = onEntry; onEntry = new NNArrayStatus(onEntry); // Copy state, since common ancestor cannot be modified any longer PushExceptionState(block, exnState); } NNArrayStatus resultState = (NNArrayStatus)base.VisitBlock(block, onEntry); if (block.UniqueId == cfg.NormalExit.UniqueId) { exitState = resultState; } if (resultState == null) { return null; } return new NNArrayStatus(resultState); }
protected override void SplitExceptions(CfgBlock handler, ref IDataFlowState currentHandlerState, out IDataFlowState nextHandlerState) { nextHandlerState = null; return; }
/// <summary> /// Merge two cState /// </summary> /// <param name="previous"></param> /// <param name="joinPoint"></param> /// <param name="atMerge"></param> /// <param name="incoming"></param> /// <param name="resultDiffersFromPreviousMerge"></param> /// <param name="mergeIsPrecise"></param> /// <returns></returns> protected override IDataFlowState Merge(CfgBlock previous, CfgBlock joinPoint, IDataFlowState atMerge, IDataFlowState incoming, out bool resultDiffersFromPreviousMerge, out bool mergeIsPrecise) { resultDiffersFromPreviousMerge = false; mergeIsPrecise = false; // No new states; if (incoming == null) return atMerge; // Initialize states if (atMerge == null) { resultDiffersFromPreviousMerge = true; return incoming; } //if (((PointsToState )atMerge).Equals(incoming)) // return atMerge; if (((PointsToState)atMerge).Includes((PointsToState)incoming)) return atMerge; // Merge the two. PointsToState newState = ((PointsToState)atMerge).Copy(); newState.Join((PointsToState)incoming); //if( newState.Method.FullName.StartsWith("System.Runtime.Remoting.Lifetime.Lease.ProcessNextSponsor")) //{ // PointsToState oldResult = (PointsToState)incoming; // PointsToState newResult = newState; // Console.Out.WriteLine("DIFERENCE a vs b"); // oldResult.PointsToGraph.DumpDifference(newResult.PointsToGraph); // Console.Out.WriteLine("DIFERENCE b vs a"); // newResult.PointsToGraph.DumpDifference(oldResult.PointsToGraph); //} resultDiffersFromPreviousMerge = true; return newState; }
/// <summary> /// Visit the statement. It calls the instruction visitor to perform the transfer function /// </summary> /// <param name="block"></param> /// <param name="statement"></param> /// <param name="dfstate"></param> /// <returns></returns> protected override IDataFlowState VisitStatement(CfgBlock block, Statement statement, IDataFlowState dfstate) { if (PointsToAnalysis.debug) { Console.Out.WriteLine("Before: {0} ({1}) {2}", CodePrinter.StatementToString(statement), statement.SourceContext.StartLine, statement.GetType()); dfstate.Dump(); } PointsToState currentState = dfstate as PointsToState; /* if (PointsToAnalysis.IsCompilerGenerated(currentState.Method)) if (!this.pointsToStateAnalysys.enclosingState.ContainsKey(currentState.Method.DeclaringType)) return currentState; */ if (PointsToAnalysis.verbose) { iterationsCounter++; if (iterationsCounter % 5000 == 0) { Console.Out.WriteLine("Counter: {3} {4} {0} ({1}) {2}", CodePrinter.StatementToString(statement), statement.SourceContext.StartLine, statement.GetType(), iterationsCounter, currentState.Method.FullName); dfstate.Dump(); } } //if (CodePrinter.StatementToString(statement).Contains("return value := this.f")) // System.Diagnostics.Debugger.Break(); IDataFlowState result = (IDataFlowState)currentState; // For Debug... if (currentState.Method.Name.Name.Equals("Push")) { } // If there are too many calls to non analyzable methods // starts to ignore the statements // if (!pointsToStateAnalysys.BoogieMode || currentState.CallsToNonAnalyzable.Count < pointsToStateAnalysys.maxCallToNonAnalyzable) if (HasToVisit(currentState)) result = (IDataFlowState)(iVisitor.Visit(statement, dfstate)); if (PointsToAnalysis.debug) { Console.Out.WriteLine("After: {0} ({1})", CodePrinter.StatementToString(statement), statement.SourceContext.StartLine); dfstate.Dump(); } //return dfstate; return result; }
/// <summary> /// Splits the exceptions into the ones that this handler will handle and the ones that should /// <code>currentHandlerState</code> and <code>nextHandlerState</code> cannot both be null. /// On exit, if <code>currentHandlerState</code> is null, <code>handler</code> handles no exceptions, /// and if <code>nextHandlerState</code> is null, <code>handler</code> handles all the exceptions in /// the initial exception set of <code>currentHandlerState</code>. /// </summary> // go on to the next handler. currentHandlerState and next protected abstract void SplitExceptions( CfgBlock handler, ref IDataFlowState currentHandlerState, out IDataFlowState nextHandlerState );
internal static bool IsInstrumentationCode(CfgBlock block) { if (block.ExceptionHandler != null) { for (CfgBlock handler = block.ExceptionHandler; handler != null; handler = handler.ExceptionHandler) { Catch catchStmt = handler[0] as Catch; if (catchStmt == null) { continue; } TypeNode exnType = catchStmt.Type; if (exnType == null) { continue; } if (Equals(exnType.FullName, "Microsoft.Contracts.ContractMarkerException")) { return true; } } } return false; }
private IDataFlowState PendingState(CfgBlock block) { return(pendingStates[block.Index]); }
protected override void SplitExceptions(CfgBlock handler, ref IDataFlowState currentHandlerState, out IDataFlowState nextHandlerState) { nextHandlerState = null; }
// Visit the block in the CFG protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState stateOnEntry) { IDataFlowState resultState = stateOnEntry; Debug.Assert(block != null); currBlock = block; Analyzer.Write("---------block: " + block.UniqueId + ";"); Analyzer.Write(" Exit:"); foreach (CfgBlock b in block.NormalSuccessors) Analyzer.Write(b.UniqueId + ";"); if (block.UniqueSuccessor != null) Analyzer.Write(" FallThrough: " + block.UniqueSuccessor + ";"); if (block.ExceptionHandler != null) Analyzer.Write(" ExHandler: " + block.ExceptionHandler.UniqueId + ";"); Analyzer.WriteLine(""); PointsToState newState = ((PointsToState)stateOnEntry).Copy(); // If there are too many calls to non analyzable methods // starts to ignore the statements //if (!pointsToStateAnalysys.BoogieMode || // newState.CallsToNonAnalyzable.Count < pointsToStateAnalysys.maxCallToNonAnalyzable) if (HasToVisit(newState)) { if (block.ExceptionHandler != null) this.PushExceptionState(block, newState); resultState = base.VisitBlock(block, newState); } if (block.UniqueId == cfg.NormalExit.UniqueId) { exitState = resultState; } if (block.UniqueId == cfg.ExceptionExit.UniqueId) { exitState = resultState; } return resultState; }
/// <summary> /// Visit the statement. It calls the instruction visitor to perform the transfer function /// </summary> /// <param name="block"></param> /// <param name="statement"></param> /// <param name="dfstate"></param> /// <returns></returns> protected override IDataFlowState VisitStatement(CfgBlock block, Statement statement, IDataFlowState dfstate) { IDataFlowState result = (IDataFlowState)(iVisitor.Visit(statement, dfstate)); return(result); }
protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState stateOnEntry) { //if (IsInstrumentationCode(block)) // return stateOnEntry; return(base.VisitBlock(block, stateOnEntry)); }
private int InitialDepthOfBlock(CfgBlock block, ControlFlowGraph cfg) { int sd = block2depth[block.Index]; if (this.visited[block.Index]) return sd; this.visited[block.Index] = true; int depth; ExceptionHandler eh = cfg.HandlerThatStartsAtBlock(block); if (eh == null) { // if we haven't seen this block and it is not the entry block // nor the Exception Exit of the method // it is unreachable if (block == cfg.Entry) { depth = 0; } else if (block == cfg.ExceptionExit) { depth = 0; } else { depth = -1; } } else { switch (eh.HandlerType) { case NodeType.Catch: case NodeType.FaultHandler: case NodeType.Filter: depth = 1; break; case NodeType.Finally: depth = 0; break; default: throw new ApplicationException("unknown handler type"); } } block2depth[block.Index] = depth; return depth; }
/// <summary> /// Merge two PtWe /// </summary> /// <param name="previous"></param> /// <param name="joinPoint"></param> /// <param name="atMerge"></param> /// <param name="incoming"></param> /// <param name="resultDiffersFromPreviousMerge"></param> /// <param name="mergeIsPrecise"></param> /// <returns></returns> protected override IDataFlowState Merge(CfgBlock previous, CfgBlock joinPoint, IDataFlowState atMerge, IDataFlowState incoming, out bool resultDiffersFromPreviousMerge, out bool mergeIsPrecise) { return base.Merge(previous,joinPoint,atMerge,incoming,out resultDiffersFromPreviousMerge, out mergeIsPrecise); }
protected override IDataFlowState VisitStatement(CfgBlock block, Statement statement, IDataFlowState dfstate) { // For debug purpose if (Analyzer.Debug) { try { Analyzer.WriteLine(new SampleInstructionVisitor().Visit(statement, null) + " ::: " + statement.SourceContext.SourceText); } catch (Exception) { Analyzer.WriteLine("Print error: " + statement); } } IDataFlowState result=null; try{ result =(IDataFlowState)(iVisitor.Visit(statement,dfstate)); if (Analyzer.Debug && result != null) { result.Dump(); } }catch(Exception e){ typeSystem.HandleError(statement,Error.InternalCompilerError,"Definite Assignement: "+e.Message); } return result; }
/// <summary> /// Visit the statement. It calls the instruction visitor to perform the transfer function /// </summary> /// <param name="block"></param> /// <param name="statement"></param> /// <param name="dfstate"></param> /// <returns></returns> protected override IDataFlowState VisitStatement(CfgBlock block, Statement statement, IDataFlowState dfstate) { PointsToAndWriteEffects ptwe = (PointsToAndWriteEffects)dfstate; // PointsToAndWriteEffects ptweOld = new PointsToAndWriteEffects(ptwe); IDataFlowState res = base.VisitStatement(block, statement, dfstate); return res; }
protected override void Run(ControlFlowGraph cfg, CfgBlock startBlock, IDataFlowState startState) { base.Run(cfg, startBlock, startState); }
/// <summary> /// Returns null, if result of Join is the same as atMerge. /// </summary> public static ExposureState Join(ExposureState atMerge, ExposureState incoming, CfgBlock joinPoint) { bool unchanged; IEGraph merged = atMerge.egraph.Join(incoming.egraph, joinPoint, out unchanged); TypeNode currentException = (atMerge.currentException != null)? ((incoming.currentException != null)? CciHelper.LeastCommonAncestor(atMerge.currentException, incoming.currentException) : null) : null; if (atMerge.currentException != currentException || !unchanged) { return(new ExposureState(merged, currentException, atMerge.typeSystem)); } return(null); }
/// <summary> /// Record the incoming status's sets of created and committed NN Arrays. /// </summary> /// <param name="block"></param> /// <param name="statement"></param> /// <param name="dfstate"></param> /// <returns></returns> protected override IDataFlowState VisitStatement(CfgBlock block, Statement statement, IDataFlowState dfstate) { //IDataFlowState result = base.VisitStatement(block, statement, dfstate); table[statement.UniqueKey] = (dfstate as NNArrayStatus).CreatedButNotInitedArrays(); tableCommitted[statement.UniqueKey] = (dfstate as NNArrayStatus).CommittedArrays(); IDataFlowState result = null; //try { result = (IDataFlowState)(iVisitor.Visit(statement, dfstate)); if (Analyzer.Debug && result != null) { result.Dump(); } //} //catch (Exception e) { // this.TypeSystem.HandleError(statement, Error.InternalCompilerError, "NNArray Pre Analysis " + e.Message); //} return result; }
// Visit the block in the CFG protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState stateOnEntry) { return base.VisitBlock(block, stateOnEntry); }
/// <summary> /// TODO: The set of vars/fields that are created only/committed must agree /// </summary> /// <returns></returns> public static NNArrayStatus Merge(NNArrayStatus atMerge, NNArrayStatus incoming, CfgBlock joinPoint) { Debug.Assert(atMerge != null && incoming != null); // if (atMerge == incoming) return null; InitializedVariables result = InitializedVariables.Merge(atMerge.ivs, incoming.ivs, joinPoint); if (result == null && atMerge.vars.Equals(incoming.vars) && atMerge.fields.Equals(incoming.fields) && atMerge.zeroInts.Equals(incoming.zeroInts) ) return null; if (result == null) result = atMerge.ivs; return new NNArrayStatus(result, (HashSet)Set.Union(atMerge.vars, incoming.vars), Set.Union(atMerge.fields,incoming.fields) as HashSet, Set.Intersect(atMerge.zeroInts, incoming.zeroInts) as HashSet, mergeStack(atMerge.stack, incoming.stack, result)); }
public IEGraph Join(IEGraph g2, CfgBlock joinPoint, out bool resultIsomorphicToThis) { IMergeInfo minfo; IEGraph result = Join(g2, joinPoint, out minfo); resultIsomorphicToThis = !minfo.Changed; return result; }