/// <summary> /// Принимает Граф потока данных и по нему ищет все естественные циклы /// </summary> /// <param name="cfg">Граф потока управления</param> /// <returns> /// Вернет все натуральные циклы /// </returns> public static IReadOnlyList <IReadOnlyList <BasicBlock> > GetAllNaturalLoops(ControlFlowGraph cfg) { if (cfg.IsReducibleGraph()) { var natLoops = new List <List <BasicBlock> >(); var ForwardEdges = cfg.GetCurrentBasicBlocks(); foreach (var(From, To) in cfg.GetBackEdges()) { if (cfg.VertexOf(To) > 0) { var tmp = new List <BasicBlock>(); for (var i = cfg.VertexOf(To); i < cfg.VertexOf(From) + 1; i++) { if (!tmp.Contains(ForwardEdges[i])) { tmp.Add(ForwardEdges[i]); } } natLoops.Add(tmp); } } return(natLoops.Where(loop => IsNaturalLoop(loop, cfg)).ToList()); } else { Console.WriteLine("Граф не приводим"); return(new List <List <BasicBlock> >()); } }
private bool IsUsedInOtherBlocks( ControlFlowGraph graph, BasicBlock blockWithDefinition, Instruction definitionToCheck, Dictionary <BasicBlock, HashSet <string> > usedVars, InOutInfo info) { var queue = new Queue <BasicBlock>(); queue.Enqueue(blockWithDefinition); while (queue.Count != 0) { var block = queue.Dequeue(); foreach (var child in graph.GetChildrenBasicBlocks(graph.VertexOf(block)).Select(z => z.block)) { var isRewritten = !info[child].Out.Contains(definitionToCheck); var isUsed = usedVars[block].Contains(definitionToCheck.Result); if (!isRewritten) { if (isUsed) { return(true); } else { queue.Enqueue(child); } } else { if (!isUsed) { continue; } else { // we need to check instructions before definitionToCheck is rewritten foreach (var instruction in child.GetInstructions()) { if (instruction.Argument1 == definitionToCheck.Result || instruction.Argument2 == definitionToCheck.Result) { return(true); } if (instruction.Result == definitionToCheck.Result) { break; } } } } } } return(false); }
/// <summary> /// Првоерка цикла на естественность /// </summary> /// <param name="loop">Проверяемый цикл</param> /// <param name="cfg">Граф потока управления</param> /// <returns> /// Вернет флаг, естественнен ли он /// </returns> private static bool IsNaturalLoop(IReadOnlyCollection <BasicBlock> loop, ControlFlowGraph cfg) { foreach (var bblock in loop.Skip(1)) { var parents = cfg.GetParentsBasicBlocks(cfg.VertexOf(bblock)); if (parents.Count > 1) { foreach (var parent in parents.Select(x => x.block)) { if (!loop.Contains(parent)) { return(false); } } } } return(true); }
/// <summary> /// Првоерка цикла на естественность /// </summary> /// <param name="loop">Проверяемый цикл</param> /// <param name="cfg">Граф потока управления</param> /// <returns> /// Вернет флаг, естественнен ли он /// </returns> private static bool IsNaturalLoop(List <BasicBlock> loop, ControlFlowGraph cfg) { for (var i = 1; i < loop.Count; i++) { var parents = cfg.GetParentsBasicBlocks(cfg.VertexOf(loop[i])); if (parents.Count > 1) { foreach (var parent in parents.Select(x => x.block)) { if (!loop.Contains(parent)) { return(false); } } } } return(true); }
public INsOUTs ExecuteNonGeneric(ControlFlowGraph g) { var blocks = g.GetCurrentBasicBlocks(); var INs = new Dictionary <BasicBlock, Dictionary <string, LatticeValue> >(); var OUTs = new Dictionary <BasicBlock, Dictionary <string, LatticeValue> >(); var variables = new HashSet <string>(); foreach (var block in blocks) { foreach (var instr in block.GetInstructions()) { if (checkStr(instr.Result) && !variables.Contains(instr.Result)) { variables.Add(instr.Result); } if (checkStr(instr.Argument1) && instr.Argument1 != "True" && instr.Argument1 != "False" && !int.TryParse(instr.Argument1, out var temp1) && !variables.Contains(instr.Argument1)) { variables.Add(instr.Argument1); } if (checkStr(instr.Argument2) && instr.Argument2 != "True" && instr.Argument2 != "False" && !int.TryParse(instr.Argument2, out var temp2) && !variables.Contains(instr.Argument2)) { variables.Add(instr.Argument2); } } } var temp = new Dictionary <string, LatticeValue>(); foreach (var elem in variables) { temp.Add(elem, new LatticeValue(LatticeTypeData.UNDEF)); } foreach (var block in blocks) { INs.Add(block, temp.ToDictionary(entry => entry.Key, entry => entry.Value)); OUTs.Add(block, temp.ToDictionary(entry => entry.Key, entry => entry.Value)); } var Changed = true; while (Changed) { Changed = false; foreach (var block in blocks) { var parents = g.GetParentsBasicBlocks(g.VertexOf(block)).Select(x => x.block); INs[block] = parents.Select(x => OUTs[x]) .Aggregate(temp.ToDictionary(entry => entry.Key, entry => entry.Value), (x, y) => Collect(x, y)); var newOut = Transfer(block, INs[block]); if (OUTs[block].Where(entry => newOut[entry.Key] != entry.Value).Any()) { Changed = true; OUTs[block] = newOut; } } } return(new INsOUTs { IN = INs, OUT = OUTs }); }