public ErrorTrace mapBackTrace(ErrorTrace trace) { if (!dict.ContainsKey(trace.procName)) { // missing transformations are assumed to be identity var ret = new ErrorTrace(getSrcProcName(trace.procName)); foreach (var blk in trace.Blocks) { ret.addBlock(new ErrorTraceBlock(blk.blockName)); foreach (var c in blk.Cmds) { if (c.isCall()) { CallInstr cc = c as CallInstr; if (cc.calleeTrace != null) { var t = mapBackTrace(cc.calleeTrace); ret.addInstr(new CallInstr(t, cc.asyncCall, cc.info)); continue; } } ret.addInstr(c); } } if (trace.returns) { ret.addReturn(trace.raisesException); } return(ret); } return(dict[trace.procName].mapBackTrace(trace, this)); }
// map back "trace" through this transformation public ErrorTrace mapBackTrace(ErrorTrace trace) { var ret = new ErrorTrace(trace.procName); foreach (var blk in trace.Blocks) { var blkTrans = getBlockTrans(trace.procName, blk.blockName); if (blkTrans == null) { // We don't have a transformation for this block: means identity // We just have to recurse on the callee traces and copy the rest. ret.addBlock(BlockTrans.mapBackTraceIdentity(blk, this)); } else { ret.addBlock(blkTrans.mapBackTrace(blk, this)); } } if (trace.returns) { ret.addReturn(trace.raisesException); } return(ret); }
public static ErrorTrace undoUnrolling(ErrorTrace trace) { // The heuristic used here is to get rid of the "#num" sign in the labels. // We assume that is the only way that Boogie.UnrollLoops changes the labels ErrorTrace ret = new ErrorTrace(trace.procName); for (int i = 0, n = trace.Blocks.Count; i < n; i++) { ret.addBlock(new ErrorTraceBlock(sanitizeLabel(trace.Blocks[i].blockName))); foreach (var c in trace.Blocks[i].Cmds) { if (c is CallInstr) { var cc = c as CallInstr; if (cc.calleeTrace != null) { ret.addInstr(new CallInstr(undoUnrolling(cc.calleeTrace), cc.asyncCall, cc.info)); continue; } } ret.addInstr(c); } } if (trace.returns) { ret.addReturn(); } return(ret); }
public override ErrorTrace mapBackTrace(ErrorTrace trace) { if (unrollNum >= 0) { return(base.mapBackTrace(trace)); } var ret = new ErrorTrace(trace.procName); var firstInfo = trace.Blocks[0].info; ErrorTraceBlock lastBlk = null; foreach (var blk in trace.Blocks) { var rblkLabel = elGetBlock(trace.procName, blk.blockName); if (rblkLabel != null) { lastBlk = new ErrorTraceBlock(rblkLabel); lastBlk.info = blk.info; if (ret.Blocks.Count == 0 && lastBlk.info == null) { lastBlk.info = firstInfo; } ret.addBlock(lastBlk); } foreach (var cmd in blk.Cmds) { var ccmd = cmd as CallInstr; if (ccmd == null || ccmd.calleeTrace == null) { if (lastBlk != null) { lastBlk.addInstr(cmd); } continue; } var ctrace = mapBackTrace(ccmd.calleeTrace); if (isLoop(ctrace.procName)) { // absorb trace ret.Blocks.AddRange(ctrace.Blocks); lastBlk = null; } else { if (lastBlk != null) { lastBlk.addInstr(new CallInstr(ctrace.procName, ctrace, ccmd.asyncCall, cmd.info)); } continue; } } } if (trace.returns && ret.Blocks.Count > 0) { ret.addReturn(trace.raisesException); } return(ret); }
public ErrorTrace mapBackTrace(ErrorTrace trace) { Debug.Assert(tinfo.ContainsKey(trace.procName)); var ret = new ErrorTrace(trace.procName); var info = tinfo[trace.procName]; foreach (var blk in trace.Blocks) { var peices = info[blk.blockName]; Debug.Assert(peices.Count != 0); // This is an index into blk.Cmds var cnt = 0; var done = false; var lastInf = blk.info; for (int i = 0; !done && i < peices.Count; i++) { // Do we have enough in blk.Cmds for peices[i]? if (cnt + peices[i].snd - 1 >= blk.Cmds.Count) { done = true; } var eblk = new ErrorTraceBlock(peices[i].fst); eblk.info = lastInf; int j = 0; while (j < peices[i].snd && cnt < blk.Cmds.Count) { var inst = blk.Cmds[cnt]; lastInf = inst.info; if (inst is CallInstr) { var cinst = inst as CallInstr; if (cinst.hasCalledTrace) { inst = new CallInstr(cinst.callee, mapBackTrace(cinst.calleeTrace), cinst.asyncCall, cinst.info); if (!(inst as CallInstr).calleeTrace.returns) { done = true; } } } eblk.addInstr(inst); cnt++; j++; } ret.addBlock(eblk); } } if (trace.returns) { ret.addReturn(); } return(ret); }
public ErrorTrace mapBackTraceRecord(ErrorTrace trace) { var ret = new ErrorTrace(trace.procName); foreach (var block in trace.Blocks) { var nb = new ErrorTraceBlock(block.blockName); foreach (var cmd in block.Cmds) { if (cmd is CallInstr) { var ccmd = cmd as CallInstr; if (ccmd.callee == recordProcNameInt || ccmd.callee == recordProcNameBool || ccmd.callee.StartsWith(recordProcNameCtor)) { Debug.Assert(nb.Cmds.Count != 0); nb.Cmds.Last().info = ccmd.info; continue; } if (ccmd.hasCalledTrace) { var c = new CallInstr(mapBackTraceRecord(ccmd.calleeTrace), ccmd.asyncCall, ccmd.info); nb.addInstr(c); } else { nb.addInstr(ccmd); } } else { nb.addInstr(cmd.Copy()); } } ret.addBlock(nb); } if (trace.returns) { ret.addReturn(trace.raisesException); } return(ret); }
public ErrorTrace mapBackTrace(ErrorTrace trace, InsertionTrans tinfo) { // Output to be constructed var ret = new ErrorTrace(tinfo.getSrcProcName(trace.procName)); // The current block being constructed ErrorTraceBlock curr = null; foreach (var blk in trace.Blocks) { if (toFromBlockMap.ContainsKey(blk.blockName)) { // This "blk" corresponds to some block in the source program, // then start a new block here. if (curr != null) { ret.addBlock(curr); } curr = new ErrorTraceBlock(toFromBlockMap[blk.blockName]); if (blk.info != null) { curr.info = blk.info.Copy(); } } for (int i = 0; i < blk.Cmds.Count; i++) { var toType = InstrTypeEnum.INTRA; string callee = null; if (blk.Cmds[i].isCall()) { var cc = (blk.Cmds[i] as CallInstr); callee = cc.callee; if (cc.asyncCall) { toType = InstrTypeEnum.ASYNC; } else { toType = InstrTypeEnum.CALL; } } var to = new InstrLocation(blk.blockName, i, new InstrType(toType, callee)); // Is there a corresponding source instruction? if (!toFromMap.ContainsKey(to)) { continue; } // This is the location of the corresponding source instruction var from = toFromMap[to]; // This is the source instruction var inst = getCorrespondingInst(from, blk.Cmds[i], tinfo); // Now we have to place "inst" in "ret" addToTrace(inst, from, ref curr, ret); } } if (curr != null) { ret.addBlock(curr); } if (trace.returns) { ret.addReturn(trace.raisesException); } return(ret); }
private ErrorTrace mapBackTraceInline(ErrorTrace trace) { Debug.Assert(trace.isIntra()); Program inputProg = inlineInput.getProgram(); var nameImplMap = BoogieUtil.nameImplMapping(inputProg); var traceLabels = trace.getBlockLabels(); var stack = new List <WorkItemR>(); Implementation startImpl = getImpl(trace.procName, nameImplMap); Debug.Assert(traceLabels[0] == startImpl.Blocks[0].Label); var curr = new WorkItemR(startImpl, traceLabels[0]); // This variable keeps our current position in traceLabels int ecount = 0; // This variable keeps our current position in traceLabels[ecount].Cmds int icount = 0; var ret = new ErrorTrace(trace.procName); ret.addBlock(new ErrorTraceBlock(traceLabels[0])); // We will walk over the input program, trying to cover the same path as // trace, knowing that trace represents an inlined path while (true) { // Reached the end of the path? if (ecount == traceLabels.Count) { break; } //Console.WriteLine(curr.impl.Name + ": " + curr.label); // Reached the end of the current block? if (curr.count == curr.block.Cmds.Count) { ecount++; icount = 0; if (ecount == traceLabels.Count) { break; } // Move onto the next block TransferCmd tc = curr.block.TransferCmd; if (tc is ReturnCmd) { ret.addReturn(); if (stack.Count == 0) { // We're done Debug.Assert(ecount == traceLabels.Count); break; } curr = stack[0]; stack.RemoveAt(0); // An inlined procedure ends with "Return" label Debug.Assert(inlinedLabelMatches("Return", traceLabels[ecount])); ecount++; icount = 0; Debug.Assert(traceLabels[ecount].Contains(curr.block.Label)); continue; } if (tc is GotoCmd) { List <String> targets = (tc as GotoCmd).labelNames; string target = matchInlinedLabelNames(targets, traceLabels[ecount]); curr = new WorkItemR(curr.impl, target); ret.addBlock(new ErrorTraceBlock(curr.label)); continue; } // Unknown transfer command Debug.Assert(false); } // We have to continue in the same block Cmd c = curr.block.Cmds[curr.count]; curr.count++; if (!(c is CallCmd)) { ret.addInstr(new IntraInstr(getInfo(trace, ecount, icount))); icount++; continue; } // We're at a procedure call CallCmd cc = c as CallCmd; // If this is a call to a procedure without implementation, then skip if (!nameImplMap.ContainsKey(cc.Proc.Name)) { ret.addInstr(new CallInstr(cc.Proc.Name, null, false, getInfo(trace, ecount, icount))); icount++; continue; } Implementation callee = getImpl(cc.Proc.Name, nameImplMap); string label = callee.Blocks[0].Label; // The first label in a inlined procedure is always called Entry ecount++; Debug.Assert(inlinedLabelMatches("Entry", traceLabels[ecount])); ecount++; icount = 0; Debug.Assert(inlinedLabelMatches(label, traceLabels[ecount])); WorkItemR next = new WorkItemR(callee, label); stack.Insert(0, curr); curr = next; ret.addCall(callee.Name); ret.addBlock(new ErrorTraceBlock(curr.label)); } return(ret); }