public override Expr VisitNAryExpr(NAryExpr node) { if (node.Fun is FunctionCall) { var collector = new VariableCollector(); collector.Visit(node); functionsUsed.Add((node.Fun as FunctionCall).Func); } return base.VisitNAryExpr(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)); } }
// perform in place update of liveSet public static void Propagate(Cmd cmd, HashSet<Variable/*!*/>/*!*/ liveSet) { Contract.Requires(cmd != null); Contract.Requires(cce.NonNullElements(liveSet)); if (cmd is AssignCmd) { AssignCmd/*!*/ assignCmd = (AssignCmd)cce.NonNull(cmd); // I must first iterate over all the targets and remove the live ones. // After the removals are done, I must add the variables referred on // the right side of the removed targets AssignCmd simpleAssignCmd = assignCmd.AsSimpleAssignCmd; HashSet<int> indexSet = new HashSet<int>(); int index = 0; foreach (AssignLhs/*!*/ lhs in simpleAssignCmd.Lhss) { Contract.Assert(lhs != null); SimpleAssignLhs salhs = lhs as SimpleAssignLhs; Contract.Assert(salhs != null); Variable var = salhs.DeepAssignedVariable; if (var != null && liveSet.Contains(var)) { indexSet.Add(index); liveSet.Remove(var); } index++; } index = 0; foreach (Expr/*!*/ expr in simpleAssignCmd.Rhss) { Contract.Assert(expr != null); if (indexSet.Contains(index)) { VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(expr); liveSet.UnionWith(collector.usedVars); } index++; } } else if (cmd is HavocCmd) { HavocCmd/*!*/ havocCmd = (HavocCmd)cmd; foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) { Contract.Assert(expr != null); if (expr.Decl != null && !(QKeyValue.FindBoolAttribute(expr.Decl.Attributes, "assumption") && expr.Decl.Name.StartsWith("a##cached##"))) { liveSet.Remove(expr.Decl); } } } else if (cmd is PredicateCmd) { Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd)); PredicateCmd/*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd); if (predicateCmd.Expr is LiteralExpr) { LiteralExpr le = (LiteralExpr)predicateCmd.Expr; if (le.IsFalse) { liveSet.Clear(); } } else { VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(predicateCmd.Expr); liveSet.UnionWith(collector.usedVars); } } else if (cmd is CommentCmd) { // comments are just for debugging and don't affect verification } else if (cmd is SugaredCmd) { SugaredCmd/*!*/ sugCmd = (SugaredCmd)cce.NonNull(cmd); Propagate(sugCmd.Desugaring, liveSet); } else if (cmd is StateCmd) { StateCmd/*!*/ stCmd = (StateCmd)cce.NonNull(cmd); List<Cmd>/*!*/ cmds = cce.NonNull(stCmd.Cmds); int len = cmds.Count; for (int i = len - 1; i >= 0; i--) { Propagate(cmds[i], liveSet); } foreach (Variable/*!*/ v in stCmd.Locals) { Contract.Assert(v != null); liveSet.Remove(v); } } else { { Contract.Assert(false); throw new cce.UnreachableException(); } } }
public override Expr VisitNAryExpr(NAryExpr node) { if (node.Fun is FunctionCall) { var collector = new VariableCollector(); collector.Visit(node); if(existentialExpr != null && existentialExpr.Dummies.Intersect(collector.usedVars).Any()) functionsUsed.Add(Tuple.Create((node.Fun as FunctionCall).Func, existentialExpr)); else functionsUsed.Add(Tuple.Create<Function, ExistsExpr>((node.Fun as FunctionCall).Func, null)); } return base.VisitNAryExpr(node); }
private static GenKillWeight getWeightAfterCall(Cmd cmd) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<GenKillWeight>() != null); if (weightCacheAfterCall.ContainsKey(cmd)) return weightCacheAfterCall[cmd]; HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>(); HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>(); Contract.Assert(cmd is CallCmd); CallCmd/*!*/ ccmd = cce.NonNull((CallCmd)cmd); foreach (IdentifierExpr/*!*/ ie in ccmd.Outs) { Contract.Assert(ie != null); if (ie.Decl != null) kill.Add(ie.Decl); } // Variables in ensures are considered as "read" foreach (Ensures/*!*/ re in cce.NonNull(ccmd.Proc).Ensures) { Contract.Assert(re != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(re.Condition); foreach (Variable/*!*/ v in collector.usedVars) { Contract.Assert(v != null); if (v is GlobalVariable) { gen.Add(v); } } } GenKillWeight/*!*/ ret = new GenKillWeight(gen, kill); Contract.Assert(ret != null); weightCacheAfterCall[cmd] = ret; return ret; }
private static GenKillWeight getWeightBeforeCall(Cmd cmd) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<GenKillWeight>() != null); Contract.Assert((cmd is CallCmd)); if (weightCacheBeforeCall.ContainsKey(cmd)) return weightCacheBeforeCall[cmd]; HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>(); HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>(); CallCmd/*!*/ ccmd = cce.NonNull((CallCmd/*!*/)cmd); foreach (Expr/*!*/ expr in ccmd.Ins) { Contract.Assert(expr != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(expr); gen.UnionWith(collector.usedVars); } Contract.Assert(ccmd.Proc != null); // Variables in requires are considered as "read" foreach (Requires/*!*/ re in ccmd.Proc.Requires) { Contract.Assert(re != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(re.Condition); foreach (Variable/*!*/ v in collector.usedVars) { Contract.Assert(v != null); if (v is GlobalVariable) { gen.Add(v); } } } // Old variables in ensures are considered as "read" foreach (Ensures/*!*/ re in ccmd.Proc.Ensures) { Contract.Assert(re != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(re.Condition); foreach (Variable/*!*/ v in collector.oldVarsUsed) { Contract.Assert(v != null); if (v is GlobalVariable) { gen.Add(v); } } } GenKillWeight/*!*/ ret = new GenKillWeight(gen, kill); Contract.Assert(ret != null); weightCacheAfterCall[cmd] = ret; return ret; }
private static GenKillWeight getWeight(Cmd cmd, Implementation impl, Program prog) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<GenKillWeight>() != null); if (weightCache.ContainsKey(cmd)) return weightCache[cmd]; HashSet<Variable/*!*/>/*!*/ gen = new HashSet<Variable/*!*/>(); HashSet<Variable/*!*/>/*!*/ kill = new HashSet<Variable/*!*/>(); GenKillWeight/*!*/ ret; if (cmd is AssignCmd) { AssignCmd/*!*/ assignCmd = (AssignCmd)cmd; Contract.Assert(cmd != null); // I must first iterate over all the targets and remove the live ones. // After the removals are done, I must add the variables referred on // the right side of the removed targets foreach (AssignLhs/*!*/ lhs in assignCmd.Lhss) { Contract.Assert(lhs != null); Variable var = lhs.DeepAssignedVariable; if (var != null) { if (lhs is SimpleAssignLhs) { // we should only remove non-map target variables because there is an implicit // read of a map variable in an assignment to it kill.Add(var); } } } int index = 0; foreach (Expr/*!*/ expr in assignCmd.Rhss) { Contract.Assert(expr != null); VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(expr); gen.UnionWith(collector.usedVars); AssignLhs lhs = assignCmd.Lhss[index]; if (lhs is MapAssignLhs) { // If the target is a map, then all indices are also read MapAssignLhs malhs = (MapAssignLhs)lhs; foreach (Expr e in malhs.Indexes) { VariableCollector/*!*/ c = new VariableCollector(); c.Visit(e); gen.UnionWith(c.usedVars); } } index++; } ret = new GenKillWeight(gen, kill); } else if (cmd is HavocCmd) { HavocCmd/*!*/ havocCmd = (HavocCmd)cce.NonNull(cmd); foreach (IdentifierExpr/*!*/ expr in havocCmd.Vars) { Contract.Assert(expr != null); if (expr.Decl != null) { kill.Add(expr.Decl); } } ret = new GenKillWeight(gen, kill); } else if (cmd is PredicateCmd) { Contract.Assert((cmd is AssertCmd || cmd is AssumeCmd)); PredicateCmd/*!*/ predicateCmd = (PredicateCmd)cce.NonNull(cmd); if (predicateCmd.Expr is LiteralExpr && prog != null && impl != null) { LiteralExpr le = (LiteralExpr)predicateCmd.Expr; if (le.IsFalse) { var globals = prog.GlobalVariables; Contract.Assert(cce.NonNullElements(globals)); foreach (Variable/*!*/ v in globals) { Contract.Assert(v != null); kill.Add(v); } foreach (Variable/*!*/ v in impl.LocVars) { Contract.Assert(v != null); kill.Add(v); } foreach (Variable/*!*/ v in impl.OutParams) { Contract.Assert(v != null); kill.Add(v); } } } else { VariableCollector/*!*/ collector = new VariableCollector(); collector.Visit(predicateCmd.Expr); gen.UnionWith(collector.usedVars); } ret = new GenKillWeight(gen, kill); } else if (cmd is CommentCmd) { ret = new GenKillWeight(gen, kill); // comments are just for debugging and don't affect verification } else if (cmd is SugaredCmd) { SugaredCmd/*!*/ sugCmd = (SugaredCmd)cmd; Contract.Assert(sugCmd != null); ret = getWeight(sugCmd.Desugaring, impl, prog); } else if (cmd is StateCmd) { StateCmd/*!*/ stCmd = (StateCmd)cmd; Contract.Assert(stCmd != null); List<Cmd>/*!*/ cmds = stCmd.Cmds; Contract.Assert(cmds != null); int len = cmds.Count; ret = GenKillWeight.one(); for (int i = len - 1; i >= 0; i--) { GenKillWeight/*!*/ w = getWeight(cmds[i], impl, prog); Contract.Assert(w != null); ret = GenKillWeight.extend(w, ret); } foreach (Variable/*!*/ v in stCmd.Locals) { Contract.Assert(v != null); kill.Add(v); } ret = GenKillWeight.extend(new GenKillWeight(gen, kill), ret); } else { { Contract.Assert(false); throw new cce.UnreachableException(); } } weightCache[cmd] = ret; return ret; }
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)); } }
private IEnumerable<VariableDescriptor> GetReferencedVariables(Absy node, string proc) { var VarCollector = new VariableCollector(); VarCollector.Visit(node); return VarCollector.usedVars.Where(Item => VariableRelevantToAnalysis(Item, proc)). Select(Item => MakeDescriptor(proc, Item)); }
void CreateProceduresForLoops(Implementation impl, Graph<Block/*!*/>/*!*/ g, List<Implementation/*!*/>/*!*/ loopImpls, Dictionary<string, Dictionary<string, Block>> fullMap) { Contract.Requires(impl != null); Contract.Requires(cce.NonNullElements(loopImpls)); // Enumerate the headers // for each header h: // create implementation p_h with // inputs = inputs, outputs, and locals of impl // outputs = outputs and locals of impl // locals = empty set // add call o := p_h(i) at the beginning of the header block // break the back edges whose target is h // Enumerate the headers again to create the bodies of p_h // for each header h: // compute the loop corresponding to h // make copies of all blocks in the loop for h // delete all target edges that do not go to a block in the loop // create a new entry block and a new return block // add edges from entry block to the loop header and the return block // add calls o := p_h(i) at the end of the blocks that are sources of back edges foreach (Block block in impl.Blocks) { AddToFullMap(fullMap, impl.Name, block.Label, block); } bool detLoopExtract = CommandLineOptions.Clo.DeterministicExtractLoops; Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToInputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>(); Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToOutputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>(); Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>/*!*/ loopHeaderToSubstMap = new Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>(); Dictionary<Block/*!*/, LoopProcedure/*!*/>/*!*/ loopHeaderToLoopProc = new Dictionary<Block/*!*/, LoopProcedure/*!*/>(); Dictionary<Block/*!*/, CallCmd/*!*/>/*!*/ loopHeaderToCallCmd1 = new Dictionary<Block/*!*/, CallCmd/*!*/>(); Dictionary<Block, CallCmd> loopHeaderToCallCmd2 = new Dictionary<Block, CallCmd>(); Dictionary<Block, AssignCmd> loopHeaderToAssignCmd = new Dictionary<Block, AssignCmd>(); foreach (Block/*!*/ header in g.Headers) { Contract.Assert(header != null); Contract.Assert(header != null); List<Variable> inputs = new List<Variable>(); List<Variable> outputs = new List<Variable>(); List<Expr> callInputs1 = new List<Expr>(); List<IdentifierExpr> callOutputs1 = new List<IdentifierExpr>(); List<Expr> callInputs2 = new List<Expr>(); List<IdentifierExpr> callOutputs2 = new List<IdentifierExpr>(); List<AssignLhs> lhss = new List<AssignLhs>(); List<Expr> rhss = new List<Expr>(); Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); // Variable -> IdentifierExpr List<Variable>/*!*/ targets = new List<Variable>(); HashSet<Variable> footprint = new HashSet<Variable>(); foreach (Block/*!*/ b in g.BackEdgeNodes(header)) { Contract.Assert(b != null); foreach (Block/*!*/ block in g.NaturalLoops(header, b)) { Contract.Assert(block != null); foreach (Cmd/*!*/ cmd in block.Cmds) { Contract.Assert(cmd != null); cmd.AddAssignedVariables(targets); VariableCollector c = new VariableCollector(); c.Visit(cmd); footprint.UnionWith(c.usedVars); } } } List<IdentifierExpr>/*!*/ globalMods = new List<IdentifierExpr>(); Set targetSet = new Set(); foreach (Variable/*!*/ v in targets) { Contract.Assert(v != null); if (targetSet.Contains(v)) continue; targetSet.Add(v); if (v is GlobalVariable) globalMods.Add(new IdentifierExpr(Token.NoToken, v)); } foreach (Variable v in impl.InParams) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f); callInputs2.Add(new IdentifierExpr(Token.NoToken, f)); substMap[v] = new IdentifierExpr(Token.NoToken, f); } foreach (Variable v in impl.OutParams) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f1); if (targetSet.Contains(v)) { callOutputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false); outputs.Add(f2); callInputs2.Add(new IdentifierExpr(Token.NoToken, f2)); callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2)); lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2))); rhss.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f2); } else { callInputs2.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f1); } } foreach (Variable v in impl.LocVars) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f1); if (targetSet.Contains(v)) { callOutputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false); outputs.Add(f2); callInputs2.Add(new IdentifierExpr(Token.NoToken, f2)); callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2)); lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2))); rhss.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f2); } else { callInputs2.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f1); } } loopHeaderToInputs[header] = inputs; loopHeaderToOutputs[header] = outputs; loopHeaderToSubstMap[header] = substMap; LoopProcedure loopProc = new LoopProcedure(impl, header, inputs, outputs, globalMods); loopHeaderToLoopProc[header] = loopProc; CallCmd callCmd1 = new CallCmd(Token.NoToken, loopProc.Name, callInputs1, callOutputs1); callCmd1.Proc = loopProc; loopHeaderToCallCmd1[header] = callCmd1; CallCmd callCmd2 = new CallCmd(Token.NoToken, loopProc.Name, callInputs2, callOutputs2); callCmd2.Proc = loopProc; loopHeaderToCallCmd2[header] = callCmd2; Debug.Assert(lhss.Count == rhss.Count); if (lhss.Count > 0) { AssignCmd assignCmd = new AssignCmd(Token.NoToken, lhss, rhss); loopHeaderToAssignCmd[header] = assignCmd; } } // Keep track of the new blocks created: maps a header node to the // header_last block that was created because of splitting header. Dictionary<Block, Block> newBlocksCreated = new Dictionary<Block, Block>(); bool headRecursion = false; // testing an option to put recursive call before loop body IEnumerable<Block> sortedHeaders = g.SortHeadersByDominance(); foreach (Block/*!*/ header in sortedHeaders) { Contract.Assert(header != null); LoopProcedure loopProc = loopHeaderToLoopProc[header]; Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>(); HashSet<string> dummyBlocks = new HashSet<string>(); CodeCopier codeCopier = new CodeCopier(loopHeaderToSubstMap[header]); // fix me List<Variable> inputs = loopHeaderToInputs[header]; List<Variable> outputs = loopHeaderToOutputs[header]; int si_unique_loc = 1; // Added by AL: to distinguish the back edges foreach (Block/*!*/ source in g.BackEdgeNodes(header)) { Contract.Assert(source != null); foreach (Block/*!*/ block in g.NaturalLoops(header, source)) { Contract.Assert(block != null); if (blockMap.ContainsKey(block)) continue; Block newBlock = new Block(); newBlock.Label = block.Label; if (headRecursion && block == header) { CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone(); addUniqueCallAttr(si_unique_loc, callCmd); si_unique_loc++; newBlock.Cmds.Add(callCmd); // add the recursive call at head of loop var rest = codeCopier.CopyCmdSeq(block.Cmds); newBlock.Cmds.AddRange(rest); } else newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds); blockMap[block] = newBlock; if (newBlocksCreated.ContainsKey(block)) { Block newBlock2 = new Block(); newBlock2.Label = newBlocksCreated[block].Label; newBlock2.Cmds = codeCopier.CopyCmdSeq(newBlocksCreated[block].Cmds); blockMap[newBlocksCreated[block]] = newBlock2; } //for detLoopExtract, need the immediate successors even outside the loop if (detLoopExtract) { GotoCmd auxGotoCmd = block.TransferCmd as GotoCmd; Contract.Assert(auxGotoCmd != null && auxGotoCmd.labelNames != null && auxGotoCmd.labelTargets != null && auxGotoCmd.labelTargets.Count >= 1); foreach(var bl in auxGotoCmd.labelTargets) { bool found = false; foreach(var n in g.NaturalLoops(header, source)) { //very expensive, can we do a contains? if (bl == n) { //clarify: is this the right comparison? found = true; break; } } if (!found) { Block auxNewBlock = new Block(); auxNewBlock.Label = ((Block)bl).Label; auxNewBlock.Cmds = codeCopier.CopyCmdSeq(((Block)bl).Cmds); //add restoration code for such blocks if (loopHeaderToAssignCmd.ContainsKey(header)) { AssignCmd assignCmd = loopHeaderToAssignCmd[header]; auxNewBlock.Cmds.Add(assignCmd); } List<AssignLhs> lhsg = new List<AssignLhs>(); List<IdentifierExpr>/*!*/ globalsMods = loopHeaderToLoopProc[header].Modifies; foreach (IdentifierExpr gl in globalsMods) lhsg.Add(new SimpleAssignLhs(Token.NoToken, gl)); List<Expr> rhsg = new List<Expr>(); foreach (IdentifierExpr gl in globalsMods) rhsg.Add(new OldExpr(Token.NoToken, gl)); if (lhsg.Count != 0) { AssignCmd globalAssignCmd = new AssignCmd(Token.NoToken, lhsg, rhsg); auxNewBlock.Cmds.Add(globalAssignCmd); } blockMap[(Block)bl] = auxNewBlock; } } } } List<Cmd> cmdSeq; if (headRecursion) cmdSeq = new List<Cmd>(); else { CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone(); addUniqueCallAttr(si_unique_loc, callCmd); si_unique_loc++; cmdSeq = new List<Cmd> { callCmd }; } Block/*!*/ block1 = new Block(Token.NoToken, source.Label + "_dummy", new List<Cmd>{ new AssumeCmd(Token.NoToken, Expr.False) }, new ReturnCmd(Token.NoToken)); Block/*!*/ block2 = new Block(Token.NoToken, block1.Label, cmdSeq, new ReturnCmd(Token.NoToken)); impl.Blocks.Add(block1); dummyBlocks.Add(block1.Label); GotoCmd gotoCmd = source.TransferCmd as GotoCmd; Contract.Assert(gotoCmd != null && gotoCmd.labelNames != null && gotoCmd.labelTargets != null && gotoCmd.labelTargets.Count >= 1); List<String>/*!*/ newLabels = new List<String>(); List<Block>/*!*/ newTargets = new List<Block>(); for (int i = 0; i < gotoCmd.labelTargets.Count; i++) { if (gotoCmd.labelTargets[i] == header) continue; newTargets.Add(gotoCmd.labelTargets[i]); newLabels.Add(gotoCmd.labelNames[i]); } newTargets.Add(block1); newLabels.Add(block1.Label); gotoCmd.labelNames = newLabels; gotoCmd.labelTargets = newTargets; blockMap[block1] = block2; } List<Block/*!*/>/*!*/ blocks = new List<Block/*!*/>(); Block exit = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken)); GotoCmd cmd = new GotoCmd(Token.NoToken, new List<String> { cce.NonNull(blockMap[header]).Label, exit.Label }, new List<Block> { blockMap[header], exit }); if (detLoopExtract) //cutting the non-determinism cmd = new GotoCmd(Token.NoToken, new List<String> { cce.NonNull(blockMap[header]).Label }, new List<Block> { blockMap[header] }); Block entry; List<Cmd> initCmds = new List<Cmd>(); if (loopHeaderToAssignCmd.ContainsKey(header)) { AssignCmd assignCmd = loopHeaderToAssignCmd[header]; initCmds.Add(assignCmd); } entry = new Block(Token.NoToken, "entry", initCmds, cmd); blocks.Add(entry); foreach (Block/*!*/ block in blockMap.Keys) { Contract.Assert(block != null); Block/*!*/ newBlock = cce.NonNull(blockMap[block]); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; if (gotoCmd == null) { newBlock.TransferCmd = new ReturnCmd(Token.NoToken); } else { Contract.Assume(gotoCmd.labelNames != null && gotoCmd.labelTargets != null); List<String> newLabels = new List<String>(); List<Block> newTargets = new List<Block>(); for (int i = 0; i < gotoCmd.labelTargets.Count; i++) { Block target = gotoCmd.labelTargets[i]; if (blockMap.ContainsKey(target)) { newLabels.Add(gotoCmd.labelNames[i]); newTargets.Add(blockMap[target]); } } if (newTargets.Count == 0) { if (!detLoopExtract) newBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False)); newBlock.TransferCmd = new ReturnCmd(Token.NoToken); } else { newBlock.TransferCmd = new GotoCmd(Token.NoToken, newLabels, newTargets); } } blocks.Add(newBlock); } blocks.Add(exit); Implementation loopImpl = new Implementation(Token.NoToken, loopProc.Name, new List<TypeVariable>(), inputs, outputs, new List<Variable>(), blocks); loopImpl.Proc = loopProc; loopImpls.Add(loopImpl); // Make a (shallow) copy of the header before splitting it Block origHeader = new Block(header.tok, header.Label, header.Cmds, header.TransferCmd); // Finally, add call to the loop in the containing procedure string lastIterBlockName = header.Label + "_last"; Block lastIterBlock = new Block(Token.NoToken, lastIterBlockName, header.Cmds, header.TransferCmd); newBlocksCreated[header] = lastIterBlock; header.Cmds = new List<Cmd> { loopHeaderToCallCmd1[header] }; header.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { lastIterBlockName }, new List<Block> { lastIterBlock }); impl.Blocks.Add(lastIterBlock); blockMap[origHeader] = blockMap[header]; blockMap.Remove(header); Contract.Assert(fullMap[impl.Name][header.Label] == header); fullMap[impl.Name][header.Label] = origHeader; foreach (Block block in blockMap.Keys) { // Don't add dummy blocks to the map if (dummyBlocks.Contains(blockMap[block].Label)) continue; // Following two statements are for nested loops: compose map if (!fullMap[impl.Name].ContainsKey(block.Label)) continue; var target = fullMap[impl.Name][block.Label]; AddToFullMap(fullMap, loopProc.Name, blockMap[block].Label, target); } fullMap[impl.Name].Remove(header.Label); fullMap[impl.Name][lastIterBlockName] = origHeader; } }
public static IEnumerable<Variable> Collect(Absy node) { var collector = new VariableCollector(); collector.Visit(node); return collector.usedVars; }