aboutsummaryrefslogtreecommitdiff
path: root/vendor/honnef.co/go/tools/functions/loops.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/honnef.co/go/tools/functions/loops.go')
-rw-r--r--vendor/honnef.co/go/tools/functions/loops.go50
1 files changed, 50 insertions, 0 deletions
diff --git a/vendor/honnef.co/go/tools/functions/loops.go b/vendor/honnef.co/go/tools/functions/loops.go
new file mode 100644
index 0000000..63011cf
--- /dev/null
+++ b/vendor/honnef.co/go/tools/functions/loops.go
@@ -0,0 +1,50 @@
+package functions
+
+import "honnef.co/go/tools/ssa"
+
+type Loop map[*ssa.BasicBlock]bool
+
+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 {
+ sets = append(sets, Loop{n: true})
+ continue
+ }
+ set := Loop{h: true, n: true}
+ for _, b := range allPredsBut(n, h, nil) {
+ set[b] = true
+ }
+ 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
+}