Пример #1
0
 public override Cmd VisitAssignCmd(AssignCmd node) {
   //Contract.Requires(node != null);
   Contract.Ensures(Contract.Result<Cmd>() != null);
   AssignCmd clone = (AssignCmd)node.Clone();
   clone.Lhss = new List<AssignLhs/*!*/>(clone.Lhss);
   clone.Rhss = new List<Expr/*!*/>(clone.Rhss);
   return base.VisitAssignCmd(clone);
 }
Пример #2
0
 public virtual Cmd VisitAssignCmd(AssignCmd node) {
   Contract.Requires(node != null);
   Contract.Ensures(Contract.Result<Cmd>() != null);
   for (int i = 0; i < node.Lhss.Count; ++i) {
     node.SetLhs(i, cce.NonNull((AssignLhs)this.Visit(node.Lhss[i])));
     node.SetRhs(i, cce.NonNull((Expr/*!*/)this.Visit(node.Rhss[i])));
   }
   return node;
 }
        private Bpl.Cmd getNavigationCheckAssign(Sink sink, bool value)
        {
            List <Bpl.AssignLhs> lhs = new List <Bpl.AssignLhs>();
            List <Bpl.Expr>      rhs = new List <Bpl.Expr>();

            Bpl.AssignLhs assignee = new Bpl.SimpleAssignLhs(Bpl.Token.NoToken, new Bpl.IdentifierExpr(Bpl.Token.NoToken,
                                                                                                       sink.FindOrCreateGlobalVariable(PhoneCodeHelper.BOOGIE_NAVIGATION_CHECK_VARIABLE, Bpl.Type.Bool)));
            lhs.Add(assignee);
            rhs.Add(value ? Bpl.IdentifierExpr.True : Bpl.IdentifierExpr.False);
            Bpl.AssignCmd assignCmd = new Bpl.AssignCmd(Bpl.Token.NoToken, lhs, rhs);
            return(assignCmd);
        }
        public Bpl.AssignCmd createBoogieNavigationUpdateCmd(Sink sink)
        {
            // the block is a potential page changer
            List <Bpl.AssignLhs> lhs = new List <Bpl.AssignLhs>();
            List <Bpl.Expr>      rhs = new List <Bpl.Expr>();

            Bpl.Expr value = new Bpl.LiteralExpr(Bpl.Token.NoToken, false);
            rhs.Add(value);
            Bpl.SimpleAssignLhs assignee =
                new Bpl.SimpleAssignLhs(Bpl.Token.NoToken,
                                        new Bpl.IdentifierExpr(Bpl.Token.NoToken,
                                                               sink.FindOrCreateGlobalVariable(PhoneCodeHelper.BOOGIE_CONTINUE_ON_PAGE_VARIABLE, Bpl.Type.Bool)));
            lhs.Add(assignee);
            Bpl.AssignCmd assignCmd = new Bpl.AssignCmd(Bpl.Token.NoToken, lhs, rhs);
            return(assignCmd);
        }
Пример #5
0
 public override Cmd VisitAssignCmd(AssignCmd node)
 {
     Contract.Ensures(Contract.Result<Cmd>() == node);
     for (int i = 0; i < node.Lhss.Count; ++i)
     {
         this.Visit(node.Lhss[i]);
         this.Visit(node.Rhss[i]);
     }
     return node;
 }
Пример #6
0
	void LabelOrAssign(out Cmd c, out IToken label) {
		IToken/*!*/ id; IToken/*!*/ x, y; Expr/*!*/ e0;
		c = dummyCmd;  label = null;
		AssignLhs/*!*/ lhs;
		List<AssignLhs/*!*/>/*!*/ lhss;
		List<Expr/*!*/>/*!*/ rhss;
		List<Expr/*!*/>/*!*/ indexes;
		
		Ident(out id);
		x = t; 
		if (la.kind == 12) {
			Get();
			c = null;  label = x; 
		} else if (la.kind == 13 || la.kind == 18 || la.kind == 51) {
			lhss = new List<AssignLhs/*!*/>(); 
			lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); 
			while (la.kind == 18) {
				MapAssignIndex(out y, out indexes);
				lhs = new MapAssignLhs(y, lhs, indexes); 
			}
			lhss.Add(lhs); 
			while (la.kind == 13) {
				Get();
				Ident(out id);
				lhs = new SimpleAssignLhs(id, new IdentifierExpr(id, id.val)); 
				while (la.kind == 18) {
					MapAssignIndex(out y, out indexes);
					lhs = new MapAssignLhs(y, lhs, indexes); 
				}
				lhss.Add(lhs); 
			}
			Expect(51);
			x = t; /* use location of := */ 
			Expression(out e0);
			rhss = new List<Expr/*!*/> ();
			rhss.Add(e0); 
			while (la.kind == 13) {
				Get();
				Expression(out e0);
				rhss.Add(e0); 
			}
			Expect(9);
			c = new AssignCmd(x, lhss, rhss); 
		} else SynErr(111);
	}
Пример #7
0
 public abstract Element Update(Element element, AssignCmd cmd);
Пример #8
0
 public abstract Element Update(Element element, AssignCmd cmd);  // requiers 'cmd' to be a simple (possibly parallel) assignment command
Пример #9
0
        /// <summary>
        ///
        /// </summary>
        public override void TraverseChildren(IMethodDefinition method)
        {
            if (method.IsStaticConstructor)
            {
                this.sawCctor = true;
            }

            bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_"));

            if (isEventAddOrRemove)
            {
                return;
            }


            Sink.ProcedureInfo procInfo;
            IMethodDefinition  stubMethod = null;

            if (IsStubMethod(method, out stubMethod))
            {
                procInfo = this.sink.FindOrCreateProcedure(stubMethod);
            }
            else
            {
                procInfo = this.sink.FindOrCreateProcedure(method);
            }

            if (method.IsAbstract || method.IsExternal) // we're done, just define the procedure
            {
                return;
            }

            this.sink.BeginMethod(method);
            var decl      = procInfo.Decl;
            var proc      = decl as Bpl.Procedure;
            var formalMap = procInfo.FormalMap;

            if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey)
            {
                decl.AddAttribute("entrypoint");
            }

            // FEEDBACK inline handler methods to avoid more false alarms
            if (PhoneCodeHelper.instance().PhoneFeedbackToggled&& PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(method) &&
                !PhoneCodeHelper.instance().isMethodIgnoredForFeedback(method))
            {
                proc.AddAttribute("inline", new Bpl.LiteralExpr(Bpl.Token.NoToken, Microsoft.Basetypes.BigNum.ONE));
                PhoneCodeHelper.instance().trackCallableMethod(proc);
            }

            try {
                StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false);

                // FEEDBACK if this is a feedback method it will be plagued with false asserts. They will trigger if $Exception becomes other than null
                // FEEDBACK for modular analysis we need it to be non-null at the start
                // FEEDBACK also, callee is obviously non null
                IMethodDefinition translatedMethod = sink.getMethodBeingTranslated();
                if (PhoneCodeHelper.instance().PhoneFeedbackToggled&& translatedMethod != null &&
                    PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(translatedMethod))
                {
                    // assign null to exception
                    List <Bpl.AssignLhs> assignee          = new List <Bpl.AssignLhs>();
                    Bpl.AssignLhs        exceptionAssignee = new Bpl.SimpleAssignLhs(Bpl.Token.NoToken, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable));
                    assignee.Add(exceptionAssignee);
                    List <Bpl.Expr> value = new List <Bpl.Expr>();
                    value.Add(Bpl.Expr.Ident(this.sink.Heap.NullRef));
                    Bpl.Cmd exceptionAssign = new Bpl.AssignCmd(Bpl.Token.NoToken, assignee, value);
                    stmtTraverser.StmtBuilder.Add(exceptionAssign);
                }

                #region Add assignments from In-Params to local-Params

                foreach (MethodParameter mparam in formalMap)
                {
                    if (mparam.inParameterCopy != null)
                    {
                        Bpl.IToken tok = method.Token();
                        stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok,
                                                                           new Bpl.IdentifierExpr(tok, mparam.outParameterCopy),
                                                                           new Bpl.IdentifierExpr(tok, mparam.inParameterCopy)));
                    }
                }

                #endregion

                #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values
                var inits = InitializeFieldsInConstructor(method);
                if (0 < inits.Count)
                {
                    foreach (var s in inits)
                    {
                        stmtTraverser.Traverse(s);
                    }
                }
                #endregion

                #region Translate method attributes
                // Don't need an expression translator because there is a limited set of things
                // that can appear as arguments to custom attributes
                // TODO: decode enum values
                try {
                    foreach (var a in method.Attributes)
                    {
                        var attrName = TypeHelper.GetTypeName(a.Type);
                        if (attrName.EndsWith("Attribute"))
                        {
                            attrName = attrName.Substring(0, attrName.Length - 9);
                        }
                        var args = new List <object>();
                        foreach (var c in a.Arguments)
                        {
                            var mdc = c as IMetadataConstant;
                            if (mdc != null)
                            {
                                object o;
                                if (mdc.Type.IsEnum)
                                {
                                    var lit = Bpl.Expr.Literal((int)mdc.Value);
                                    lit.Type = Bpl.Type.Int;
                                    o        = lit;
                                }
                                else
                                {
                                    switch (mdc.Type.TypeCode)
                                    {
                                    case PrimitiveTypeCode.Boolean:
                                        o = (bool)mdc.Value ? Bpl.Expr.True : Bpl.Expr.False;
                                        break;

                                    case PrimitiveTypeCode.Int32:
                                        var lit = Bpl.Expr.Literal((int)mdc.Value);
                                        lit.Type = Bpl.Type.Int;
                                        o        = lit;
                                        break;

                                    case PrimitiveTypeCode.String:
                                        o = mdc.Value;
                                        break;

                                    default:
                                        throw new InvalidCastException("Invalid metadata constant type");
                                    }
                                }
                                args.Add(o);
                            }
                        }
                        decl.AddAttribute(attrName, args.ToArray());
                    }
                } catch (InvalidCastException) {
                    Console.WriteLine("Warning: Cannot translate custom attributes for method\n    '{0}':",
                                      MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                    Console.WriteLine("    >>Skipping attributes, continuing with method translation");
                }
                #endregion

                #region Translate body
                var helperTypes = stmtTraverser.TranslateMethod(method);
                if (helperTypes != null)
                {
                    this.privateTypes.AddRange(helperTypes);
                }
                #endregion

                #region Create Local Vars For Implementation
                List <Bpl.Variable> vars = new List <Bpl.Variable>();
                foreach (MethodParameter mparam in formalMap)
                {
                    if (!mparam.underlyingParameter.IsByReference)
                    {
                        vars.Add(mparam.outParameterCopy);
                    }
                }
                foreach (Bpl.Variable v in this.sink.LocalVarMap.Values)
                {
                    vars.Add(v);
                }
                // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions
                if (0 < this.sink.Options.modelExceptions)
                {
                    vars.Add(procInfo.LocalExcVariable);
                }
                vars.Add(procInfo.LabelVariable);
                List <Bpl.Variable> vseq = new List <Bpl.Variable>(vars.ToArray());
                #endregion

                var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken);

                #region Add implementation to Boogie program
                if (proc != null)
                {
                    Bpl.Implementation impl =
                        new Bpl.Implementation(method.Token(),
                                               decl.Name,
                                               new List <Bpl.TypeVariable>(),
                                               decl.InParams,
                                               decl.OutParams,
                                               vseq,
                                               translatedBody);

                    impl.Proc = proc;
                    this.sink.TranslatedProgram.AddTopLevelDeclaration(impl);
                }
                else // method is translated as a function
                //var func = decl as Bpl.Function;
                //Contract.Assume(func != null);
                //var blocks = new List<Bpl.Block>();
                //var counter = 0;
                //var returnValue = decl.OutParams[0];
                //foreach (var bb in translatedBody.BigBlocks) {
                //  var label = bb.LabelName ?? "L" + counter++.ToString();
                //  var newTransferCmd = (bb.tc is Bpl.ReturnCmd)
                //    ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue))
                //    : bb.tc;
                //  var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd);
                //  blocks.Add(b);
                //}
                //var localVars = new List<Bpl.Variable>();
                //localVars.Add(returnValue);
                //func.Body = new Bpl.CodeExpr(localVars, blocks);
                {
                }
                #endregion
            } catch (TranslationException te) {
                Console.WriteLine("Translation error in body of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t" + te.Message);
            } catch (Exception e) {
                Console.WriteLine("Error encountered during translation of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t>>" + e.Message);
            } finally {
            }
        }
 private Bpl.Cmd getNavigationCheckAssign(Sink sink, bool value) {
   List<Bpl.AssignLhs> lhs = new List<Bpl.AssignLhs>();
   List<Bpl.Expr> rhs = new List<Bpl.Expr>();
   Bpl.AssignLhs assignee = new Bpl.SimpleAssignLhs(Bpl.Token.NoToken, new Bpl.IdentifierExpr(Bpl.Token.NoToken,
                            sink.FindOrCreateGlobalVariable(PhoneCodeHelper.BOOGIE_NAVIGATION_CHECK_VARIABLE, Bpl.Type.Bool)));
   lhs.Add(assignee);
   rhs.Add(value ? Bpl.IdentifierExpr.True : Bpl.IdentifierExpr.False);
   Bpl.AssignCmd assignCmd = new Bpl.AssignCmd(Bpl.Token.NoToken, lhs, rhs);
   return assignCmd;
 }
Пример #11
0
 public override Cmd VisitAssignCmd(AssignCmd node)
 {
     HashSet<Variable> rhsVars = new HashSet<Variable>();
     for (int i = 0; i < node.Lhss.Count; i++)
     {
         AssignLhs lhs = node.Lhss[i];
         Variable lhsVar = lhs.DeepAssignedVariable;
         string domainName = FindDomainName(lhsVar);
         if (domainName == null) continue;
         SimpleAssignLhs salhs = lhs as SimpleAssignLhs;
         if (salhs == null)
         {
             Error(node, string.Format("Only simple assignment allowed on linear variable {0}", lhsVar.Name));
             continue;
         }
         IdentifierExpr rhs = node.Rhss[i] as IdentifierExpr;
         if (rhs == null)
         {
             Error(node, string.Format("Only variable can be assigned to linear variable {0}", lhsVar.Name));
             continue; 
         }
         string rhsDomainName = FindDomainName(rhs.Decl);
         if (rhsDomainName == null)
         {
             Error(node, string.Format("Only linear variable can be assigned to linear variable {0}", lhsVar.Name));
             continue;
         }
         if (domainName != rhsDomainName)
         {
             Error(node, string.Format("Linear variable of domain {0} cannot be assigned to linear variable of domain {1}", rhsDomainName, domainName));
             continue;
         }
         if (rhsVars.Contains(rhs.Decl))
         {
             Error(node, string.Format("Linear variable {0} can occur only once in the right-hand-side of an assignment", rhs.Decl.Name));
             continue;
         }
         rhsVars.Add(rhs.Decl);
     }
     return base.VisitAssignCmd(node);
 }
Пример #12
0
    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;
    }
Пример #13
0
 public override Cmd VisitAssignCmd(AssignCmd node)
 {
     Contract.Ensures(Contract.Result<Cmd>() == node);
     for (int i = 0; i < node.Lhss.Count; ++i)
     {
         bool savedCanAccessSharedVars = canAccessSharedVars;
         bool savedCanAccessAuxVars = canAccessGhostVars;
         Variable v = node.Lhss[i].DeepAssignedVariable;
         if (v is LocalVariable && ghostVars.Contains(v))
         {
             canAccessSharedVars = true;
             canAccessGhostVars = true;
         }
         this.Visit(node.Lhss[i]);
         this.Visit(node.Rhss[i]);
         canAccessSharedVars = savedCanAccessSharedVars;
         canAccessGhostVars = savedCanAccessAuxVars;
     }
     return node;
 }
Пример #14
0
            public override Cmd VisitAssignCmd(AssignCmd node)
            {
                var renamedLhss = new List<AssignLhs>();
                foreach (var l in node.Lhss)
                {
                    if (l is SimpleAssignLhs)
                    {
                        renamedLhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(VisitVariable(l.DeepAssignedVariable))));
                    }
                    else if (l is MapAssignLhs)
                    {
                        var mal = l as MapAssignLhs;
                        renamedLhss.Add(new MapAssignLhs(Token.NoToken,
                            new SimpleAssignLhs(Token.NoToken, VisitIdentifierExpr(mal.DeepAssignedIdentifier) as IdentifierExpr),
                            mal.Indexes.Select(i => VisitExpr(i)).ToList()));
                    }
                    else
                    {
                        ErrorAndDie("Unknown assign type");
                    }
                }

                var renamedRhss = new List<Expr>();
                node.Rhss.Iter(r => renamedRhss.Add(VisitExpr(r)));

                var result = new AssignCmd(Token.NoToken, renamedLhss, renamedRhss);
                return result;
            }
 private void HandleAssign(string proc, Block b, AssignCmd assign)
 {
     foreach (var assignPair in assign.Lhss.Zip(assign.Rhss).Where
     (Item => VariableRelevantToAnalysis(Item.Item1.DeepAssignedVariable, proc))) {
     VariableDescriptor assignedVariable = MakeDescriptor(proc, assignPair.Item1.DeepAssignedVariable);
     AddDependences(assignedVariable, GetReferencedVariables(assignPair.Item1, proc),
       "LHS of assignment", assign.tok);
     AddDependences(assignedVariable, GetReferencedVariables(assignPair.Item2, proc),
       "RHS of assignment", assign.tok);
     AddControlDependences(b, assignedVariable, "Variable assigned under control dependence", assign.tok);
       }
 }
    /// <summary>
    /// 
    /// </summary>
    public override void TraverseChildren(IMethodDefinition method) {

      if (method.IsStaticConstructor) this.sawCctor = true;

      bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_"));
      if (isEventAddOrRemove)
        return;


      Sink.ProcedureInfo procInfo;
      IMethodDefinition stubMethod = null;
      if (IsStubMethod(method, out stubMethod)) {
        procInfo = this.sink.FindOrCreateProcedure(stubMethod);
      } else {
        procInfo = this.sink.FindOrCreateProcedure(method);
      }

      if (method.IsAbstract || method.IsExternal) { // we're done, just define the procedure
        return;
      }

      this.sink.BeginMethod(method);
      var decl = procInfo.Decl;
      var proc = decl as Bpl.Procedure;
      var formalMap = procInfo.FormalMap;

      if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey) {
        decl.AddAttribute("entrypoint");
      }

      // FEEDBACK inline handler methods to avoid more false alarms
      if (PhoneCodeHelper.instance().PhoneFeedbackToggled && PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(method) &&
          !PhoneCodeHelper.instance().isMethodIgnoredForFeedback(method)) {
            proc.AddAttribute("inline", new Bpl.LiteralExpr(Bpl.Token.NoToken, Microsoft.Basetypes.BigNum.ONE));
            PhoneCodeHelper.instance().trackCallableMethod(proc);
      }

      try {
        StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false);

        // FEEDBACK if this is a feedback method it will be plagued with false asserts. They will trigger if $Exception becomes other than null
        // FEEDBACK for modular analysis we need it to be non-null at the start
        // FEEDBACK also, callee is obviously non null
        IMethodDefinition translatedMethod= sink.getMethodBeingTranslated();
        if (PhoneCodeHelper.instance().PhoneFeedbackToggled && translatedMethod != null &&
            PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(translatedMethod)) {
          // assign null to exception
          List<Bpl.AssignLhs> assignee= new List<Bpl.AssignLhs>();
          Bpl.AssignLhs exceptionAssignee= new Bpl.SimpleAssignLhs(Bpl.Token.NoToken, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable));
          assignee.Add(exceptionAssignee);
          List<Bpl.Expr> value= new List<Bpl.Expr>();
          value.Add(Bpl.Expr.Ident(this.sink.Heap.NullRef));
          Bpl.Cmd exceptionAssign= new Bpl.AssignCmd(Bpl.Token.NoToken, assignee, value);
          stmtTraverser.StmtBuilder.Add(exceptionAssign);
        }

        #region Add assignments from In-Params to local-Params

        foreach (MethodParameter mparam in formalMap) {
          if (mparam.inParameterCopy != null) {
            Bpl.IToken tok = method.Token();
            stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok,
              new Bpl.IdentifierExpr(tok, mparam.outParameterCopy),
              new Bpl.IdentifierExpr(tok, mparam.inParameterCopy)));
          }
        }

        #endregion

        #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values
        var inits = InitializeFieldsInConstructor(method);
        if (0 < inits.Count) {
          foreach (var s in inits) {
            stmtTraverser.Traverse(s);
          }
        }
        #endregion

        #region Translate method attributes
        // Don't need an expression translator because there is a limited set of things
        // that can appear as arguments to custom attributes
        // TODO: decode enum values
        try {
          foreach (var a in method.Attributes) {
            var attrName = TypeHelper.GetTypeName(a.Type);
            if (attrName.EndsWith("Attribute"))
              attrName = attrName.Substring(0, attrName.Length - 9);
            var args = new List<object>();
            foreach (var c in a.Arguments) {
              var mdc = c as IMetadataConstant;
              if (mdc != null) {
                object o;
                if (mdc.Type.IsEnum) {
                  var lit = Bpl.Expr.Literal((int) mdc.Value);
                  lit.Type = Bpl.Type.Int;
                  o = lit;
                } else {
                  switch (mdc.Type.TypeCode) {
                    case PrimitiveTypeCode.Boolean:
                      o = (bool) mdc.Value ? Bpl.Expr.True : Bpl.Expr.False;
                      break;
                    case PrimitiveTypeCode.Int32:
                      var lit = Bpl.Expr.Literal((int) mdc.Value);
                      lit.Type = Bpl.Type.Int;
                      o = lit;
                      break;
                    case PrimitiveTypeCode.String:
                      o = mdc.Value;
                      break;
                    default:
                      throw new InvalidCastException("Invalid metadata constant type");
                  }
                }
                args.Add(o);
              }
            }
            decl.AddAttribute(attrName, args.ToArray());
          }
        } catch (InvalidCastException) {
          Console.WriteLine("Warning: Cannot translate custom attributes for method\n    '{0}':",
            MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
          Console.WriteLine("    >>Skipping attributes, continuing with method translation");
        }
        #endregion

        #region Translate body
        var helperTypes = stmtTraverser.TranslateMethod(method);
        if (helperTypes != null) {
          this.privateTypes.AddRange(helperTypes);
        }
        #endregion

        #region Create Local Vars For Implementation
        List<Bpl.Variable> vars = new List<Bpl.Variable>();
        foreach (MethodParameter mparam in formalMap) {
          if (!mparam.underlyingParameter.IsByReference)
            vars.Add(mparam.outParameterCopy);
        }
        foreach (Bpl.Variable v in this.sink.LocalVarMap.Values) {
          vars.Add(v);
        }
        // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions
        if (0 <this.sink.Options.modelExceptions)
          vars.Add(procInfo.LocalExcVariable);
        vars.Add(procInfo.LabelVariable);
        List<Bpl.Variable> vseq = new List<Bpl.Variable>(vars.ToArray());
        #endregion

        var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken);

        #region Add implementation to Boogie program
        if (proc != null) {
          Bpl.Implementation impl =
              new Bpl.Implementation(method.Token(),
                  decl.Name,
                  new List<Bpl.TypeVariable>(),
                  decl.InParams,
                  decl.OutParams,
                  vseq,
                  translatedBody);

          impl.Proc = proc;
          this.sink.TranslatedProgram.AddTopLevelDeclaration(impl);
        } else { // method is translated as a function
          //var func = decl as Bpl.Function;
          //Contract.Assume(func != null);
          //var blocks = new List<Bpl.Block>();
          //var counter = 0;
          //var returnValue = decl.OutParams[0];
          //foreach (var bb in translatedBody.BigBlocks) {
          //  var label = bb.LabelName ?? "L" + counter++.ToString();
          //  var newTransferCmd = (bb.tc is Bpl.ReturnCmd)
          //    ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue))
          //    : bb.tc;
          //  var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd);
          //  blocks.Add(b);
          //}
          //var localVars = new List<Bpl.Variable>();
          //localVars.Add(returnValue);
          //func.Body = new Bpl.CodeExpr(localVars, blocks);
        }
        #endregion

      } catch (TranslationException te) {
        Console.WriteLine("Translation error in body of \n    '{0}':",
          MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
        Console.WriteLine("\t" + te.Message);
      } catch (Exception e) {
        Console.WriteLine("Error encountered during translation of \n    '{0}':",
          MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
        Console.WriteLine("\t>>" + e.Message);
      } finally {
      }
    }
Пример #17
0
    void CreateProceduresForLoops(Implementation impl, Graph<Block/*!*/>/*!*/ g,
                                  List<Implementation/*!*/>/*!*/ loopImpls,
                                  Dictionary<string, Dictionary<string, Block>> fullMap) {
      Contract.Requires(impl != null);
      Contract.Requires(cce.NonNullElements(loopImpls));
      // Enumerate the headers
      // for each header h:
      //   create implementation p_h with
      //     inputs = inputs, outputs, and locals of impl
      //     outputs = outputs and locals of impl
      //     locals = empty set
      //   add call o := p_h(i) at the beginning of the header block
      //   break the back edges whose target is h
      // Enumerate the headers again to create the bodies of p_h
      // for each header h:
      //   compute the loop corresponding to h
      //   make copies of all blocks in the loop for h
      //   delete all target edges that do not go to a block in the loop
      //   create a new entry block and a new return block
      //   add edges from entry block to the loop header and the return block
      //   add calls o := p_h(i) at the end of the blocks that are sources of back edges
      foreach (Block block in impl.Blocks)
      {
          AddToFullMap(fullMap, impl.Name, block.Label, block);
      }

      bool detLoopExtract = CommandLineOptions.Clo.DeterministicExtractLoops;

      Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToInputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>();
      Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToOutputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>();
      Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>/*!*/ loopHeaderToSubstMap = new Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>();
      Dictionary<Block/*!*/, LoopProcedure/*!*/>/*!*/ loopHeaderToLoopProc = new Dictionary<Block/*!*/, LoopProcedure/*!*/>();
      Dictionary<Block/*!*/, CallCmd/*!*/>/*!*/ loopHeaderToCallCmd1 = new Dictionary<Block/*!*/, CallCmd/*!*/>();
      Dictionary<Block, CallCmd> loopHeaderToCallCmd2 = new Dictionary<Block, CallCmd>();
      Dictionary<Block, AssignCmd> loopHeaderToAssignCmd = new Dictionary<Block, AssignCmd>();

      foreach (Block/*!*/ header in g.Headers) {
        Contract.Assert(header != null);
        Contract.Assert(header != null);
        List<Variable> inputs = new List<Variable>();
        List<Variable> outputs = new List<Variable>();
        List<Expr> callInputs1 = new List<Expr>();
        List<IdentifierExpr> callOutputs1 = new List<IdentifierExpr>();
        List<Expr> callInputs2 = new List<Expr>();
        List<IdentifierExpr> callOutputs2 = new List<IdentifierExpr>();
        List<AssignLhs> lhss = new List<AssignLhs>();
        List<Expr> rhss = new List<Expr>();
        Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); // Variable -> IdentifierExpr

        List<Variable>/*!*/ targets = new List<Variable>();
        HashSet<Variable> footprint = new HashSet<Variable>();

        foreach (Block/*!*/ b in g.BackEdgeNodes(header))
        {
            Contract.Assert(b != null);
            foreach (Block/*!*/ block in g.NaturalLoops(header, b))
            {
                Contract.Assert(block != null);
                foreach (Cmd/*!*/ cmd in block.Cmds)
                {
                    Contract.Assert(cmd != null);
                    cmd.AddAssignedVariables(targets);

                    VariableCollector c = new VariableCollector();
                    c.Visit(cmd);
                    footprint.UnionWith(c.usedVars);
                }
            }
        }

        List<IdentifierExpr>/*!*/ globalMods = new List<IdentifierExpr>();
        Set targetSet = new Set();
        foreach (Variable/*!*/ v in targets)
        {
            Contract.Assert(v != null);
            if (targetSet.Contains(v))
                continue;
            targetSet.Add(v);
            if (v is GlobalVariable)
                globalMods.Add(new IdentifierExpr(Token.NoToken, v));
        }

        foreach (Variable v in impl.InParams) {
          Contract.Assert(v != null);
          if (!footprint.Contains(v)) continue;
          callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
          Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
          inputs.Add(f);
          callInputs2.Add(new IdentifierExpr(Token.NoToken, f));
          substMap[v] = new IdentifierExpr(Token.NoToken, f);
        }
        foreach (Variable v in impl.OutParams) {
          Contract.Assert(v != null);
          if (!footprint.Contains(v)) continue;
          callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
          Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
          inputs.Add(f1);
          if (targetSet.Contains(v))
          {
              callOutputs1.Add(new IdentifierExpr(Token.NoToken, v));
              Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false);
              outputs.Add(f2);
              callInputs2.Add(new IdentifierExpr(Token.NoToken, f2));
              callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2));
              lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2)));
              rhss.Add(new IdentifierExpr(Token.NoToken, f1));
              substMap[v] = new IdentifierExpr(Token.NoToken, f2);
          }
          else
          {
              callInputs2.Add(new IdentifierExpr(Token.NoToken, f1));
              substMap[v] = new IdentifierExpr(Token.NoToken, f1);
          }
        }
        foreach (Variable v in impl.LocVars) {
          Contract.Assert(v != null);
          if (!footprint.Contains(v)) continue;
          callInputs1.Add(new IdentifierExpr(Token.NoToken, v));
          Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true);
          inputs.Add(f1);
          if (targetSet.Contains(v))
          {
              callOutputs1.Add(new IdentifierExpr(Token.NoToken, v));
              Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false);
              outputs.Add(f2);
              callInputs2.Add(new IdentifierExpr(Token.NoToken, f2));
              callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2));
              lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2)));
              rhss.Add(new IdentifierExpr(Token.NoToken, f1));
              substMap[v] = new IdentifierExpr(Token.NoToken, f2);
          }
          else
          {
              callInputs2.Add(new IdentifierExpr(Token.NoToken, f1));
              substMap[v] = new IdentifierExpr(Token.NoToken, f1);
          }
        }

        loopHeaderToInputs[header] = inputs;
        loopHeaderToOutputs[header] = outputs;
        loopHeaderToSubstMap[header] = substMap;
        LoopProcedure loopProc = new LoopProcedure(impl, header, inputs, outputs, globalMods);
        loopHeaderToLoopProc[header] = loopProc;

        CallCmd callCmd1 = new CallCmd(Token.NoToken, loopProc.Name, callInputs1, callOutputs1);
        callCmd1.Proc = loopProc;
        loopHeaderToCallCmd1[header] = callCmd1;

        CallCmd callCmd2 = new CallCmd(Token.NoToken, loopProc.Name, callInputs2, callOutputs2);
        callCmd2.Proc = loopProc;
        loopHeaderToCallCmd2[header] = callCmd2;

        Debug.Assert(lhss.Count == rhss.Count);
        if (lhss.Count > 0)
        {
            AssignCmd assignCmd = new AssignCmd(Token.NoToken, lhss, rhss);
            loopHeaderToAssignCmd[header] = assignCmd;
        }
      }

      // Keep track of the new blocks created: maps a header node to the
      // header_last block that was created because of splitting header.
      Dictionary<Block, Block> newBlocksCreated = new Dictionary<Block, Block>();

      bool headRecursion = false; // testing an option to put recursive call before loop body

      IEnumerable<Block> sortedHeaders = g.SortHeadersByDominance();
      foreach (Block/*!*/ header in sortedHeaders)
      {
        Contract.Assert(header != null);
        LoopProcedure loopProc = loopHeaderToLoopProc[header];
        Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>();
        HashSet<string> dummyBlocks = new HashSet<string>();

        CodeCopier codeCopier = new CodeCopier(loopHeaderToSubstMap[header]);  // fix me
        List<Variable> inputs = loopHeaderToInputs[header];
        List<Variable> outputs = loopHeaderToOutputs[header];
        int si_unique_loc = 1; // Added by AL: to distinguish the back edges
        foreach (Block/*!*/ source in g.BackEdgeNodes(header)) {
          Contract.Assert(source != null);
          foreach (Block/*!*/ block in g.NaturalLoops(header, source)) {
            Contract.Assert(block != null);
            if (blockMap.ContainsKey(block))
              continue;
            Block newBlock = new Block();
            newBlock.Label = block.Label;
            if (headRecursion && block == header)
            {
                CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone();
                addUniqueCallAttr(si_unique_loc, callCmd);
                si_unique_loc++;
                newBlock.Cmds.Add(callCmd);  // add the recursive call at head of loop
                var rest = codeCopier.CopyCmdSeq(block.Cmds);
                newBlock.Cmds.AddRange(rest);
            }
            else
              newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds);
            blockMap[block] = newBlock;
            if (newBlocksCreated.ContainsKey(block))
            {
                Block newBlock2 = new Block();
                newBlock2.Label = newBlocksCreated[block].Label;
                newBlock2.Cmds = codeCopier.CopyCmdSeq(newBlocksCreated[block].Cmds);
                blockMap[newBlocksCreated[block]] = newBlock2;
            }
            //for detLoopExtract, need the immediate successors even outside the loop
            if (detLoopExtract) {
                GotoCmd auxGotoCmd = block.TransferCmd as GotoCmd;
                Contract.Assert(auxGotoCmd != null && auxGotoCmd.labelNames != null && 
                    auxGotoCmd.labelTargets != null && auxGotoCmd.labelTargets.Count >= 1);
                foreach(var bl in auxGotoCmd.labelTargets) {
                    bool found = false;
                    foreach(var n in g.NaturalLoops(header, source)) { //very expensive, can we do a contains?
                        if (bl == n) { //clarify: is this the right comparison?
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        Block auxNewBlock = new Block();
                        auxNewBlock.Label = ((Block)bl).Label;
                        auxNewBlock.Cmds = codeCopier.CopyCmdSeq(((Block)bl).Cmds);
                        //add restoration code for such blocks
                        if (loopHeaderToAssignCmd.ContainsKey(header))
                        {
                            AssignCmd assignCmd = loopHeaderToAssignCmd[header];
                            auxNewBlock.Cmds.Add(assignCmd);
                        }
                        List<AssignLhs> lhsg = new List<AssignLhs>();
                        List<IdentifierExpr>/*!*/ globalsMods = loopHeaderToLoopProc[header].Modifies;
                        foreach (IdentifierExpr gl in globalsMods)
                            lhsg.Add(new SimpleAssignLhs(Token.NoToken, gl));
                        List<Expr> rhsg = new List<Expr>();
                        foreach (IdentifierExpr gl in globalsMods)
                            rhsg.Add(new OldExpr(Token.NoToken, gl));
                        if (lhsg.Count != 0)
                        {
                            AssignCmd globalAssignCmd = new AssignCmd(Token.NoToken, lhsg, rhsg);
                            auxNewBlock.Cmds.Add(globalAssignCmd);
                        }
                        blockMap[(Block)bl] = auxNewBlock;
                    }
                }

            }
          }

          List<Cmd> cmdSeq;
          if (headRecursion)
              cmdSeq = new List<Cmd>();
          else
          {
              CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone();
              addUniqueCallAttr(si_unique_loc, callCmd);
              si_unique_loc++;
              cmdSeq = new List<Cmd> { callCmd };
          }

          Block/*!*/ block1 = new Block(Token.NoToken, source.Label + "_dummy",
                              new List<Cmd>{ new AssumeCmd(Token.NoToken, Expr.False) }, new ReturnCmd(Token.NoToken));
          Block/*!*/ block2 = new Block(Token.NoToken, block1.Label,
                              cmdSeq, new ReturnCmd(Token.NoToken));
          impl.Blocks.Add(block1);
          dummyBlocks.Add(block1.Label);

          GotoCmd gotoCmd = source.TransferCmd as GotoCmd;
          Contract.Assert(gotoCmd != null && gotoCmd.labelNames != null && gotoCmd.labelTargets != null && gotoCmd.labelTargets.Count >= 1);
          List<String>/*!*/ newLabels = new List<String>();
          List<Block>/*!*/ newTargets = new List<Block>();
          for (int i = 0; i < gotoCmd.labelTargets.Count; i++) {
            if (gotoCmd.labelTargets[i] == header)
              continue;
            newTargets.Add(gotoCmd.labelTargets[i]);
            newLabels.Add(gotoCmd.labelNames[i]);
          }
          newTargets.Add(block1);
          newLabels.Add(block1.Label);
          gotoCmd.labelNames = newLabels;
          gotoCmd.labelTargets = newTargets;
          blockMap[block1] = block2;
        }
        List<Block/*!*/>/*!*/ blocks = new List<Block/*!*/>();
        Block exit = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken));
        GotoCmd cmd = new GotoCmd(Token.NoToken,
                                    new List<String> { cce.NonNull(blockMap[header]).Label, exit.Label },
                                    new List<Block> { blockMap[header], exit });

        if (detLoopExtract) //cutting the non-determinism
            cmd = new GotoCmd(Token.NoToken,
                                    new List<String> { cce.NonNull(blockMap[header]).Label },
                                    new List<Block> { blockMap[header] });

        Block entry;
        List<Cmd> initCmds = new List<Cmd>();
        if (loopHeaderToAssignCmd.ContainsKey(header)) {
            AssignCmd assignCmd = loopHeaderToAssignCmd[header];
            initCmds.Add(assignCmd);
        }

        entry = new Block(Token.NoToken, "entry", initCmds, cmd);
        blocks.Add(entry);

        foreach (Block/*!*/ block in blockMap.Keys) {
          Contract.Assert(block != null);
          Block/*!*/ newBlock = cce.NonNull(blockMap[block]);
          GotoCmd gotoCmd = block.TransferCmd as GotoCmd;
          if (gotoCmd == null) {
            newBlock.TransferCmd = new ReturnCmd(Token.NoToken);
          } else {
            Contract.Assume(gotoCmd.labelNames != null && gotoCmd.labelTargets != null);
            List<String> newLabels = new List<String>();
            List<Block> newTargets = new List<Block>();
            for (int i = 0; i < gotoCmd.labelTargets.Count; i++) {
              Block target = gotoCmd.labelTargets[i];
              if (blockMap.ContainsKey(target)) {
                newLabels.Add(gotoCmd.labelNames[i]);
                newTargets.Add(blockMap[target]);
              }  
            }
            if (newTargets.Count == 0) {
                if (!detLoopExtract)
                    newBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
                newBlock.TransferCmd = new ReturnCmd(Token.NoToken);
            } else {
              newBlock.TransferCmd = new GotoCmd(Token.NoToken, newLabels, newTargets);
            }
          }
          blocks.Add(newBlock);
        }
        blocks.Add(exit);
        Implementation loopImpl =
            new Implementation(Token.NoToken, loopProc.Name,
                                new List<TypeVariable>(), inputs, outputs, new List<Variable>(), blocks);
        loopImpl.Proc = loopProc;
        loopImpls.Add(loopImpl);

        // Make a (shallow) copy of the header before splitting it
        Block origHeader = new Block(header.tok, header.Label, header.Cmds, header.TransferCmd);

        // Finally, add call to the loop in the containing procedure
        string lastIterBlockName = header.Label + "_last";
        Block lastIterBlock = new Block(Token.NoToken, lastIterBlockName, header.Cmds, header.TransferCmd);
        newBlocksCreated[header] = lastIterBlock;
        header.Cmds = new List<Cmd> { loopHeaderToCallCmd1[header] };
        header.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { lastIterBlockName }, new List<Block> { lastIterBlock });
        impl.Blocks.Add(lastIterBlock);
        blockMap[origHeader] = blockMap[header];
        blockMap.Remove(header);

        Contract.Assert(fullMap[impl.Name][header.Label] == header);
        fullMap[impl.Name][header.Label] = origHeader;

        foreach (Block block in blockMap.Keys)
        {
            // Don't add dummy blocks to the map
            if (dummyBlocks.Contains(blockMap[block].Label)) continue;

            // Following two statements are for nested loops: compose map
            if (!fullMap[impl.Name].ContainsKey(block.Label)) continue;
            var target = fullMap[impl.Name][block.Label];

            AddToFullMap(fullMap, loopProc.Name, blockMap[block].Label, target);
        }

        fullMap[impl.Name].Remove(header.Label);
        fullMap[impl.Name][lastIterBlockName] = origHeader;
      }
    }
Пример #18
0
    public Implementation Inject(Implementation implementation, Program programInCachedSnapshot)
    {
      Contract.Requires(implementation != null && programInCachedSnapshot != null);

      this.programInCachedSnapshot = programInCachedSnapshot;
      assumptionVariableCount = 0;
      temporaryVariableCount = 0;
      currentImplementation = implementation;

      #region Introduce explict assumption about the precondition.

      var oldProc = programInCachedSnapshot.FindProcedure(currentImplementation.Proc.Name);
      if (oldProc != null
          && oldProc.DependencyChecksum != currentImplementation.Proc.DependencyChecksum
          && currentImplementation.ExplicitAssumptionAboutCachedPrecondition == null)
      {
        var axioms = new List<Axiom>();
        var after = new List<Cmd>();
        Expr assumedExpr = new LiteralExpr(Token.NoToken, false);
        var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program, true);
        if (canUseSpecs && oldProc.SignatureEquals(currentImplementation.Proc))
        {
          var always = Substituter.SubstitutionFromHashtable(currentImplementation.GetImplFormalMap(), true, currentImplementation.Proc);
          var forOld = Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>());
          var clauses = oldProc.Requires.Select(r => Substituter.FunctionCallReresolvingApply(always, forOld, r.Condition, Program));
          var conj = Expr.And(clauses, true);
          assumedExpr = conj != null ? FunctionExtractor.Extract(conj, Program, axioms) : 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));
          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(currentImplementation.tok, new List<AssignLhs> { lhs }, new List<Expr> { rhs });
          assumed.IrrelevantForChecksumComputation = true;
          currentImplementation.ExplicitAssumptionAboutCachedPrecondition = assumed;
          after.Add(assumed);
        }

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

      #endregion

      var result = VisitImplementation(currentImplementation);
      currentImplementation = null;
      this.programInCachedSnapshot = null;
      return result;
    }
Пример #19
0
 public override Cmd VisitAssignCmd(AssignCmd assignCmd) {
   //Contract.Requires(assignCmd != null);
   Contract.Ensures(Contract.Result<Cmd>() != null);
   Cmd ret = base.VisitAssignCmd(assignCmd);
   foreach (AssignLhs/*!*/ lhs in assignCmd.Lhss) {
     Contract.Assert(lhs != null);
     ProcessVariable(lhs.DeepAssignedVariable);
   }
   return ret;
 }
Пример #20
0
 public override Cmd VisitAssignCmd(AssignCmd node)
 {
     node.tok = Token.NoToken;
     TokenCount++; 
     return base.VisitAssignCmd(node);
 }
 public Bpl.AssignCmd createBoogieNavigationUpdateCmd(Sink sink) {
   // the block is a potential page changer
   List<Bpl.AssignLhs> lhs = new List<Bpl.AssignLhs>();
   List<Bpl.Expr> rhs = new List<Bpl.Expr>();
   Bpl.Expr value = new Bpl.LiteralExpr(Bpl.Token.NoToken, false);
   rhs.Add(value);
   Bpl.SimpleAssignLhs assignee =
     new Bpl.SimpleAssignLhs(Bpl.Token.NoToken,
                             new Bpl.IdentifierExpr(Bpl.Token.NoToken,
                                                    sink.FindOrCreateGlobalVariable(PhoneCodeHelper.BOOGIE_CONTINUE_ON_PAGE_VARIABLE, Bpl.Type.Bool)));
   lhs.Add(assignee);
   Bpl.AssignCmd assignCmd = new Bpl.AssignCmd(Bpl.Token.NoToken, lhs, rhs);
   return assignCmd;
 }