loops.go 989 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package functions
  2. import "honnef.co/go/tools/ssa"
  3. type Loop struct{ ssa.BlockSet }
  4. func FindLoops(fn *ssa.Function) []Loop {
  5. if fn.Blocks == nil {
  6. return nil
  7. }
  8. tree := fn.DomPreorder()
  9. var sets []Loop
  10. for _, h := range tree {
  11. for _, n := range h.Preds {
  12. if !h.Dominates(n) {
  13. continue
  14. }
  15. // n is a back-edge to h
  16. // h is the loop header
  17. if n == h {
  18. set := Loop{}
  19. set.Add(n)
  20. sets = append(sets, set)
  21. continue
  22. }
  23. set := Loop{}
  24. set.Add(h)
  25. set.Add(n)
  26. for _, b := range allPredsBut(n, h, nil) {
  27. set.Add(b)
  28. }
  29. sets = append(sets, set)
  30. }
  31. }
  32. return sets
  33. }
  34. func allPredsBut(b, but *ssa.BasicBlock, list []*ssa.BasicBlock) []*ssa.BasicBlock {
  35. outer:
  36. for _, pred := range b.Preds {
  37. if pred == but {
  38. continue
  39. }
  40. for _, p := range list {
  41. // TODO improve big-o complexity of this function
  42. if pred == p {
  43. continue outer
  44. }
  45. }
  46. list = append(list, pred)
  47. list = allPredsBut(pred, but, list)
  48. }
  49. return list
  50. }