Exemple #1
0
 public override Cmd VisitCallCmd(CallCmd node)
 {
     CallCmd callCmd = (CallCmd) base.VisitCallCmd(node);
     callCmd.Proc = VisitProcedure(callCmd.Proc);
     callCmd.callee = callCmd.Proc.Name;
     absyMap[callCmd] = node;
     return callCmd;
 }
Exemple #2
0
 public override bpl.Cmd VisitCallCmd(bpl.CallCmd node)
 {
     if (callGraph[curProc].ContainsKey(node.callee))
     {
         callGraph[curProc][node.callee]++;
     }
     else
     {
         callGraph[curProc][node.callee] = 1;
     }
     visited[node.callee] = 0;
     if (con.isAsyncCall(node))
     {
         instances[node.callee] = 0;
     }
     return(base.VisitCallCmd(node));
 }
        private void addMethodCalling(Bpl.Procedure proc, Bpl.Program program, Sink sink)
        {
            Bpl.Procedure callingProc = new Bpl.Procedure(Bpl.Token.NoToken, "__BOOGIE_CALL_" + proc.Name, new List <Bpl.TypeVariable>(), new List <Bpl.Variable>(),
                                                          new List <Bpl.Variable>(), new List <Bpl.Requires>(), new List <Bpl.IdentifierExpr>(), new List <Bpl.Ensures>());
            sink.TranslatedProgram.AddTopLevelDeclaration(callingProc);

            Bpl.StmtListBuilder       codeBuilder = new Bpl.StmtListBuilder();
            List <Bpl.Variable>       localVars   = new List <Bpl.Variable>(proc.InParams);
            List <Bpl.IdentifierExpr> identVars   = new List <Bpl.IdentifierExpr>();

            for (int i = 0; i < localVars.Count; i++)
            {
                identVars.Add(new Bpl.IdentifierExpr(Bpl.Token.NoToken, localVars[i]));
            }
            codeBuilder.Add(new Bpl.HavocCmd(Bpl.Token.NoToken, identVars));

            // FEEDBACK TODO this is possibly too much, I'm guessing sometimes this args might well be null
            Bpl.Expr notNullExpr;
            foreach (Bpl.IdentifierExpr idExpr in identVars)
            {
                if (idExpr.Type.Equals(sink.Heap.RefType))
                {
                    notNullExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, idExpr, Bpl.Expr.Ident(sink.Heap.NullRef));
                    codeBuilder.Add(new Bpl.AssumeCmd(Bpl.Token.NoToken, notNullExpr));
                }
            }

            List <Bpl.Expr> callParams = new List <Bpl.Expr>();

            for (int i = 0; i < identVars.Count; i++)
            {
                callParams.Add(identVars[i]);
            }
            Bpl.CallCmd callCmd = new Bpl.CallCmd(Bpl.Token.NoToken, proc.Name, callParams, new List <Bpl.IdentifierExpr>());
            codeBuilder.Add(callCmd);
            Bpl.Implementation impl = new Bpl.Implementation(Bpl.Token.NoToken, callingProc.Name, new List <Bpl.TypeVariable>(), new List <Bpl.Variable>(),
                                                             new List <Bpl.Variable>(), localVars, codeBuilder.Collect(Bpl.Token.NoToken));
            sink.TranslatedProgram.AddTopLevelDeclaration(impl);
        }
Exemple #4
0
 private void ProcessCallCmd(CallCmd originalCallCmd, CallCmd callCmd, List<Cmd> newCmds)
 {
     int enclosingProcLayerNum = moverTypeChecker.procToActionInfo[enclosingImpl.Proc].createdAtLayerNum;
     Procedure originalProc = originalCallCmd.Proc;
     if (moverTypeChecker.procToActionInfo.ContainsKey(originalProc))
     {
         AtomicActionInfo atomicActionInfo = moverTypeChecker.procToActionInfo[originalProc] as AtomicActionInfo;
         if (atomicActionInfo != null && atomicActionInfo.thisGate.Count > 0 && layerNum == enclosingProcLayerNum)
         {
             newCmds.Add(new HavocCmd(Token.NoToken, new List<IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(dummyLocalVar) })));
             Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
             for (int i = 0; i < originalProc.InParams.Count; i++)
             {
                 map[originalProc.InParams[i]] = callCmd.Ins[i];
             }
             Substitution subst = Substituter.SubstitutionFromHashtable(map);
             foreach (AssertCmd assertCmd in atomicActionInfo.thisGate)
             {
                 newCmds.Add(Substituter.Apply(subst, assertCmd));
             }
         }
     }
     newCmds.Add(callCmd);
 }
Exemple #5
0
        public void AddRecordCall(string label, Bpl.Type typeBpl, Bpl.Expr valueBpl)
        {
            /* Without this, some record calls show up on the wrong source lines in
             * the Corral trace or don't show up at all.  With it, the number of extra
             * blank lines in the trace increases in some cases but not in others.  I
             * think we're better off with this line.  TODO: understand how Corral
             * line directives are actually supposed to be used.
             * ~ REDACTED 2016-07-08 */
            EmitSecondaryLineDirective(Bpl.Token.NoToken);

            var logProcedureName = sink.FindOrCreateRecordProcedure(typeBpl);
            var call             = new Bpl.CallCmd(Bpl.Token.NoToken, logProcedureName, new List <Bpl.Expr> {
                valueBpl
            }, new List <Bpl.IdentifierExpr> {
            });

            // This seems to be the idiom (see Bpl.Program.addUniqueCallAttr).
            // XXX What does the token mean?  Should there be one?
            // ~ REDACTED 2016-06-13
            call.Attributes = new Bpl.QKeyValue(Bpl.Token.NoToken, "cexpr", new List <object> {
                label
            }, call.Attributes);
            StmtBuilder.Add(call);
        }
Exemple #6
0
 public override Cmd VisitCallCmd(CallCmd node)
 {
     HashSet<Variable> inVars = new HashSet<Variable>();
     for (int i = 0; i < node.Proc.InParams.Count; i++)
     {
         Variable formal = node.Proc.InParams[i];
         string domainName = FindDomainName(formal);
         if (domainName == null) continue;
         IdentifierExpr actual = node.Ins[i] as IdentifierExpr;
         if (actual == null)
         {
             Error(node, string.Format("Only variable can be passed to linear parameter {0}", formal.Name));
             continue;
         }
         string actualDomainName = FindDomainName(actual.Decl);
         if (actualDomainName == null)
         {
             Error(node, string.Format("Only a linear argument can be passed to linear parameter {0}", formal.Name));
             continue;
         }
         if (domainName != actualDomainName)
         {
             Error(node, "The domains of formal and actual parameters must be the same");
             continue;
         }
         if (actual.Decl is GlobalVariable)
         {
             Error(node, "Only local linear variable can be an actual input parameter of a procedure call");
             continue;
         }
         if (inVars.Contains(actual.Decl))
         {
             Error(node, string.Format("Linear variable {0} can occur only once as an input parameter", actual.Decl.Name));
             continue;
         }
         inVars.Add(actual.Decl);
     }
     for (int i = 0; i < node.Proc.OutParams.Count; i++)
     {
         IdentifierExpr actual = node.Outs[i];
         string actualDomainName = FindDomainName(actual.Decl);
         if (actualDomainName == null) continue;
         Variable formal = node.Proc.OutParams[i];
         string domainName = FindDomainName(formal);
         if (domainName == null)
         {
             Error(node, "Only a linear variable can be passed to a linear parameter");
             continue;
         }
         if (domainName != actualDomainName)
         {
             Error(node, "The domains of formal and actual parameters must be the same");
             continue;
         }
         if (actual.Decl is GlobalVariable)
         {
             Error(node, "Only local linear variable can be actual output parameter of a procedure call");
             continue;
         }
     }
     return base.VisitCallCmd(node);
 }
    public override Cmd VisitCallCmd(CallCmd node)
    {
      if (currentDeclaration != null)
      {
        currentDeclaration.AddProcedureDependency(node.Proc);
      }

      return base.VisitCallCmd(node);
    }
Exemple #8
0
 public override Cmd VisitCallCmd(CallCmd node)
 {
     Contract.Ensures(Contract.Result<Cmd>() == node);
     for (int i = 0; i < node.Ins.Count; ++i)
         if (node.Ins[i] != null)
             this.VisitExpr(node.Ins[i]);
     for (int i = 0; i < node.Outs.Count; ++i)
         if (node.Outs[i] != null)
             this.VisitIdentifierExpr(node.Outs[i]);
     return node;
 }
        public override Cmd VisitCallCmd(CallCmd node)
        {
            var visited = dependencies.Contains(node.Proc);
              if (!visited)
              {
            node.Proc = VisitProcedure(node.Proc);
              }

              return base.VisitCallCmd(node);
        }
Exemple #10
0
 public bool CallExists(CallCmd callCmd, int enclosingProcLayerNum, int layerNum)
 {
     Debug.Assert(procToAtomicProcedureInfo.ContainsKey(callCmd.Proc));
     var atomicProcedureInfo = procToAtomicProcedureInfo[callCmd.Proc];
     if (atomicProcedureInfo.isPure)
     {
         return pureCallLayer[callCmd] <= layerNum;
     }
     else
     {
         return enclosingProcLayerNum == layerNum;
     }
 }
Exemple #11
0
	void CallParams(bool isAsync, bool isFree, QKeyValue kv, IToken x, out Cmd c) {
		List<IdentifierExpr> ids = new List<IdentifierExpr>();
		List<Expr> es = new List<Expr>();
		Expr en;
		IToken first; 
		IToken p;
		c = null;
		
		Ident(out first);
		if (la.kind == 10) {
			Get();
			if (StartOf(9)) {
				Expression(out en);
				es.Add(en); 
				while (la.kind == 13) {
					Get();
					Expression(out en);
					es.Add(en); 
				}
			}
			Expect(11);
			c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; 
		} else if (la.kind == 13 || la.kind == 51) {
			ids.Add(new IdentifierExpr(first, first.val)); 
			if (la.kind == 13) {
				Get();
				Ident(out p);
				ids.Add(new IdentifierExpr(p, p.val)); 
				while (la.kind == 13) {
					Get();
					Ident(out p);
					ids.Add(new IdentifierExpr(p, p.val)); 
				}
			}
			Expect(51);
			Ident(out first);
			Expect(10);
			if (StartOf(9)) {
				Expression(out en);
				es.Add(en); 
				while (la.kind == 13) {
					Get();
					Expression(out en);
					es.Add(en); 
				}
			}
			Expect(11);
			c = new CallCmd(x, first.val, es, ids, kv); ((CallCmd) c).IsFree = isFree; ((CallCmd) c).IsAsync = isAsync; 
		} else SynErr(112);
	}
Exemple #12
0
 // Redundant for this class; but gives a chance for other classes to
 // override this and implement their own inlining policy
 protected virtual int GetInlineCount(CallCmd callCmd, Implementation impl)
 {
     return GetInlineCount(impl);
 }
Exemple #13
0
        private void CreateStructCopyConstructor(ITypeDefinition typeDefinition)
        {
            Contract.Requires(typeDefinition.IsStruct);

            var proc = this.sink.FindOrCreateProcedureForStructCopy(typeDefinition);

            var stmtBuilder = new Bpl.StmtListBuilder();

            var tok = Bpl.Token.NoToken;

            var o = Bpl.Expr.Ident(proc.OutParams[0]);

            // other := Alloc();
            stmtBuilder.Add(new Bpl.CallCmd(tok, this.sink.AllocationMethodName, new List <Bpl.Expr>(), new List <Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] { o })));
            // assume DynamicType(other) == DynamicType(this);
            stmtBuilder.Add(new Bpl.AssumeCmd(tok, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, this.sink.Heap.DynamicType(o), this.sink.Heap.DynamicType(Bpl.Expr.Ident(proc.InParams[0])))));

            var localVars = new List <Bpl.Variable>();

            foreach (var f in typeDefinition.Fields)
            {
                if (f.IsStatic)
                {
                    continue;
                }

                var fExp       = Bpl.Expr.Ident(this.sink.FindOrCreateFieldVariable(f));
                var boogieType = sink.CciTypeToBoogie(f.Type);

                if (TranslationHelper.IsStruct(f.Type))
                {
                    // generate a call to the copy constructor to copy the contents of f
                    var proc2     = this.sink.FindOrCreateProcedureForStructCopy(f.Type);
                    var e         = this.sink.Heap.ReadHeap(Bpl.Expr.Ident(proc.InParams[0]), fExp, AccessType.Struct, boogieType);
                    var bplLocal  = this.sink.CreateFreshLocal(f.Type);
                    var localExpr = Bpl.Expr.Ident(bplLocal);
                    localVars.Add(bplLocal);
                    var cmd = new Bpl.CallCmd(tok, proc2.Name, new List <Bpl.Expr> {
                        e,
                    }, new List <Bpl.IdentifierExpr> {
                        localExpr,
                    });
                    stmtBuilder.Add(cmd);
                    this.sink.Heap.WriteHeap(tok, o, fExp, localExpr, AccessType.Struct, boogieType, stmtBuilder);
                }
                else
                {
                    // just generate a normal assignment to the field f
                    var e = this.sink.Heap.ReadHeap(Bpl.Expr.Ident(proc.InParams[0]), fExp, AccessType.Struct, boogieType);
                    this.sink.Heap.WriteHeap(tok, o, fExp, e, AccessType.Struct, boogieType, stmtBuilder);
                }
            }

            var lit = Bpl.Expr.Literal(1);

            lit.Type = Bpl.Type.Int;
            var args = new List <object> {
                lit
            };
            var attrib = new Bpl.QKeyValue(typeDefinition.Token(), "inline", args, null);

            Bpl.Implementation impl =
                new Bpl.Implementation(Bpl.Token.NoToken,
                                       proc.Name,
                                       new List <Bpl.TypeVariable>(),
                                       proc.InParams,
                                       proc.OutParams,
                                       localVars,
                                       stmtBuilder.Collect(Bpl.Token.NoToken),
                                       attrib,
                                       new Bpl.Errors()
                                       );

            impl.Proc = (Bpl.Procedure)proc; // TODO: get rid of cast
            this.sink.TranslatedProgram.AddTopLevelDeclaration(impl);
        }
Exemple #14
0
        public bpl.Program split(bpl.Program prog)
        {
            originalProgram = prog;
            ////////////////// First identify the thread entries in the program ////////////////////
            // A procedure is a thread entry if there is any async call to it
            HashSet <string> threadEntries = new HashSet <string>();
            var impls = new Func <bpl.Program, IEnumerable <bpl.Implementation> >(p => from impl in p.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation);

            foreach (var impl in impls(originalProgram))
            {
                var cmdsRaw    = from blk in impl.Blocks select blk.Cmds;
                var cmds       = cmdsRaw.Aggregate(new List <bpl.Cmd>(), (curCmds, nextList) => { curCmds.AddRange(nextList); return(curCmds); });
                var asyncCalls = from cmd in cmds where  con.isAsyncCall(cmd as bpl.Cmd) select cmd;
                foreach (bpl.Cmd asyncCall in asyncCalls)
                {
                    threadEntries.Add((asyncCall as bpl.CallCmd).callee);
                }
            }
            // Finally add the entry function also as a thread entry.
            threadEntries.Add(con.entryFunc);

            //////////////// Next, identify all the procedures belonging to each thread ////////////
            Dictionary <string, HashSet <string> > threadToProcs = new Dictionary <string, HashSet <string> >();
            // This is done in two steps.
            // First step: Find all non-async calls in each procedure.
            var procToCalls = new Dictionary <string, HashSet <string> >();

            //impls = from impl in prog.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation;
            foreach (var impl in impls(originalProgram))
            {
                procToCalls[impl.Name] = new HashSet <string>();
                var cmdsRaw   = from blk in impl.Blocks select blk.Cmds;
                var cmds      = cmdsRaw.Aggregate(new List <bpl.Cmd>(), (curCmds, nextList) => { curCmds.AddRange(nextList); return(curCmds); });
                var syncCalls = from cmd in cmds where con.isSyncCall(cmd as bpl.Cmd) select cmd;
                foreach (bpl.Cmd syncCall in syncCalls)
                {
                    procToCalls[impl.Name].Add((syncCall as bpl.CallCmd).callee);
                }
            }
            // Second step: Find all procedures in each thread.
            foreach (var thr in threadEntries)
            {
                threadToProcs[thr] = new HashSet <string>();
            }
            foreach (var thr in threadEntries)
            {
                findReachable(procToCalls, thr, threadToProcs[thr]);
            }
            //DEBUGGING
            if (dbg)
            {
                System.Console.WriteLine("Threads in the original program:");
                foreach (var iter in threadToProcs)
                {
                    System.Console.Write(iter.Key + ": ");
                    foreach (var proc in iter.Value)
                    {
                        System.Console.Write(proc + " ");
                    }
                    System.Console.WriteLine();
                }
            }


            // [Optional]
            // Remove unreachable procs.
            // These procedures are neither reachable from Main, nor from a thread entry. They can obviously not be called in any execution.
            var reachableProcs = new HashSet <string>();

            foreach (var vals in threadToProcs.Values)
            {
                foreach (var proc in vals)
                {
                    reachableProcs.Add(proc);
                }
            }
            foreach (var val in threadToProcs.Keys)
            {
                reachableProcs.Add(val);
            }
            removeUnreachable(reachableProcs);



            //////////////// Finally, Actually split the procedures when needed //////////////////
            // For every procedure, find out how many threads contain it. We need as many copies of
            // that procedure.
            // Note: We do not want to duplicate procedures without implementation.
            //impls = from impl in prog.TopLevelDeclarations where impl is bpl.Implementation select impl as bpl.Implementation;
            var implNames = from impl in impls(originalProgram) select impl.Name;
            Dictionary <string, int> procCopies = new Dictionary <string, int>();
            var procs = from proc in originalProgram.TopLevelDeclarations where proc is bpl.Procedure select proc as bpl.Procedure;

            foreach (var proc in procs)
            {
                procCopies[proc.Name] = 0;
            }
            foreach (var iter in threadToProcs)
            {
                foreach (var proc in iter.Value)
                {
                    if (implNames.Contains(proc))
                    {
                        procCopies[proc]++;
                    }
                }
            }

            // Now duplicate
            // The new procedures and implementations for each thread
            // thread name --> (old procedure name --> new procedure)
            var newProcsPerThread = new Dictionary <string, Dictionary <string, bpl.Procedure> >();
            // thread name --> (old procedure name --> new implementation)
            var newImplsPerThread = new Dictionary <string, Dictionary <string, bpl.Implementation> >();
            // old name --> proc, old name --> impl
            var oldNameToImpl = new Dictionary <string, bpl.Implementation>();

            foreach (var impl in impls(originalProgram))
            {
                oldNameToImpl[impl.Name] = impl;
            }
            var oldNameToProc = new Dictionary <string, bpl.Procedure>();

            foreach (var proc in procs)
            {
                oldNameToProc[proc.Name] = proc;
            }
            foreach (var elem in threadToProcs)
            {
                string threadName = elem.Key;
                newProcsPerThread[threadName] = new Dictionary <string, bpl.Procedure>();
                newImplsPerThread[threadName] = new Dictionary <string, bpl.Implementation>();
                foreach (var procName in elem.Value)
                {
                    if (procCopies[procName] > 1)
                    {
                        // We will duplicate this procedure.
                        // Make a copy of the procedure and implementation
                        var dup  = new cba.Util.FixedDuplicator();
                        var impl = (bpl.Implementation)dup.VisitDeclaration(oldNameToImpl[procName]);
                        var proc = (bpl.Procedure)dup.VisitDeclaration(oldNameToProc[procName]);
                        impl.Proc = proc;

                        // Rename the new instances using thread id.
                        impl.Name = con.getSplitProcName(procName);
                        proc.Name = con.getSplitProcName(procName);
                        var origProcAttr = con.originalProcAttr(procName);
                        origProcAttr.Next = proc.Attributes;
                        proc.Attributes   = origProcAttr;

                        // Also add an attribute to the definition specifying the thread.
                        var threadAttr = con.getThreadAttr(threadName);
                        threadAttr.Next = proc.Attributes;
                        proc.Attributes = threadAttr;

                        //add to duplicated procedures/impls
                        newProcsPerThread[threadName][procName] = proc;
                        newImplsPerThread[threadName][procName] = impl;

                        //Add to the program
                        originalProgram.AddTopLevelDeclaration(proc);
                        originalProgram.AddTopLevelDeclaration(impl);

                        var s1 = new HashSet <string>();
                        var s2 = new HashSet <string>();
                        foreach (var im in originalProgram.TopLevelDeclarations.OfType <bpl.Implementation>())
                        {
                            s1.Add(im.Name);
                        }
                        foreach (var im in impls(originalProgram))
                        {
                            s2.Add(im.Name);
                        }

                        // We have split away the procedure calls for one thread.
                        procCopies[procName]--;
                    }
                    else if (procCopies[procName] == 1)
                    {
                        //We still need to rename this procedure
                        var impl = oldNameToImpl[procName];
                        var proc = oldNameToProc[procName];

                        //rename the new instances using thread id.
                        impl.Name = con.getSplitProcName(procName);
                        proc.Name = con.getSplitProcName(procName);
                        var origProcAttr = con.originalProcAttr(procName);
                        origProcAttr.Next = proc.Attributes;
                        proc.Attributes   = origProcAttr;

                        // Also add an attribute to the definition specifying the thread.
                        var threadAttr = con.getThreadAttr(threadName);
                        threadAttr.Next = proc.Attributes;
                        proc.Attributes = threadAttr;

                        //add to duplicated procedures/impls
                        newProcsPerThread[threadName][procName] = proc;
                        newImplsPerThread[threadName][procName] = impl;

                        // We have split away the procedure calls for one thread.
                        procCopies[procName]--;
                    }
                }
                // Tell con that we're done with one thread.
                con.nextThread();
            }

            // New re-route procedure calls as needed
            // First async calls.
            foreach (var impl in impls(originalProgram))
            {
                foreach (var blk in impl.Blocks)
                {
                    for (int i = 0; i < blk.Cmds.Count; i++)
                    {
                        bpl.Cmd cmd = blk.Cmds[i];
                        if (con.isAsyncCall(cmd))
                        {
                            var callCmd    = cmd as bpl.CallCmd;
                            var newCallCmd = new bpl.CallCmd(bpl.Token.NoToken, newProcsPerThread[callCmd.callee][callCmd.callee].Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes, callCmd.IsAsync);
                            newCallCmd.TypeParameters = callCmd.TypeParameters;
                            newCallCmd.Proc           = newProcsPerThread[callCmd.callee][callCmd.callee];
                            blk.Cmds[i] = newCallCmd;
                        }
                    }
                }
            }
            // Now sync calls.
            foreach (var elem in newImplsPerThread)
            {
                string threadName = elem.Key;
                var    newImpls   = newImplsPerThread[threadName];
                foreach (var implTuple in newImpls)
                {
                    var impl = implTuple.Value;
                    foreach (var blk in impl.Blocks)
                    {
                        for (int i = 0; i < blk.Cmds.Count; ++i)
                        {
                            bpl.Cmd cmd = blk.Cmds[i];
                            if (con.isSyncCall(cmd) && newProcsPerThread[threadName].ContainsKey((cmd as bpl.CallCmd).callee))
                            {
                                var callCmd    = cmd as bpl.CallCmd;
                                var newCallCmd = new bpl.CallCmd(bpl.Token.NoToken, newProcsPerThread[threadName][callCmd.callee].Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes, callCmd.IsAsync);
                                newCallCmd.TypeParameters = callCmd.TypeParameters;
                                newCallCmd.Proc           = newProcsPerThread[threadName][callCmd.callee];
                                blk.Cmds[i] = newCallCmd;
                            }
                        }
                    }
                }
            }

            // Finally, label the entry of each thread as thread entry.
            foreach (var elem in newProcsPerThread)
            {
                var proc            = elem.Value[elem.Key];
                var threadEntryAttr = con.getThreadEntryAttr();
                threadEntryAttr.Next = proc.Attributes;
                proc.Attributes      = threadEntryAttr;
            }

            return(originalProgram);
        }
Exemple #15
0
        private void AddYieldProcAndImpl(List<Declaration> decls)
        {
            if (yieldProc == null) return;

            Program program = linearTypeChecker.program;
            List<Variable> inputs = new List<Variable>();
            foreach (string domainName in linearTypeChecker.linearDomains.Keys)
            {
                var domain = linearTypeChecker.linearDomains[domainName];
                Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
                inputs.Add(f);
            }
            foreach (IdentifierExpr ie in globalMods)
            {
                Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", ie.Decl.Name), ie.Decl.TypedIdent.Type), true);
                inputs.Add(f);
            }
            List<Block> blocks = new List<Block>();
            TransferCmd transferCmd = new ReturnCmd(Token.NoToken);
            if (yieldCheckerProcs.Count > 0)
            {
                List<Block> blockTargets = new List<Block>();
                List<String> labelTargets = new List<String>();
                int labelCount = 0;
                foreach (Procedure proc in yieldCheckerProcs)
                {
                    List<Expr> exprSeq = new List<Expr>();
                    foreach (Variable v in inputs)
                    {
                        exprSeq.Add(Expr.Ident(v));
                    }
                    CallCmd callCmd = new CallCmd(Token.NoToken, proc.Name, exprSeq, new List<IdentifierExpr>());
                    callCmd.Proc = proc;
                    string label = string.Format("L_{0}", labelCount++);
                    Block block = new Block(Token.NoToken, label, new List<Cmd> { callCmd }, new ReturnCmd(Token.NoToken));
                    labelTargets.Add(label);
                    blockTargets.Add(block);
                    blocks.Add(block);
                }
                transferCmd = new GotoCmd(Token.NoToken, labelTargets, blockTargets);
            }
            blocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), transferCmd));

            var yieldImpl = new Implementation(Token.NoToken, yieldProc.Name, new List<TypeVariable>(), inputs, new List<Variable>(), new List<Variable>(), blocks);
            yieldImpl.Proc = yieldProc;
            yieldImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
            decls.Add(yieldProc);
            decls.Add(yieldImpl);
        }
Exemple #16
0
        private List<List<Cmd>> CollectAndDesugarYields(Implementation impl,
            Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap)
        {
            // Collect the yield predicates and desugar yields
            List<List<Cmd>> yields = new List<List<Cmd>>();
            List<Cmd> cmds = new List<Cmd>();
            foreach (Block b in impl.Blocks)
            {
                YieldCmd yieldCmd = null;
                List<Cmd> newCmds = new List<Cmd>();
                for (int i = 0; i < b.Cmds.Count; i++)
                {
                    Cmd cmd = b.Cmds[i];
                    if (cmd is YieldCmd)
                    {
                        yieldCmd = (YieldCmd)cmd;
                        continue;
                    }
                    if (yieldCmd != null)
                    {
                        PredicateCmd pcmd = cmd as PredicateCmd;
                        if (pcmd == null)
                        {
                            DesugarYield(yieldCmd, cmds, newCmds, ogOldGlobalMap, domainNameToInputVar, domainNameToLocalVar);
                            if (cmds.Count > 0)
                            {
                                yields.Add(cmds);
                                cmds = new List<Cmd>();
                            }
                            yieldCmd = null;
                        }
                        else
                        {
                            cmds.Add(pcmd);
                        }
                    }

                    if (cmd is CallCmd)
                    {
                        CallCmd callCmd = cmd as CallCmd;
                        if (yieldingProcs.Contains(callCmd.Proc))
                        {
                            AddCallToYieldProc(callCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
                        }
                        if (callCmd.IsAsync)
                        {
                            if (!asyncAndParallelCallDesugarings.ContainsKey(callCmd.Proc.Name))
                            {
                                asyncAndParallelCallDesugarings[callCmd.Proc.Name] = new Procedure(Token.NoToken, string.Format("DummyAsyncTarget_{0}", callCmd.Proc.Name), callCmd.Proc.TypeParameters, callCmd.Proc.InParams, callCmd.Proc.OutParams, callCmd.Proc.Requires, new List<IdentifierExpr>(), new List<Ensures>());
                            }
                            var dummyAsyncTargetProc = asyncAndParallelCallDesugarings[callCmd.Proc.Name];
                            CallCmd dummyCallCmd = new CallCmd(callCmd.tok, dummyAsyncTargetProc.Name, callCmd.Ins, callCmd.Outs, callCmd.Attributes);
                            dummyCallCmd.Proc = dummyAsyncTargetProc;
                            newCmds.Add(dummyCallCmd);
                        }
                        else
                        {
                            newCmds.Add(callCmd);
                        }
                        if (yieldingProcs.Contains(callCmd.Proc))
                        {
                            HashSet<Variable> availableLinearVars = new HashSet<Variable>(AvailableLinearVars(callCmd));
                            linearTypeChecker.AddAvailableVars(callCmd, availableLinearVars);

                            if (!callCmd.IsAsync && globalMods.Count > 0 && pc != null)
                            {
                                // assume pc || alpha(i, g);
                                Expr assumeExpr = Expr.Or(Expr.Ident(pc), alpha);
                                assumeExpr.Type = Type.Bool;
                                newCmds.Add(new AssumeCmd(Token.NoToken, assumeExpr));
                            }

                            Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(availableLinearVars, domainNameToInputVar);
                            AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
                        }
                    }
                    else if (cmd is ParCallCmd)
                    {
                        ParCallCmd parCallCmd = cmd as ParCallCmd;
                        AddCallToYieldProc(parCallCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
                        DesugarParallelCallCmd(newCmds, parCallCmd);
                        HashSet<Variable> availableLinearVars = new HashSet<Variable>(AvailableLinearVars(parCallCmd));
                        linearTypeChecker.AddAvailableVars(parCallCmd, availableLinearVars);

                        if (globalMods.Count > 0 && pc != null)
                        {
                            // assume pc || alpha(i, g);
                            Expr assumeExpr = Expr.Or(Expr.Ident(pc), alpha);
                            assumeExpr.Type = Type.Bool;
                            newCmds.Add(new AssumeCmd(Token.NoToken, assumeExpr));
                        }

                        Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(availableLinearVars, domainNameToInputVar);
                        AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr);
                    }
                    else
                    {
                        newCmds.Add(cmd);
                    }
                }
                if (yieldCmd != null)
                {
                    DesugarYield(yieldCmd, cmds, newCmds, ogOldGlobalMap, domainNameToInputVar, domainNameToLocalVar);
                    if (cmds.Count > 0)
                    {
                        yields.Add(cmds);
                        cmds = new List<Cmd>();
                    }
                }
                if (b.TransferCmd is ReturnCmd)
                {
                    AddCallToYieldProc(b.TransferCmd.tok, newCmds, ogOldGlobalMap, domainNameToLocalVar);
                    if (pc != null)
                    {
                        AssertCmd assertCmd = new AssertCmd(b.TransferCmd.tok, Expr.Ident(ok));
                        assertCmd.ErrorData = "Failed to execute atomic action before procedure return";
                        newCmds.Add(assertCmd);
                    }
                }
                b.Cmds = newCmds;
            }
            return yields;
        }
Exemple #17
0
    private int InlineCallCmd(Block block, CallCmd callCmd, Implementation impl, List<Cmd> newCmds, List<Block> newBlocks, int lblCount)
    {
        Contract.Assume(impl != null);
        Contract.Assert(cce.NonNull(impl.OriginalBlocks).Count > 0);

        // do inline now
        int nextlblCount = lblCount + 1;
        string nextBlockLabel = block.Label + "$" + nextlblCount;

        // run the callback before each inline
        if (inlineCallback != null)
        {
            inlineCallback(impl);
        }

        // increment the counter for the procedure to be used in constructing the locals and formals
        NextInlinedProcLabel(impl.Proc.Name);

        BeginInline(impl);

        List<Block/*!*/>/*!*/ inlinedBlocks = CreateInlinedBlocks(callCmd, impl, nextBlockLabel);
        Contract.Assert(cce.NonNullElements(inlinedBlocks));

        EndInline();

        if (inlineDepth >= 0)
        {
            Debug.Assert(inlineDepth > 0);
            inlineDepth = inlineDepth - 1;
        }
        else
        {
            recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] - 1;
        }

        bool inlinedSomething = true;
        inlinedBlocks = DoInlineBlocks(inlinedBlocks, ref inlinedSomething);

        if (inlineDepth >= 0)
        {
            inlineDepth = inlineDepth + 1;
        }
        else
        {
            recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] + 1;
        }

        Block/*!*/ startBlock = inlinedBlocks[0];
        Contract.Assert(startBlock != null);

        GotoCmd gotoCmd = new GotoCmd(Token.NoToken, new List<String> { startBlock.Label });
        Block newBlock = new Block(block.tok, ((lblCount == 0) ? (block.Label) : (block.Label + "$" + lblCount)), newCmds, gotoCmd);

        newBlocks.Add(newBlock);
        newBlocks.AddRange(inlinedBlocks);

        return nextlblCount;
    }
    // REVIEW: Does "thisExpr" really need to come back as an identifier? Can't it be a general expression?
    protected Bpl.DeclWithFormals TranslateArgumentsAndReturnProcedure(Bpl.IToken token, IMethodReference methodToCall, IMethodDefinition resolvedMethod, IExpression/*?*/ thisArg, IEnumerable<IExpression> arguments, out List<Bpl.Expr> inexpr, out List<Bpl.IdentifierExpr> outvars, out Bpl.IdentifierExpr thisExpr, out Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> toUnioned) {
      inexpr = new List<Bpl.Expr>();
      outvars = new List<Bpl.IdentifierExpr>();

      #region Create the 'this' argument for the function call
      thisExpr = null;
      if (thisArg != null) {

        // Special case! thisArg is going to be an AddressOf expression if the receiver is a value-type
        // But if the method's containing type is something that doesn't get translated as a Ref, then
        // the AddressOf node should be ignored.
        var addrOf = thisArg as IAddressOf;
        var boogieType = this.sink.CciTypeToBoogie(methodToCall.ContainingType);
        if (false && addrOf != null && boogieType != this.sink.Heap.RefType) {
          thisArg = addrOf.Expression;
        }

        this.Traverse(thisArg);

        var e = this.TranslatedExpressions.Pop();
        var identifierExpr = e as Bpl.IdentifierExpr;
        if (identifierExpr == null) {
          var newLocal = Bpl.Expr.Ident(this.sink.CreateFreshLocal(methodToCall.ContainingType));
          var cmd = Bpl.Cmd.SimpleAssign(token, newLocal, e);
          this.StmtTraverser.StmtBuilder.Add(cmd);
          e = newLocal;
        } else {

        }
        inexpr.Add(e);
        thisExpr = (Bpl.IdentifierExpr) e;
      }
      #endregion

      toUnioned = new Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>>();
      IEnumerator<IParameterDefinition> penum = resolvedMethod.Parameters.GetEnumerator();
      penum.MoveNext();
      foreach (IExpression exp in arguments) {
        if (penum.Current == null) {
          throw new TranslationException("More arguments than parameters in method call");
        }

        var expressionToTraverse = exp;
        //Bpl.Type boogieTypeOfExpression;

        //// Special case! exp can be an AddressOf expression if it is a value type being passed by reference.
        //// But since we pass reference parameters by in-out value passing, need to short-circuit the
        //// AddressOf node if the underlying type is not a Ref.
        //var addrOf = exp as IAddressOf;
        //if (addrOf != null) {
        //  boogieTypeOfExpression = this.sink.CciTypeToBoogie(addrOf.Expression.Type);
        //  if (boogieTypeOfExpression != this.sink.Heap.RefType) {
        //    expressionToTraverse = addrOf.Expression;
        //  }
        //}

        //boogieTypeOfExpression = this.sink.CciTypeToBoogie(expressionToTraverse.Type);
        this.Traverse(expressionToTraverse);

        Bpl.Expr e = this.TranslatedExpressions.Pop();
        var currentType = penum.Current.Type;

        // If the argument is a struct, then make a copy of it to pass to the procedure.
        if (TranslationHelper.IsStruct(exp.Type)) {
          var proc = this.sink.FindOrCreateProcedureForStructCopy(exp.Type);
          var bplLocal = Bpl.Expr.Ident(this.sink.CreateFreshLocal(exp.Type));
          var cmd = new Bpl.CallCmd(token, proc.Name, new List<Bpl.Expr> { e, }, new List<Bpl.IdentifierExpr> { bplLocal, });
          this.StmtTraverser.StmtBuilder.Add(cmd);
          e = bplLocal;
        }

        if (currentType is IGenericParameterReference && this.sink.CciTypeToBoogie(currentType) == this.sink.Heap.UnionType) {
            inexpr.Add(sink.Heap.ToUnion(token, this.sink.CciTypeToBoogie(expressionToTraverse.Type), e, TranslationHelper.IsStruct(expressionToTraverse.Type), StmtTraverser.StmtBuilder));
        } else {
            inexpr.Add(e);
        }
        if (penum.Current.IsByReference) {
          Bpl.IdentifierExpr unboxed = e as Bpl.IdentifierExpr;
          if (unboxed == null) {
            throw new TranslationException("Trying to pass a complex expression for an out or ref parameter");
          }
          if (penum.Current.Type is IGenericParameterReference) {
            var boogieType = this.sink.CciTypeToBoogie(penum.Current.Type);
            if (boogieType == this.sink.Heap.UnionType) {
              Bpl.IdentifierExpr boxed = Bpl.Expr.Ident(sink.CreateFreshLocal(this.sink.Heap.UnionType));
              toUnioned[unboxed] = Tuple.Create(boxed,false);
              outvars.Add(boxed);
            } else {
              outvars.Add(unboxed);
            }
          } else {
            outvars.Add(unboxed);
          }
        }
        penum.MoveNext();
      }

      if (resolvedMethod.IsStatic) {
        List<ITypeReference> consolidatedTypeArguments = new List<ITypeReference>();
        Sink.GetConsolidatedTypeArguments(consolidatedTypeArguments, methodToCall.ContainingType);
        foreach (ITypeReference typeReference in consolidatedTypeArguments) {
          inexpr.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference));
        }
      }
      IGenericMethodInstanceReference methodInstanceReference = methodToCall as IGenericMethodInstanceReference;
      if (methodInstanceReference != null) {
        foreach (ITypeReference typeReference in methodInstanceReference.GenericArguments) {
          inexpr.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference));
        }
      }

      var procInfo = this.sink.FindOrCreateProcedure(resolvedMethod);
      var translateAsFunctionCall = procInfo.Decl is Bpl.Function;
      if (!translateAsFunctionCall) {
        if (resolvedMethod.Type.ResolvedType.TypeCode != PrimitiveTypeCode.Void) {
          Bpl.Variable v = this.sink.CreateFreshLocal(methodToCall.ResolvedMethod.Type.ResolvedType);
          Bpl.IdentifierExpr unUnioned = new Bpl.IdentifierExpr(token, v);
          if (resolvedMethod.Type is IGenericParameterReference) {
            var boogieType = this.sink.CciTypeToBoogie(resolvedMethod.Type);
            if (boogieType == this.sink.Heap.UnionType) {
              Bpl.IdentifierExpr unioned = Bpl.Expr.Ident(this.sink.CreateFreshLocal(this.sink.Heap.UnionType));
              toUnioned[unUnioned] = Tuple.Create(unioned, TranslationHelper.IsStruct(methodToCall.ResolvedMethod.Type.ResolvedType));
              outvars.Add(unioned);
            } else {
              outvars.Add(unUnioned);
            }
          } else {
            outvars.Add(unUnioned);
          }
          TranslatedExpressions.Push(unUnioned);
        }
      }

      return procInfo.Decl;
    }
Exemple #19
0
 private Cmd InlinedRequires(CallCmd callCmd, Requires req) {
   Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone());
   if (req.Free)
     reqCopy.Condition = Expr.True;
   else 
     reqCopy.Condition = codeCopier.CopyExpr(req.Condition);
   AssertCmd/*!*/ a = new AssertRequiresCmd(callCmd, reqCopy);
   a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
   return a;
 }
Exemple #20
0
 public override Cmd VisitCallCmd(CallCmd node)
 {
     Procedure enclosingProc = civlTypeChecker.enclosingImpl.Proc;
     if (!civlTypeChecker.procToAtomicProcedureInfo.ContainsKey(node.Proc))
     {
         civlTypeChecker.Error(node, "Atomic procedure can only call an atomic procedure");
         return base.VisitCallCmd(node);
     }
     var callerInfo = civlTypeChecker.procToAtomicProcedureInfo[enclosingProc];
     var calleeInfo = civlTypeChecker.procToAtomicProcedureInfo[node.Proc];
     if (calleeInfo.isPure)
     {
         // do nothing
     }
     else if (callerInfo.isPure)
     {
         civlTypeChecker.Error(node, "Pure procedure can only call pure procedures");
     }
     else if (!callerInfo.layerRange.Subset(calleeInfo.layerRange))
     {
         civlTypeChecker.Error(node, "Caller layers must be subset of callee layers");
     }
     return base.VisitCallCmd(node);
 }
Exemple #21
0
 private Cmd InlinedEnsures(CallCmd callCmd, Ensures ens) {
   if (QKeyValue.FindBoolAttribute(ens.Attributes, "InlineAssume")) {
     return new AssumeCmd(ens.tok, codeCopier.CopyExpr(ens.Condition));
   } else if (ens.Free) {
     return new AssumeCmd(ens.tok, Expr.True); 
   } else {
     Ensures/*!*/ ensCopy = (Ensures/*!*/)cce.NonNull(ens.Clone());
     ensCopy.Condition = codeCopier.CopyExpr(ens.Condition);
     return new AssertEnsuresCmd(ensCopy);
   }
 }
Exemple #22
0
 public override Cmd VisitCallCmd(CallCmd node)
 {
     int enclosingProcLayerNum = procToActionInfo[enclosingImpl.Proc].createdAtLayerNum;
     if (procToActionInfo.ContainsKey(node.Proc))
     {
         ActionInfo actionInfo = procToActionInfo[node.Proc];
         if (node.IsAsync && actionInfo is AtomicActionInfo)
         {
             AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
             if (!atomicActionInfo.IsLeftMover)
             {
                 Error(node, "Target of async call must be a left mover");
             }
         }
         int calleeLayerNum = procToActionInfo[node.Proc].createdAtLayerNum;
         if (enclosingProcLayerNum < calleeLayerNum ||
             (enclosingProcLayerNum == calleeLayerNum && actionInfo is AtomicActionInfo))
         {
             Error(node, "The layer of the caller must be greater than the layer of the callee");
         }
         else if (enclosingProcLayerNum == calleeLayerNum && enclosingImpl.OutParams.Count > 0)
         {
             HashSet<Variable> outParams = new HashSet<Variable>(enclosingImpl.OutParams);
             foreach (var x in node.Outs)
             {
                 if (x.Decl is GlobalVariable)
                 {
                     Error(node, "A global variable cannot be used as output argument for this call");
                 }
                 else if (outParams.Contains(x.Decl))
                 {
                     Error(node, "An output variable of the enclosing implementation cannot be used as output argument for this call");
                 }
             }
         }
         if (actionInfo.availableUptoLayerNum < enclosingProcLayerNum)
         {
             Error(node, "The callee is not available in the caller procedure");
         }
         for (int i = 0; i < node.Ins.Count; i++)
         {
             Visit(node.Ins[i]);
             if (introducedLocalVarsUpperBound != int.MinValue)
             {
                 var formal = node.Proc.InParams[i];
                 if (!localVarToLocalVariableInfo.ContainsKey(formal) ||
                     introducedLocalVarsUpperBound > localVarToLocalVariableInfo[formal].layer)
                 {
                     Error(node, "An introduced local variable is accessed but not available");
                 }
                 introducedLocalVarsUpperBound = int.MinValue;
             }
         }
         for (int i = 0; i < node.Outs.Count; i++)
         {
             var formal = node.Proc.OutParams[i];
             if (!localVarToLocalVariableInfo.ContainsKey(formal)) continue;
             var actual = node.Outs[i].Decl;
             if (localVarToLocalVariableInfo.ContainsKey(actual) && 
                 localVarToLocalVariableInfo[formal].layer <= localVarToLocalVariableInfo[actual].layer)
                 continue;
             Error(node, "Formal parameter of call must be introduced no later than the actual parameter");
         }
         return node;
     }
     else if (procToAtomicProcedureInfo.ContainsKey(node.Proc))
     {
         var atomicProcedureInfo = procToAtomicProcedureInfo[node.Proc];                
         if (atomicProcedureInfo.isPure)
         {
             if (node.Outs.Count > 0)
             {
                 int inferredLayer = int.MinValue;
                 foreach (var ie in node.Outs)
                 {
                     if (!localVarToLocalVariableInfo.ContainsKey(ie.Decl)) continue;
                     if (inferredLayer < localVarToLocalVariableInfo[ie.Decl].layer)
                     {
                         inferredLayer = localVarToLocalVariableInfo[ie.Decl].layer;
                     }
                 }
                 pureCallLayer[node] = inferredLayer;
                 if (inferredLayer != int.MinValue)
                 {
                     foreach (var ie in node.Outs)
                     {
                         if (!localVarToLocalVariableInfo.ContainsKey(ie.Decl))
                         {
                             Error(node, "Output variable must be introduced");
                         }
                         else if (inferredLayer != localVarToLocalVariableInfo[ie.Decl].layer)
                         {
                             Error(node, "All output variables must be introduced at the same layer");
                         }
                     }
                 }
                 Debug.Assert(introducedLocalVarsUpperBound == int.MinValue);
                 foreach (var e in node.Ins)
                 {
                     Visit(e);
                     if (inferredLayer < introducedLocalVarsUpperBound)
                     {
                         Error(node, "An introduced local variable is not accessible");
                     }
                     introducedLocalVarsUpperBound = int.MinValue;
                 }
             }
             else
             {
                 Debug.Assert(introducedLocalVarsUpperBound == int.MinValue);
                 int inferredLayer = int.MinValue;
                 foreach (var e in node.Ins)
                 {
                     Visit(e);
                     if (inferredLayer < introducedLocalVarsUpperBound)
                     {
                         inferredLayer = introducedLocalVarsUpperBound;
                     }
                     introducedLocalVarsUpperBound = int.MinValue;
                 }
                 pureCallLayer[node] = inferredLayer;
             }
         }
         else
         {
             if (enclosingProcLayerNum != atomicProcedureInfo.layerRange.upperLayerNum)
             {
                 Error(node, "Creation layer of caller must be the upper bound of the layer range of callee");
             }
             foreach (var ie in node.Proc.Modifies)
             {
                 if (enclosingProcLayerNum != globalVarToSharedVarInfo[ie.Decl].introLayerNum)
                 {
                     Error(node, "Creation layer of caller must be identical to the introduction layer of modified variable");
                 }
             }
             foreach (var ie in node.Outs)
             {
                 if (localVarToLocalVariableInfo.ContainsKey(ie.Decl) &&
                     enclosingProcLayerNum == localVarToLocalVariableInfo[ie.Decl].layer)
                     continue;
                 Error(node, "Output variable must be introduced at the creation layer of caller");
             }
         }
         return node;
     }
     else  
     {
         Error(node, "A yielding procedure can call only atomic or yielding procedures");
         return node;
     }
 }
Exemple #23
0
    // result[0] is the entry block
    protected List<Block/*!*/>/*!*/ CreateInlinedBlocks(CallCmd callCmd, Implementation impl, string nextBlockLabel) {
      Contract.Requires(nextBlockLabel != null);
      Contract.Requires(impl != null);
      Contract.Requires(impl.Proc != null);
      Contract.Requires(callCmd != null);
      Contract.Requires(codeCopier.Subst != null);

      Contract.Requires(codeCopier.OldSubst != null);
      Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
      List<Block/*!*/>/*!*/ implBlocks = cce.NonNull(impl.OriginalBlocks);
      Contract.Assert(implBlocks.Count > 0);

      Procedure proc = impl.Proc;
      string startLabel = implBlocks[0].Label;

      List<Block/*!*/>/*!*/ inlinedBlocks = new List<Block/*!*/>();

      // create in block
      List<Cmd> inCmds = new List<Cmd>();

      // assign in parameters
      for (int i = 0; i < impl.InParams.Count; ++i) {
        Cmd cmd = Cmd.SimpleAssign(impl.tok,
                                   (IdentifierExpr)cce.NonNull(codeCopier.Subst)(cce.NonNull(impl.InParams[i])),
                                   cce.NonNull(callCmd.Ins[i]));
        inCmds.Add(cmd);
      }

      // inject requires
      for (int i = 0; i < proc.Requires.Count; i++) {
        Requires/*!*/ req = cce.NonNull(proc.Requires[i]);
        inCmds.Add(InlinedRequires(callCmd, req));
      }

      List<Variable> locVars = cce.NonNull(impl.OriginalLocVars);

      // havoc locals and out parameters in case procedure is invoked in a loop
      List<IdentifierExpr> havocVars = new List<IdentifierExpr>();
      foreach (Variable v in locVars)
      {
          havocVars.Add((IdentifierExpr)codeCopier.Subst(v));
      }
      foreach (Variable v in impl.OutParams)
      {
          havocVars.Add((IdentifierExpr)codeCopier.Subst(v));
      }
      if (havocVars.Count > 0)
      {
          inCmds.Add(new HavocCmd(Token.NoToken, havocVars));
      }

      // add where clauses of local vars as assume
      for (int i = 0; i < locVars.Count; ++i) {
        Expr whereExpr = (cce.NonNull(locVars[i])).TypedIdent.WhereExpr;
        if (whereExpr != null) {
          whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
          // FIXME we cannot overwrite it, can we?!
          (cce.NonNull(locVars[i])).TypedIdent.WhereExpr = whereExpr;
          AssumeCmd/*!*/ a = new AssumeCmd(Token.NoToken, whereExpr);
          Contract.Assert(a != null);
          inCmds.Add(a);
        }
      }

      // add where clauses of output params as assume
      for (int i = 0; i < impl.OutParams.Count; ++i) {
        Expr whereExpr = (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr;
        if (whereExpr != null) {
          whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr);
          // FIXME likewise
          (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr = whereExpr;
          AssumeCmd/*!*/ a = new AssumeCmd(Token.NoToken, whereExpr);
          Contract.Assert(a != null);
          inCmds.Add(a);
        }
      }

      // assign modifies old values
      foreach (IdentifierExpr/*!*/ mie in proc.Modifies) {
        Contract.Assert(mie != null);
        Variable/*!*/ mvar = cce.NonNull(mie.Decl);
        AssignCmd assign = Cmd.SimpleAssign(impl.tok, (IdentifierExpr)cce.NonNull(codeCopier.OldSubst(mvar)), mie);
        inCmds.Add(assign);
      }

      GotoCmd inGotoCmd = new GotoCmd(callCmd.tok, new List<String> { GetInlinedProcLabel(proc.Name) + "$" + startLabel });
      Block inBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Entry", inCmds, inGotoCmd);
      inlinedBlocks.Add(inBlock);

      // inject the blocks of the implementation
      Block intBlock;
      foreach (Block block in implBlocks) {
        List<Cmd> copyCmds = codeCopier.CopyCmdSeq(block.Cmds);
        if (0 <= inlineDepth) {
          copyCmds = RemoveAsserts(copyCmds);
        }
        TransferCmd transferCmd = CreateInlinedTransferCmd(cce.NonNull(block.TransferCmd), GetInlinedProcLabel(proc.Name));
        intBlock = new Block(block.tok, GetInlinedProcLabel(proc.Name) + "$" + block.Label, copyCmds, transferCmd);
        inlinedBlocks.Add(intBlock);
      }

      // create out block
      List<Cmd> outCmds = new List<Cmd>();

      // inject ensures
      for (int i = 0; i < proc.Ensures.Count; i++) {
        Ensures/*!*/ ens = cce.NonNull(proc.Ensures[i]);
        outCmds.Add(InlinedEnsures(callCmd, ens));
      }

      // assign out params
      for (int i = 0; i < impl.OutParams.Count; ++i) {
        Expr/*!*/ cout_exp = (IdentifierExpr)cce.NonNull(codeCopier.Subst(cce.NonNull(impl.OutParams[i])));
        Cmd cmd = Cmd.SimpleAssign(impl.tok, cce.NonNull(callCmd.Outs[i]), cout_exp);
        outCmds.Add(cmd);
      }

      // create out block
      GotoCmd outGotoCmd = new GotoCmd(Token.NoToken, new List<String> { nextBlockLabel });
      Block outBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Return", outCmds, outGotoCmd);
      inlinedBlocks.Add(outBlock);

      return inlinedBlocks;
    }
Exemple #24
0
 public virtual Cmd VisitCallCmd(CallCmd node) {
   Contract.Requires(node != null);
   Contract.Ensures(Contract.Result<Cmd>() != null);
   for (int i = 0; i < node.Ins.Count; ++i)
     if (node.Ins[i] != null)
       node.Ins[i] = this.VisitExpr(cce.NonNull(node.Ins[i]));
   for (int i = 0; i < node.Outs.Count; ++i)
     if (node.Outs[i] != null)
       node.Outs[i] = (IdentifierExpr)this.VisitIdentifierExpr(cce.NonNull(node.Outs[i]));
   return node;
 }
 /// <summary>
 /// Patch, to account for URIs that cannot be tracked because of current dataflow restrictions
 /// </summary>
 private void TranslateHavocCurrentURI() {
   // TODO move away phone related code from the translation, it would be better to have 2 or more translation phases
   IMethodReference havocMethod= PhoneCodeHelper.instance().getUriHavocerMethod(sink);
   Sink.ProcedureInfo procInfo= sink.FindOrCreateProcedure(havocMethod.ResolvedMethod);
   Bpl.CallCmd havocCall = new Bpl.CallCmd(Bpl.Token.NoToken, procInfo.Decl.Name, new List<Bpl.Expr>(), new List<Bpl.IdentifierExpr>());
   StmtTraverser.StmtBuilder.Add(havocCall);
 }
    public override Cmd VisitCallCmd(CallCmd node)
    {
      var result = base.VisitCallCmd(node);

      var oldProc = programInCachedSnapshot.FindProcedure(node.Proc.Name);
      if (oldProc != null
          && oldProc.DependencyChecksum != node.Proc.DependencyChecksum
          && node.AssignedAssumptionVariable == null)
      {
        var before = new List<Cmd>();
        var beforePrecondtionCheck = new List<Cmd>();
        var after = new List<Cmd>();
        var axioms = new List<Axiom>();
        Expr assumedExpr = new LiteralExpr(Token.NoToken, false);
        // TODO(wuestholz): Try out two alternatives: only do this for low priority implementations or not at all.
        var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program);
        if (canUseSpecs && oldProc.SignatureEquals(node.Proc))
        {
          var desugaring = node.Desugaring;
          Contract.Assert(desugaring != null);
          var precond = node.CheckedPrecondition(oldProc, Program, e => FunctionExtractor.Extract(e, Program, axioms));
          if (precond != null)
          {
            var assume = new AssumeCmd(node.tok, precond, new QKeyValue(Token.NoToken, "precondition_previous_snapshot", new List<object>(), null));
            assume.IrrelevantForChecksumComputation = true;
            beforePrecondtionCheck.Add(assume);
          }

          var unmods = node.UnmodifiedBefore(oldProc);
          var eqs = new List<Expr>();
          foreach (var unmod in unmods)
          {
            var oldUnmod = new LocalVariable(Token.NoToken,
              new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", unmod.Name, FreshTemporaryVariableName), unmod.Type));
            var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldUnmod));
            var rhs = new IdentifierExpr(Token.NoToken, unmod.Decl);
            var cmd = new AssignCmd(Token.NoToken, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
            cmd.IrrelevantForChecksumComputation = true;
            before.Add(cmd);
            var eq = LiteralExpr.Eq(new IdentifierExpr(Token.NoToken, oldUnmod), new IdentifierExpr(Token.NoToken, unmod.Decl));
            eq.Type = Type.Bool;
            eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY;
            eqs.Add(eq);
          }

          var mods = node.ModifiedBefore(oldProc);
          var oldSubst = new Dictionary<Variable, Expr>();
          foreach (var mod in mods)
          {
            var oldMod = new LocalVariable(Token.NoToken,
              new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", mod.Name, FreshTemporaryVariableName), mod.Type));
            oldSubst[mod.Decl] = new IdentifierExpr(Token.NoToken, oldMod);
            var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldMod));
            var rhs = new IdentifierExpr(Token.NoToken, mod.Decl);
            var cmd = new AssignCmd(Token.NoToken, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
            cmd.IrrelevantForChecksumComputation = true;
            before.Add(cmd);
          }
          
          assumedExpr = node.Postcondition(oldProc, eqs, oldSubst, Program, e => FunctionExtractor.Extract(e, Program, axioms));
          if (assumedExpr == null)
          {
            assumedExpr = new LiteralExpr(Token.NoToken, true);
          }
        }

        if (assumedExpr != null)
        {
          var lv = new LocalVariable(Token.NoToken,
            new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool),
            new QKeyValue(Token.NoToken, "assumption", new List<object>(), null));
          node.AssignedAssumptionVariable = lv;
          currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs);
          var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv));
          var rhs = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr);
          var assumed = new AssignCmd(node.tok, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
          assumed.IrrelevantForChecksumComputation = true;
          after.Add(assumed);
        }

        node.ExtendDesugaring(before, beforePrecondtionCheck, after);
        if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking)
        {
          using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
          {
            var loc = node.tok != null && node.tok != Token.NoToken ? string.Format("{0}({1},{2})", node.tok.filename, node.tok.line, node.tok.col) : "<unknown location>";
            Console.Out.WriteLine("Processing call to procedure {0} in implementation {1} (at {2}):", node.Proc.Name, currentImplementation.Name, loc);
            foreach (var a in axioms)
            {
              Console.Out.Write("  >>> added axiom: ");
              a.Expr.Emit(tokTxtWr);
              Console.Out.WriteLine();
            }
            foreach (var b in before)
            {
              Console.Out.Write("  >>> added before: ");
              b.Emit(tokTxtWr, 0);
            }
            foreach (var b in beforePrecondtionCheck)
            {
              Console.Out.Write("  >>> added before precondition check: ");
              b.Emit(tokTxtWr, 0);
            }
            foreach (var a in after)
            {
              Console.Out.Write("  >>> added after: ");
              a.Emit(tokTxtWr, 0);
            }
          }
        }
      }

      return result;
    }
    /// <summary>
    /// Handles "instance.container := source".
    /// Note that instance can be null in which case the container better be
    /// a local, parameter, static field, or address dereference.
    /// </summary>
    private void TranslateAssignment(Bpl.IToken tok, object container, IExpression/*?*/ instance, IExpression source) {
      Contract.Assert(TranslatedExpressions.Count == 0);

      var typ = source.Type;
      var structCopy = TranslationHelper.IsStruct(typ) && !(source is IDefaultValue);
      // then a struct value of type S is being assigned: "lhs := s"
      // model this as the statement "call lhs := S..#copy_ctor(s)" that does the bit-wise copying
      Bpl.DeclWithFormals proc = null;
      if (structCopy) {
        proc = this.sink.FindOrCreateProcedureForStructCopy(typ);
      }
      Bpl.Cmd cmd;

      EmitLineDirective(tok);

      var/*?*/ local = container as ILocalDefinition;
      if (local != null) {
        Contract.Assume(instance == null);
        this.Traverse(source);
        var e = this.TranslatedExpressions.Pop();
        var bplLocal = Bpl.Expr.Ident(this.sink.FindOrCreateLocalVariable(local));
        if (structCopy) {
          cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr>{ e, }, new List<Bpl.IdentifierExpr>{ bplLocal, });
        } else {
          cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e);
        }
        StmtTraverser.StmtBuilder.Add(cmd);
        this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
        return;
      }

      var/*?*/ parameter = container as IParameterDefinition;
      if (parameter != null) {
        Contract.Assume(instance == null);
        this.Traverse(source);
        var e = this.TranslatedExpressions.Pop();
        var bplParam = Bpl.Expr.Ident(this.sink.FindParameterVariable(parameter, this.contractContext));
        if (structCopy) {
          cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { e, }, new List<Bpl.IdentifierExpr>{ bplParam });
        } else {
          cmd = Bpl.Cmd.SimpleAssign(tok, bplParam, e);
        }
        StmtTraverser.StmtBuilder.Add(cmd);
        this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
        return;
      }

      var/*?*/ field = container as IFieldReference;
      if (field != null) {
        this.Traverse(source);
        var e = this.TranslatedExpressions.Pop();
        var f = Bpl.Expr.Ident(this.sink.FindOrCreateFieldVariable(field));
        if (instance == null) {
          // static fields are not kept in the heap
          StmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, f, e));
        }
        else {
          this.Traverse(instance);
          var x = this.TranslatedExpressions.Pop();
          var boogieType = sink.CciTypeToBoogie(field.Type);
          this.sink.Heap.WriteHeap(tok, x, f, e,
            field.ResolvedField.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap,
            boogieType, StmtTraverser.StmtBuilder);
          this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
        }
        return;
      }

      var/*?*/ arrayIndexer = container as IArrayIndexer;
      if (arrayIndexer != null) {
        this.Traverse(instance);
        var x = this.TranslatedExpressions.Pop();
        this.Traverse(arrayIndexer.Indices);
        var indices_prime = this.TranslatedExpressions.Pop();
        this.Traverse(source);
        var e = this.TranslatedExpressions.Pop();
        sink.Heap.WriteHeap(Bpl.Token.NoToken, x, indices_prime, e, AccessType.Array, sink.CciTypeToBoogie(arrayIndexer.Type), StmtTraverser.StmtBuilder);
        this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
        return;
      }

      var/*?*/ addressDereference = container as IAddressDereference;
      if (addressDereference != null) {
        var addressOf = addressDereference.Address as IAddressOf;
        if (addressOf != null) {
          var ae = addressOf.Expression;
          TranslateAssignment(tok, ae.Definition, ae.Instance, source);
          return;
        }
        var pop = addressDereference.Address as IPopValue;
        if (pop != null) {
          var popValue = this.sink.operandStack.Pop();
          var identifierExpr = popValue as Bpl.IdentifierExpr;
          if (identifierExpr != null) {
            Contract.Assume(instance == null);
            this.Traverse(source);
            var e = this.TranslatedExpressions.Pop();
            cmd = Bpl.Cmd.SimpleAssign(tok, identifierExpr, e);
            StmtTraverser.StmtBuilder.Add(cmd);
            this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
            return;
          }
        }
        var be2 = addressDereference.Address as IBoundExpression;
        if (be2 != null) {
          TranslateAssignment(tok, be2.Definition, be2.Instance, source);
          return;
        }
        var thisExp = addressDereference.Address as IThisReference;
        if (thisExp != null) {
          // I believe this happens only when a struct calls the default
          // ctor (probably only ever done in a different ctor for the
          // struct). The assignment actually looks like "*this := DefaultValue(S)"
          Contract.Assume(instance == null);
          this.Traverse(source);
          var e = this.TranslatedExpressions.Pop();
          var bplLocal = Bpl.Expr.Ident(this.sink.ThisVariable);
          cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e);
          StmtTraverser.StmtBuilder.Add(cmd);
          this.TranslatedExpressions.Push(e); // value of assignment might be needed for an enclosing expression
          return;
        }
      }
      throw new TranslationException("Untranslatable assignment statement.");
    }
Exemple #28
0
 public void AddAvailableVars(CallCmd callCmd, HashSet<Variable> start)
 {
     foreach (IdentifierExpr ie in callCmd.Outs)
     {
         if (FindDomainName(ie.Decl) == null) continue;
         start.Add(ie.Decl);
     }
     for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
     {
         IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
         if (ie == null) continue;
         Variable v = callCmd.Proc.InParams[i];
         if (FindDomainName(v) == null) continue;
         if (FindLinearKind(v) == LinearKind.LINEAR_OUT)
         {
             start.Add(ie.Decl);
         }
     }
 }
    private void VisitAssignment(ITargetExpression target, IExpression source, SourceTraverser sourceTraverser,
      bool treatAsStatement, bool pushTargetRValue, bool resultIsInitialTargetRValue) {
      Contract.Requires(target != null);
      Contract.Requires(source != null);
      Contract.Requires(sourceTraverser != null);
      Contract.Requires(!resultIsInitialTargetRValue || pushTargetRValue);
      Contract.Requires(!pushTargetRValue || source is IBinaryOperation);

      var tok = source.Token();
      var typ = source.Type;
      var structCopy = TranslationHelper.IsStruct(typ) && !(source is IDefaultValue);
      // then a struct value of type S is being assigned: "lhs := s"
      // model this as the statement "call lhs := S..#copy_ctor(s)" that does the bit-wise copying
      Bpl.DeclWithFormals proc = null;
      if (structCopy) {
        proc = this.sink.FindOrCreateProcedureForStructCopy(typ);
      }

      object container = target.Definition;

      Top:

      ILocalDefinition/*?*/ local = container as ILocalDefinition;
      if (local != null) {
        if (source is IDefaultValue && !local.Type.ResolvedType.IsReferenceType) {
        //  this.LoadAddressOf(local, null);
        //  this.generator.Emit(OperationCode.Initobj, local.Type);
        //  if (!treatAsStatement) this.LoadLocal(local);
        } else {
          Bpl.IdentifierExpr temp = null;
          var bplLocal = Bpl.Expr.Ident(this.sink.FindOrCreateLocalVariable(local));
          if (pushTargetRValue) {
            this.TranslatedExpressions.Push(bplLocal);
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              var loc = this.sink.CreateFreshLocal(source.Type);
              temp = Bpl.Expr.Ident(loc);
              var e3 = this.TranslatedExpressions.Pop();
              var cmd3 = Bpl.Cmd.SimpleAssign(tok, temp, e3);
              this.StmtTraverser.StmtBuilder.Add(cmd3);
              this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);
          var e = this.TranslatedExpressions.Pop();
          if (temp != null) this.TranslatedExpressions.Push(temp);

          Bpl.Cmd cmd;
          if (structCopy) {
            cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { e, }, new List<Bpl.IdentifierExpr> { bplLocal, });
          } else {
            cmd = Bpl.Cmd.SimpleAssign(tok, bplLocal, e);
          }
          StmtTraverser.StmtBuilder.Add(cmd);

          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.TranslatedExpressions.Push(bplLocal);
          }
        }
        return;
      }
      IParameterDefinition/*?*/ parameter = container as IParameterDefinition;
      if (parameter != null) {
        if (source is IDefaultValue && !parameter.Type.ResolvedType.IsReferenceType) {
          //this.LoadAddressOf(parameter, null);
          //this.generator.Emit(OperationCode.Initobj, parameter.Type);
          //if (!treatAsStatement) this.LoadParameter(parameter);
        } else {
          Bpl.IdentifierExpr temp = null;
          if (pushTargetRValue) {
            this.LoadParameter(parameter);
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              var loc = this.sink.CreateFreshLocal(source.Type);
              temp = Bpl.Expr.Ident(loc);
              var e3 = this.TranslatedExpressions.Pop();
              var cmd3 = Bpl.Cmd.SimpleAssign(tok, temp, e3);
              this.StmtTraverser.StmtBuilder.Add(cmd3);
              this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);
          var e = this.TranslatedExpressions.Pop();
          if (temp != null) this.TranslatedExpressions.Push(temp);
          var bplParam = Bpl.Expr.Ident(this.sink.FindParameterVariable(parameter, this.contractContext));

          Bpl.Cmd cmd;
          if (structCopy) {
            cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { e, bplParam, }, new List<Bpl.IdentifierExpr>());
          } else {
            cmd = Bpl.Cmd.SimpleAssign(tok, bplParam, e);
          }
          StmtTraverser.StmtBuilder.Add(cmd);

          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.LoadParameter(parameter);
          }
        }
        return;
      }
      IFieldReference/*?*/ field = container as IFieldReference;
      if (field != null) {

        var f = Bpl.Expr.Ident(this.sink.FindOrCreateFieldVariable(field));
        var boogieTypeOfField = sink.CciTypeToBoogie(field.Type);

        if (source is IDefaultValue && !field.Type.ResolvedType.IsReferenceType) {
          //this.LoadAddressOf(field, target.Instance);
          //if (!treatAsStatement) {
          //  this.generator.Emit(OperationCode.Dup);
          //  this.StackSize++;
          //}
          //this.generator.Emit(OperationCode.Initobj, field.Type);
          //if (!treatAsStatement)
          //  this.generator.Emit(OperationCode.Ldobj, field.Type);
          //else
          //  this.StackSize--;
        } else {
          Bpl.Expr x = null;
          Bpl.IdentifierExpr temp = null;
          if (pushTargetRValue) {
            if (target.Instance != null) {
              this.Traverse(target.Instance);
              x = this.TranslatedExpressions.Pop();
              AssertOrAssumeNonNull(tok, x);
              var e2 = this.sink.Heap.ReadHeap(x, f, TranslationHelper.IsStruct(field.ContainingType) ? AccessType.Struct : AccessType.Heap, boogieTypeOfField);
              this.TranslatedExpressions.Push(e2);
            } else {
              TranslatedExpressions.Push(f);
            }
            
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              var loc = this.sink.CreateFreshLocal(source.Type);
              temp = Bpl.Expr.Ident(loc);
              var e3 = this.TranslatedExpressions.Pop();
              var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
              this.StmtTraverser.StmtBuilder.Add(cmd);
              this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            var loc = this.sink.CreateFreshLocal(source.Type);
            temp = Bpl.Expr.Ident(loc);
            var e3 = this.TranslatedExpressions.Pop();
            var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
            this.StmtTraverser.StmtBuilder.Add(cmd);
            this.TranslatedExpressions.Push(temp);
          }

          var e = this.TranslatedExpressions.Pop();
          if (temp != null) this.TranslatedExpressions.Push(temp);

          if (target.Instance == null) {
            // static fields are not kept in the heap
            StmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, f, e));
          } else {
            this.sink.Heap.WriteHeap(tok, x, f, e,
              field.ResolvedField.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap,
              boogieTypeOfField, StmtTraverser.StmtBuilder);
          }

        }
        return;
      }

      VisitArrayIndexer:

      IArrayIndexer/*?*/ arrayIndexer = container as IArrayIndexer;
      if (arrayIndexer != null) {
        Contract.Assume(arrayIndexer.Indices.Count() == 1); // BUG: deal with multi-dimensional arrays
        if (source is IDefaultValue && !arrayIndexer.Type.ResolvedType.IsReferenceType) {
        //  this.LoadAddressOf(arrayIndexer, target.Instance);
        //  if (!treatAsStatement) {
        //    this.generator.Emit(OperationCode.Dup);
        //    this.StackSize++;
        //  }
        //  this.generator.Emit(OperationCode.Initobj, arrayIndexer.Type);
        //  if (!treatAsStatement)
        //    this.generator.Emit(OperationCode.Ldobj, arrayIndexer.Type);
        //  else
        //    this.StackSize--;
        } else {
          Bpl.IdentifierExpr/*?*/ temp = null;
          this.Traverse(arrayIndexer.IndexedObject);
          var arrayExpr = this.TranslatedExpressions.Peek();
          this.Traverse(arrayIndexer.Indices);
          var indexExpr = this.TranslatedExpressions.Peek();
          if (pushTargetRValue) {
            AssertOrAssumeNonNull(tok, arrayExpr);
            var e2 = this.sink.Heap.ReadHeap(arrayExpr, indexExpr, AccessType.Array, this.sink.CciTypeToBoogie(arrayIndexer.Type));
            this.TranslatedExpressions.Push(e2);

            if (!treatAsStatement && resultIsInitialTargetRValue) {
                var loc = this.sink.CreateFreshLocal(source.Type);
                temp = Bpl.Expr.Ident(loc);
                var e3 = this.TranslatedExpressions.Pop();
                var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
                this.StmtTraverser.StmtBuilder.Add(cmd);
                this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);

          var e = this.TranslatedExpressions.Pop();
          var indices_prime = this.TranslatedExpressions.Pop();
          var x = this.TranslatedExpressions.Pop();
          sink.Heap.WriteHeap(Bpl.Token.NoToken, x, indices_prime, e, AccessType.Array, sink.CciTypeToBoogie(arrayIndexer.Type), StmtTraverser.StmtBuilder);

          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            AssertOrAssumeNonNull(tok, arrayExpr);
            var e2 = this.sink.Heap.ReadHeap(arrayExpr, indexExpr, AccessType.Array, this.sink.CciTypeToBoogie(arrayIndexer.Type));
            this.TranslatedExpressions.Push(e2);
          } else {
            if (temp != null) this.TranslatedExpressions.Push(temp);
          }
        }
        return;
      }
      IAddressDereference/*?*/ addressDereference = container as IAddressDereference;
      if (addressDereference != null) {
        var addrOf = addressDereference.Address as IAddressOf;
        if (addrOf != null) {
          var arrayIndexer2 = addrOf.Expression.Definition as IArrayIndexer;
          if (arrayIndexer2 != null) {
            container = arrayIndexer2;
            goto VisitArrayIndexer;
          }
        }
        var be = addressDereference.Address as IBoundExpression;
        if (be != null) {
          container = be.Definition;
          goto Top;
        }
        this.Traverse(addressDereference.Address);
        if (source is IDefaultValue && !addressDereference.Type.ResolvedType.IsReferenceType) {
          //if (!treatAsStatement) {
          //  this.generator.Emit(OperationCode.Dup);
          //  this.StackSize++;
          //}
          //this.generator.Emit(OperationCode.Initobj, addressDereference.Type);
          //if (!treatAsStatement)
          //  this.generator.Emit(OperationCode.Ldobj, addressDereference.Type);
          //else
          //  this.StackSize--;
        } else if (source is IAddressDereference) {
          //if (!treatAsStatement) {
          //  this.generator.Emit(OperationCode.Dup);
          //  this.StackSize++;
          //}
          //this.Traverse(((IAddressDereference)source).Address);
          //this.generator.Emit(OperationCode.Cpobj, addressDereference.Type);
          //this.StackSize -= 2;
          //if (!treatAsStatement)
          //  this.generator.Emit(OperationCode.Ldobj, addressDereference.Type);
        } else {
          Bpl.IdentifierExpr/*?*/ temp = null;
          if (pushTargetRValue) {
            this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek());
            if (!treatAsStatement && resultIsInitialTargetRValue) {
              this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek());
              var loc = this.sink.CreateFreshLocal(source.Type);
              temp = Bpl.Expr.Ident(loc);
              var e3 = this.TranslatedExpressions.Pop();
              var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
              this.StmtTraverser.StmtBuilder.Add(cmd);
              this.TranslatedExpressions.Push(temp);
            }
          }
          sourceTraverser(source);
          if (!treatAsStatement && !resultIsInitialTargetRValue) {
            this.TranslatedExpressions.Push(this.TranslatedExpressions.Peek());
            var loc = this.sink.CreateFreshLocal(source.Type);
            temp = Bpl.Expr.Ident(loc);
            var e3 = this.TranslatedExpressions.Pop();
            var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
            this.StmtTraverser.StmtBuilder.Add(cmd);
            this.TranslatedExpressions.Push(temp);
          }
          //this.VisitAssignmentTo(addressDereference);
          if (temp != null) this.TranslatedExpressions.Push(temp);
        }
        return;
      }
      IPropertyDefinition/*?*/ propertyDefinition = container as IPropertyDefinition;
      if (propertyDefinition != null) {
        Contract.Assume(propertyDefinition.Getter != null && propertyDefinition.Setter != null);
        if (!propertyDefinition.IsStatic) {
          this.Traverse(target.Instance);
        }
        Bpl.IdentifierExpr temp = null;
        var token = Bpl.Token.NoToken;
        if (pushTargetRValue) {

          List<Bpl.Expr> inexpr;
          List<Bpl.IdentifierExpr> outvars;
          Bpl.IdentifierExpr thisExpr;
          Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr, bool>> toBoxed;
          var proc2 = TranslateArgumentsAndReturnProcedure(token, propertyDefinition.Getter, propertyDefinition.Getter.ResolvedMethod, target.Instance, Enumerable<IExpression>.Empty, out inexpr, out outvars, out thisExpr, out toBoxed);

          EmitLineDirective(token);

          this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(token, proc2.Name, inexpr, outvars));

          if (!treatAsStatement && resultIsInitialTargetRValue) {
            //var 
            //this.generator.Emit(OperationCode.Dup);
            //this.StackSize++;
            //temp = new TemporaryVariable(source.Type, this.method);
            //this.VisitAssignmentTo(temp);
          }
        }
        sourceTraverser(source);
        if (!treatAsStatement && !resultIsInitialTargetRValue) {
          var e3 = this.TranslatedExpressions.Pop();
          var loc = this.sink.CreateFreshLocal(source.Type);
          temp = Bpl.Expr.Ident(loc);
          var cmd = Bpl.Cmd.SimpleAssign(tok, temp, e3);
          this.StmtTraverser.StmtBuilder.Add(cmd);
          this.TranslatedExpressions.Push(temp);
        }

        var setterArgs = new List<Bpl.Expr>();
        var setterArg = this.TranslatedExpressions.Pop();
        if (!propertyDefinition.IsStatic)
          setterArgs.Add(this.TranslatedExpressions.Pop());
        setterArgs.Add(setterArg);

        var setterProc = this.sink.FindOrCreateProcedure(propertyDefinition.Setter.ResolvedMethod);
        EmitLineDirective(token);
        this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(token, setterProc.Decl.Name, setterArgs, new List<Bpl.IdentifierExpr>()));

        if (temp != null) this.TranslatedExpressions.Push(temp);
        return;
      }
      Contract.Assume(false);
    }
Exemple #30
0
 public void DesugarParallelCallCmd(List<Cmd> newCmds, ParCallCmd parCallCmd)
 {
     List<string> parallelCalleeNames = new List<string>();
     List<Expr> ins = new List<Expr>();
     List<IdentifierExpr> outs = new List<IdentifierExpr>();
     string procName = "og";
     foreach (CallCmd callCmd in parCallCmd.CallCmds)
     {
         procName = procName + "_" + callCmd.Proc.Name;
         ins.AddRange(callCmd.Ins);
         outs.AddRange(callCmd.Outs);
     }
     Procedure proc;
     if (asyncAndParallelCallDesugarings.ContainsKey(procName))
     {
         proc = asyncAndParallelCallDesugarings[procName];
     }
     else
     {
         List<Variable> inParams = new List<Variable>();
         List<Variable> outParams = new List<Variable>();
         List<Requires> requiresSeq = new List<Requires>();
         List<Ensures> ensuresSeq = new List<Ensures>();
         int count = 0;
         foreach (CallCmd callCmd in parCallCmd.CallCmds)
         {
             Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
             foreach (Variable x in callCmd.Proc.InParams)
             {
                 Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_{0}_{1}", count, x.Name), x.TypedIdent.Type), true);
                 inParams.Add(y);
                 map[x] = Expr.Ident(y);
             }
             foreach (Variable x in callCmd.Proc.OutParams)
             {
                 Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_{0}_{1}", count, x.Name), x.TypedIdent.Type), false);
                 outParams.Add(y);
                 map[x] = Expr.Ident(y);
             }
             Contract.Assume(callCmd.Proc.TypeParameters.Count == 0);
             Substitution subst = Substituter.SubstitutionFromHashtable(map);
             foreach (Requires req in callCmd.Proc.Requires)
             {
                 requiresSeq.Add(new Requires(req.tok, req.Free, Substituter.Apply(subst, req.Condition), null, req.Attributes));
             }
             foreach (Ensures ens in callCmd.Proc.Ensures)
             {
                 ensuresSeq.Add(new Ensures(ens.tok, ens.Free, Substituter.Apply(subst, ens.Condition), null, ens.Attributes));
             }
             count++;
         }
         proc = new Procedure(Token.NoToken, procName, new List<TypeVariable>(), inParams, outParams, requiresSeq, globalMods, ensuresSeq);
         asyncAndParallelCallDesugarings[procName] = proc;
     }
     CallCmd dummyCallCmd = new CallCmd(parCallCmd.tok, proc.Name, ins, outs, parCallCmd.Attributes);
     dummyCallCmd.Proc = proc;
     newCmds.Add(dummyCallCmd);
 }
    public override void TraverseChildren(IConversion conversion) {
      var tok = conversion.ValueToConvert.Token();
      this.Traverse(conversion.ValueToConvert);
      var boogieTypeOfValue = this.sink.CciTypeToBoogie(conversion.ValueToConvert.Type);
      var boogieTypeToBeConvertedTo = this.sink.CciTypeToBoogie(conversion.TypeAfterConversion);
      if (boogieTypeOfValue == boogieTypeToBeConvertedTo && !TranslationHelper.IsStruct(conversion.ValueToConvert.Type)
        && !TranslationHelper.IsStruct(conversion.TypeAfterConversion)) {
        // then this conversion is a nop, just ignore it
        return;
      }
      var nameOfTypeToConvert = TypeHelper.GetTypeName(conversion.ValueToConvert.Type);
      var nameOfTypeToBeConvertedTo = TypeHelper.GetTypeName(conversion.TypeAfterConversion);
      var msg = String.Format("Can't convert '{0}' to '{1}'", nameOfTypeToConvert, nameOfTypeToBeConvertedTo);

      var exp = TranslatedExpressions.Pop();

      if (boogieTypeOfValue == this.sink.Heap.UnionType && boogieTypeToBeConvertedTo != this.sink.Heap.RefType) {
        var e = this.sink.Heap.FromUnion(tok, boogieTypeToBeConvertedTo, exp, false);
        TranslatedExpressions.Push(e);
        return;
      }
      if (boogieTypeToBeConvertedTo == this.sink.Heap.UnionType) {
        Bpl.Expr e;
        if (boogieTypeOfValue == this.sink.Heap.RefType)
          e = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Union), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        else
          e = this.sink.Heap.ToUnion(tok, boogieTypeOfValue, exp, false, StmtTraverser.StmtBuilder);
        TranslatedExpressions.Push(e);
        return;
      }

      if (boogieTypeToBeConvertedTo == this.sink.Heap.RefType &&
        TranslationHelper.IsStruct(conversion.TypeAfterConversion) &&
        boogieTypeOfValue == this.sink.Heap.RefType) {
        // REVIEW: This also applies to conversions from one struct type to another!
        TranslatedExpressions.Push(exp);
        return;
      }

      if (boogieTypeToBeConvertedTo == Bpl.Type.Bool) {
        Bpl.Expr expr;
        if (boogieTypeOfValue == Bpl.Type.Int) {
          expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, exp, Bpl.Expr.Literal(0));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RefType) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Bool), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RealType) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Real2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
          expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, expr, Bpl.Expr.Literal(0));
        }
        else if (boogieTypeOfValue == this.sink.Heap.UnionType) {
          expr = this.sink.Heap.FromUnion(tok, Bpl.Type.Bool, exp, false);
        }
        else {
          throw new NotImplementedException(msg);
        }
        TranslatedExpressions.Push(expr);
        return;
      }

      if (boogieTypeToBeConvertedTo == Bpl.Type.Int) {
        Bpl.Expr expr;
        if (boogieTypeOfValue == Bpl.Type.Bool) {
          expr = new Bpl.NAryExpr(tok, new Bpl.IfThenElse(tok), new List<Bpl.Expr>(new Bpl.Expr[] {exp, Bpl.Expr.Literal(1), Bpl.Expr.Literal(0)}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RefType) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RealType) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Real2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.UnionType) {
          expr = this.sink.Heap.FromUnion(Bpl.Token.NoToken, Bpl.Type.Int, exp, false);
        }
        else {
          throw new NotImplementedException(msg);
        }
        TranslatedExpressions.Push(expr);
        return;
      }

      if (boogieTypeToBeConvertedTo == this.sink.Heap.RefType) {
        // var a = BoxFromXXX(exp);
        Bpl.Variable a = this.sink.CreateFreshLocal(conversion.TypeAfterConversion);
        Bpl.Procedure boxOperator;
        if (boogieTypeOfValue == Bpl.Type.Bool)
          boxOperator = this.sink.Heap.BoxFromBool;
        else if (boogieTypeOfValue == Bpl.Type.Int)
          boxOperator = this.sink.Heap.BoxFromInt;
        else if (boogieTypeOfValue == this.sink.Heap.RealType)
          boxOperator = this.sink.Heap.BoxFromReal;
        else if (TranslationHelper.IsStruct(conversion.ValueToConvert.Type)) {
          // Boxing a struct implicitly makes a copy of the struct
          var typeOfValue = conversion.ValueToConvert.Type;
          var proc = this.sink.FindOrCreateProcedureForStructCopy(typeOfValue);
          var bplLocal = Bpl.Expr.Ident(this.sink.CreateFreshLocal(typeOfValue));
          var cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { exp, }, new List<Bpl.IdentifierExpr> { bplLocal, });
          this.StmtTraverser.StmtBuilder.Add(cmd);
          TranslatedExpressions.Push(bplLocal);
          return;
        }  else {
          if (boogieTypeOfValue != this.sink.Heap.UnionType)
            throw new NotImplementedException(msg);
          boxOperator = this.sink.Heap.BoxFromUnion;
        }
        var name = boxOperator.Name;

        this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(Bpl.Token.NoToken, name, new List<Bpl.Expr>(new Bpl.Expr[] {exp}), new List<Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] {Bpl.Expr.Ident(a)})));
        TranslatedExpressions.Push(Bpl.Expr.Ident(a));
        return;
      }

      if (boogieTypeToBeConvertedTo == this.sink.Heap.RealType) {
        Bpl.Expr expr;
        if (boogieTypeOfValue == Bpl.Type.Bool) {
          expr = new Bpl.NAryExpr(tok, new Bpl.IfThenElse(tok), new List<Bpl.Expr>(new Bpl.Expr[] {exp, Bpl.Expr.Literal(1), Bpl.Expr.Literal(0)}));
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Int2Real), new List<Bpl.Expr>(new Bpl.Expr[] {expr}));
        }
        else if (boogieTypeOfValue == Bpl.Type.Int) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Int2Real), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RefType) {
            expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Real), new List<Bpl.Expr>(new Bpl.Expr[] { exp }));
        }
        else if (boogieTypeOfValue == this.sink.Heap.UnionType) {
          expr = this.sink.Heap.FromUnion(tok, this.sink.Heap.RealType, exp, false);
        }
        else {
          throw new NotImplementedException(msg);
        }
        TranslatedExpressions.Push(expr);
        return;
      }
      
      //if (boogieTypeToBeConvertedTo == this.sink.Heap.UnionType) {
      //  Bpl.Function func;
      //  if (boogieTypeOfValue == Bpl.Type.Bool) {
      //    func = this.sink.Heap.Bool2Union;
      //  }
      //  else if (boogieTypeOfValue == Bpl.Type.Int) {
      //    func = this.sink.Heap.Int2Union;
      //  }
      //  else if (boogieTypeOfValue == this.sink.Heap.RefType) {
      //    func = this.sink.Heap.Ref2Union;
      //  }
      //  else if (boogieTypeOfValue == this.sink.Heap.RealType) {
      //    func = this.sink.Heap.Real2Union;
      //  }
      //  else {
      //    throw new NotImplementedException(msg);
      //  }
      //  var boxExpr = new Bpl.NAryExpr(conversion.Token(), new Bpl.FunctionCall(func), new List<Bpl.Expr>(exp));
      //  TranslatedExpressions.Push(boxExpr);
      //  return;
      //}
    }
Exemple #32
0
 private CallCmd CallToYieldProc(IToken tok, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar)
 {
     List<Expr> exprSeq = new List<Expr>();
     foreach (string domainName in linearTypeChecker.linearDomains.Keys)
     {
         exprSeq.Add(Expr.Ident(domainNameToLocalVar[domainName]));
     }
     foreach (IdentifierExpr ie in globalMods)
     {
         exprSeq.Add(Expr.Ident(ogOldGlobalMap[ie.Decl]));
     }
     if (yieldProc == null)
     {
         List<Variable> inputs = new List<Variable>();
         foreach (string domainName in linearTypeChecker.linearDomains.Keys)
         {
             var domain = linearTypeChecker.linearDomains[domainName];
             Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
             inputs.Add(f);
         }
         foreach (IdentifierExpr ie in globalMods)
         {
             Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", ie.Decl.Name), ie.Decl.TypedIdent.Type), true);
             inputs.Add(f);
         }
         yieldProc = new Procedure(Token.NoToken, string.Format("og_yield_{0}", layerNum), new List<TypeVariable>(), inputs, new List<Variable>(), new List<Requires>(), new List<IdentifierExpr>(), new List<Ensures>());
         yieldProc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
     }
     CallCmd yieldCallCmd = new CallCmd(Token.NoToken, yieldProc.Name, exprSeq, new List<IdentifierExpr>());
     yieldCallCmd.Proc = yieldProc;
     return yieldCallCmd;
 }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="methodCall"></param>
    /// <remarks>Stub, This one really needs comments!</remarks>
    public override void TraverseChildren(IMethodCall methodCall) {
      var resolvedMethod = ResolveUnspecializedMethodOrThrow(methodCall.MethodToCall);

      Bpl.IToken methodCallToken = methodCall.Token();

      if (this.sink.Options.getMeHere) {
        // TODO: Get a method reference so this isn't a string comparison?
        var methodName = MemberHelper.GetMethodSignature(methodCall.MethodToCall, NameFormattingOptions.None);
        if (methodName.Equals("GetMeHere.GetMeHere.Assert")) {
          // for now, just translate it as "assert e"
          this.Traverse(methodCall.Arguments.First());
          Bpl.Expr e = this.TranslatedExpressions.Pop();
          this.StmtTraverser.StmtBuilder.Add(new Bpl.AssertCmd(methodCallToken, e));
          return;
        }
      }

      // Handle type equality specially when it is testing against a constant, i.e., o.GetType() == typeof(T)
      if (IsOperator(resolvedMethod) && !IsConversionOperator(resolvedMethod) && 
        TypeHelper.TypesAreEquivalent(resolvedMethod.ContainingType, this.sink.host.PlatformType.SystemType)) {
        // REVIEW: Assume the only operators on System.Type are == and !=
        var typeToTest = methodCall.Arguments.ElementAtOrDefault(0) as ITypeOf;
        IMethodCall callToGetType;
        if (typeToTest == null) {
          typeToTest = methodCall.Arguments.ElementAtOrDefault(1) as ITypeOf;
          callToGetType = methodCall.Arguments.ElementAtOrDefault(0) as IMethodCall;
        } else {
          callToGetType = methodCall.Arguments.ElementAtOrDefault(1) as IMethodCall;
        }
        if (typeToTest != null && callToGetType != null &&
          TypeHelper.TypesAreEquivalent(callToGetType.MethodToCall.ContainingType, this.sink.host.PlatformType.SystemObject) &&
          MemberHelper.GetMethodSignature(callToGetType.MethodToCall).Equals("System.Object.GetType")) {

          IExpression objectToTest = callToGetType.ThisArgument;

          // generate: $TypeConstructor($DynamicType(o)) == TypeConstructorId
          var typeConstructorId = this.sink.FindOrDefineType(typeToTest.TypeToGet.ResolvedType).ConstructorId;
          Contract.Assume(typeConstructorId != null);

          this.Traverse(objectToTest);
          var e = this.TranslatedExpressions.Pop();

          var exprs = new List<Bpl.Expr>(new Bpl.Expr[] {this.sink.Heap.DynamicType(e)});
          Bpl.Expr typeTestExpression = 
              Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, 
                              new Bpl.NAryExpr(methodCallToken, new Bpl.FunctionCall(sink.Heap.TypeConstructorFunction), exprs),
                              Bpl.Expr.Ident(typeConstructorId));
          if (MemberHelper.GetMethodSignature(resolvedMethod).Equals("System.Type.op_Inequality"))
            typeTestExpression = Bpl.Expr.Unary( methodCallToken, Bpl.UnaryOperator.Opcode.Not, typeTestExpression);
          this.TranslatedExpressions.Push(typeTestExpression);
          return;
        }
      }

      // Handle calls to Contract.ForAll and Contract.Exists specially (if they are to the overloads that take two ints and a predicate on ints)
      if (resolvedMethod.ContainingTypeDefinition.InternedKey == this.sink.host.PlatformType.SystemDiagnosticsContractsContract.InternedKey)
      {
          var methodName = resolvedMethod.Name.Value;
          if (methodCall.Arguments.Count() == 3 && (methodName == "ForAll" || methodName == "Exists"))
          {
              var noToken = Bpl.Token.NoToken;

              this.Traverse(methodCall.Arguments.ElementAt(0));
              var lb = this.TranslatedExpressions.Pop();
              this.Traverse(methodCall.Arguments.ElementAt(1));
              var ub = this.TranslatedExpressions.Pop();
              var delegateArgument = methodCall.Arguments.ElementAt(2);
              this.Traverse(delegateArgument);
              var del = this.TranslatedExpressions.Pop();

              var boundVar = new Bpl.LocalVariable(noToken, new Bpl.TypedIdent(noToken, TranslationHelper.GenerateTempVarName(), Bpl.Type.Int));

              var resultVar = new Bpl.LocalVariable(noToken, new Bpl.TypedIdent(noToken, TranslationHelper.GenerateTempVarName(), Bpl.Type.Bool));

              var delegateType = delegateArgument.Type;
              var invokeMethod = delegateType.ResolvedType.GetMembersNamed(this.sink.host.NameTable.GetNameFor("Invoke"), false).First() as IMethodReference;
              var unspecializedInvokeMethod = Sink.Unspecialize(invokeMethod).ResolvedMethod;
              var invokeProcedureInfo = sink.FindOrCreateProcedure(unspecializedInvokeMethod);
              var ins = new List<Bpl.Expr>();
              ins.Add(del);
              var localStmtTraverser = this.StmtTraverser.factory.MakeStatementTraverser(this.sink, this.StmtTraverser.PdbReader, this.contractContext);

              var secondArg = new Bpl.NAryExpr(noToken, new Bpl.FunctionCall(this.sink.Heap.Int2Union), new List<Bpl.Expr>(new Bpl.Expr[] {Bpl.Expr.Ident(boundVar)}));
              ins.Add(secondArg);
              var outs = new List<Bpl.IdentifierExpr>();
              outs.Add(Bpl.Expr.Ident(resultVar));

              var callCmd = new Bpl.CallCmd(noToken, invokeProcedureInfo.Decl.Name, ins, outs);
              var blockCmds = new List<Bpl.Cmd>();
              blockCmds.Add(
                new Bpl.AssumeCmd(noToken,
                Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
                                new Bpl.NAryExpr(noToken, new Bpl.FunctionCall(this.sink.Heap.Union2Int), new List<Bpl.Expr>(new Bpl.Expr[] {secondArg})),
                                Bpl.Expr.Ident(boundVar))));
              blockCmds.Add(callCmd);
              Bpl.Block block = new Bpl.Block(noToken, "A", blockCmds, new Bpl.ReturnExprCmd(noToken, Bpl.Expr.Ident(resultVar)));
              Bpl.Expr body = new Bpl.CodeExpr(new List<Bpl.Variable>(new Bpl.Variable[] {resultVar}), new List<Bpl.Block>{block});


              Bpl.Expr antecedent = Bpl.Expr.And(Bpl.Expr.Le(lb, Bpl.Expr.Ident(boundVar)), Bpl.Expr.Lt(Bpl.Expr.Ident(boundVar), ub));

              Bpl.Expr quantifier;
              if (methodName == "ForAll")
              {
                  body = Bpl.Expr.Imp(antecedent, body);
                  quantifier = new Bpl.ForallExpr(methodCallToken, new List<Bpl.Variable>(new Bpl.Variable[] {boundVar}), body);
              }
              else
              {
                  body = Bpl.Expr.And(antecedent, body);
                  quantifier = new Bpl.ExistsExpr(methodCallToken, new List<Bpl.Variable>(new Bpl.Variable[] {boundVar}), body);
              }
              this.TranslatedExpressions.Push(quantifier);
              return;
          }
      }

      List<Bpl.Expr> inexpr;
      List<Bpl.IdentifierExpr> outvars;
      Bpl.IdentifierExpr thisExpr;
      Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> toBoxed;
      var proc = TranslateArgumentsAndReturnProcedure(methodCallToken, methodCall.MethodToCall, resolvedMethod, methodCall.IsStaticCall ? null : methodCall.ThisArgument, methodCall.Arguments, out inexpr, out outvars, out thisExpr, out toBoxed);
      string methodname = proc.Name;
      var translateAsFunctionCall = proc is Bpl.Function;
      bool isAsync = false;

      // this code structure is quite chaotic, and some code needs to be evaluated regardless, hence the try-finally
      try {
        if (!translateAsFunctionCall) {
          foreach (var a in resolvedMethod.Attributes) {
            if (TypeHelper.GetTypeName(a.Type).EndsWith("AsyncAttribute")) {
                isAsync = true;
            }
          }
        }

        var deferringCtorCall = resolvedMethod.IsConstructor && methodCall.ThisArgument is IThisReference;
        // REVIEW!! Ask Herman: is the above test enough? The following test is used in FindCtorCall.IsDeferringCtor,
        // but it doesn't work when the type is a struct S because then "this" has a type of "&S".
          //&& TypeHelper.TypesAreEquivalent(resolvedMethod.ContainingType, methodCall.ThisArgument.Type);

        if (resolvedMethod.IsConstructor && resolvedMethod.ContainingTypeDefinition.IsStruct && !deferringCtorCall) {
          handleStructConstructorCall(methodCall, methodCallToken, inexpr, outvars, thisExpr, proc);
          return;
        }

        Bpl.CallCmd call;
        bool isEventAdd = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("add_");
        bool isEventRemove = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("remove_");
        if (isEventAdd || isEventRemove) {
          call = translateAddRemoveCall(methodCall, resolvedMethod, methodCallToken, inexpr, outvars, thisExpr, isEventAdd);
        } else {
          if (translateAsFunctionCall) {
            var func = proc as Bpl.Function;
            var exprSeq = new List<Bpl.Expr>();
            foreach (var e in inexpr) {
              exprSeq.Add(e);
            }
            var callFunction = new Bpl.NAryExpr(methodCallToken, new Bpl.FunctionCall(func), exprSeq);
            this.TranslatedExpressions.Push(callFunction);
            return;
          } else {
            EmitLineDirective(methodCallToken);
            call = new Bpl.CallCmd(methodCallToken, methodname, inexpr, outvars);
            call.IsAsync = isAsync;
            this.StmtTraverser.StmtBuilder.Add(call);
          }
        }

        foreach (KeyValuePair<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> kv in toBoxed) {
          var lhs = kv.Key;
          var tuple = kv.Value;
          var rhs = tuple.Item1;
          Bpl.Expr fromUnion = this.sink.Heap.FromUnion(Bpl.Token.NoToken, lhs.Type, rhs, tuple.Item2);
          this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(lhs, fromUnion));
        }

        if (this.sink.Options.modelExceptions == 2
          || (this.sink.Options.modelExceptions == 1 && this.sink.MethodThrowsExceptions(resolvedMethod))) {
          Bpl.Expr expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef));
          this.StmtTraverser.RaiseException(expr);
        }
      } finally {
        // TODO move away phone related code from the translation, it would be better to have 2 or more translation phases
        if (PhoneCodeHelper.instance().PhonePlugin != null) {
          if (PhoneCodeHelper.instance().PhoneNavigationToggled) {
            if (PhoneCodeHelper.instance().isNavigationCall(methodCall)) {
              Bpl.AssignCmd assignCmd = PhoneCodeHelper.instance().createBoogieNavigationUpdateCmd(sink);
              this.StmtTraverser.StmtBuilder.Add(assignCmd);
            }
          }

          if (PhoneCodeHelper.instance().PhoneFeedbackToggled) {
            if (PhoneCodeHelper.instance().isMethodKnownUIChanger(methodCall)) {
              Bpl.AssumeCmd assumeFalse = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.LiteralExpr.False);
              this.StmtTraverser.StmtBuilder.Add(assumeFalse);
            }
          }
        }
      }
    }
Exemple #34
0
 public override Cmd VisitCallCmd(CallCmd node) {
   //Contract.Requires(node != null);
   Contract.Ensures(Contract.Result<Cmd>() != null);
   CallCmd clone = (CallCmd)node.Clone();
   Contract.Assert(clone != null);
   clone.Ins = new List<Expr>(clone.Ins);
   clone.Outs = new List<IdentifierExpr>(clone.Outs);
   return base.VisitCallCmd(clone);
 }
    private Bpl.CallCmd translateAddRemoveCall(IMethodCall methodCall, IMethodDefinition resolvedMethod, Bpl.IToken methodCallToken, List<Bpl.Expr> inexpr, List<Bpl.IdentifierExpr> outvars, Bpl.IdentifierExpr thisExpr, bool isEventAdd) {
      Bpl.CallCmd call;
      var mName = resolvedMethod.Name.Value;
      var eventName = mName.Substring(mName.IndexOf('_') + 1);
      var eventDef = TypeHelper.GetEvent(resolvedMethod.ContainingTypeDefinition, this.sink.host.NameTable.GetNameFor(eventName));
      Contract.Assert(eventDef != Dummy.Event);
      Bpl.Variable eventVar = this.sink.FindOrCreateEventVariable(eventDef);
      Bpl.Variable local = this.sink.CreateFreshLocal(eventDef.Type);

      if (methodCall.IsStaticCall) {
        this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(local), Bpl.Expr.Ident(eventVar)));
        inexpr.Insert(0, Bpl.Expr.Ident(local));
      } else {
        AssertOrAssumeNonNull(methodCallToken, thisExpr);
        this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(local), this.sink.Heap.ReadHeap(thisExpr, Bpl.Expr.Ident(eventVar), resolvedMethod.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap, local.TypedIdent.Type)));
        inexpr[0] = Bpl.Expr.Ident(local);
      }

      System.Diagnostics.Debug.Assert(outvars.Count == 0);
      outvars.Insert(0, Bpl.Expr.Ident(local));
      string methodName = isEventAdd ? this.sink.DelegateAdd(eventDef.Type.ResolvedType) : this.sink.DelegateRemove(eventDef.Type.ResolvedType);
      call = new Bpl.CallCmd(methodCallToken, methodName, inexpr, outvars);
      this.StmtTraverser.StmtBuilder.Add(call);
      if (methodCall.IsStaticCall) {
        this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(eventVar), Bpl.Expr.Ident(local)));
      } else {
        this.sink.Heap.WriteHeap(methodCallToken, thisExpr, Bpl.Expr.Ident(eventVar), Bpl.Expr.Ident(local), resolvedMethod.ContainingType.ResolvedType.IsStruct ? AccessType.Struct : AccessType.Heap, local.TypedIdent.Type, this.StmtTraverser.StmtBuilder);
      }
      return call;
    }