public BBLoop(BasicBlock head, BasicBlock tail, IMSet <BasicBlock> body, JST.Identifier label) { Head = head; Tail = tail; Body = body; Label = label; var headEscapes = false; var headbranchbb = head as BranchBasicBlock; foreach (var t in head.Targets) { if (!body.Contains(t)) { headEscapes = true; } } var tailEscapes = false; var tailbranchbb = tail as BranchBasicBlock; foreach (var t in tail.Targets) { if (!body.Contains(t)) { tailEscapes = true; } } if (!headEscapes && tailEscapes && tailbranchbb != null) { if (tailbranchbb.Target.Equals(head)) { Flavor = LoopFlavor.DoWhile; } else if (tailbranchbb.Fallthrough.Equals(head)) { Flavor = LoopFlavor.FlippedDoWhile; } else { throw new InvalidOperationException("invalid loop"); } } else if (headEscapes && !tailEscapes && headbranchbb != null) { if (body.Contains(headbranchbb.Target)) { Flavor = LoopFlavor.WhileDo; } else if (body.Contains(headbranchbb.Fallthrough)) { Flavor = LoopFlavor.FlippedWhileDo; } else { throw new InvalidOperationException("invalid loop"); } } else if (!headEscapes && !tailEscapes) { Flavor = LoopFlavor.Loop; } else if (headEscapes && tailEscapes && headbranchbb != null && tailbranchbb != null) { // Could encode as do-while with a break at start, or while-do with a break at end. if (body.Contains(headbranchbb.Target)) { Flavor = LoopFlavor.WhileDo; } else if (body.Contains(headbranchbb.Fallthrough)) { Flavor = LoopFlavor.FlippedWhileDo; } else { throw new InvalidOperationException("invalid loop"); } } else { Flavor = LoopFlavor.Unknown; } }