public void Transform() { foreach (var decl in program.TopLevelDeclarations) { Implementation impl = decl as Implementation; if (impl == null) { continue; } Dictionary <string, Variable> domainNameToInputVar = new Dictionary <string, Variable>(); foreach (string domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; Formal f = new Formal( Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List <TypeVariable>(), new List <Type> { domain.elementType }, Type.Bool)), true); impl.InParams.Add(f); domainNameToInputVar[domainName] = f; } foreach (Block b in impl.Blocks) { List <Cmd> newCmds = new List <Cmd>(); for (int i = 0; i < b.Cmds.Count; i++) { Cmd cmd = b.Cmds[i]; newCmds.Add(cmd); if (cmd is CallCmd) { CallCmd callCmd = cmd as CallCmd; if (callCmd.IsAsync) { foreach (var domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List <Expr> { Expr.False }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); callCmd.Ins.Add(expr); } } else { Dictionary <string, Expr> domainNameToExpr = new Dictionary <string, Expr>(); foreach (var domainName in linearDomains.Keys) { domainNameToExpr[domainName] = new IdentifierExpr(Token.NoToken, domainNameToInputVar[domainName]); } foreach (Variable v in availableLinearVars[callCmd]) { var domainName = FindDomainName(v); var domain = linearDomains[domainName]; IdentifierExpr ie = new IdentifierExpr(Token.NoToken, v); var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List <Expr> { v.TypedIdent.Type is MapType ? ie : Singleton(ie, domainName), domainNameToExpr[domainName] }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); domainNameToExpr[domainName] = expr; } foreach (var domainName in linearDomains.Keys) { callCmd.Ins.Add(domainNameToExpr[domainName]); } } } else if (cmd is ParCallCmd) { ParCallCmd parCallCmd = (ParCallCmd)cmd; foreach (CallCmd callCmd in parCallCmd.CallCmds) { foreach (var domainName in linearDomains.Keys) { var domain = linearDomains[domainName]; var expr = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapConstBool), new List <Expr> { Expr.False }); expr.Resolve(new ResolutionContext(null)); expr.Typecheck(new TypecheckingContext(null)); callCmd.Ins.Add(expr); } } } else if (cmd is YieldCmd) { AddDisjointnessExpr(newCmds, cmd, domainNameToInputVar); } } b.Cmds = newCmds; } { // Loops impl.PruneUnreachableBlocks(); impl.ComputePredecessorsForBlocks(); GraphUtil.Graph <Block> g = Program.GraphFromImpl(impl); g.ComputeLoops(); if (g.Reducible) { foreach (Block header in g.Headers) { List <Cmd> newCmds = new List <Cmd>(); AddDisjointnessExpr(newCmds, header, domainNameToInputVar); newCmds.AddRange(header.Cmds); header.Cmds = newCmds; } } } } foreach (var decl in program.TopLevelDeclarations) { Procedure proc = decl as Procedure; if (proc == null) { continue; } Dictionary <string, HashSet <Variable> > domainNameToInputScope = new Dictionary <string, HashSet <Variable> >(); Dictionary <string, HashSet <Variable> > domainNameToOutputScope = new Dictionary <string, HashSet <Variable> >(); foreach (var domainName in linearDomains.Keys) { domainNameToInputScope[domainName] = new HashSet <Variable>(); domainNameToOutputScope[domainName] = new HashSet <Variable>(); } foreach (Variable v in globalVarToDomainName.Keys) { var domainName = globalVarToDomainName[v]; domainNameToInputScope[domainName].Add(v); domainNameToOutputScope[domainName].Add(v); } foreach (Variable v in proc.InParams) { var domainName = FindDomainName(v); if (domainName == null) { continue; } domainNameToInputScope[domainName].Add(v); } foreach (Variable v in proc.OutParams) { var domainName = FindDomainName(v); if (domainName == null) { continue; } domainNameToOutputScope[domainName].Add(v); } foreach (var domainName in linearDomains.Keys) { proc.Requires.Add(new Requires(true, DisjointnessExpr(domainName, domainNameToInputScope[domainName]))); var domain = linearDomains[domainName]; Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List <TypeVariable>(), new List <Type> { domain.elementType }, Type.Bool)), true); proc.InParams.Add(f); domainNameToOutputScope[domainName].Add(f); proc.Ensures.Add(new Ensures(true, DisjointnessExpr(domainName, domainNameToOutputScope[domainName]))); } } foreach (LinearDomain domain in linearDomains.Values) { program.TopLevelDeclarations.Add(domain.mapConstBool); program.TopLevelDeclarations.Add(domain.mapConstInt); program.TopLevelDeclarations.Add(domain.mapEqInt); program.TopLevelDeclarations.Add(domain.mapImpBool); program.TopLevelDeclarations.Add(domain.mapOrBool); foreach (Axiom axiom in domain.axioms) { program.TopLevelDeclarations.Add(axiom); } } //int oldPrintUnstructured = CommandLineOptions.Clo.PrintUnstructured; //CommandLineOptions.Clo.PrintUnstructured = 1; //PrintBplFile("lsd.bpl", program, false, false); //CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured; }
public override Implementation VisitImplementation(Implementation node) { if (civlTypeChecker.procToAtomicAction.ContainsKey(node.Proc) || civlTypeChecker.procToIntroductionAction.ContainsKey(node.Proc) || civlTypeChecker.procToLemmaProc.ContainsKey(node.Proc)) return node; node.PruneUnreachableBlocks(); node.ComputePredecessorsForBlocks(); GraphUtil.Graph<Block> graph = Program.GraphFromImpl(node); graph.ComputeLoops(); HashSet<Variable> start = new HashSet<Variable>(globalVarToDomainName.Keys); for (int i = 0; i < node.InParams.Count; i++) { Variable v = node.Proc.InParams[i]; string domainName = FindDomainName(v); if (domainName != null) { var kind = FindLinearKind(v); inParamToLinearQualifier[node.InParams[i]] = new LinearQualifier(domainName, kind); if (kind == LinearKind.LINEAR || kind == LinearKind.LINEAR_IN) { start.Add(node.InParams[i]); } } } for (int i = 0; i < node.OutParams.Count; i++) { string domainName = FindDomainName(node.Proc.OutParams[i]); if (domainName != null) { outParamToDomainName[node.OutParams[i]] = domainName; } } var oldErrorCount = checkingContext.ErrorCount; var impl = base.VisitImplementation(node); if (oldErrorCount < checkingContext.ErrorCount) return impl; Stack<Block> dfsStack = new Stack<Block>(); HashSet<Block> dfsStackAsSet = new HashSet<Block>(); availableLinearVars[node.Blocks[0]] = start; dfsStack.Push(node.Blocks[0]); dfsStackAsSet.Add(node.Blocks[0]); while (dfsStack.Count > 0) { Block b = dfsStack.Pop(); dfsStackAsSet.Remove(b); HashSet<Variable> end = PropagateAvailableLinearVarsAcrossBlock(b); if (b.TransferCmd is ReturnCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(end)) { Error(b.TransferCmd, $"Global variable {g.Name} must be available at a return"); } foreach (Variable v in node.InParams) { if (FindDomainName(v) == null || FindLinearKind(v) == LinearKind.LINEAR_IN || end.Contains(v)) continue; Error(b.TransferCmd, $"Input variable {v.Name} must be available at a return"); } foreach (Variable v in node.OutParams) { if (FindDomainName(v) == null || end.Contains(v)) continue; Error(b.TransferCmd, $"Output variable {v.Name} must be available at a return"); } continue; } GotoCmd gotoCmd = b.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { if (!availableLinearVars.ContainsKey(target)) { availableLinearVars[target] = new HashSet<Variable>(end); dfsStack.Push(target); dfsStackAsSet.Add(target); } else { var savedAvailableVars = new HashSet<Variable>(availableLinearVars[target]); availableLinearVars[target].IntersectWith(end); if (savedAvailableVars.IsProperSupersetOf(availableLinearVars[target]) && !dfsStackAsSet.Contains(target)) { dfsStack.Push(target); dfsStackAsSet.Add(target); } } } } if (graph.Reducible) { foreach (Block header in graph.Headers) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(availableLinearVars[header])) { Error(header, $"Global variable {g.Name} must be available at a loop head"); } } } return impl; }
private void PrepareCommon() { if (common.Length == 0) { SendCommon("(set-option :print-success false)"); SendCommon("(set-info :smt-lib-version 2.0)"); if (options.ProduceModel()) SendCommon("(set-option :produce-models true)"); foreach (var opt in options.SmtOptions) { SendCommon("(set-option :" + opt.Option + " " + opt.Value + ")"); } if (!string.IsNullOrEmpty(options.Logic)) { SendCommon("(set-logic " + options.Logic + ")"); } // Set produce-unsat-cores last. It seems there's a bug in Z3 where if we set it earlier its value // gets reset by other set-option commands ( https://z3.codeplex.com/workitem/188 ) if (CommandLineOptions.Clo.PrintNecessaryAssumes || (CommandLineOptions.Clo.ContractInfer && (CommandLineOptions.Clo.UseUnsatCoreForContractInfer || CommandLineOptions.Clo.ExplainHoudini))) { SendCommon("(set-option :produce-unsat-cores true)"); this.usingUnsatCore = true; } SendCommon("; done setting options\n"); SendCommon(_backgroundPredicates); if (options.UseTickleBool) { SendCommon("(declare-fun tickleBool (Bool) Bool)"); SendCommon("(assert (and (tickleBool true) (tickleBool false)))"); } if (CommandLineOptions.Clo.RunDiagnosticsOnTimeout) { SendCommon("(declare-fun timeoutDiagnostics (Int) Bool)"); } if (ctx.KnownDatatypeConstructors.Count > 0) { GraphUtil.Graph<CtorType> dependencyGraph = new GraphUtil.Graph<CtorType>(); foreach (CtorType datatype in ctx.KnownDatatypeConstructors.Keys) { dependencyGraph.AddSource(datatype); foreach (Function f in ctx.KnownDatatypeConstructors[datatype]) { List<CtorType> dependentTypes = new List<CtorType>(); foreach (Variable v in f.InParams) { FindDependentTypes(v.TypedIdent.Type, dependentTypes); } foreach (CtorType result in dependentTypes) { dependencyGraph.AddEdge(datatype, result); } } } GraphUtil.StronglyConnectedComponents<CtorType> sccs = new GraphUtil.StronglyConnectedComponents<CtorType>(dependencyGraph.Nodes, dependencyGraph.Predecessors, dependencyGraph.Successors); sccs.Compute(); foreach (GraphUtil.SCC<CtorType> scc in sccs) { string datatypeString = ""; foreach (CtorType datatype in scc) { datatypeString += "(" + SMTLibExprLineariser.TypeToString(datatype) + " "; foreach (Function f in ctx.KnownDatatypeConstructors[datatype]) { string quotedConstructorName = Namer.GetQuotedName(f, f.Name); if (f.InParams.Count == 0) { datatypeString += quotedConstructorName + " "; } else { datatypeString += "(" + quotedConstructorName + " "; foreach (Variable v in f.InParams) { string quotedSelectorName = Namer.GetQuotedName(v, v.Name + "#" + f.Name); datatypeString += "(" + quotedSelectorName + " " + DeclCollector.TypeToStringReg(v.TypedIdent.Type) + ") "; } datatypeString += ") "; } } datatypeString += ") "; } List<string> decls = DeclCollector.GetNewDeclarations(); foreach (string decl in decls) { SendCommon(decl); } SendCommon("(declare-datatypes () (" + datatypeString + "))"); } } if (CommandLineOptions.Clo.ProverPreamble != null) SendCommon("(include \"" + CommandLineOptions.Clo.ProverPreamble + "\")"); } if (!AxiomsAreSetup) { var axioms = ctx.Axioms; var nary = axioms as VCExprNAry; if (nary != null && nary.Op == VCExpressionGenerator.AndOp) foreach (var expr in nary.UniformArguments) { var str = VCExpr2String(expr, -1); if (str != "true") AddAxiom(str); } else AddAxiom(VCExpr2String(axioms, -1)); AxiomsAreSetup = true; } }
private void PrepareCommon() { if (common.Length == 0) { SendCommon("(set-option :print-success false)"); SendCommon("(set-info :smt-lib-version 2.0)"); if (options.ProduceModel()) SendCommon("(set-option :produce-models true)"); foreach (var opt in options.SmtOptions) { SendCommon("(set-option :" + opt.Option + " " + opt.Value + ")"); } if (!string.IsNullOrEmpty(options.Logic)) { SendCommon("(set-logic " + options.Logic + ")"); } SendCommon("; done setting options\n"); SendCommon(_backgroundPredicates); if (options.UseTickleBool) { SendCommon("(declare-fun tickleBool (Bool) Bool)"); SendCommon("(assert (and (tickleBool true) (tickleBool false)))"); } if (ctx.KnownDatatypeConstructors.Count > 0) { GraphUtil.Graph<CtorType> dependencyGraph = new GraphUtil.Graph<CtorType>(); foreach (CtorType datatype in ctx.KnownDatatypeConstructors.Keys) { dependencyGraph.AddSource(datatype); foreach (Function f in ctx.KnownDatatypeConstructors[datatype]) { List<CtorType> dependentTypes = new List<CtorType>(); foreach (Variable v in f.InParams) { FindDependentTypes(v.TypedIdent.Type, dependentTypes); } foreach (CtorType result in dependentTypes) { dependencyGraph.AddEdge(datatype, result); } } } GraphUtil.StronglyConnectedComponents<CtorType> sccs = new GraphUtil.StronglyConnectedComponents<CtorType>(dependencyGraph.Nodes, dependencyGraph.Predecessors, dependencyGraph.Successors); sccs.Compute(); foreach (GraphUtil.SCC<CtorType> scc in sccs) { string datatypeString = ""; foreach (CtorType datatype in scc) { datatypeString += "(" + SMTLibExprLineariser.TypeToString(datatype) + " "; foreach (Function f in ctx.KnownDatatypeConstructors[datatype]) { string quotedConstructorName = Namer.GetQuotedName(f, f.Name); if (f.InParams.Count == 0) { datatypeString += quotedConstructorName + " "; } else { datatypeString += "(" + quotedConstructorName + " "; foreach (Variable v in f.InParams) { string quotedSelectorName = Namer.GetQuotedName(v, v.Name + "#" + f.Name); datatypeString += "(" + quotedSelectorName + " " + DeclCollector.TypeToStringReg(v.TypedIdent.Type) + ") "; } datatypeString += ") "; } } datatypeString += ") "; } List<string> decls = DeclCollector.GetNewDeclarations(); foreach (string decl in decls) { SendCommon(decl); } SendCommon("(declare-datatypes () (" + datatypeString + "))"); } } } if (!AxiomsAreSetup) { var axioms = ctx.Axioms; var nary = axioms as VCExprNAry; if (nary != null && nary.Op == VCExpressionGenerator.AndOp) foreach (var expr in nary.UniformArguments) { var str = VCExpr2String(expr, -1); if (str != "true") AddAxiom(str); } else AddAxiom(VCExpr2String(axioms, -1)); AxiomsAreSetup = true; } }