| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- package functions
- import "honnef.co/go/tools/ssa"
- type Loop struct{ ssa.BlockSet }
- func FindLoops(fn *ssa.Function) []Loop {
- if fn.Blocks == nil {
- return nil
- }
- tree := fn.DomPreorder()
- var sets []Loop
- for _, h := range tree {
- for _, n := range h.Preds {
- if !h.Dominates(n) {
- continue
- }
- // n is a back-edge to h
- // h is the loop header
- if n == h {
- set := Loop{}
- set.Add(n)
- sets = append(sets, set)
- continue
- }
- set := Loop{}
- set.Add(h)
- set.Add(n)
- for _, b := range allPredsBut(n, h, nil) {
- set.Add(b)
- }
- sets = append(sets, set)
- }
- }
- return sets
- }
- func allPredsBut(b, but *ssa.BasicBlock, list []*ssa.BasicBlock) []*ssa.BasicBlock {
- outer:
- for _, pred := range b.Preds {
- if pred == but {
- continue
- }
- for _, p := range list {
- // TODO improve big-o complexity of this function
- if pred == p {
- continue outer
- }
- }
- list = append(list, pred)
- list = allPredsBut(pred, but, list)
- }
- return list
- }
|