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); }
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); }
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; }
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); }
public abstract Element Update(Element element, AssignCmd cmd);
public abstract Element Update(Element element, AssignCmd cmd); // requiers 'cmd' to be a simple (possibly parallel) assignment command
/// <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; }
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); }
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; }
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; }
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 { } }
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; } }
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; }
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; }
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; }