Пример #1
0
        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);
        }