private void addToTrace(ErrorTraceInstr inst, InstrLocation loc, ref ErrorTraceBlock curr, ErrorTrace trace) { if (curr == null) { curr = new ErrorTraceBlock(loc.blockName); Debug.Assert(loc.num == 0); curr.addInstr(inst); return; } // curr != null. We need to see if inst should be put inside curr or start a new block? if (loc.num == curr.Cmds.Count && loc.blockName == curr.blockName) { curr.addInstr(inst); } else { // start a new block Debug.Assert(loc.num == 0); trace.addBlock(curr); curr = new ErrorTraceBlock(loc.blockName); curr.addInstr(inst); } }
// map back through an identity transformation (basically just recurse // on the callee traces) public static ErrorTraceBlock mapBackTraceIdentity(ErrorTraceBlock tblock, ModifyTrans tinfo) { var ret = new ErrorTraceBlock(tblock.blockName); ret.info = tblock.info; for (int i = 0; i < tblock.Cmds.Count; i++) { var tp = new InstrType(); if (tblock.Cmds[i] is CallInstr) { var ci = tblock.Cmds[i] as CallInstr; if (ci.asyncCall) { tp = new InstrType(InstrTypeEnum.ASYNC, ci.callee); } else { tp = new InstrType(InstrTypeEnum.CALL, ci.callee); } } var it = new InstrTrans(tp); ret.addInstr(it.mapBackTrace(tblock.Cmds, i, tinfo)); } 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); }
// map back "trace" through this transformation. tinfo is the parent // transformation info for the whole program -- it is used for recursively // calling the mapBack procedure on callee traces public ErrorTraceBlock mapBackTrace(ErrorTraceBlock tblock, ModifyTrans tinfo) { var ret = new ErrorTraceBlock(tblock.blockName); ret.info = tblock.info; // This is the number of instructions in tblock that we've processed int count = 0; // This is an index into trans int trans_index = 0; while (trans_index < trans.Count) { var it = trans[trans_index]; // Does tblock have enough instructions for this transformation to apply? //if (count + it.Size <= tblock.Cmds.Count || // (it.correspondingInstr >= 0 && count + it.correspondingInstr <= tblock.Cmds.Count ) // break; var inst = it.mapBackTrace(tblock.Cmds, count, tinfo); if (inst == null) { break; } ret.addInstr(inst); // Are we done? if (inst is CallInstr && (inst as CallInstr).calleeTrace != null && ( !(inst as CallInstr).calleeTrace.returns || ( (inst as CallInstr).calleeTrace.raisesException && !(inst as CallInstr).asyncCall ) )) { break; } count += it.Size; trans_index++; } return(ret); }