private SymbolicExpressionTracker <Variable, Expression> RenameInternal(Dictionary <Variable, FList <Variable> > renaming, Variable slackVar) { Contract.Requires(renaming != null); Contract.Ensures(Contract.Result <SymbolicExpressionTracker <Variable, Expression> >() != null); Contract.Ensures(renaming.Count == Contract.OldValue(renaming.Count)); if (symbolicConditions.IsNormal()) { renaming[slackVar] = FList <Variable> .Cons(slackVar, FList <Variable> .Empty); Set <Expression> result = new Set <Expression>(); foreach (var exp in symbolicConditions.Values) { result.AddIfNotNull(expressionRenamer(exp, renaming)); } var renamedExpressions = result.Count != 0 ? new SetOfConstraints <Expression>(result, false) : SetOfConstraints <Expression> .Unknown; renaming.Remove(slackVar); // We should remove the slack variable! return(new SymbolicExpressionTracker <Variable, Expression>(this.slackVar, symbolicConditions)); } else { return(this); } }
private static FList <string> AddExtraArgs(FList <string> args, string serviceAddress) { if (!String.IsNullOrWhiteSpace(serviceAddress) && serviceAddress != "*") // if not specified and not wildcard, use default address { args = args.Cons("-serviceAddress:" + serviceAddress); } return(args); }
/// <summary> /// Assumes that exception edges always target join points, so we never need to reach /// backwards across a throw edges. /// </summary> /// <param name="apc"></param> /// <param name="ifMissing"></param> /// <returns></returns> public AState /*?*/ GetPreState(APC apc, AState /*?*/ ifMissing, out bool noInfo) { // Find closest preceeding cached point // Keep a list of program points we visit backward so we can take the // same path forward. FList <APC> /*?*/ path = null; APC current = apc; APC pred; AState /*?*/ state; bool found; while (!(found = this.TryPreStateCache(current, out state)) && !RequiresJoining(current) && !this.CacheThisPC(current) && this.cfg.HasSinglePredecessor(current, out pred)) { current = pred; path = path.Cons(current); } if (!found) { noInfo = true; return(ifMissing); // unreachable } bool nonTrivialPath = path != null; // Now forward simulate and cache while (path != null) { if (IsBottom(path.Head, state)) { noInfo = true; // equate no info with bottom since we cannot manufacture bottom here return(state); } // must get a mutable version if we are going to change it. state = MutableVersion(state, path.Head); state = Transfer(path.Head, state); if (IsBottom(path.Head, state)) { noInfo = false; return(state); } path = path.Tail; if (path != null) { // cache on next this.CachePreState(path.Head, ImmutableVersion(state, path.Head)); // this.joinState.Add(path.Head, state); } } // cache on lookedup up apc if (nonTrivialPath) { this.CachePreState(apc, ImmutableVersion(state, apc)); // this.joinState.Add(apc, state); } noInfo = false; return(state); }
private void AssignInParallel (WeakUpperBoundsEqual <Variable, Expression> wubeq, WeakUpperBounds <Variable, Expression> wub, Dictionary <Variable, FList <Variable> > sourcesToTargets, INumericalAbstractDomain <Variable, Expression> oracleDomain) { Contract.Requires(wubeq != null); Contract.Requires(wub != null); // adding the domain-generated variables to the map as identity var oldToNewMap = new Dictionary <Variable, FList <Variable> >(sourcesToTargets); if (!wubeq.IsTop) { foreach (var e in wubeq.SlackVariables) { oldToNewMap[e] = FList <Variable> .Cons(e, FList <Variable> .Empty); } } if (!wub.IsTop) { foreach (var e in wub.SlackVariables) { oldToNewMap[e] = FList <Variable> .Cons(e, FList <Variable> .Empty); } } // when x has several targets including itself, the canonical element shouldn't be itself foreach (var sourceToTargets in sourcesToTargets) { var source = sourceToTargets.Key; var targets = sourceToTargets.Value; Contract.Assume(targets != null); if (targets.Length() > 1 && targets.Head.Equals(source)) { var tail = targets.Tail; Contract.Assert(tail != null); var newTargets = FList <Variable> .Cons(tail.Head, FList <Variable> .Cons(source, tail.Tail)); oldToNewMap[source] = newTargets; } } AssignInParallelWUBSpecific(wub, oldToNewMap); AssignInParallelWUBEQSpecific(wubeq, sourcesToTargets, oldToNewMap); }
/// <summary> /// Given a method driver, compute a parallel renaming relation between the (symbolic) values at the return point /// of a method and those at the entry of the same method. This renaming relation will be used to map an abstract /// state at the end of one pass of analysis to the starting point of the next pass. /// /// Implementation is to use SymbolicValuesAt method to find symbolic values for "important" access pathes and /// match the symbolic values that represent the same access path. /// </summary> /// <param name="driver"></param> /// <returns></returns> IFunctionalMap <Variable, FList <Variable> > GetFieldMapping(IMethodDriver <Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly, Expression, Variable, ILogOptions> driver, APC pc1, APC pc2) { FunctionalMap <Variable, FList <Variable> > fieldMapping = null; fieldMapping = FunctionalMap <Variable, FList <Variable> > .Empty; foreach (Pair <string, Variable> pair in SymbolicValuesAt(pc1, driver)) { if (!fieldMapping.Contains(pair.Two)) { fieldMapping = (FunctionalMap <Variable, FList <Variable> >)fieldMapping.Add(pair.Two, FList <Variable> .Empty); } foreach (Pair <string, Variable> pair2 in SymbolicValuesAt(pc2, driver)) { if (pair.One == pair2.One) { FList <Variable> list = fieldMapping[pair.Two]; list = list.Cons(pair2.Two); fieldMapping = (FunctionalMap <Variable, FList <Variable> >)fieldMapping.Add(pair.Two, list); } } } return(fieldMapping); }
public static void Push <Arg0, Arg1, Arg2, Arg3, TResult>(Func <Func <Arg0, Arg1, Arg2, Arg3, TResult>, Arg0, Arg1, Arg2, Arg3, TResult> adapter) { currentCallAdapters = currentCallAdapters.Cons(adapter); }
private static FList <IOperationExceptionInformation> PopPushHandlers(BasicBlock block, FList <IOperationExceptionInformation> currentHandlers, IOperationExceptionInformation[] handlers, ref FList <IOperationExceptionInformation> containingHandlers) { Contract.Requires(block != null); Contract.Requires(handlers != null); Contract.Requires(Contract.ForAll(handlers, h => h != null)); // pop fault/finally subroutines off subroutine stack whose scope ends here var blockOffset = block.Offset; #region Pop protecting handlers off stack whose scope ends here for (int i = 0; i < handlers.Length; i++) { if (handlers[i].TryEndOffset == blockOffset) { // must be head if (currentHandlers != null && Object.Equals(handlers[i], currentHandlers.Head)) { currentHandlers = currentHandlers.Tail; } else { throw new ApplicationException("bad order of handlers"); } } } #endregion #region Push protecting handlers on stack whose scope starts here // reverse order for (int i = handlers.Length - 1; i >= 0; i--) { if (handlers[i].TryStartOffset == blockOffset) { // push this handler on top of current block enclosing handlers currentHandlers = FList <IOperationExceptionInformation> .Cons(handlers[i], currentHandlers); // Push handler } } #endregion #region Pop containing handlers off containing handler stack whose scope ends here for (int i = 0; i < handlers.Length; i++) { if (handlers[i].HandlerEndOffset == blockOffset) { // must be head if (containingHandlers != null && Object.Equals(handlers[i], containingHandlers.Head)) { containingHandlers = containingHandlers.Tail; } else { throw new ApplicationException("bad order of handlers"); } } } #endregion #region Push containing handler on stack whose scope starts here // reverse order for (int i = handlers.Length - 1; i >= 0; i--) { if (handlers[i].HandlerStartOffset == blockOffset) { // push this handler on top of containing handlers containingHandlers = FList <IOperationExceptionInformation> .Cons(handlers[i], containingHandlers); // Push handler } } #endregion // record handlers for this block block.Handlers = currentHandlers; block.ContainingHandler = (containingHandlers != null) ? containingHandlers.Head : null; return(currentHandlers); }
private void AddUpdate(Update upd) { Debug.Assert(!this.IsConstant, "modification of locked down egraph"); this.updates = FList.Cons(upd, this.updates); }
/// <summary> /// Compute a pre order (ignoring back edges) of the CFG reachable from the entry node /// /// As a side effect, assigns each block its DF finishing number. /// </summary> public static FList /*<BasicBlocks>*/ Compute(ControlFlowGraph cfg) { // depth-first search bool[] markBit = new bool[cfg.BlockCount]; FList result = null; int DFTime = 0; // Use a stack to represent the state of the search. // Each stack element consists of a basic block and the // the index of the next successor of that block to process. Stack stack = new Stack(); CfgBlock[] blocks = cfg.Blocks(); CfgBlock start = cfg.Entry; // invariant: all blocks pushed on the stack are marked. markBit[start.Index] = true; stack.Push(new StackElem(start)); while (stack.Count > 0) { StackElem elem = (StackElem)stack.Peek(); CfgBlock b = elem.node; int nextChild = elem.nextChild; CfgBlock[] normalNodes = cfg.NormalSucc(b); CfgBlock[] exnNodes = cfg.ExcpSucc(b); int normalNodesCount = normalNodes.Length; int exnNodesCount = exnNodes.Length; // Is there another child to process? if (nextChild < normalNodesCount + exnNodesCount) { // Figure out the actual block. CfgBlock child; if (nextChild < normalNodesCount) { child = normalNodes[nextChild]; } else { child = exnNodes[nextChild - normalNodesCount]; } elem.nextChild = nextChild + 1; // push the child block on to the stack. if (!markBit[child.Index]) { markBit[child.Index] = true; stack.Push(new StackElem(child)); } } else { // After all children are processed, place the block // on the result. stack.Pop(); b.priority = ++DFTime; result = FList.Cons(b, result); } } return(result); }