ssautil.go 985 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package ssautil
  2. import (
  3. "honnef.co/go/tools/ssa"
  4. )
  5. func Reachable(from, to *ssa.BasicBlock) bool {
  6. if from == to {
  7. return true
  8. }
  9. if from.Dominates(to) {
  10. return true
  11. }
  12. found := false
  13. Walk(from, func(b *ssa.BasicBlock) bool {
  14. if b == to {
  15. found = true
  16. return false
  17. }
  18. return true
  19. })
  20. return found
  21. }
  22. func Walk(b *ssa.BasicBlock, fn func(*ssa.BasicBlock) bool) {
  23. seen := map[*ssa.BasicBlock]bool{}
  24. wl := []*ssa.BasicBlock{b}
  25. for len(wl) > 0 {
  26. b := wl[len(wl)-1]
  27. wl = wl[:len(wl)-1]
  28. if seen[b] {
  29. continue
  30. }
  31. seen[b] = true
  32. if !fn(b) {
  33. continue
  34. }
  35. wl = append(wl, b.Succs...)
  36. }
  37. }
  38. func Vararg(x *ssa.Slice) ([]ssa.Value, bool) {
  39. var out []ssa.Value
  40. slice, ok := x.X.(*ssa.Alloc)
  41. if !ok || slice.Comment != "varargs" {
  42. return nil, false
  43. }
  44. for _, ref := range *slice.Referrers() {
  45. idx, ok := ref.(*ssa.IndexAddr)
  46. if !ok {
  47. continue
  48. }
  49. v := (*idx.Referrers())[0].(*ssa.Store).Val
  50. out = append(out, v)
  51. }
  52. return out, true
  53. }