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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
        }