.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.1.1 / go / ir / irutil / loops.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/go/ir/irutil/loops.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/go/ir/irutil/loops.go
new file mode 100644 (file)
index 0000000..751cc68
--- /dev/null
@@ -0,0 +1,54 @@
+package irutil
+
+import "honnef.co/go/tools/go/ir"
+
+type Loop struct{ *ir.BlockSet }
+
+func FindLoops(fn *ir.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{ir.NewBlockSet(len(fn.Blocks))}
+                               set.Add(n)
+                               sets = append(sets, set)
+                               continue
+                       }
+                       set := Loop{ir.NewBlockSet(len(fn.Blocks))}
+                       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 *ir.BasicBlock, list []*ir.BasicBlock) []*ir.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
+}