void Executor_ImplementationEntered(object sender, Symbooglix.Executor.EnterImplementationEventArgs e) { // Handle the case where we enter a new implementation and the first block // is a loop header. This is the only case we don't get notified of a basic block // change. var state = Executor.CurrentState; // FIXME: The state should be part of the event arg var sf = state.Mem.Stack.Last(); var loopInfo = ProgramLoopInfo.GetLoopInfoForHeader(sf.CurrentBlock); if (loopInfo == null) { return; // Not a loop. Nothing to do. } var executionStateSingleLoopInfo = new ExecutionStateSingleLoopInfo(sf, loopInfo); StateToCurrentLoops[state].NestedLoops.Push(executionStateSingleLoopInfo); }
public ExecutionStateNestedLoopInfo Clone(ExecutionState newState) { var other = (ExecutionStateNestedLoopInfo)this.MemberwiseClone(); other.State = newState; other.NestedLoops = new Stack <ExecutionStateSingleLoopInfo>(NestedLoops.Count); // Traverse in reverse order (i.e. start at bottom of the stack) // so we can push elements on to the new stack in the right order foreach (var sli in NestedLoops.Reverse()) { StackFrame stackFrameInNewState = GetCorrespondingStackFrame(newState, sli.Stack); ExecutionStateSingleLoopInfo newSli = sli.Clone(stackFrameInNewState); other.NestedLoops.Push(newSli); } Debug.Assert(other.NestedLoops.Count == NestedLoops.Count); return(other); }
void Executor_BasicBlockChanged(object sender, Symbooglix.Executor.TransferToBlockEventArgs eventArgs) { // Control flow has transferred to a different basic block var state = eventArgs.State; var sf = state.Mem.Stack.Last(); var executionStateNestedLoopInfo = StateToCurrentLoops[state]; // Cases: // * No existing loops, enter loop header // * No existing loops, do not enter loop header // * Existing loop, stackframe doesn't match (i.e. a call must have happenend), enter loop header // * Existing loop, stackframe doesn't match (i.e. a call must have happenend), do not enter loop header // * Existing loop, stackframe matches, enter loop header (must increment counter) // * Existing loop, stackframe matches, leave loop via exit basic block (we are leaving the current loop) // * Existing loop, stackframe matches, enter nested loop header (must push new loop on to stack) // * Existing loop, stackframe matches, stay in current loop (nothing to do) bool stackframeMatches = false; if (executionStateNestedLoopInfo.NestedLoops.Count > 0) { stackframeMatches = object.ReferenceEquals(executionStateNestedLoopInfo.NestedLoops.Peek().Stack, sf); } ExecutionStateSingleLoopInfo executionStateSingleLoopInfo = null; if (!stackframeMatches) { // This handles the case that there are no existing loops on the stack or // there are existing loops but they are in another stackframe (i.e. we were in a loop // and then called into another implementation). var loopInfo = ProgramLoopInfo.GetLoopInfoForHeader(eventArgs.NewBlock); if (loopInfo == null) { // The block we've entered is not a loop header and there are no // existing loops we are in that we can enter/exit so there is nothing // left to do return; } // We've enterred a new loop push it on to the loop stack executionStateSingleLoopInfo = new ExecutionStateSingleLoopInfo(sf, loopInfo); executionStateNestedLoopInfo.NestedLoops.Push(executionStateSingleLoopInfo); return; } // We are currently inside a loop and are still in the context of that loop's stackframe on the // call stack. executionStateSingleLoopInfo = executionStateNestedLoopInfo.NestedLoops.Peek(); if (object.ReferenceEquals(executionStateSingleLoopInfo.LInfo.Header, eventArgs.NewBlock)) { // We are going to the loop header so we must have just completed one iteration // of the loop. Increment the counter. executionStateSingleLoopInfo.IncrementCounter(); // Don't check bound here. The executor will misbehave (see goto look ahead) // if we try to terminate state here. return; } else if (executionStateSingleLoopInfo.LInfo.EscapingBlocks.Contains(eventArgs.NewBlock)) { // We are in a loop but are about to jump to a basic block that escapes from the loop. // So pop this loop from the stack. executionStateNestedLoopInfo.NestedLoops.Pop(); return; } var newLoopInfo = ProgramLoopInfo.GetLoopInfoForHeader(eventArgs.NewBlock); if (newLoopInfo == null) { // We are in a loop but we are jumping to a basic block that // * does not escape the current loop // * does not go to the loop head // * does not enter a nested loop (i.e. another loop head) // So there is nothing left to do. return; } // We are entering a nested loop. Push this loop onto the stack. var newExecutionStateSingleLoopInfo = new ExecutionStateSingleLoopInfo(sf, newLoopInfo); executionStateNestedLoopInfo.NestedLoops.Push(newExecutionStateSingleLoopInfo); return; }