void LabelOrCmd(out Cmd c, out IToken label) { IToken/*!*/ x; Expr/*!*/ e; List<IToken>/*!*/ xs; List<IdentifierExpr> ids; c = dummyCmd; label = null; Cmd/*!*/ cn; QKeyValue kv = null; switch (la.kind) { case 1: { LabelOrAssign(out c, out label); break; } case 47: { Get(); x = t; while (la.kind == 28) { Attribute(ref kv); } Proposition(out e); c = new AssertCmd(x, e, kv); Expect(9); break; } case 48: { Get(); x = t; while (la.kind == 28) { Attribute(ref kv); } Proposition(out e); c = new AssumeCmd(x, e, kv); Expect(9); break; } case 49: { Get(); x = t; Idents(out xs); Expect(9); ids = new List<IdentifierExpr>(); foreach(IToken/*!*/ y in xs){ Contract.Assert(y != null); ids.Add(new IdentifierExpr(y, y.val)); } c = new HavocCmd(x,ids); break; } case 36: case 52: case 53: { CallCmd(out cn); Expect(9); c = cn; break; } case 54: { ParCallCmd(out cn); c = cn; break; } case 50: { Get(); x = t; Expect(9); c = new YieldCmd(x); break; } default: SynErr(106); break; } }
private void GenerateHelperBlocks(Implementation impl) { Contract.Requires(impl != null); Dictionary<TransferCmd, ReturnCmd> gotoCmdOrigins = new Dictionary<TransferCmd, ReturnCmd>(); exitBlock = GenerateUnifiedExit(impl, gotoCmdOrigins); Contract.Assert(exitBlock != null); AddBlocksBetween(impl.Blocks); #region Insert pre- and post-conditions and where clauses as assume and assert statements { List<Cmd> cc = new List<Cmd>(); // where clauses of global variables foreach (Declaration d in program.TopLevelDeclarations) { GlobalVariable gvar = d as GlobalVariable; if (gvar != null && gvar.TypedIdent.WhereExpr != null) { Cmd c = new AssumeCmd(gvar.tok, gvar.TypedIdent.WhereExpr); cc.Add(c); } } // where clauses of in- and out-parameters cc.AddRange(GetParamWhereClauses(impl)); // where clauses of local variables foreach (Variable lvar in impl.LocVars) { Contract.Assert(lvar != null); if (lvar.TypedIdent.WhereExpr != null) { Cmd c = new AssumeCmd(lvar.tok, lvar.TypedIdent.WhereExpr); cc.Add(c); } } // add cc and the preconditions to new blocks preceding impl.Blocks[0] InjectPreconditions(impl, cc); // append postconditions, starting in exitBlock and continuing into other blocks, if needed exitBlock = InjectPostConditions(impl, exitBlock, gotoCmdOrigins); } #endregion }
/// <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); } } } } }
static void Instrument(Implementation impl, NativeLattice.Element[] pre, NativeLattice.Element[] post) { Contract.Requires(impl != null); Contract.Requires(pre != null); foreach (var b in impl.Blocks) { var element = pre[b.aiId]; if (element != null && (b.widenBlock || CommandLineOptions.Clo.InstrumentInfer == CommandLineOptions.InstrumentationPlaces.Everywhere)) { List<Cmd> newCommands = new List<Cmd>(); Expr inv = element.ToExpr(); PredicateCmd cmd; var kv = new QKeyValue(Token.NoToken, "inferred", new List<object>(), null); if (CommandLineOptions.Clo.InstrumentWithAsserts) { cmd = new AssertCmd(Token.NoToken, inv, kv); } else { cmd = new AssumeCmd(Token.NoToken, inv, kv); } newCommands.Add(cmd); newCommands.AddRange(b.Cmds); if (post != null && post[b.aiId] != null) { inv = post[b.aiId].ToExpr(); kv = new QKeyValue(Token.NoToken, "inferred", new List<object>(), null); if (CommandLineOptions.Clo.InstrumentWithAsserts) { cmd = new AssertCmd(Token.NoToken, inv, kv); } else { cmd = new AssumeCmd(Token.NoToken, inv, kv); } newCommands.Add(cmd); } b.Cmds = newCommands; // destructively replace the commands of the block } } }
void PredicateImplementation() { blockGraph = prog.ProcessLoops(impl); sortedBlocks = blockGraph.LoopyTopSort(); AssignPredicates(); partInfo = BuildPartitionInfo(); if (myUseProcedurePredicates) fp = Expr.Ident(impl.InParams[0]); var newBlocks = new List<Block>(); Block prevBlock = null; foreach (var n in sortedBlocks) { if (predMap.ContainsKey(n.Item1)) { var p = predMap[n.Item1]; var pExpr = Expr.Ident(p); if (n.Item2) { var dominator = FindImmediateDominator(n.Item1); if (dominator != null && predMap.ContainsKey(dominator)) { AssumeCmd aCmd = new AssumeCmd(Token.NoToken, Expr.True); aCmd.Attributes = new QKeyValue(Token.NoToken, "dominator_predicate", new List<object>() { predMap[dominator].ToString() }, aCmd.Attributes); aCmd.Attributes = new QKeyValue(Token.NoToken, "predicate", new List<object>() { predMap[n.Item1].ToString() }, aCmd.Attributes); n.Item1.Cmds.Insert(0, aCmd); } var backedgeBlock = new Block(); newBlocks.Add(backedgeBlock); backedgeBlock.Label = n.Item1.Label + ".backedge"; backedgeBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken, pExpr, 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.Not(pExpr)) }; if (uni != null && !uni.IsUniform(impl.Name, n.Item1)) { uni.AddNonUniform(impl.Name, backedgeBlock); uni.AddNonUniform(impl.Name, tailBlock); } if (prevBlock != null) prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { backedgeBlock, tailBlock }); prevBlock = tailBlock; } else { PredicateBlock(pExpr, n.Item1, newBlocks, ref prevBlock); } } else { if (!n.Item2) { PredicateBlock(null, n.Item1, newBlocks, ref prevBlock); } } } if (prevBlock != null) prevBlock.TransferCmd = new ReturnCmd(Token.NoToken); impl.Blocks = newBlocks; }
private void AddHoudiniConstant(AssumeCmd assumeCmd) { Variable houdiniConstant; if (houdini.MatchCandidate(assumeCmd.Expr, out houdiniConstant)) houdiniAssumeConstants.Add(houdiniConstant); }
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); }
public virtual Cmd VisitAssumeCmd(AssumeCmd node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result<Cmd>() != null); node.Expr = this.VisitExpr(node.Expr); return node; }
// If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label; // otherwise, it is null. void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) { Contract.Requires(stmtList != null); Contract.Requires(blocks != null); List<Cmd> cmdPrefixToApply = stmtList.PrefixCommands; int n = stmtList.BigBlocks.Count; foreach (BigBlock b in stmtList.BigBlocks) { n--; Contract.Assert(b.LabelName != null); List<Cmd> theSimpleCmds; if (cmdPrefixToApply == null) { theSimpleCmds = b.simpleCmds; } else { theSimpleCmds = new List<Cmd>(); theSimpleCmds.AddRange(cmdPrefixToApply); theSimpleCmds.AddRange(b.simpleCmds); cmdPrefixToApply = null; // now, we've used 'em up } if (b.tc != null) { // this BigBlock has the very same components as a Block Contract.Assert(b.ec == null); Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc); blocks.Add(block); } else if (b.ec == null) { TransferCmd trCmd; if (n == 0 && runOffTheEndLabel != null) { // goto the given label instead of the textual successor block trCmd = new GotoCmd(stmtList.EndCurly, new List<String> { runOffTheEndLabel }); } else { trCmd = GotoSuccessor(stmtList.EndCurly, b); } Block block = new Block(b.tok, b.LabelName, theSimpleCmds, trCmd); blocks.Add(block); } else if (b.ec is BreakCmd) { BreakCmd bcmd = (BreakCmd)b.ec; Contract.Assert(bcmd.BreakEnclosure != null); Block block = new Block(b.tok, b.LabelName, theSimpleCmds, GotoSuccessor(b.ec.tok, bcmd.BreakEnclosure)); blocks.Add(block); } else if (b.ec is WhileCmd) { WhileCmd wcmd = (WhileCmd)b.ec; string loopHeadLabel = prefix + anon + "_LoopHead"; string/*!*/ loopBodyLabel = prefix + anon + "_LoopBody"; string loopDoneLabel = prefix + anon + "_LoopDone"; anon++; List<Cmd> ssBody = new List<Cmd>(); List<Cmd> ssDone = new List<Cmd>(); if (wcmd.Guard != null) { var ac = new AssumeCmd(wcmd.tok, wcmd.Guard); ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null); ssBody.Add(ac); ac = new AssumeCmd(wcmd.tok, Expr.Not(wcmd.Guard)); ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null); ssDone.Add(ac); } // Try to squeeze in ssBody into the first block of wcmd.Body bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel); // ... goto LoopHead; Block block = new Block(b.tok, b.LabelName, theSimpleCmds, new GotoCmd(wcmd.tok, new List<String> { loopHeadLabel })); blocks.Add(block); // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody; List<Cmd> ssHead = new List<Cmd>(); foreach (PredicateCmd inv in wcmd.Invariants) { ssHead.Add(inv); } block = new Block(wcmd.tok, loopHeadLabel, ssHead, new GotoCmd(wcmd.tok, new List<String> { loopDoneLabel, loopBodyLabel })); blocks.Add(block); if (!bodyGuardTakenCareOf) { // LoopBody: assume guard; goto firstLoopBlock; block = new Block(wcmd.tok, loopBodyLabel, ssBody, new GotoCmd(wcmd.tok, new List<String> { wcmd.Body.BigBlocks[0].LabelName })); blocks.Add(block); } // recurse to create the blocks for the loop body CreateBlocks(wcmd.Body, loopHeadLabel); // LoopDone: assume !guard; goto loopSuccessor; TransferCmd trCmd; if (n == 0 && runOffTheEndLabel != null) { // goto the given label instead of the textual successor block trCmd = new GotoCmd(wcmd.tok, new List<String> { runOffTheEndLabel }); } else { trCmd = GotoSuccessor(wcmd.tok, b); } block = new Block(wcmd.tok, loopDoneLabel, ssDone, trCmd); blocks.Add(block); } else { IfCmd ifcmd = (IfCmd)b.ec; string predLabel = b.LabelName; List<Cmd> predCmds = theSimpleCmds; for (; ifcmd != null; ifcmd = ifcmd.elseIf) { string thenLabel = prefix + anon + "_Then"; Contract.Assert(thenLabel != null); string elseLabel = prefix + anon + "_Else"; Contract.Assert(elseLabel != null); anon++; List<Cmd> ssThen = new List<Cmd>(); List<Cmd> ssElse = new List<Cmd>(); if (ifcmd.Guard != null) { var ac = new AssumeCmd(ifcmd.tok, ifcmd.Guard); ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null); ssThen.Add(ac); ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard)); ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null); ssElse.Add(ac); } // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel); bool elseGuardTakenCareOf = false; if (ifcmd.elseBlock != null) { elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel); } // ... goto Then, Else; Block block = new Block(b.tok, predLabel, predCmds, new GotoCmd(ifcmd.tok, new List<String> { thenLabel, elseLabel })); blocks.Add(block); if (!thenGuardTakenCareOf) { // Then: assume guard; goto firstThenBlock; block = new Block(ifcmd.tok, thenLabel, ssThen, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.thn.BigBlocks[0].LabelName })); blocks.Add(block); } // recurse to create the blocks for the then branch CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null); if (ifcmd.elseBlock != null) { Contract.Assert(ifcmd.elseIf == null); if (!elseGuardTakenCareOf) { // Else: assume !guard; goto firstElseBlock; block = new Block(ifcmd.tok, elseLabel, ssElse, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.elseBlock.BigBlocks[0].LabelName })); blocks.Add(block); } // recurse to create the blocks for the else branch CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null); } else if (ifcmd.elseIf != null) { // this is an "else if" predLabel = elseLabel; predCmds = new List<Cmd>(); if (ifcmd.Guard != null) { var ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard)); ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null); predCmds.Add(ac); } } else { // no else alternative is specified, so else branch is just "skip" // Else: assume !guard; goto ifSuccessor; TransferCmd trCmd; if (n == 0 && runOffTheEndLabel != null) { // goto the given label instead of the textual successor block trCmd = new GotoCmd(ifcmd.tok, new List<String> { runOffTheEndLabel }); } else { trCmd = GotoSuccessor(ifcmd.tok, b); } block = new Block(ifcmd.tok, elseLabel, ssElse, trCmd); blocks.Add(block); } } } } }
public AtomicActionInfo(Procedure proc, Ensures ensures, MoverType moverType, int layerNum, int availableUptoLayerNum) : base(proc, layerNum, availableUptoLayerNum) { CodeExpr codeExpr = ensures.Condition as CodeExpr; this.ensures = ensures; this.moverType = moverType; this.thisGate = new List<AssertCmd>(); this.thisAction = codeExpr; this.thisInParams = new List<Variable>(); this.thisOutParams = new List<Variable>(); this.thatGate = new List<AssertCmd>(); this.thatInParams = new List<Variable>(); this.thatOutParams = new List<Variable>(); this.hasAssumeCmd = false; foreach (Block block in codeExpr.Blocks) { block.Cmds.ForEach(x => this.hasAssumeCmd = this.hasAssumeCmd || x is AssumeCmd); } var cmds = thisAction.Blocks[0].Cmds; for (int i = 0; i < cmds.Count; i++) { AssertCmd assertCmd = cmds[i] as AssertCmd; if (assertCmd == null) break; thisGate.Add(assertCmd); cmds[i] = new AssumeCmd(assertCmd.tok, Expr.True); } Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>(); foreach (Variable x in proc.InParams) { this.thisInParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), true, x.Attributes); this.thatInParams.Add(y); map[x] = Expr.Ident(y); } foreach (Variable x in proc.OutParams) { this.thisOutParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false, x.Attributes); this.thatOutParams.Add(y); map[x] = Expr.Ident(y); } List<Variable> thatLocVars = new List<Variable>(); foreach (Variable x in thisAction.LocVars) { Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); map[x] = Expr.Ident(y); thatLocVars.Add(y); } Contract.Assume(proc.TypeParameters.Count == 0); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (AssertCmd assertCmd in thisGate) { thatGate.Add((AssertCmd)Substituter.Apply(subst, assertCmd)); } Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>(); List<Block> thatBlocks = new List<Block>(); foreach (Block block in thisAction.Blocks) { List<Cmd> otherCmds = new List<Cmd>(); foreach (Cmd cmd in block.Cmds) { otherCmds.Add(Substituter.Apply(subst, cmd)); } Block thatBlock = new Block(); thatBlock.Cmds = otherCmds; thatBlock.Label = "that_" + block.Label; block.Label = "this_" + block.Label; thatBlocks.Add(thatBlock); blockMap[block] = thatBlock; if (block.TransferCmd is GotoCmd) { GotoCmd gotoCmd = block.TransferCmd as GotoCmd; for (int i = 0; i < gotoCmd.labelNames.Count; i++) { gotoCmd.labelNames[i] = "this_" + gotoCmd.labelNames[i]; } } } foreach (Block block in thisAction.Blocks) { if (block.TransferCmd is ReturnExprCmd) { block.TransferCmd = new ReturnCmd(block.TransferCmd.tok); blockMap[block].TransferCmd = new ReturnCmd(block.TransferCmd.tok); continue; } List<Block> thatGotoCmdLabelTargets = new List<Block>(); List<string> thatGotoCmdLabelNames = new List<string>(); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { thatGotoCmdLabelTargets.Add(blockMap[target]); thatGotoCmdLabelNames.Add(blockMap[target].Label); } blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, thatGotoCmdLabelNames, thatGotoCmdLabelTargets); } this.thatAction = new CodeExpr(thatLocVars, thatBlocks); { VariableCollector collector = new VariableCollector(); collector.Visit(codeExpr); this.actionUsedGlobalVars = new HashSet<Variable>(collector.usedVars.Where(x => x is GlobalVariable)); } List<Variable> modifiedVars = new List<Variable>(); foreach (Block block in codeExpr.Blocks) { block.Cmds.ForEach(cmd => cmd.AddAssignedVariables(modifiedVars)); } this.modifiedGlobalVars = new HashSet<Variable>(modifiedVars.Where(x => x is GlobalVariable)); { VariableCollector collector = new VariableCollector(); this.thisGate.ForEach(assertCmd => collector.Visit(assertCmd)); this.gateUsedGlobalVars = new HashSet<Variable>(collector.usedVars.Where(x => x is GlobalVariable)); } }
protected override Cmd ComputeDesugaring() { Contract.Ensures(Contract.Result<Cmd>() != null); List<Cmd> newBlockBody = new List<Cmd>(); Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); Dictionary<Variable, Expr> substMapOld = new Dictionary<Variable, Expr>(); Dictionary<Variable, Expr> substMapBound = new Dictionary<Variable, Expr>(); List<Variable>/*!*/ tempVars = new List<Variable>(); // proc P(ins) returns (outs) // requires Pre // //modifies frame // ensures Post // // call aouts := P(ains) // ins : formal in parameters of procedure // frame : a list of global variables from the modifies clause // outs : formal out parameters of procedure // ains : actual in arguments passed to call // aouts : actual variables assigned to from call // cins : new variables created just for this call, one per ains // cframe : new variables created just for this call, to keep track of OLD values // couts : new variables created just for this call, one per aouts // WildcardVars : new variables created just for this call, one per null in ains #region Create cins; each one is an incarnation of the corresponding in parameter List<Variable>/*!*/ cins = new List<Variable>(); List<Variable> wildcardVars = new List<Variable>(); Contract.Assume(this.Proc != null); for (int i = 0; i < this.Proc.InParams.Count; ++i) { Variable/*!*/ param = cce.NonNull(this.Proc.InParams[i]); bool isWildcard = this.Ins[i] == null; Type/*!*/ actualType; if (isWildcard) actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution()); else // during type checking, we have ensured that the type of the actual // parameter Ins[i] is correct, so we can use it here actualType = cce.NonNull(cce.NonNull(Ins[i]).Type); Variable cin = CreateTemporaryVariable(tempVars, param, actualType, TempVarKind.Formal); cins.Add(cin); IdentifierExpr ie = new IdentifierExpr(cin.tok, cin); substMap.Add(param, ie); if (isWildcard) { cin = CreateTemporaryVariable(tempVars, param, actualType, TempVarKind.Bound); wildcardVars.Add(cin); ie = new IdentifierExpr(cin.tok, cin); } substMapBound.Add(param, ie); } #endregion #region call aouts := P(ains) becomes: (open outlining one level to see) #region cins := ains (or havoc cin when ain is null) for (int i = 0, n = this.Ins.Count; i < n; i++) { IdentifierExpr/*!*/ cin_exp = new IdentifierExpr(cce.NonNull(cins[i]).tok, cce.NonNull(cins[i])); Contract.Assert(cin_exp != null); if (this.Ins[i] != null) { AssignCmd assign = Cmd.SimpleAssign(Token.NoToken, cin_exp, cce.NonNull(this.Ins[i])); newBlockBody.Add(assign); } else { List<IdentifierExpr>/*!*/ ies = new List<IdentifierExpr>(); ies.Add(cin_exp); HavocCmd havoc = new HavocCmd(Token.NoToken, ies); newBlockBody.Add(havoc); } } #endregion #region assert (exists wildcardVars :: Pre[ins := cins]) Substitution s = Substituter.SubstitutionFromHashtable(substMapBound); bool hasWildcard = (wildcardVars.Count != 0); Expr preConjunction = null; for (int i = 0; i < this.Proc.Requires.Count; i++) { Requires/*!*/ req = cce.NonNull(this.Proc.Requires[i]); if (!req.Free && !IsFree) { if (hasWildcard) { Expr pre = Substituter.Apply(s, req.Condition); if (preConjunction == null) { preConjunction = pre; } else { preConjunction = Expr.And(preConjunction, pre); } } else { Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone()); reqCopy.Condition = Substituter.Apply(s, req.Condition); AssertCmd/*!*/ a = new AssertRequiresCmd(this, reqCopy); Contract.Assert(a != null); a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced; newBlockBody.Add(a); } } else if (CommandLineOptions.Clo.StratifiedInlining > 0) { // inject free requires as assume statements at the call site AssumeCmd/*!*/ a = new AssumeCmd(req.tok, Substituter.Apply(s, req.Condition)); Contract.Assert(a != null); newBlockBody.Add(a); } } if (hasWildcard) { if (preConjunction == null) { preConjunction = Expr.True; } Expr/*!*/ expr = new ExistsExpr(tok, wildcardVars, preConjunction); Contract.Assert(expr != null); AssertCmd/*!*/ a = new AssertCmd(tok, expr); Contract.Assert(a != null); a.ErrorDataEnhanced = AssertCmd.GenerateBoundVarMiningStrategy(expr); newBlockBody.Add(a); } #endregion #region assume Pre[ins := cins] with formal paramters if (hasWildcard) { s = Substituter.SubstitutionFromHashtable(substMap); for (int i = 0; i < this.Proc.Requires.Count; i++) { Requires/*!*/ req = cce.NonNull(this.Proc.Requires[i]); if (!req.Free) { Requires/*!*/ reqCopy = (Requires/*!*/)cce.NonNull(req.Clone()); reqCopy.Condition = Substituter.Apply(s, req.Condition); AssumeCmd/*!*/ a = new AssumeCmd(tok, reqCopy.Condition); Contract.Assert(a != null); newBlockBody.Add(a); } } } #endregion #region cframe := frame (to hold onto frame values in case they are referred to in the postcondition) List<IdentifierExpr> havocVarExprs = new List<IdentifierExpr>(); foreach (IdentifierExpr/*!*/ f in this.Proc.Modifies) { Contract.Assert(f != null); Contract.Assume(f.Decl != null); Contract.Assert(f.Type != null); Variable v = CreateTemporaryVariable(tempVars, f.Decl, f.Type, TempVarKind.Old); IdentifierExpr v_exp = new IdentifierExpr(v.tok, v); substMapOld.Add(f.Decl, v_exp); // this assumes no duplicates in this.Proc.Modifies AssignCmd assign = Cmd.SimpleAssign(f.tok, v_exp, f); newBlockBody.Add(assign); // fra if (!havocVarExprs.Contains(f)) havocVarExprs.Add(f); } #endregion #region Create couts List<Variable>/*!*/ couts = new List<Variable>(); for (int i = 0; i < this.Proc.OutParams.Count; ++i) { Variable/*!*/ param = cce.NonNull(this.Proc.OutParams[i]); bool isWildcard = this.Outs[i] == null; Type/*!*/ actualType; if (isWildcard) actualType = param.TypedIdent.Type.Substitute(TypeParamSubstitution()); else // during type checking, we have ensured that the type of the actual // out parameter Outs[i] is correct, so we can use it here actualType = cce.NonNull(cce.NonNull(Outs[i]).Type); Variable cout = CreateTemporaryVariable(tempVars, param, actualType, TempVarKind.Formal); couts.Add(cout); IdentifierExpr ie = new IdentifierExpr(cout.tok, cout); substMap.Add(param, ie); if (!havocVarExprs.Contains(ie)) havocVarExprs.Add(ie); } // add the where clauses, now that we have the entire substitution map foreach (Variable/*!*/ param in this.Proc.OutParams) { Contract.Assert(param != null); Expr w = param.TypedIdent.WhereExpr; if (w != null) { IdentifierExpr ie = (IdentifierExpr/*!*/)cce.NonNull(substMap[param]); Contract.Assert(ie.Decl != null); ie.Decl.TypedIdent.WhereExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(substMap), w); } } #endregion #region havoc frame, couts // pass on this's token HavocCmd hc = new HavocCmd(this.tok, havocVarExprs); newBlockBody.Add(hc); #endregion #region assume Post[ins, outs, old(frame) := cins, couts, cframe] Substitution s2 = Substituter.SubstitutionFromHashtable(substMap); Substitution s2old = Substituter.SubstitutionFromHashtable(substMapOld); foreach (Ensures/*!*/ e in this.Proc.Ensures) { Contract.Assert(e != null); Expr copy = Substituter.ApplyReplacingOldExprs(s2, s2old, e.Condition); AssumeCmd assume = new AssumeCmd(this.tok, copy); #region stratified inlining support if (QKeyValue.FindBoolAttribute(e.Attributes, "si_fcall")) { assume.Attributes = Attributes; } if (QKeyValue.FindBoolAttribute(e.Attributes, "candidate")) { assume.Attributes = new QKeyValue(Token.NoToken, "candidate", new List<object>(), assume.Attributes); assume.Attributes.Params.Add(this.callee); } #endregion newBlockBody.Add(assume); } #endregion #region aouts := couts for (int i = 0, n = this.Outs.Count; i < n; i++) { if (this.Outs[i] != null) { Variable/*!*/ param_i = cce.NonNull(this.Proc.OutParams[i]); Expr/*!*/ cout_exp = new IdentifierExpr(cce.NonNull(couts[i]).tok, cce.NonNull(couts[i])); Contract.Assert(cout_exp != null); AssignCmd assign = Cmd.SimpleAssign(param_i.tok, cce.NonNull(this.Outs[i]), cout_exp); newBlockBody.Add(assign); } } #endregion #endregion return new StateCmd(this.tok, tempVars, newBlockBody); }
public ActionInfo(Procedure proc, CodeExpr codeExpr, MoverType moverType, int phaseNum) { this.proc = proc; this.moverType = moverType; this.phaseNum = phaseNum; this.callerPhaseNums = new HashSet<int>(); this.thisGate = new List<AssertCmd>(); this.thisAction = codeExpr; this.thisInParams = new List<Variable>(); this.thisOutParams = new List<Variable>(); this.thatGate = new List<AssertCmd>(); this.thatInParams = new List<Variable>(); this.thatOutParams = new List<Variable>(); var cmds = thisAction.Blocks[0].Cmds; for (int i = 0; i < cmds.Count; i++) { AssertCmd assertCmd = cmds[i] as AssertCmd; if (assertCmd == null) break; thisGate.Add(assertCmd); cmds[i] = new AssumeCmd(assertCmd.tok, assertCmd.Expr); } Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>(); foreach (Variable x in proc.InParams) { this.thisInParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), true); this.thatInParams.Add(y); map[x] = new IdentifierExpr(Token.NoToken, y); } foreach (Variable x in proc.OutParams) { this.thisOutParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); this.thatOutParams.Add(y); map[x] = new IdentifierExpr(Token.NoToken, y); } List<Variable> otherLocVars = new List<Variable>(); foreach (Variable x in thisAction.LocVars) { Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); map[x] = new IdentifierExpr(Token.NoToken, y); otherLocVars.Add(y); } Contract.Assume(proc.TypeParameters.Count == 0); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (AssertCmd assertCmd in thisGate) { thatGate.Add((AssertCmd)Substituter.Apply(subst, assertCmd)); } Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>(); List<Block> otherBlocks = new List<Block>(); foreach (Block block in thisAction.Blocks) { List<Cmd> otherCmds = new List<Cmd>(); foreach (Cmd cmd in block.Cmds) { otherCmds.Add(Substituter.Apply(subst, cmd)); } Block otherBlock = new Block(); otherBlock.Cmds = otherCmds; otherBlock.Label = "that_" + block.Label; block.Label = "this_" + block.Label; otherBlocks.Add(otherBlock); blockMap[block] = otherBlock; if (block.TransferCmd is GotoCmd) { GotoCmd gotoCmd = block.TransferCmd as GotoCmd; for (int i = 0; i < gotoCmd.labelNames.Count; i++) { gotoCmd.labelNames[i] = "this_" + gotoCmd.labelNames[i]; } } } foreach (Block block in thisAction.Blocks) { if (block.TransferCmd is ReturnExprCmd) { block.TransferCmd = new ReturnCmd(block.TransferCmd.tok); blockMap[block].TransferCmd = new ReturnCmd(block.TransferCmd.tok); continue; } List<Block> otherGotoCmdLabelTargets = new List<Block>(); List<string> otherGotoCmdLabelNames = new List<string>(); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { otherGotoCmdLabelTargets.Add(blockMap[target]); otherGotoCmdLabelNames.Add(blockMap[target].Label); } blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, otherGotoCmdLabelNames, otherGotoCmdLabelTargets); } this.thatAction = new CodeExpr(otherLocVars, otherBlocks); }
public override Cmd VisitAssumeCmd(AssumeCmd node) { AddHoudiniConstant(node); return base.VisitAssumeCmd(node); }
public AtomicActionInfo(Procedure proc, Ensures ensures, MoverType moverType, int layerNum, int availableUptoLayerNum) : base(proc, layerNum, availableUptoLayerNum) { this.ensures = ensures; this.moverType = moverType; this.gate = new List<AssertCmd>(); this.action = ensures.Condition as CodeExpr; this.thisGate = new List<AssertCmd>(); this.thisInParams = new List<Variable>(); this.thisOutParams = new List<Variable>(); this.thatGate = new List<AssertCmd>(); this.thatInParams = new List<Variable>(); this.thatOutParams = new List<Variable>(); this.hasAssumeCmd = false; this.thisMap = new Dictionary<Variable, Expr>(); this.thatMap = new Dictionary<Variable, Expr>(); this.triggerFuns = new Dictionary<Variable, Function>(); foreach (Block block in this.action.Blocks) { block.Cmds.ForEach(x => this.hasAssumeCmd = this.hasAssumeCmd || x is AssumeCmd); } foreach (Block block in this.action.Blocks) { if (block.TransferCmd is ReturnExprCmd) { block.TransferCmd = new ReturnCmd(block.TransferCmd.tok); } } var cmds = this.action.Blocks[0].Cmds; for (int i = 0; i < cmds.Count; i++) { AssertCmd assertCmd = cmds[i] as AssertCmd; if (assertCmd == null) break; this.gate.Add(assertCmd); cmds[i] = new AssumeCmd(assertCmd.tok, Expr.True); } foreach (Variable x in proc.InParams) { Variable thisx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "this_" + x.Name, x.TypedIdent.Type), true, x.Attributes); this.thisInParams.Add(thisx); this.thisMap[x] = Expr.Ident(thisx); Variable thatx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), true, x.Attributes); this.thatInParams.Add(thatx); this.thatMap[x] = Expr.Ident(thatx); } foreach (Variable x in proc.OutParams) { Variable thisx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "this_" + x.Name, x.TypedIdent.Type), false, x.Attributes); this.thisOutParams.Add(thisx); this.thisMap[x] = Expr.Ident(thisx); Variable thatx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false, x.Attributes); this.thatOutParams.Add(thatx); this.thatMap[x] = Expr.Ident(thatx); } List<Variable> thisLocVars = new List<Variable>(); List<Variable> thatLocVars = new List<Variable>(); foreach (Variable x in this.action.LocVars) { Variable thisx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "this_" + x.Name, x.TypedIdent.Type), false); thisMap[x] = Expr.Ident(thisx); thisLocVars.Add(thisx); Variable thatx = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); thatMap[x] = Expr.Ident(thatx); thatLocVars.Add(thatx); } Contract.Assume(proc.TypeParameters.Count == 0); Substitution thisSubst = Substituter.SubstitutionFromHashtable(this.thisMap); Substitution thatSubst = Substituter.SubstitutionFromHashtable(this.thatMap); foreach (AssertCmd assertCmd in this.gate) { this.thisGate.Add((AssertCmd)Substituter.Apply(thisSubst, assertCmd)); this.thatGate.Add((AssertCmd)Substituter.Apply(thatSubst, assertCmd)); } this.thisAction = new CodeExpr(thisLocVars, SubstituteBlocks(this.action.Blocks, thisSubst, "this_")); this.thatAction = new CodeExpr(thatLocVars, SubstituteBlocks(this.action.Blocks, thatSubst, "that_")); { VariableCollector collector = new VariableCollector(); collector.Visit(this.action); this.actionUsedGlobalVars = new HashSet<Variable>(collector.usedVars.Where(x => x is GlobalVariable)); } List<Variable> modifiedVars = new List<Variable>(); foreach (Block block in this.action.Blocks) { block.Cmds.ForEach(cmd => cmd.AddAssignedVariables(modifiedVars)); } this.modifiedGlobalVars = new HashSet<Variable>(modifiedVars.Where(x => x is GlobalVariable)); { VariableCollector collector = new VariableCollector(); this.gate.ForEach(assertCmd => collector.Visit(assertCmd)); this.gateUsedGlobalVars = new HashSet<Variable>(collector.usedVars.Where(x => x is GlobalVariable)); } }
public override Cmd VisitAssumeCmd(AssumeCmd node) { node.tok = Token.NoToken; TokenCount++; return base.VisitAssumeCmd(node); }
public override Cmd VisitAssumeCmd(AssumeCmd node) { Contract.Ensures(Contract.Result<Cmd>() == node); this.VisitExpr(node.Expr); return node; }
// result[0] is the entry block protected List<Block/*!*/>/*!*/ CreateInlinedBlocks(CallCmd callCmd, Implementation impl, string nextBlockLabel) { Contract.Requires(nextBlockLabel != null); Contract.Requires(impl != null); Contract.Requires(impl.Proc != null); Contract.Requires(callCmd != null); Contract.Requires(codeCopier.Subst != null); Contract.Requires(codeCopier.OldSubst != null); Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>())); List<Block/*!*/>/*!*/ implBlocks = cce.NonNull(impl.OriginalBlocks); Contract.Assert(implBlocks.Count > 0); Procedure proc = impl.Proc; string startLabel = implBlocks[0].Label; List<Block/*!*/>/*!*/ inlinedBlocks = new List<Block/*!*/>(); // create in block List<Cmd> inCmds = new List<Cmd>(); // assign in parameters for (int i = 0; i < impl.InParams.Count; ++i) { Cmd cmd = Cmd.SimpleAssign(impl.tok, (IdentifierExpr)cce.NonNull(codeCopier.Subst)(cce.NonNull(impl.InParams[i])), cce.NonNull(callCmd.Ins[i])); inCmds.Add(cmd); } // inject requires for (int i = 0; i < proc.Requires.Count; i++) { Requires/*!*/ req = cce.NonNull(proc.Requires[i]); inCmds.Add(InlinedRequires(callCmd, req)); } List<Variable> locVars = cce.NonNull(impl.OriginalLocVars); // havoc locals and out parameters in case procedure is invoked in a loop List<IdentifierExpr> havocVars = new List<IdentifierExpr>(); foreach (Variable v in locVars) { havocVars.Add((IdentifierExpr)codeCopier.Subst(v)); } foreach (Variable v in impl.OutParams) { havocVars.Add((IdentifierExpr)codeCopier.Subst(v)); } if (havocVars.Count > 0) { inCmds.Add(new HavocCmd(Token.NoToken, havocVars)); } // add where clauses of local vars as assume for (int i = 0; i < locVars.Count; ++i) { Expr whereExpr = (cce.NonNull(locVars[i])).TypedIdent.WhereExpr; if (whereExpr != null) { whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr); // FIXME we cannot overwrite it, can we?! (cce.NonNull(locVars[i])).TypedIdent.WhereExpr = whereExpr; AssumeCmd/*!*/ a = new AssumeCmd(Token.NoToken, whereExpr); Contract.Assert(a != null); inCmds.Add(a); } } // add where clauses of output params as assume for (int i = 0; i < impl.OutParams.Count; ++i) { Expr whereExpr = (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr; if (whereExpr != null) { whereExpr = Substituter.Apply(codeCopier.Subst, whereExpr); // FIXME likewise (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr = whereExpr; AssumeCmd/*!*/ a = new AssumeCmd(Token.NoToken, whereExpr); Contract.Assert(a != null); inCmds.Add(a); } } // assign modifies old values foreach (IdentifierExpr/*!*/ mie in proc.Modifies) { Contract.Assert(mie != null); Variable/*!*/ mvar = cce.NonNull(mie.Decl); AssignCmd assign = Cmd.SimpleAssign(impl.tok, (IdentifierExpr)cce.NonNull(codeCopier.OldSubst(mvar)), mie); inCmds.Add(assign); } GotoCmd inGotoCmd = new GotoCmd(callCmd.tok, new List<String> { GetInlinedProcLabel(proc.Name) + "$" + startLabel }); Block inBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Entry", inCmds, inGotoCmd); inlinedBlocks.Add(inBlock); // inject the blocks of the implementation Block intBlock; foreach (Block block in implBlocks) { List<Cmd> copyCmds = codeCopier.CopyCmdSeq(block.Cmds); if (0 <= inlineDepth) { copyCmds = RemoveAsserts(copyCmds); } TransferCmd transferCmd = CreateInlinedTransferCmd(cce.NonNull(block.TransferCmd), GetInlinedProcLabel(proc.Name)); intBlock = new Block(block.tok, GetInlinedProcLabel(proc.Name) + "$" + block.Label, copyCmds, transferCmd); inlinedBlocks.Add(intBlock); } // create out block List<Cmd> outCmds = new List<Cmd>(); // inject ensures for (int i = 0; i < proc.Ensures.Count; i++) { Ensures/*!*/ ens = cce.NonNull(proc.Ensures[i]); outCmds.Add(InlinedEnsures(callCmd, ens)); } // assign out params for (int i = 0; i < impl.OutParams.Count; ++i) { Expr/*!*/ cout_exp = (IdentifierExpr)cce.NonNull(codeCopier.Subst(cce.NonNull(impl.OutParams[i]))); Cmd cmd = Cmd.SimpleAssign(impl.tok, cce.NonNull(callCmd.Outs[i]), cout_exp); outCmds.Add(cmd); } // create out block GotoCmd outGotoCmd = new GotoCmd(Token.NoToken, new List<String> { nextBlockLabel }); Block outBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Return", outCmds, outGotoCmd); inlinedBlocks.Add(outBlock); return inlinedBlocks; }
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; }
private void AssertOrAssumeNonNull(Bpl.IToken token, Bpl.Expr instance) { if (this.sink.Options.dereference != Options.Dereference.None) { Bpl.Cmd c; var n = Bpl.Expr.Ident(this.sink.Heap.NullRef); var neq = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, instance, n); if (this.sink.Options.dereference == Options.Dereference.Assume) { c = new Bpl.AssumeCmd(token, neq); } else { c = new Bpl.AssertCmd(token, neq); } this.StmtTraverser.StmtBuilder.Add(c); } }
public override Cmd VisitAssumeCmd(AssumeCmd node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<Cmd>() != null); return base.VisitAssumeCmd((AssumeCmd)node.Clone()); }
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; }