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); }