/// <summary> /// Creates a fresh local var of the given Type and adds it to the /// Bpl Implementation /// </summary> /// <param name="typeReference"> The type of the new variable </param> /// <returns> A fresh Variable with automatic generated name and location </returns> public Bpl.Variable CreateFreshLocal(ITypeReference typeReference) { Bpl.IToken loc = Bpl.Token.NoToken; // Helper Variables do not have a location Bpl.Type t = TranslationHelper.CciTypeToBoogie(typeReference); Bpl.LocalVariable v = new Bpl.LocalVariable(loc, new Bpl.TypedIdent(loc, TranslationHelper.GenerateTempVarName(), t)); ILocalDefinition dummy = new LocalDefinition(); // Creates a dummy entry for the Dict, since only locals in the dict are translated to boogie localVarMap.Add(dummy, v); return v; }
static Bpl.LocalVariable BplLocalVar(string name, Bpl.Type ty, out Bpl.Expr e) { Contract.Requires(ty != null); var v = new Bpl.LocalVariable(ty.tok, new Bpl.TypedIdent(ty.tok, name, ty)); e = new Bpl.IdentifierExpr(ty.tok, name, ty); return(v); }
/// <summary> /// /// </summary> /// <param name="local"></param> /// <returns></returns> public Bpl.Variable FindOrCreateLocalVariable(ILocalDefinition local) { Bpl.LocalVariable v; Bpl.IToken tok = local.Token(); Bpl.Type t = TranslationHelper.CciTypeToBoogie(local.Type.ResolvedType); if (!localVarMap.TryGetValue(local, out v)) { v = new Bpl.LocalVariable(tok, new Bpl.TypedIdent(tok, local.Name.Value, t)); localVarMap.Add(local, v); } return v; }
void PredicateCmd(List<Cmd> cmdSeq, Cmd cmd) { if (cmd is AssignCmd) { var aCmd = (AssignCmd)cmd; cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss, new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) => new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List<Expr> { p, rhs, lhs.AsExpr }))))); } else if (cmd is AssertCmd) { var aCmd = (AssertCmd)cmd; if (cmdSeq.Last() is AssignCmd && cmdSeq.Cast<Cmd>().SkipEnd(1).All(c => c is AssertCmd)) { // This may be a loop invariant. Make sure it continues to appear as // the first statement in the block. var assign = cmdSeq.Last(); cmdSeq.RemoveAt(cmdSeq.Count-1); Expr newExpr = new EnabledReplacementVisitor(pExpr).VisitExpr(aCmd.Expr); aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(pExpr, newExpr); cmdSeq.Add(aCmd); // cmdSeq.Add(new AssertCmd(aCmd.tok, Expr.Imp(pExpr, aCmd.Expr))); cmdSeq.Add(assign); } else { aCmd.Expr = Expr.Imp(p, aCmd.Expr); cmdSeq.Add(aCmd); // cmdSeq.Add(new AssertCmd(aCmd.tok, Expr.Imp(p, aCmd.Expr))); } } else if (cmd is AssumeCmd) { var aCmd = (AssumeCmd)cmd; cmdSeq.Add(new AssumeCmd(Token.NoToken, Expr.Imp(p, aCmd.Expr))); } else if (cmd is HavocCmd) { var hCmd = (HavocCmd)cmd; foreach (IdentifierExpr v in hCmd.Vars) { Microsoft.Boogie.Type type = v.Decl.TypedIdent.Type; Contract.Assert(type != null); IdentifierExpr havocTempExpr; if (havocVars.ContainsKey(type)) { havocTempExpr = havocVars[type]; } else { var havocVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "_HAVOC_" + type.ToString(), type)); impl.LocVars.Add(havocVar); havocVars[type] = havocTempExpr = new IdentifierExpr(Token.NoToken, havocVar); } cmdSeq.Add(new HavocCmd(Token.NoToken, new List<IdentifierExpr> { havocTempExpr })); cmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, v, new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List<Expr> { p, havocTempExpr, v }))); } } else if (cmd is CallCmd) { Debug.Assert(useProcedurePredicates); var cCmd = (CallCmd)cmd; cCmd.Ins.Insert(0, p); cmdSeq.Add(cCmd); } else if (cmd is CommentCmd) { // skip } else if (cmd is StateCmd) { var sCmd = (StateCmd)cmd; var newCmdSeq = new List<Cmd>(); foreach (Cmd c in sCmd.Cmds) PredicateCmd(newCmdSeq, c); sCmd.Cmds = newCmdSeq; cmdSeq.Add(sCmd); } else { Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString()); } }
public override LocalVariable VisitLocalVariable(LocalVariable node) { Contract.Ensures(Contract.Result<LocalVariable>() == node); return node; }
public override LocalVariable VisitLocalVariable(LocalVariable node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<LocalVariable>() != null); return base.VisitLocalVariable((LocalVariable)node.Clone()); }
private void ProcessLoopHeaders(Implementation impl, Graph<Block> graph, HashSet<Block> yieldingHeaders, Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap, out List<Variable> oldPcs, out List<Variable> oldOks) { oldPcs = new List<Variable>(); oldOks = new List<Variable>(); foreach (Block header in yieldingHeaders) { LocalVariable oldPc = null; LocalVariable oldOk = null; if (pc != null) { oldPc = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}", pc.Name, header.Label), Type.Bool)); oldPcs.Add(oldPc); oldOk = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}_{1}", ok.Name, header.Label), Type.Bool)); oldOks.Add(oldOk); } Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(AvailableLinearVars(header), domainNameToInputVar); foreach (Block pred in header.Predecessors) { AddCallToYieldProc(header.tok, pred.Cmds, ogOldGlobalMap, domainNameToLocalVar); if (pc != null && !graph.BackEdgeNodes(header).Contains(pred)) { pred.Cmds.Add(new AssignCmd(Token.NoToken, new List<AssignLhs>( new AssignLhs[] { new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldPc)), new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldOk)) }), new List<Expr>(new Expr[] { Expr.Ident(pc), Expr.Ident(ok) }))); } AddUpdatesToOldGlobalVars(pred.Cmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr); } List<Cmd> newCmds = new List<Cmd>(); if (pc != null) { AssertCmd assertCmd; assertCmd = new AssertCmd(header.tok, Expr.Eq(Expr.Ident(oldPc), Expr.Ident(pc))); assertCmd.ErrorData = "Specification state must not change for transitions ending in loop headers"; newCmds.Add(assertCmd); assertCmd = new AssertCmd(header.tok, Expr.Imp(Expr.Ident(oldOk), Expr.Ident(ok))); assertCmd.ErrorData = "Specification state must not change for transitions ending in loop headers"; newCmds.Add(assertCmd); } foreach (string domainName in linearTypeChecker.linearDomains.Keys) { newCmds.Add(new AssumeCmd(Token.NoToken, Expr.Eq(Expr.Ident(domainNameToLocalVar[domainName]), domainNameToExpr[domainName]))); } foreach (Variable v in ogOldGlobalMap.Keys) { newCmds.Add(new AssumeCmd(Token.NoToken, Expr.Eq(Expr.Ident(v), Expr.Ident(ogOldGlobalMap[v])))); } newCmds.AddRange(header.Cmds); header.Cmds = newCmds; } }
void PredicateCmd(Expr p, Expr pDom, List<Cmd> cmdSeq, Cmd cmd) { if (cmd is CallCmd) { var cCmd = (CallCmd)cmd; Debug.Assert(useProcedurePredicates(cCmd.Proc)); cCmd.Ins.Insert(0, p != null ? p : Expr.True); cmdSeq.Add(cCmd); } else if (p == null) { new EnabledReplacementVisitor(Expr.True, pDom).Visit(cmd); cmdSeq.Add(cmd); } else if (cmd is AssignCmd) { var aCmd = (AssignCmd)cmd; cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss, new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) => new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List<Expr> { p, rhs, lhs.AsExpr }))))); } else if (cmd is AssertCmd) { var aCmd = (AssertCmd)cmd; Expr newExpr = new EnabledReplacementVisitor(p, pDom).VisitExpr(aCmd.Expr); aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr); cmdSeq.Add(aCmd); } else if (cmd is AssumeCmd) { var aCmd = (AssumeCmd)cmd; Expr newExpr = new EnabledReplacementVisitor(p, pDom).VisitExpr(aCmd.Expr); aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr); cmdSeq.Add(aCmd); } else if (cmd is HavocCmd) { var hCmd = (HavocCmd)cmd; foreach (IdentifierExpr v in hCmd.Vars) { Microsoft.Boogie.Type type = v.Decl.TypedIdent.Type; Contract.Assert(type != null); IdentifierExpr havocTempExpr; if (havocVars.ContainsKey(type)) { havocTempExpr = havocVars[type]; } else { var havocVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "_HAVOC_" + type.ToString(), type)); impl.LocVars.Add(havocVar); havocVars[type] = havocTempExpr = new IdentifierExpr(Token.NoToken, havocVar); } cmdSeq.Add(new HavocCmd(Token.NoToken, new List<IdentifierExpr> { havocTempExpr })); cmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, v, new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List<Expr> { p, havocTempExpr, v }))); } } else if (cmd is CommentCmd) { // skip } else if (cmd is StateCmd) { var sCmd = (StateCmd)cmd; var newCmdSeq = new List<Cmd>(); foreach (Cmd c in sCmd.Cmds) PredicateCmd(p, pDom, newCmdSeq, c); sCmd.Cmds = newCmdSeq; cmdSeq.Add(sCmd); } else { Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString()); } }
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 Bpl.Procedure addHandlerStubCaller(Sink sink, IMethodDefinition def) { MethodBody callerBody = new MethodBody(); MethodDefinition callerDef = new MethodDefinition() { InternFactory = (def as MethodDefinition).InternFactory, ContainingTypeDefinition = def.ContainingTypeDefinition, IsStatic = true, Name = sink.host.NameTable.GetNameFor("BOOGIE_STUB_CALLER_" + def.Name.Value), Type = sink.host.PlatformType.SystemVoid, Body = callerBody, }; callerBody.MethodDefinition = callerDef; Sink.ProcedureInfo procInfo = sink.FindOrCreateProcedure(def); Sink.ProcedureInfo callerInfo = sink.FindOrCreateProcedure(callerDef); Bpl.LocalVariable[] localVars = new Bpl.LocalVariable[procInfo.Decl.InParams.Count]; Bpl.IdentifierExpr[] varExpr = new Bpl.IdentifierExpr[procInfo.Decl.InParams.Count]; for (int i = 0; i < procInfo.Decl.InParams.Count; i++) { Bpl.LocalVariable loc = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, TranslationHelper.GenerateTempVarName(), procInfo.Decl.InParams[i].TypedIdent.Type)); localVars[i] = loc; varExpr[i] = new Bpl.IdentifierExpr(Bpl.Token.NoToken, loc); } Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder(); builder.Add(getResetNavigationCheck(sink)); string pageXaml = PhoneCodeHelper.instance().PhonePlugin.getXAMLForPage(def.ContainingTypeDefinition.ToString()); Bpl.Variable boogieCurrentURI = sink.FindOrCreateFieldVariable(PhoneCodeHelper.CurrentURIFieldDefinition); Bpl.Constant boogieXamlConstant; if (pageXaml != null) { boogieXamlConstant = sink.FindOrCreateConstant(pageXaml); } else { boogieXamlConstant = null; } // NAVIGATION TODO: For now just assume we are in this page to be able to call the handler, this is NOT true for any handler // NAVIGATION TODO: ie, a network event handler if (boogieXamlConstant != null) { Bpl.AssumeCmd assumeCurrentPage = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI), new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant))); builder.Add(assumeCurrentPage); } // NAVIGATION TODO: have to do the pair generation all in one go instead of having different files that need to be sed'ed boogieXamlConstant = sink.FindOrCreateConstant(BOOGIE_STARTING_URI_PLACEHOLDER); Bpl.AssumeCmd assumeStartPage = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI), new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant))); builder.Add(assumeStartPage); builder.Add(new Bpl.CallCmd(Bpl.Token.NoToken, procInfo.Decl.Name, new List <Bpl.Expr>(varExpr), new List <Bpl.IdentifierExpr>())); boogieXamlConstant = sink.FindOrCreateConstant(BOOGIE_ENDING_URI_PLACEHOLDER); Bpl.AssertCmd assertEndPage = new Bpl.AssertCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI), new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant))); Bpl.Expr guard = new Bpl.IdentifierExpr(Bpl.Token.NoToken, sink.FindOrCreateGlobalVariable(PhoneCodeHelper.BOOGIE_NAVIGATION_CHECK_VARIABLE, Bpl.Type.Bool)); Bpl.StmtListBuilder thenBuilder = new Bpl.StmtListBuilder(); thenBuilder.Add(assertEndPage); Bpl.IfCmd ifNavigated = new Bpl.IfCmd(Bpl.Token.NoToken, guard, thenBuilder.Collect(Bpl.Token.NoToken), null, new Bpl.StmtListBuilder().Collect(Bpl.Token.NoToken)); builder.Add(ifNavigated); Bpl.Implementation impl = new Bpl.Implementation(Bpl.Token.NoToken, callerInfo.Decl.Name, new List <Bpl.TypeVariable>(), new List <Bpl.Variable>(), new List <Bpl.Variable>(), new List <Bpl.Variable>(localVars), builder.Collect(Bpl.Token.NoToken), null, new Bpl.Errors()); sink.TranslatedProgram.AddTopLevelDeclaration(impl); return(impl.Proc); }
private static void CreateDispatchMethod(Sink sink, ITypeDefinition type, HashSet <IMethodDefinition> delegates) { Contract.Assert(type.IsDelegate); IMethodDefinition invokeMethod = null; foreach (IMethodDefinition m in type.Methods) { if (m.Name.Value == "Invoke") { invokeMethod = m; break; } } try { IMethodDefinition unspecializedInvokeMethod = Sink.Unspecialize(invokeMethod).ResolvedMethod; Sink.ProcedureInfo invokeProcedureInfo = sink.FindOrCreateProcedure(unspecializedInvokeMethod); Bpl.Procedure invokeProcedure = (Bpl.Procedure)invokeProcedureInfo.Decl; invokeProcedure.AddAttribute("inline", Bpl.Expr.Literal(1)); Bpl.Formal delegateVariable = invokeProcedureInfo.ThisVariable; Bpl.IToken token = invokeMethod.Token(); List <Bpl.Variable> dispatchProcInExprs = new List <Bpl.Variable>(); for (int i = 1; i < invokeProcedure.InParams.Count; i++) { Bpl.Variable v = invokeProcedure.InParams[i]; dispatchProcInExprs.Add(v); } List <Bpl.Variable> dispatchProcOutExprs = new List <Bpl.Variable>(); foreach (Bpl.Variable v in invokeProcedure.OutParams) { dispatchProcOutExprs.Add(v); } List <Bpl.Variable> localVariables = new List <Bpl.Variable>(); Bpl.StmtListBuilder stmtBuilder = new Bpl.StmtListBuilder(); int localCounter = 0; foreach (IMethodDefinition defn in delegates) { Bpl.Constant c = sink.FindOrCreateDelegateMethodConstant(defn); Sink.ProcedureInfo delegateProcedureInfo = sink.FindOrCreateProcedure(defn); Bpl.Procedure delegateProcedure = (Bpl.Procedure)delegateProcedureInfo.Decl; Bpl.Formal thisVariable = delegateProcedureInfo.ThisVariable; int numArguments = defn.ParameterCount; List <Bpl.Variable> tempInputs = new List <Bpl.Variable>(); List <Bpl.Variable> tempOutputs = new List <Bpl.Variable>(); for (int i = 0; i < defn.ParameterCount; i++) { Bpl.Variable v = delegateProcedure.InParams[(thisVariable == null ? 0 : 1) + i]; Bpl.LocalVariable localVariable = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "local" + localCounter++, v.TypedIdent.Type)); localVariables.Add(localVariable); tempInputs.Add(localVariable); } for (int i = 0; i < delegateProcedure.OutParams.Count; i++) { Bpl.Variable v = delegateProcedure.OutParams[i]; Bpl.LocalVariable localVariable = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "local" + localCounter++, v.TypedIdent.Type)); localVariables.Add(localVariable); tempOutputs.Add(localVariable); } List <Bpl.Expr> ins = new List <Bpl.Expr>(); List <Bpl.IdentifierExpr> outs = new List <Bpl.IdentifierExpr>(); if (!defn.IsStatic) { ins.Add(sink.ReadReceiver(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable))); } for (int i = 0; i < tempInputs.Count; i++) { ins.Add(Bpl.Expr.Ident(tempInputs[i])); } if (defn.IsGeneric) { for (int i = 0; i < defn.GenericParameterCount; i++) { ins.Add(new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(sink.FindOrCreateTypeParameterFunction(i)), new List <Bpl.Expr>(new Bpl.Expr[] { sink.ReadTypeParameters(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable)) }))); } } if (defn.IsStatic) { int numTypeParameters = Sink.ConsolidatedGenericParameterCount(defn.ContainingType); for (int i = 0; i < numTypeParameters; i++) { ins.Add(new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(sink.FindOrCreateTypeParameterFunction(i)), new List <Bpl.Expr>(new Bpl.Expr[] { sink.ReadTypeParameters(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable)) }))); } } for (int i = 0; i < tempOutputs.Count; i++) { outs.Add(Bpl.Expr.Ident(tempOutputs[i])); } Bpl.Expr bexpr = sink.ReadMethod(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable)); Bpl.StmtListBuilder ifStmtBuilder = new Bpl.StmtListBuilder(); System.Diagnostics.Debug.Assert(tempInputs.Count == dispatchProcInExprs.Count); if (tempInputs.Count > 0) { BuildAssignment(sink, ifStmtBuilder, tempInputs, dispatchProcInExprs); } ifStmtBuilder.Add(EmitDummySourceContext()); ifStmtBuilder.Add(new Bpl.CallCmd(token, delegateProcedure.Name, ins, outs)); System.Diagnostics.Debug.Assert(tempOutputs.Count == dispatchProcOutExprs.Count); if (tempOutputs.Count > 0) { BuildAssignment(sink, ifStmtBuilder, dispatchProcOutExprs, tempOutputs); } stmtBuilder.Add(new Bpl.IfCmd(bexpr.tok, bexpr, ifStmtBuilder.Collect(bexpr.tok), null, null)); } Bpl.Implementation dispatchImpl = new Bpl.Implementation(token, invokeProcedure.Name, new List <Bpl.TypeVariable>(), invokeProcedure.InParams, invokeProcedure.OutParams, localVariables, stmtBuilder.Collect(token) ); dispatchImpl.Proc = invokeProcedure; dispatchImpl.AddAttribute("inline", Bpl.Expr.Literal(1)); sink.TranslatedProgram.AddTopLevelDeclaration(dispatchImpl); } catch (TranslationException te) { throw new NotImplementedException(te.ToString()); } catch { throw; } finally { // Maybe this is a good place to add the procedure to the toplevel declarations } }
// We have to give the type explicitly, because the type of the formal "likeThisOne" can contain type variables protected Variable CreateTemporaryVariable(List<Variable> tempVars, Variable likeThisOne, Type ty, TempVarKind kind) { Contract.Requires(ty != null); Contract.Requires(likeThisOne != null); Contract.Requires(tempVars != null); Contract.Ensures(Contract.Result<Variable>() != null); string/*!*/ tempNamePrefix; switch (kind) { case TempVarKind.Formal: tempNamePrefix = "formal@"; break; case TempVarKind.Old: tempNamePrefix = "old@"; break; case TempVarKind.Bound: tempNamePrefix = "forall@"; break; default: { Contract.Assert(false); throw new cce.UnreachableException(); } // unexpected kind } TypedIdent ti = likeThisOne.TypedIdent; TypedIdent newTi = new TypedIdent(ti.tok, "call" + UniqueId + tempNamePrefix + ti.Name, ty); Variable/*!*/ v; if (kind == TempVarKind.Bound) { v = new BoundVariable(likeThisOne.tok, newTi); } else { v = new LocalVariable(likeThisOne.tok, newTi); tempVars.Add(v); } return v; }
private static void CreateDispatchMethod(Sink sink, ITypeDefinition type, HashSet<IMethodDefinition> delegates) { Contract.Assert(type.IsDelegate); IMethodDefinition invokeMethod = null; foreach (IMethodDefinition m in type.Methods) { if (m.Name.Value == "Invoke") { invokeMethod = m; break; } } try { IMethodDefinition unspecializedInvokeMethod = Sink.Unspecialize(invokeMethod).ResolvedMethod; Sink.ProcedureInfo invokeProcedureInfo = sink.FindOrCreateProcedure(unspecializedInvokeMethod); Bpl.Procedure invokeProcedure = (Bpl.Procedure) invokeProcedureInfo.Decl; invokeProcedure.AddAttribute("inline", Bpl.Expr.Literal(1)); Bpl.Formal delegateVariable = invokeProcedureInfo.ThisVariable; Bpl.IToken token = invokeMethod.Token(); List<Bpl.Variable> dispatchProcInExprs = new List<Bpl.Variable>(); for (int i = 1; i < invokeProcedure.InParams.Count; i++) { Bpl.Variable v = invokeProcedure.InParams[i]; dispatchProcInExprs.Add(v); } List<Bpl.Variable> dispatchProcOutExprs = new List<Bpl.Variable>(); foreach (Bpl.Variable v in invokeProcedure.OutParams) { dispatchProcOutExprs.Add(v); } List<Bpl.Variable> localVariables = new List<Bpl.Variable>(); Bpl.StmtListBuilder stmtBuilder = new Bpl.StmtListBuilder(); int localCounter = 0; foreach (IMethodDefinition defn in delegates) { Bpl.Constant c = sink.FindOrCreateDelegateMethodConstant(defn); Sink.ProcedureInfo delegateProcedureInfo = sink.FindOrCreateProcedure(defn); Bpl.Procedure delegateProcedure = (Bpl.Procedure)delegateProcedureInfo.Decl; Bpl.Formal thisVariable = delegateProcedureInfo.ThisVariable; int numArguments = defn.ParameterCount; List<Bpl.Variable> tempInputs = new List<Bpl.Variable>(); List<Bpl.Variable> tempOutputs = new List<Bpl.Variable>(); for (int i = 0; i < defn.ParameterCount; i++) { Bpl.Variable v = delegateProcedure.InParams[(thisVariable == null ? 0 : 1) + i]; Bpl.LocalVariable localVariable = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "local" + localCounter++, v.TypedIdent.Type)); localVariables.Add(localVariable); tempInputs.Add(localVariable); } for (int i = 0; i < delegateProcedure.OutParams.Count; i++) { Bpl.Variable v = delegateProcedure.OutParams[i]; Bpl.LocalVariable localVariable = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, "local" + localCounter++, v.TypedIdent.Type)); localVariables.Add(localVariable); tempOutputs.Add(localVariable); } List<Bpl.Expr> ins = new List<Bpl.Expr>(); List<Bpl.IdentifierExpr> outs = new List<Bpl.IdentifierExpr>(); if (!defn.IsStatic) ins.Add(sink.ReadReceiver(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable))); for (int i = 0; i < tempInputs.Count; i++) { ins.Add(Bpl.Expr.Ident(tempInputs[i])); } if (defn.IsGeneric) { for (int i = 0; i < defn.GenericParameterCount; i++) { ins.Add(new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(sink.FindOrCreateTypeParameterFunction(i)), new List<Bpl.Expr>(new Bpl.Expr[] {sink.ReadTypeParameters(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable))}))); } } if (defn.IsStatic) { int numTypeParameters = Sink.ConsolidatedGenericParameterCount(defn.ContainingType); for (int i = 0; i < numTypeParameters; i++) { ins.Add(new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(sink.FindOrCreateTypeParameterFunction(i)), new List<Bpl.Expr>(new Bpl.Expr[] {sink.ReadTypeParameters(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable))}))); } } for (int i = 0; i < tempOutputs.Count; i++) { outs.Add(Bpl.Expr.Ident(tempOutputs[i])); } Bpl.Expr bexpr = sink.ReadMethod(Bpl.Expr.Ident(c), Bpl.Expr.Ident(delegateVariable)); Bpl.StmtListBuilder ifStmtBuilder = new Bpl.StmtListBuilder(); System.Diagnostics.Debug.Assert(tempInputs.Count == dispatchProcInExprs.Count); if (tempInputs.Count > 0) { BuildAssignment(sink, ifStmtBuilder, tempInputs, dispatchProcInExprs); } ifStmtBuilder.Add(EmitDummySourceContext()); ifStmtBuilder.Add(new Bpl.CallCmd(token, delegateProcedure.Name, ins, outs)); System.Diagnostics.Debug.Assert(tempOutputs.Count == dispatchProcOutExprs.Count); if (tempOutputs.Count > 0) { BuildAssignment(sink, ifStmtBuilder, dispatchProcOutExprs, tempOutputs); } stmtBuilder.Add(new Bpl.IfCmd(bexpr.tok, bexpr, ifStmtBuilder.Collect(bexpr.tok), null, null)); } Bpl.Implementation dispatchImpl = new Bpl.Implementation(token, invokeProcedure.Name, new List<Bpl.TypeVariable>(), invokeProcedure.InParams, invokeProcedure.OutParams, localVariables, stmtBuilder.Collect(token) ); dispatchImpl.Proc = invokeProcedure; dispatchImpl.AddAttribute("inline", Bpl.Expr.Literal(1)); sink.TranslatedProgram.AddTopLevelDeclaration(dispatchImpl); } catch (TranslationException te) { throw new NotImplementedException(te.ToString()); } catch { throw; } finally { // Maybe this is a good place to add the procedure to the toplevel declarations } }
private void TransformImpl(Implementation impl) { if (!QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "yields")) return; // Find the yielding loop headers impl.PruneUnreachableBlocks(); impl.ComputePredecessorsForBlocks(); GraphUtil.Graph<Block> graph = Program.GraphFromImpl(impl); graph.ComputeLoops(); if (!graph.Reducible) { throw new Exception("Irreducible flow graphs are unsupported."); } HashSet<Block> yieldingHeaders = new HashSet<Block>(); IEnumerable<Block> sortedHeaders = graph.SortHeadersByDominance(); foreach (Block header in sortedHeaders) { if (yieldingHeaders.Any(x => graph.DominatorMap.DominatedBy(x, header))) { yieldingHeaders.Add(header); } else if (IsYieldingHeader(graph, header)) { yieldingHeaders.Add(header); } else { continue; } } Program program = linearTypeChecker.program; Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>(); foreach (Variable local in impl.LocVars) { var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, local.Name, local.TypedIdent.Type)); map[local] = new IdentifierExpr(Token.NoToken, copy); } Dictionary<Variable, Variable> ogOldGlobalMap = new Dictionary<Variable, Variable>(); foreach (IdentifierExpr ie in globalMods) { Variable g = ie.Decl; LocalVariable l = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type)); ogOldGlobalMap[g] = l; impl.LocVars.Add(l); } Dictionary<string, Variable> domainNameToInputVar = new Dictionary<string, Variable>(); Dictionary<string, Variable> domainNameToLocalVar = new Dictionary<string, Variable>(); { int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count; foreach (string domainName in linearTypeChecker.linearDomains.Keys) { Variable inParam = impl.InParams[i]; domainNameToInputVar[domainName] = inParam; Variable l = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name + "_local", inParam.TypedIdent.Type)); domainNameToLocalVar[domainName] = l; impl.LocVars.Add(l); i++; } } // Collect the yield predicates and desugar yields List<List<Cmd>> yields = new List<List<Cmd>>(); List<Cmd> cmds = new List<Cmd>(); foreach (Block b in impl.Blocks) { YieldCmd yieldCmd = null; List<Cmd> newCmds = new List<Cmd>(); for (int i = 0; i < b.Cmds.Count; i++) { Cmd cmd = b.Cmds[i]; if (cmd is YieldCmd) { yieldCmd = (YieldCmd)cmd; continue; } if (yieldCmd != null) { PredicateCmd pcmd = cmd as PredicateCmd; if (pcmd == null) { DesugarYield(yieldCmd, cmds, newCmds, ogOldGlobalMap, domainNameToInputVar, domainNameToLocalVar); if (cmds.Count > 0) { yields.Add(cmds); cmds = new List<Cmd>(); } yieldCmd = null; } else { cmds.Add(pcmd); } } if (cmd is CallCmd) { CallCmd callCmd = cmd as CallCmd; if (callCmd.IsAsync || QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "yields")) { AddCallToYieldProc(newCmds, ogOldGlobalMap, domainNameToLocalVar); } if (callCmd.IsAsync) { if (!asyncAndParallelCallDesugarings.ContainsKey(callCmd.Proc.Name)) { asyncAndParallelCallDesugarings[callCmd.Proc.Name] = new Procedure(Token.NoToken, string.Format("DummyAsyncTarget_{0}", callCmd.Proc.Name), callCmd.Proc.TypeParameters, callCmd.Proc.InParams, callCmd.Proc.OutParams, callCmd.Proc.Requires, new List<IdentifierExpr>(), new List<Ensures>()); } var dummyAsyncTargetProc = asyncAndParallelCallDesugarings[callCmd.Proc.Name]; CallCmd dummyCallCmd = new CallCmd(Token.NoToken, dummyAsyncTargetProc.Name, callCmd.Ins, callCmd.Outs); dummyCallCmd.Proc = dummyAsyncTargetProc; newCmds.Add(dummyCallCmd); } else { newCmds.Add(callCmd); } if (callCmd.IsAsync || QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "yields")) { HashSet<Variable> availableLinearVars = new HashSet<Variable>(AvailableLinearVars(callCmd)); foreach (IdentifierExpr ie in callCmd.Outs) { if (linearTypeChecker.FindDomainName(ie.Decl) == null) continue; availableLinearVars.Add(ie.Decl); } Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(availableLinearVars, domainNameToInputVar); AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr); } } else if (cmd is ParCallCmd) { ParCallCmd parCallCmd = cmd as ParCallCmd; AddCallToYieldProc(newCmds, ogOldGlobalMap, domainNameToLocalVar); DesugarParallelCallCmd(newCmds, parCallCmd); HashSet<Variable> availableLinearVars = new HashSet<Variable>(AvailableLinearVars(parCallCmd)); foreach (CallCmd callCmd in parCallCmd.CallCmds) { foreach (IdentifierExpr ie in callCmd.Outs) { if (linearTypeChecker.FindDomainName(ie.Decl) == null) continue; availableLinearVars.Add(ie.Decl); } } Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(availableLinearVars, domainNameToInputVar); AddUpdatesToOldGlobalVars(newCmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr); } else { newCmds.Add(cmd); } } if (yieldCmd != null) { DesugarYield(yieldCmd, cmds, newCmds, ogOldGlobalMap, domainNameToInputVar, domainNameToLocalVar); if (cmds.Count > 0) { yields.Add(cmds); cmds = new List<Cmd>(); } } if (b.TransferCmd is ReturnCmd && QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "yields")) { AddCallToYieldProc(newCmds, ogOldGlobalMap, domainNameToLocalVar); } b.Cmds = newCmds; } foreach (Block header in yieldingHeaders) { Dictionary<string, Expr> domainNameToExpr = ComputeAvailableExprs(AvailableLinearVars(header), domainNameToInputVar); foreach (Block pred in header.Predecessors) { AddCallToYieldProc(pred.Cmds, ogOldGlobalMap, domainNameToLocalVar); AddUpdatesToOldGlobalVars(pred.Cmds, ogOldGlobalMap, domainNameToLocalVar, domainNameToExpr); } List<Cmd> newCmds = new List<Cmd>(); foreach (string domainName in linearTypeChecker.linearDomains.Keys) { newCmds.Add(new AssumeCmd(Token.NoToken, Expr.Binary(BinaryOperator.Opcode.Eq, Expr.Ident(domainNameToLocalVar[domainName]), domainNameToExpr[domainName]))); } foreach (Variable v in ogOldGlobalMap.Keys) { newCmds.Add(new AssumeCmd(Token.NoToken, Expr.Binary(BinaryOperator.Opcode.Eq, new IdentifierExpr(Token.NoToken, v), Expr.Ident(ogOldGlobalMap[v])))); } newCmds.AddRange(header.Cmds); header.Cmds = newCmds; } { // Add initial block List<AssignLhs> lhss = new List<AssignLhs>(); List<Expr> rhss = new List<Expr>(); Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>(); foreach (var domainName in linearTypeChecker.linearDomains.Keys) { domainNameToExpr[domainName] = new IdentifierExpr(Token.NoToken, domainNameToInputVar[domainName]); } for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++) { Variable v = impl.InParams[i]; var domainName = linearTypeChecker.FindDomainName(v); if (domainName == null) continue; var domain = linearTypeChecker.linearDomains[domainName]; IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v); domainNameToExpr[domainName] = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { v.TypedIdent.Type is MapType ? ie : linearTypeChecker.Singleton(ie, domainName), domainNameToExpr[domainName] }); } foreach (string domainName in linearTypeChecker.linearDomains.Keys) { lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, domainNameToLocalVar[domainName]))); rhss.Add(domainNameToExpr[domainName]); } foreach (Variable g in ogOldGlobalMap.Keys) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ogOldGlobalMap[g]))); rhss.Add(Expr.Ident(g)); } if (lhss.Count > 0) { Block initBlock = new Block(Token.NoToken, "og_init", new List<Cmd> { new AssignCmd(Token.NoToken, lhss, rhss) }, new GotoCmd(Token.NoToken, new List<String> { impl.Blocks[0].Label }, new List<Block> { impl.Blocks[0] })); impl.Blocks.Insert(0, initBlock); } } CreateYieldCheckerImpl(impl, yields, map); }
void PredicateImplementation() { blockGraph = prog.ProcessLoops(impl); var sortedBlocks = blockGraph.LoopyTopSort(); int blockId = 0; foreach (var block in impl.Blocks) blockIds[block] = Expr.Literal(blockId++); returnBlockId = Expr.Literal(blockId++); curVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "cur", Microsoft.Boogie.Type.Int)); impl.LocVars.Add(curVar); cur = Expr.Ident(curVar); pVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "p", Microsoft.Boogie.Type.Bool)); impl.LocVars.Add(pVar); p = Expr.Ident(pVar); if (useProcedurePredicates) fp = Expr.Ident(impl.InParams[0]); var newBlocks = new List<Block>(); Block entryBlock = new Block(); entryBlock.Label = "entry"; entryBlock.Cmds = new List<Cmd> { Cmd.SimpleAssign(Token.NoToken, cur, CreateIfFPThenElse(blockIds[sortedBlocks[0].Item1], returnBlockId)) }; newBlocks.Add(entryBlock); var prevBlock = entryBlock; foreach (var n in sortedBlocks) { if (n.Item2) { var backedgeBlock = new Block(); newBlocks.Add(backedgeBlock); backedgeBlock.Label = n.Item1.Label + ".backedge"; backedgeBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken, Expr.Eq(cur, blockIds[n.Item1]), new QKeyValue(Token.NoToken, "backedge", new List<object>(), null)) }; backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { n.Item1 }); var tailBlock = new Block(); newBlocks.Add(tailBlock); tailBlock.Label = n.Item1.Label + ".tail"; tailBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken, Expr.Neq(cur, blockIds[n.Item1])) }; prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { backedgeBlock, tailBlock }); prevBlock = tailBlock; } else { var runBlock = n.Item1; var oldCmdSeq = runBlock.Cmds; runBlock.Cmds = new List<Cmd>(); newBlocks.Add(runBlock); prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { runBlock }); pExpr = Expr.Eq(cur, blockIds[runBlock]); if (createCandidateInvariants && blockGraph.Headers.Contains(runBlock)) { AddUniformCandidateInvariant(runBlock.Cmds, runBlock); AddNonUniformCandidateInvariant(runBlock.Cmds, runBlock); } runBlock.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, p, pExpr)); var transferCmd = runBlock.TransferCmd; foreach (Cmd cmd in oldCmdSeq) PredicateCmd(newBlocks, runBlock, cmd, out runBlock); PredicateTransferCmd(runBlock.Cmds, transferCmd); prevBlock = runBlock; doneBlocks.Add(runBlock); } } prevBlock.TransferCmd = new ReturnCmd(Token.NoToken); impl.Blocks = newBlocks; }
protected void BeginInline(Implementation impl) { Contract.Requires(impl != null); Contract.Requires(impl.Proc != null); Contract.Requires(newModifies != null); Contract.Requires(newLocalVars != null); Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); Procedure proc = impl.Proc; foreach (Variable/*!*/ locVar in cce.NonNull(impl.OriginalLocVars)) { Contract.Assert(locVar != null); LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, locVar.Name), locVar.TypedIdent.Type, locVar.TypedIdent.WhereExpr)); localVar.Attributes = locVar.Attributes; // copy attributes newLocalVars.Add(localVar); IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar); substMap.Add(locVar, ie); } for (int i = 0; i < impl.InParams.Count; i++) { Variable inVar = cce.NonNull(impl.InParams[i]); LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, inVar.Name), inVar.TypedIdent.Type, inVar.TypedIdent.WhereExpr)); newLocalVars.Add(localVar); if (impl.Proc != null) localVar.Attributes = impl.Proc.InParams[i].Attributes; // copy attributes IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar); substMap.Add(inVar, ie); // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration Variable procInVar = cce.NonNull(proc.InParams[i]); if (procInVar != inVar) { substMap.Add(procInVar, ie); } } for (int i = 0; i < impl.OutParams.Count; i++) { Variable outVar = cce.NonNull(impl.OutParams[i]); LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, outVar.Name), outVar.TypedIdent.Type, outVar.TypedIdent.WhereExpr)); if (impl.Proc != null) localVar.Attributes = impl.Proc.OutParams[i].Attributes; // copy attributes newLocalVars.Add(localVar); IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar); substMap.Add(outVar, ie); // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration Variable procOutVar = cce.NonNull(proc.OutParams[i]); if (procOutVar != outVar) { substMap.Add(procOutVar, ie); } } Dictionary<Variable, Expr> substMapOld = new Dictionary<Variable, Expr>(); foreach (IdentifierExpr/*!*/ mie in proc.Modifies) { Contract.Assert(mie != null); Variable/*!*/ mVar = cce.NonNull(mie.Decl); LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, mVar.Name), mVar.TypedIdent.Type)); newLocalVars.Add(localVar); IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar); substMapOld.Add(mVar, ie); // FIXME why are we doing this? the modifies list should already include them. // add the modified variable to the modifies list of the procedure if (!newModifies.Contains(mie)) { newModifies.Add(mie); } } codeCopier.Subst = Substituter.SubstitutionFromHashtable(substMap); codeCopier.OldSubst = Substituter.SubstitutionFromHashtable(substMapOld); }
public override Cmd VisitCallCmd(CallCmd node) { var result = base.VisitCallCmd(node); var oldProc = programInCachedSnapshot.FindProcedure(node.Proc.Name); if (oldProc != null && oldProc.DependencyChecksum != node.Proc.DependencyChecksum && node.AssignedAssumptionVariable == null) { var before = new List<Cmd>(); var beforePrecondtionCheck = new List<Cmd>(); var after = new List<Cmd>(); var axioms = new List<Axiom>(); Expr assumedExpr = new LiteralExpr(Token.NoToken, false); // TODO(wuestholz): Try out two alternatives: only do this for low priority implementations or not at all. var canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program); if (canUseSpecs && oldProc.SignatureEquals(node.Proc)) { var desugaring = node.Desugaring; Contract.Assert(desugaring != null); var precond = node.CheckedPrecondition(oldProc, Program, e => FunctionExtractor.Extract(e, Program, axioms)); if (precond != null) { var assume = new AssumeCmd(node.tok, precond, new QKeyValue(Token.NoToken, "precondition_previous_snapshot", new List<object>(), null)); assume.IrrelevantForChecksumComputation = true; beforePrecondtionCheck.Add(assume); } var unmods = node.UnmodifiedBefore(oldProc); var eqs = new List<Expr>(); foreach (var unmod in unmods) { var oldUnmod = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", unmod.Name, FreshTemporaryVariableName), unmod.Type)); var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldUnmod)); var rhs = new IdentifierExpr(Token.NoToken, unmod.Decl); var cmd = new AssignCmd(Token.NoToken, new List<AssignLhs> { lhs }, new List<Expr> { rhs }); cmd.IrrelevantForChecksumComputation = true; before.Add(cmd); var eq = LiteralExpr.Eq(new IdentifierExpr(Token.NoToken, oldUnmod), new IdentifierExpr(Token.NoToken, unmod.Decl)); eq.Type = Type.Bool; eq.TypeParameters = SimpleTypeParamInstantiation.EMPTY; eqs.Add(eq); } var mods = node.ModifiedBefore(oldProc); var oldSubst = new Dictionary<Variable, Expr>(); foreach (var mod in mods) { var oldMod = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("{0}##old##{1}", mod.Name, FreshTemporaryVariableName), mod.Type)); oldSubst[mod.Decl] = new IdentifierExpr(Token.NoToken, oldMod); var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, oldMod)); var rhs = new IdentifierExpr(Token.NoToken, mod.Decl); var cmd = new AssignCmd(Token.NoToken, new List<AssignLhs> { lhs }, new List<Expr> { rhs }); cmd.IrrelevantForChecksumComputation = true; before.Add(cmd); } assumedExpr = node.Postcondition(oldProc, eqs, oldSubst, Program, e => FunctionExtractor.Extract(e, Program, axioms)); if (assumedExpr == null) { assumedExpr = new LiteralExpr(Token.NoToken, true); } } if (assumedExpr != null) { var lv = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool), new QKeyValue(Token.NoToken, "assumption", new List<object>(), null)); node.AssignedAssumptionVariable = lv; currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs); var lhs = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv)); var rhs = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr); var assumed = new AssignCmd(node.tok, new List<AssignLhs> { lhs }, new List<Expr> { rhs }); assumed.IrrelevantForChecksumComputation = true; after.Add(assumed); } node.ExtendDesugaring(before, beforePrecondtionCheck, after); if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking) { using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false)) { var loc = node.tok != null && node.tok != Token.NoToken ? string.Format("{0}({1},{2})", node.tok.filename, node.tok.line, node.tok.col) : "<unknown location>"; Console.Out.WriteLine("Processing call to procedure {0} in implementation {1} (at {2}):", node.Proc.Name, currentImplementation.Name, loc); foreach (var a in axioms) { Console.Out.Write(" >>> added axiom: "); a.Expr.Emit(tokTxtWr); Console.Out.WriteLine(); } foreach (var b in before) { Console.Out.Write(" >>> added before: "); b.Emit(tokTxtWr, 0); } foreach (var b in beforePrecondtionCheck) { Console.Out.Write(" >>> added before precondition check: "); b.Emit(tokTxtWr, 0); } foreach (var a in after) { Console.Out.Write(" >>> added after: "); a.Emit(tokTxtWr, 0); } } } } return result; }
/// <summary> /// /// </summary> /// <param name="methodCall"></param> /// <remarks>Stub, This one really needs comments!</remarks> public override void TraverseChildren(IMethodCall methodCall) { var resolvedMethod = ResolveUnspecializedMethodOrThrow(methodCall.MethodToCall); Bpl.IToken methodCallToken = methodCall.Token(); if (this.sink.Options.getMeHere) { // TODO: Get a method reference so this isn't a string comparison? var methodName = MemberHelper.GetMethodSignature(methodCall.MethodToCall, NameFormattingOptions.None); if (methodName.Equals("GetMeHere.GetMeHere.Assert")) { // for now, just translate it as "assert e" this.Traverse(methodCall.Arguments.First()); Bpl.Expr e = this.TranslatedExpressions.Pop(); this.StmtTraverser.StmtBuilder.Add(new Bpl.AssertCmd(methodCallToken, e)); return; } } // Handle type equality specially when it is testing against a constant, i.e., o.GetType() == typeof(T) if (IsOperator(resolvedMethod) && !IsConversionOperator(resolvedMethod) && TypeHelper.TypesAreEquivalent(resolvedMethod.ContainingType, this.sink.host.PlatformType.SystemType)) { // REVIEW: Assume the only operators on System.Type are == and != var typeToTest = methodCall.Arguments.ElementAtOrDefault(0) as ITypeOf; IMethodCall callToGetType; if (typeToTest == null) { typeToTest = methodCall.Arguments.ElementAtOrDefault(1) as ITypeOf; callToGetType = methodCall.Arguments.ElementAtOrDefault(0) as IMethodCall; } else { callToGetType = methodCall.Arguments.ElementAtOrDefault(1) as IMethodCall; } if (typeToTest != null && callToGetType != null && TypeHelper.TypesAreEquivalent(callToGetType.MethodToCall.ContainingType, this.sink.host.PlatformType.SystemObject) && MemberHelper.GetMethodSignature(callToGetType.MethodToCall).Equals("System.Object.GetType")) { IExpression objectToTest = callToGetType.ThisArgument; // generate: $TypeConstructor($DynamicType(o)) == TypeConstructorId var typeConstructorId = this.sink.FindOrDefineType(typeToTest.TypeToGet.ResolvedType).ConstructorId; Contract.Assume(typeConstructorId != null); this.Traverse(objectToTest); var e = this.TranslatedExpressions.Pop(); var exprs = new List<Bpl.Expr>(new Bpl.Expr[] {this.sink.Heap.DynamicType(e)}); Bpl.Expr typeTestExpression = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(methodCallToken, new Bpl.FunctionCall(sink.Heap.TypeConstructorFunction), exprs), Bpl.Expr.Ident(typeConstructorId)); if (MemberHelper.GetMethodSignature(resolvedMethod).Equals("System.Type.op_Inequality")) typeTestExpression = Bpl.Expr.Unary( methodCallToken, Bpl.UnaryOperator.Opcode.Not, typeTestExpression); this.TranslatedExpressions.Push(typeTestExpression); return; } } // Handle calls to Contract.ForAll and Contract.Exists specially (if they are to the overloads that take two ints and a predicate on ints) if (resolvedMethod.ContainingTypeDefinition.InternedKey == this.sink.host.PlatformType.SystemDiagnosticsContractsContract.InternedKey) { var methodName = resolvedMethod.Name.Value; if (methodCall.Arguments.Count() == 3 && (methodName == "ForAll" || methodName == "Exists")) { var noToken = Bpl.Token.NoToken; this.Traverse(methodCall.Arguments.ElementAt(0)); var lb = this.TranslatedExpressions.Pop(); this.Traverse(methodCall.Arguments.ElementAt(1)); var ub = this.TranslatedExpressions.Pop(); var delegateArgument = methodCall.Arguments.ElementAt(2); this.Traverse(delegateArgument); var del = this.TranslatedExpressions.Pop(); var boundVar = new Bpl.LocalVariable(noToken, new Bpl.TypedIdent(noToken, TranslationHelper.GenerateTempVarName(), Bpl.Type.Int)); var resultVar = new Bpl.LocalVariable(noToken, new Bpl.TypedIdent(noToken, TranslationHelper.GenerateTempVarName(), Bpl.Type.Bool)); var delegateType = delegateArgument.Type; var invokeMethod = delegateType.ResolvedType.GetMembersNamed(this.sink.host.NameTable.GetNameFor("Invoke"), false).First() as IMethodReference; var unspecializedInvokeMethod = Sink.Unspecialize(invokeMethod).ResolvedMethod; var invokeProcedureInfo = sink.FindOrCreateProcedure(unspecializedInvokeMethod); var ins = new List<Bpl.Expr>(); ins.Add(del); var localStmtTraverser = this.StmtTraverser.factory.MakeStatementTraverser(this.sink, this.StmtTraverser.PdbReader, this.contractContext); var secondArg = new Bpl.NAryExpr(noToken, new Bpl.FunctionCall(this.sink.Heap.Int2Union), new List<Bpl.Expr>(new Bpl.Expr[] {Bpl.Expr.Ident(boundVar)})); ins.Add(secondArg); var outs = new List<Bpl.IdentifierExpr>(); outs.Add(Bpl.Expr.Ident(resultVar)); var callCmd = new Bpl.CallCmd(noToken, invokeProcedureInfo.Decl.Name, ins, outs); var blockCmds = new List<Bpl.Cmd>(); blockCmds.Add( new Bpl.AssumeCmd(noToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.NAryExpr(noToken, new Bpl.FunctionCall(this.sink.Heap.Union2Int), new List<Bpl.Expr>(new Bpl.Expr[] {secondArg})), Bpl.Expr.Ident(boundVar)))); blockCmds.Add(callCmd); Bpl.Block block = new Bpl.Block(noToken, "A", blockCmds, new Bpl.ReturnExprCmd(noToken, Bpl.Expr.Ident(resultVar))); Bpl.Expr body = new Bpl.CodeExpr(new List<Bpl.Variable>(new Bpl.Variable[] {resultVar}), new List<Bpl.Block>{block}); Bpl.Expr antecedent = Bpl.Expr.And(Bpl.Expr.Le(lb, Bpl.Expr.Ident(boundVar)), Bpl.Expr.Lt(Bpl.Expr.Ident(boundVar), ub)); Bpl.Expr quantifier; if (methodName == "ForAll") { body = Bpl.Expr.Imp(antecedent, body); quantifier = new Bpl.ForallExpr(methodCallToken, new List<Bpl.Variable>(new Bpl.Variable[] {boundVar}), body); } else { body = Bpl.Expr.And(antecedent, body); quantifier = new Bpl.ExistsExpr(methodCallToken, new List<Bpl.Variable>(new Bpl.Variable[] {boundVar}), body); } this.TranslatedExpressions.Push(quantifier); return; } } List<Bpl.Expr> inexpr; List<Bpl.IdentifierExpr> outvars; Bpl.IdentifierExpr thisExpr; Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> toBoxed; var proc = TranslateArgumentsAndReturnProcedure(methodCallToken, methodCall.MethodToCall, resolvedMethod, methodCall.IsStaticCall ? null : methodCall.ThisArgument, methodCall.Arguments, out inexpr, out outvars, out thisExpr, out toBoxed); string methodname = proc.Name; var translateAsFunctionCall = proc is Bpl.Function; bool isAsync = false; // this code structure is quite chaotic, and some code needs to be evaluated regardless, hence the try-finally try { if (!translateAsFunctionCall) { foreach (var a in resolvedMethod.Attributes) { if (TypeHelper.GetTypeName(a.Type).EndsWith("AsyncAttribute")) { isAsync = true; } } } var deferringCtorCall = resolvedMethod.IsConstructor && methodCall.ThisArgument is IThisReference; // REVIEW!! Ask Herman: is the above test enough? The following test is used in FindCtorCall.IsDeferringCtor, // but it doesn't work when the type is a struct S because then "this" has a type of "&S". //&& TypeHelper.TypesAreEquivalent(resolvedMethod.ContainingType, methodCall.ThisArgument.Type); if (resolvedMethod.IsConstructor && resolvedMethod.ContainingTypeDefinition.IsStruct && !deferringCtorCall) { handleStructConstructorCall(methodCall, methodCallToken, inexpr, outvars, thisExpr, proc); return; } Bpl.CallCmd call; bool isEventAdd = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("add_"); bool isEventRemove = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("remove_"); if (isEventAdd || isEventRemove) { call = translateAddRemoveCall(methodCall, resolvedMethod, methodCallToken, inexpr, outvars, thisExpr, isEventAdd); } else { if (translateAsFunctionCall) { var func = proc as Bpl.Function; var exprSeq = new List<Bpl.Expr>(); foreach (var e in inexpr) { exprSeq.Add(e); } var callFunction = new Bpl.NAryExpr(methodCallToken, new Bpl.FunctionCall(func), exprSeq); this.TranslatedExpressions.Push(callFunction); return; } else { EmitLineDirective(methodCallToken); call = new Bpl.CallCmd(methodCallToken, methodname, inexpr, outvars); call.IsAsync = isAsync; this.StmtTraverser.StmtBuilder.Add(call); } } foreach (KeyValuePair<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> kv in toBoxed) { var lhs = kv.Key; var tuple = kv.Value; var rhs = tuple.Item1; Bpl.Expr fromUnion = this.sink.Heap.FromUnion(Bpl.Token.NoToken, lhs.Type, rhs, tuple.Item2); this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(lhs, fromUnion)); } if (this.sink.Options.modelExceptions == 2 || (this.sink.Options.modelExceptions == 1 && this.sink.MethodThrowsExceptions(resolvedMethod))) { Bpl.Expr expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef)); this.StmtTraverser.RaiseException(expr); } } finally { // TODO move away phone related code from the translation, it would be better to have 2 or more translation phases if (PhoneCodeHelper.instance().PhonePlugin != null) { if (PhoneCodeHelper.instance().PhoneNavigationToggled) { if (PhoneCodeHelper.instance().isNavigationCall(methodCall)) { Bpl.AssignCmd assignCmd = PhoneCodeHelper.instance().createBoogieNavigationUpdateCmd(sink); this.StmtTraverser.StmtBuilder.Add(assignCmd); } } if (PhoneCodeHelper.instance().PhoneFeedbackToggled) { if (PhoneCodeHelper.instance().isMethodKnownUIChanger(methodCall)) { Bpl.AssumeCmd assumeFalse = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.LiteralExpr.False); this.StmtTraverser.StmtBuilder.Add(assumeFalse); } } } } }
Variable FreshPredicate(ref int predCount) { var pVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "p" + predCount++, Microsoft.Boogie.Type.Bool)); impl.LocVars.Add(pVar); return pVar; }
/// <summary> /// Add additional variable to allow checking as described in the paper /// "It's doomed; we can prove it" /// </summary> private List<Cmd> GenerateReachabilityPredicates(Implementation impl) { Contract.Requires(impl != null); foreach (Block b in impl.Blocks) { Contract.Assert(b != null); //if (b.Predecessors.Length==0) continue; //if (b.Cmds.Length == 0 ) continue; Variable v_ = new LocalVariable(Token.NoToken, new TypedIdent(b.tok, b.Label + reachvarsuffix, new BasicType(SimpleType.Int ))); impl.LocVars.Add(v_); m_BlockReachabilityMap[b] = v_; IdentifierExpr lhs = new IdentifierExpr(b.tok, v_); Contract.Assert(lhs != null); impl.Proc.Modifies.Add(lhs); List<AssignLhs> lhsl = new List<AssignLhs>(); lhsl.Add(new SimpleAssignLhs(Token.NoToken, lhs)); List<Expr> rhsl = new List<Expr>(); rhsl.Add(Expr.Literal(1) ); List<Cmd> cs = new List<Cmd> { new AssignCmd(Token.NoToken, lhsl, rhsl) }; cs.AddRange(b.Cmds); b.Cmds = cs; //checkBlocks.Add(new CheckableBlock(v_,b)); } List<Cmd> incReachVars = new List<Cmd>(); foreach (KeyValuePair<Block, Variable> kvp in m_BlockReachabilityMap) { IdentifierExpr lhs = new IdentifierExpr(Token.NoToken, kvp.Value); impl.Proc.Modifies.Add(lhs); incReachVars.Add(new AssumeCmd(Token.NoToken, Expr.Le(lhs, Expr.Literal(1)))); } return incReachVars; }
private void CreateYieldCheckerImpl(Implementation impl, List<List<Cmd>> yields) { if (yields.Count == 0) return; Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>(); foreach (Variable local in impl.LocVars) { var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, local.Name, local.TypedIdent.Type)); map[local] = Expr.Ident(copy); } Program program = linearTypeChecker.program; List<Variable> locals = new List<Variable>(); List<Variable> inputs = new List<Variable>(); foreach (IdentifierExpr ie in map.Values) { locals.Add(ie.Decl); } for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++) { Variable inParam = impl.InParams[i]; Variable copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type)); locals.Add(copy); map[impl.InParams[i]] = Expr.Ident(copy); } { int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count; foreach (string domainName in linearTypeChecker.linearDomains.Keys) { Variable inParam = impl.InParams[i]; Variable copy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type), true); inputs.Add(copy); map[impl.InParams[i]] = Expr.Ident(copy); i++; } } for (int i = 0; i < impl.OutParams.Count; i++) { Variable outParam = impl.OutParams[i]; var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, outParam.Name, outParam.TypedIdent.Type)); locals.Add(copy); map[impl.OutParams[i]] = Expr.Ident(copy); } Dictionary<Variable, Expr> ogOldLocalMap = new Dictionary<Variable, Expr>(); Dictionary<Variable, Expr> assumeMap = new Dictionary<Variable, Expr>(map); foreach (IdentifierExpr ie in globalMods) { Variable g = ie.Decl; var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_local_old_{0}", g.Name), g.TypedIdent.Type)); locals.Add(copy); ogOldLocalMap[g] = Expr.Ident(copy); Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type), true); inputs.Add(f); assumeMap[g] = Expr.Ident(f); } Substitution assumeSubst = Substituter.SubstitutionFromHashtable(assumeMap); Substitution oldSubst = Substituter.SubstitutionFromHashtable(ogOldLocalMap); Substitution subst = Substituter.SubstitutionFromHashtable(map); List<Block> yieldCheckerBlocks = new List<Block>(); List<String> labels = new List<String>(); List<Block> labelTargets = new List<Block>(); Block yieldCheckerBlock = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken)); labels.Add(yieldCheckerBlock.Label); labelTargets.Add(yieldCheckerBlock); yieldCheckerBlocks.Add(yieldCheckerBlock); int yieldCount = 0; foreach (List<Cmd> cs in yields) { List<Cmd> newCmds = new List<Cmd>(); foreach (Cmd cmd in cs) { PredicateCmd predCmd = (PredicateCmd)cmd; newCmds.Add(new AssumeCmd(Token.NoToken, Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr))); } foreach (Cmd cmd in cs) { PredicateCmd predCmd = (PredicateCmd)cmd; var newExpr = Substituter.ApplyReplacingOldExprs(subst, oldSubst, predCmd.Expr); if (predCmd is AssertCmd) { AssertCmd assertCmd = new AssertCmd(predCmd.tok, newExpr, predCmd.Attributes); assertCmd.ErrorData = "Non-interference check failed"; newCmds.Add(assertCmd); } else { newCmds.Add(new AssumeCmd(Token.NoToken, newExpr)); } } newCmds.Add(new AssumeCmd(Token.NoToken, Expr.False)); yieldCheckerBlock = new Block(Token.NoToken, "L" + yieldCount++, newCmds, new ReturnCmd(Token.NoToken)); labels.Add(yieldCheckerBlock.Label); labelTargets.Add(yieldCheckerBlock); yieldCheckerBlocks.Add(yieldCheckerBlock); } yieldCheckerBlocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), new GotoCmd(Token.NoToken, labels, labelTargets))); // Create the yield checker procedure var yieldCheckerName = string.Format("{0}_YieldChecker_{1}", "Impl", impl.Name); var yieldCheckerProc = new Procedure(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), new List<Requires>(), new List<IdentifierExpr>(), new List<Ensures>()); yieldCheckerProc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1))); yieldCheckerProcs.Add(yieldCheckerProc); // Create the yield checker implementation var yieldCheckerImpl = new Implementation(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), locals, yieldCheckerBlocks); yieldCheckerImpl.Proc = yieldCheckerProc; yieldCheckerImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1))); yieldCheckerImpls.Add(yieldCheckerImpl); }
void LocalIdentTypeOptional(out LocalVariable var, bool isGhost) { IToken id; Type ty; Type optType = null; WildIdent(out id, true); if (la.kind == 21) { Get(); Type(out ty); optType = ty; } var = new LocalVariable(id, id, id.val, optType == null ? new InferredTypeProxy() : optType, isGhost); }
private void SetupRefinementCheck(Implementation impl, out List<Variable> newLocalVars, out Dictionary<string, Variable> domainNameToInputVar, out Dictionary<string, Variable> domainNameToLocalVar, out Dictionary<Variable, Variable> ogOldGlobalMap) { pc = null; ok = null; alpha = null; beta = null; frame = null; newLocalVars = new List<Variable>(); Program program = linearTypeChecker.program; ogOldGlobalMap = new Dictionary<Variable, Variable>(); foreach (IdentifierExpr ie in globalMods) { Variable g = ie.Decl; LocalVariable l = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type)); ogOldGlobalMap[g] = l; newLocalVars.Add(l); } Procedure originalProc = implMap[impl].Proc; ActionInfo actionInfo = civlTypeChecker.procToActionInfo[originalProc]; if (actionInfo.createdAtLayerNum == this.layerNum) { pc = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_pc", Type.Bool)); newLocalVars.Add(pc); ok = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_ok", Type.Bool)); newLocalVars.Add(ok); Dictionary<Variable, Expr> alwaysMap = new Dictionary<Variable, Expr>(); for (int i = 0; i < originalProc.InParams.Count; i++) { alwaysMap[originalProc.InParams[i]] = Expr.Ident(impl.InParams[i]); } for (int i = 0; i < originalProc.OutParams.Count; i++) { alwaysMap[originalProc.OutParams[i]] = Expr.Ident(impl.OutParams[i]); } Substitution always = Substituter.SubstitutionFromHashtable(alwaysMap); Dictionary<Variable, Expr> foroldMap = new Dictionary<Variable, Expr>(); foreach (IdentifierExpr ie in globalMods) { foroldMap[ie.Decl] = Expr.Ident(ogOldGlobalMap[ie.Decl]); } Substitution forold = Substituter.SubstitutionFromHashtable(foroldMap); frame = new HashSet<Variable>(civlTypeChecker.SharedVariables); foreach (Variable v in civlTypeChecker.SharedVariables) { if (civlTypeChecker.globalVarToSharedVarInfo[v].hideLayerNum <= actionInfo.createdAtLayerNum || civlTypeChecker.globalVarToSharedVarInfo[v].introLayerNum > actionInfo.createdAtLayerNum) { frame.Remove(v); } } AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo; if (atomicActionInfo == null) { beta = Expr.True; foreach (var v in frame) { beta = Expr.And(beta, Expr.Eq(Expr.Ident(v), foroldMap[v])); } alpha = Expr.True; } else { Expr betaExpr = (new MoverCheck.TransitionRelationComputation(civlTypeChecker.program, atomicActionInfo, frame, new HashSet<Variable>())).TransitionRelationCompute(true); beta = Substituter.ApplyReplacingOldExprs(always, forold, betaExpr); Expr alphaExpr = Expr.True; foreach (AssertCmd assertCmd in atomicActionInfo.gate) { alphaExpr = Expr.And(alphaExpr, assertCmd.Expr); alphaExpr.Type = Type.Bool; } alpha = Substituter.Apply(always, alphaExpr); } foreach (Variable f in impl.OutParams) { LocalVariable copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_old_{0}", f.Name), f.TypedIdent.Type)); newLocalVars.Add(copy); ogOldGlobalMap[f] = copy; } } domainNameToInputVar = new Dictionary<string, Variable>(); domainNameToLocalVar = new Dictionary<string, Variable>(); { int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count; foreach (string domainName in linearTypeChecker.linearDomains.Keys) { Variable inParam = impl.InParams[i]; domainNameToInputVar[domainName] = inParam; Variable l = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name + "_local", inParam.TypedIdent.Type)); domainNameToLocalVar[domainName] = l; newLocalVars.Add(l); i++; } } }
public virtual LocalVariable VisitLocalVariable(LocalVariable node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result<LocalVariable>() != null); return node; }
private List<Block> CreateAssertsBlocks(Implementation queryImplementation, Implementation targetImplementation, List<Tuple<Variable, Expr, Expr>> assumeVars) { var exprs = CreateAssertsExprs(queryImplementation, targetImplementation); var assertsCmds = CreateAsserts(exprs); queryImplementation.InParams.Iter(iq => { targetImplementation.InParams.Iter(it => { if (Equals(iq.TypedIdent.Type, it.TypedIdent.Type)) { var eqVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, AssumeVarPrefix + "_" + _eqVarsCounter++, BType.Bool)); assumeVars.Add(new Tuple<Variable, Expr, Expr>(eqVar, Expr.Ident(iq), Expr.Ident(it))); queryImplementation.Blocks[0].Cmds.Insert(0, Utils.BoogieUtils.CreateAssignCmd(new List<IdentifierExpr>() { Expr.Ident(eqVar) }, new List<Expr>() { Expr.Eq(Expr.Ident(iq), Expr.Ident(it)) })); } }); }); // The equality vars are grouped according to lhs. This means that expressions like eq_0 = `rax == v2.rcx` and eq_13 = `rax == v2.p0` will be // grouped together, to make the assumes choosing algorithm more efficient (we won't select eq_0 and eq_13 for the same section) var eqVarsGroups = new Dictionary<string, List<Tuple<Variable, Expr, Expr>>>(); assumeVars.Iter(t => { var lhs = t.Item2.ToString(); if (!eqVarsGroups.ContainsKey(lhs)) eqVarsGroups[lhs] = new List<Tuple<Variable, Expr, Expr>>(); eqVarsGroups[lhs].Add(t); }); assumeVars.Iter(t => queryImplementation.LocVars.Add(t.Item1)); return CreateAssertsWithAssumes(eqVarsGroups.Values.ToList(), assertsCmds); }
public Bpl.Procedure addHandlerStubCaller(Sink sink, IMethodDefinition def) { MethodBody callerBody = new MethodBody(); MethodDefinition callerDef = new MethodDefinition() { InternFactory = (def as MethodDefinition).InternFactory, ContainingTypeDefinition = def.ContainingTypeDefinition, IsStatic = true, Name = sink.host.NameTable.GetNameFor("BOOGIE_STUB_CALLER_" + def.Name.Value), Type = sink.host.PlatformType.SystemVoid, Body = callerBody, }; callerBody.MethodDefinition = callerDef; Sink.ProcedureInfo procInfo = sink.FindOrCreateProcedure(def); Sink.ProcedureInfo callerInfo = sink.FindOrCreateProcedure(callerDef); Bpl.LocalVariable[] localVars = new Bpl.LocalVariable[procInfo.Decl.InParams.Count]; Bpl.IdentifierExpr[] varExpr = new Bpl.IdentifierExpr[procInfo.Decl.InParams.Count]; for (int i = 0; i < procInfo.Decl.InParams.Count; i++) { Bpl.LocalVariable loc = new Bpl.LocalVariable(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, TranslationHelper.GenerateTempVarName(), procInfo.Decl.InParams[i].TypedIdent.Type)); localVars[i] = loc; varExpr[i] = new Bpl.IdentifierExpr(Bpl.Token.NoToken, loc); } Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder(); builder.Add(getResetNavigationCheck(sink)); string pageXaml= PhoneCodeHelper.instance().PhonePlugin.getXAMLForPage(def.ContainingTypeDefinition.ToString()); Bpl.Variable boogieCurrentURI = sink.FindOrCreateFieldVariable(PhoneCodeHelper.CurrentURIFieldDefinition); Bpl.Constant boogieXamlConstant; if (pageXaml != null) boogieXamlConstant = sink.FindOrCreateConstant(pageXaml); else boogieXamlConstant = null; // NAVIGATION TODO: For now just assume we are in this page to be able to call the handler, this is NOT true for any handler // NAVIGATION TODO: ie, a network event handler if (boogieXamlConstant != null) { Bpl.AssumeCmd assumeCurrentPage = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI), new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant))); builder.Add(assumeCurrentPage); } // NAVIGATION TODO: have to do the pair generation all in one go instead of having different files that need to be sed'ed boogieXamlConstant = sink.FindOrCreateConstant(BOOGIE_STARTING_URI_PLACEHOLDER); Bpl.AssumeCmd assumeStartPage = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI), new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant))); builder.Add(assumeStartPage); builder.Add(new Bpl.CallCmd(Bpl.Token.NoToken, procInfo.Decl.Name, new List<Bpl.Expr>(varExpr), new List<Bpl.IdentifierExpr>())); boogieXamlConstant = sink.FindOrCreateConstant(BOOGIE_ENDING_URI_PLACEHOLDER); Bpl.AssertCmd assertEndPage = new Bpl.AssertCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI), new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant))); Bpl.Expr guard= new Bpl.IdentifierExpr(Bpl.Token.NoToken, sink.FindOrCreateGlobalVariable(PhoneCodeHelper.BOOGIE_NAVIGATION_CHECK_VARIABLE, Bpl.Type.Bool)); Bpl.StmtListBuilder thenBuilder = new Bpl.StmtListBuilder(); thenBuilder.Add(assertEndPage); Bpl.IfCmd ifNavigated = new Bpl.IfCmd(Bpl.Token.NoToken, guard, thenBuilder.Collect(Bpl.Token.NoToken), null, new Bpl.StmtListBuilder().Collect(Bpl.Token.NoToken)); builder.Add(ifNavigated); Bpl.Implementation impl = new Bpl.Implementation(Bpl.Token.NoToken, callerInfo.Decl.Name, new List<Bpl.TypeVariable>(), new List<Bpl.Variable>(), new List<Bpl.Variable>(), new List<Bpl.Variable>(localVars), builder.Collect(Bpl.Token.NoToken), null, new Bpl.Errors()); sink.TranslatedProgram.AddTopLevelDeclaration(impl); return impl.Proc; }