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; }