示例#1
0
        // Note: this does not reconstruct the failing assert in trace
        public static void ReconstructImperativeTrace(Counterexample trace, string currProc, Dictionary <string, Implementation> origProg)
        {
            if (trace == null)
            {
                return;
            }

            var originalBlocks = BoogieUtil.labelBlockMapping(origProg[currProc]);

            var newBlocks       = new List <Block>();
            var newCalleeTraces = new Dictionary <TraceLocation, CalleeCounterexampleInfo>();

            for (int numBlock = 0; numBlock < trace.Trace.Count; numBlock++)
            {
                Block b = trace.Trace[numBlock];

                Block ib;
                originalBlocks.TryGetValue(b.Label, out ib);
                if (ib == null)
                {
                    // Such blocks correspond to "itermediate" blocks inserted
                    // by Boogie. We can ignore them. (But note that we should
                    // still check that the counterexample is a valid path in impl
                    // to guard against vagaries of Boogie.)

                    //Log.Out(Log.Normal, "Could not find block " + b.Label);
                    //b.Emit(new TokenTextWriter(Console.Out), 0);
                    for (int numInstr = 0; numInstr < b.Cmds.Count; numInstr++)
                    {
                        if (trace.calleeCounterexamples.ContainsKey(new TraceLocation(numBlock, numInstr)))
                        {
                            throw new InternalError("BoogieVerify: An intermediate block has a procedure call");
                        }
                    }
                }
                else
                {
                    // We have a corresponding block. The number of Commands in b and ib won't match. We
                    // simply use all of the Cmds of ib -- and match the calls manually
                    // TODO: Fix this! It doesn't work when the failing assert is not the last statement
                    // of the block
                    newBlocks.Add(ib);
                    var calleeTraces = new List <Duple <string, CalleeCounterexampleInfo> >();
                    for (int numInstr = 0; numInstr < b.Cmds.Count; numInstr++)
                    {
                        var loc = new TraceLocation(numBlock, numInstr);
                        if (trace.calleeCounterexamples.ContainsKey(loc))
                        {
                            Cmd c           = b.Cmds[numInstr];
                            var calleeName  = trace.getCalledProcName(c);
                            var calleeTrace = trace.calleeCounterexamples[loc].counterexample;
                            ReconstructImperativeTrace(calleeTrace, calleeName, origProg);
                            calleeTraces.Add(
                                new Duple <string, CalleeCounterexampleInfo>(
                                    calleeName,
                                    new CalleeCounterexampleInfo(calleeTrace,
                                                                 trace.calleeCounterexamples[loc].args)
                                    ));
                        }
                    }

                    // Check consistency and map calleeTraces to the actual call instructions
                    var currCount = 0;
                    for (int numInstr = 0; numInstr < ib.Cmds.Count; numInstr++)
                    {
                        Cmd c = ib.Cmds[numInstr];

                        if (!(c is CallCmd))
                        {
                            continue;
                        }

                        var cc = c as CallCmd;

                        // No more calls left to process
                        if (calleeTraces.Count <= currCount)
                        {
                            break;
                        }

                        if (cc.Proc.Name != calleeTraces[currCount].fst)
                        {
                            continue;
                        }

                        // Check if this proc has an implementation
                        //if (!origProg.ContainsKey(cc.Proc.Name))
                        //    continue;

                        // Check if the proc is inlined
                        //if (QKeyValue.FindExprAttribute(cc.Proc.Attributes, "inline") == null)
                        //    continue;

                        // Some thing wrong about the interprocedural trace returned by Boogie if the
                        // following don't match
                        // TODO: Fix when the failing assert is not the last statement of the block
                        //Debug.Assert(cc.Proc.Name == calleeTraces[currCount].fst);

                        newCalleeTraces.Add(new TraceLocation(newBlocks.Count - 1, numInstr), calleeTraces[currCount].snd);
                        currCount++;
                    }
                }
            }
            trace.Trace = newBlocks;
            // reset other info. Safe thing to do unless we know what it is
            trace.calleeCounterexamples = newCalleeTraces;
        }
示例#2
0
        public static Counterexample ReconstructTrace(Counterexample trace, string currProc, TraceLocation currLocation, Dictionary <string, Tuple <Block, Implementation> > origProg)
        {
            // we cannot be starting in the last block
            Debug.Assert(currLocation.numBlock != trace.Trace.Count - 1);
            // we cannot be starting in the middle of a block
            Debug.Assert(currLocation.numInstr == 0);

            var newTrace        = new List <Block>();
            var newTraceCallees = new Dictionary <TraceLocation, CalleeCounterexampleInfo>();

            Block          currOrigBlock = null;
            Implementation currOrigImpl  = null;
            int            currOrigInstr = 0;

            while (true)
            {
                if (currLocation.numInstr == 0 && origProg.ContainsKey(trace.Trace[currLocation.numBlock].Label))
                {
                    var origPlace = origProg[trace.Trace[currLocation.numBlock].Label];
                    if (currOrigImpl != null && currOrigImpl.Name != origPlace.Item2.Name)
                    {
                        // change of proc

                        // First, recurse
                        var calleeTrace = ReconstructTrace(trace, origPlace.Item2.Name, currLocation, origProg);
                        // Find the call to this guy in currOrigBlock
                        while (currOrigInstr < currOrigBlock.Cmds.Count)
                        {
                            var cmd = currOrigBlock.Cmds[currOrigInstr] as CallCmd;
                            if (cmd != null && cmd.callee == origPlace.Item2.Name)
                            {
                                break;
                            }
                            currOrigInstr++;
                        }
                        Debug.Assert(currOrigInstr != currOrigBlock.Cmds.Count);
                        newTraceCallees.Add(new TraceLocation(newTrace.Count - 1, currOrigInstr), new CalleeCounterexampleInfo(calleeTrace, new List <object>()));
                        // we're done
                        break;
                    }

                    currOrigBlock = origPlace.Item1;
                    currOrigImpl  = origProg[trace.Trace[currLocation.numBlock].Label].Item2;
                    currOrigInstr = 0;

                    newTrace.Add(currOrigBlock);
                }

                if (trace.calleeCounterexamples.ContainsKey(currLocation))
                {
                    // find the corresponding call in origBlock
                    var calleeInfo = trace.calleeCounterexamples[currLocation];
                    var calleeName = trace.getCalledProcName(trace.Trace[currLocation.numBlock].Cmds[currLocation.numInstr]);
                    while (currOrigInstr < currOrigBlock.Cmds.Count)
                    {
                        var cmd = currOrigBlock.Cmds[currOrigInstr] as CallCmd;
                        if (cmd != null && cmd.callee == calleeName)
                        {
                            break;
                        }
                        currOrigInstr++;
                    }
                    Debug.Assert(currOrigInstr != currOrigBlock.Cmds.Count);
                    newTraceCallees.Add(new TraceLocation(newTrace.Count - 1, currOrigInstr), calleeInfo);
                }

                // increment location
                currLocation.numInstr++;
                if (currLocation.numInstr >= trace.Trace[currLocation.numBlock].Cmds.Count)
                {
                    currLocation.numBlock++;
                    currLocation.numInstr = 0;
                }
                if (currLocation.numBlock == trace.Trace.Count)
                {
                    break;
                }
            }

            var ret = new AssertCounterexample(newTrace, null, null, trace.Model, trace.MvInfo, trace.Context);

            ret.calleeCounterexamples = newTraceCallees;

            return(ret);
        }