private static Graph <MoverProc> ConstructMoverProcedureCallGraph(CivlTypeChecker civlTypeChecker) { var moverProcedureCallGraph = new Graph <MoverProc>(); foreach (var impl in civlTypeChecker.program.Implementations.Where(impl => civlTypeChecker.procToYieldingProc.ContainsKey(impl.Proc))) { MoverProc callerProc = civlTypeChecker.procToYieldingProc[impl.Proc] as MoverProc; if (callerProc == null) { continue; } foreach (var callCmd in impl.Blocks.SelectMany(b => b.Cmds).OfType <CallCmd>()) { if (civlTypeChecker.procToYieldingProc.ContainsKey(callCmd.Proc)) { MoverProc calleeProc = civlTypeChecker.procToYieldingProc[callCmd.Proc] as MoverProc; if (calleeProc == null) { continue; } Debug.Assert(callerProc.upperLayer == calleeProc.upperLayer); moverProcedureCallGraph.AddEdge(callerProc, calleeProc); } } } return(moverProcedureCallGraph); }
private bool IsRecursiveMoverProcedureCall(CallCmd call) { MoverProc source = null; if (civlTypeChecker.procToYieldingProc.ContainsKey(call.Proc)) { source = civlTypeChecker.procToYieldingProc[call.Proc] as MoverProc; } if (source == null) { return(false); } MoverProc target = (MoverProc)yieldingProc; HashSet <MoverProc> frontier = new HashSet <MoverProc> { source }; HashSet <MoverProc> visited = new HashSet <MoverProc>(); while (frontier.Count > 0) { var curr = frontier.First(); frontier.Remove(curr); visited.Add(curr); if (curr == target) { return(true); } frontier.UnionWith(moverProcedureCallGraph.Successors(curr).Except(visited)); } return(false); }
public void TypeCheck() { // Mover procedures can only call other mover procedures on the same layer. // Thus, the constructed call graph naturally forms disconnected components w.r.t. layers and we // can keep a single graph instead of one for each layer; foreach (var impl in civlTypeChecker.program.Implementations.Where(impl => civlTypeChecker.procToYieldingProc.ContainsKey(impl.Proc))) { MoverProc callerProc = civlTypeChecker.procToYieldingProc[impl.Proc] as MoverProc; if (callerProc == null) { continue; } foreach (var callCmd in impl.Blocks.SelectMany(b => b.Cmds).OfType <CallCmd>()) { if (civlTypeChecker.procToYieldingProc.ContainsKey(callCmd.Proc)) { MoverProc calleeProc = civlTypeChecker.procToYieldingProc[callCmd.Proc] as MoverProc; if (calleeProc == null) { continue; } Debug.Assert(callerProc.upperLayer == calleeProc.upperLayer); moverProcedureCallGraph.AddEdge(callerProc, calleeProc); } } } foreach (var impl in civlTypeChecker.program.Implementations.Where(impl => civlTypeChecker.procToYieldingProc.ContainsKey(impl.Proc))) { var yieldingProc = civlTypeChecker.procToYieldingProc[impl.Proc]; impl.PruneUnreachableBlocks(); Graph <Block> implGraph = Program.GraphFromImpl(impl); implGraph.ComputeLoops(); foreach (int layerNum in civlTypeChecker.allRefinementLayers.Where(l => l <= yieldingProc.upperLayer)) { PerLayerYieldSufficiencyTypeChecker perLayerSufficiencyTypeChecker = new PerLayerYieldSufficiencyTypeChecker(this, yieldingProc, impl, layerNum, implGraph); perLayerSufficiencyTypeChecker.TypeCheckLayer(); } } // To allow garbage collection moverProcedureCallGraph = null; }