slice.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. package vrp
  2. // TODO(dh): most of the constraints have implementations identical to
  3. // that of strings. Consider reusing them.
  4. import (
  5. "fmt"
  6. "go/types"
  7. "honnef.co/go/tools/ssa"
  8. )
  9. type SliceInterval struct {
  10. Length IntInterval
  11. }
  12. func (s SliceInterval) Union(other Range) Range {
  13. i, ok := other.(SliceInterval)
  14. if !ok {
  15. i = SliceInterval{EmptyIntInterval}
  16. }
  17. if s.Length.Empty() || !s.Length.IsKnown() {
  18. return i
  19. }
  20. if i.Length.Empty() || !i.Length.IsKnown() {
  21. return s
  22. }
  23. return SliceInterval{
  24. Length: s.Length.Union(i.Length).(IntInterval),
  25. }
  26. }
  27. func (s SliceInterval) String() string { return s.Length.String() }
  28. func (s SliceInterval) IsKnown() bool { return s.Length.IsKnown() }
  29. type SliceAppendConstraint struct {
  30. aConstraint
  31. A ssa.Value
  32. B ssa.Value
  33. }
  34. type SliceSliceConstraint struct {
  35. aConstraint
  36. X ssa.Value
  37. Lower ssa.Value
  38. Upper ssa.Value
  39. }
  40. type ArraySliceConstraint struct {
  41. aConstraint
  42. X ssa.Value
  43. Lower ssa.Value
  44. Upper ssa.Value
  45. }
  46. type SliceIntersectionConstraint struct {
  47. aConstraint
  48. X ssa.Value
  49. I IntInterval
  50. }
  51. type SliceLengthConstraint struct {
  52. aConstraint
  53. X ssa.Value
  54. }
  55. type MakeSliceConstraint struct {
  56. aConstraint
  57. Size ssa.Value
  58. }
  59. type SliceIntervalConstraint struct {
  60. aConstraint
  61. I IntInterval
  62. }
  63. func NewSliceAppendConstraint(a, b, y ssa.Value) Constraint {
  64. return &SliceAppendConstraint{NewConstraint(y), a, b}
  65. }
  66. func NewSliceSliceConstraint(x, lower, upper, y ssa.Value) Constraint {
  67. return &SliceSliceConstraint{NewConstraint(y), x, lower, upper}
  68. }
  69. func NewArraySliceConstraint(x, lower, upper, y ssa.Value) Constraint {
  70. return &ArraySliceConstraint{NewConstraint(y), x, lower, upper}
  71. }
  72. func NewSliceIntersectionConstraint(x ssa.Value, i IntInterval, y ssa.Value) Constraint {
  73. return &SliceIntersectionConstraint{NewConstraint(y), x, i}
  74. }
  75. func NewSliceLengthConstraint(x, y ssa.Value) Constraint {
  76. return &SliceLengthConstraint{NewConstraint(y), x}
  77. }
  78. func NewMakeSliceConstraint(size, y ssa.Value) Constraint {
  79. return &MakeSliceConstraint{NewConstraint(y), size}
  80. }
  81. func NewSliceIntervalConstraint(i IntInterval, y ssa.Value) Constraint {
  82. return &SliceIntervalConstraint{NewConstraint(y), i}
  83. }
  84. func (c *SliceAppendConstraint) Operands() []ssa.Value { return []ssa.Value{c.A, c.B} }
  85. func (c *SliceSliceConstraint) Operands() []ssa.Value {
  86. ops := []ssa.Value{c.X}
  87. if c.Lower != nil {
  88. ops = append(ops, c.Lower)
  89. }
  90. if c.Upper != nil {
  91. ops = append(ops, c.Upper)
  92. }
  93. return ops
  94. }
  95. func (c *ArraySliceConstraint) Operands() []ssa.Value {
  96. ops := []ssa.Value{c.X}
  97. if c.Lower != nil {
  98. ops = append(ops, c.Lower)
  99. }
  100. if c.Upper != nil {
  101. ops = append(ops, c.Upper)
  102. }
  103. return ops
  104. }
  105. func (c *SliceIntersectionConstraint) Operands() []ssa.Value { return []ssa.Value{c.X} }
  106. func (c *SliceLengthConstraint) Operands() []ssa.Value { return []ssa.Value{c.X} }
  107. func (c *MakeSliceConstraint) Operands() []ssa.Value { return []ssa.Value{c.Size} }
  108. func (s *SliceIntervalConstraint) Operands() []ssa.Value { return nil }
  109. func (c *SliceAppendConstraint) String() string {
  110. return fmt.Sprintf("%s = append(%s, %s)", c.Y().Name(), c.A.Name(), c.B.Name())
  111. }
  112. func (c *SliceSliceConstraint) String() string {
  113. var lname, uname string
  114. if c.Lower != nil {
  115. lname = c.Lower.Name()
  116. }
  117. if c.Upper != nil {
  118. uname = c.Upper.Name()
  119. }
  120. return fmt.Sprintf("%s[%s:%s]", c.X.Name(), lname, uname)
  121. }
  122. func (c *ArraySliceConstraint) String() string {
  123. var lname, uname string
  124. if c.Lower != nil {
  125. lname = c.Lower.Name()
  126. }
  127. if c.Upper != nil {
  128. uname = c.Upper.Name()
  129. }
  130. return fmt.Sprintf("%s[%s:%s]", c.X.Name(), lname, uname)
  131. }
  132. func (c *SliceIntersectionConstraint) String() string {
  133. return fmt.Sprintf("%s = %s.%t ⊓ %s", c.Y().Name(), c.X.Name(), c.Y().(*ssa.Sigma).Branch, c.I)
  134. }
  135. func (c *SliceLengthConstraint) String() string {
  136. return fmt.Sprintf("%s = len(%s)", c.Y().Name(), c.X.Name())
  137. }
  138. func (c *MakeSliceConstraint) String() string {
  139. return fmt.Sprintf("%s = make(slice, %s)", c.Y().Name(), c.Size.Name())
  140. }
  141. func (c *SliceIntervalConstraint) String() string { return fmt.Sprintf("%s = %s", c.Y().Name(), c.I) }
  142. func (c *SliceAppendConstraint) Eval(g *Graph) Range {
  143. l1 := g.Range(c.A).(SliceInterval).Length
  144. var l2 IntInterval
  145. switch r := g.Range(c.B).(type) {
  146. case SliceInterval:
  147. l2 = r.Length
  148. case StringInterval:
  149. l2 = r.Length
  150. default:
  151. return SliceInterval{}
  152. }
  153. if !l1.IsKnown() || !l2.IsKnown() {
  154. return SliceInterval{}
  155. }
  156. return SliceInterval{
  157. Length: l1.Add(l2),
  158. }
  159. }
  160. func (c *SliceSliceConstraint) Eval(g *Graph) Range {
  161. lr := NewIntInterval(NewZ(0), NewZ(0))
  162. if c.Lower != nil {
  163. lr = g.Range(c.Lower).(IntInterval)
  164. }
  165. ur := g.Range(c.X).(SliceInterval).Length
  166. if c.Upper != nil {
  167. ur = g.Range(c.Upper).(IntInterval)
  168. }
  169. if !lr.IsKnown() || !ur.IsKnown() {
  170. return SliceInterval{}
  171. }
  172. ls := []Z{
  173. ur.Lower.Sub(lr.Lower),
  174. ur.Upper.Sub(lr.Lower),
  175. ur.Lower.Sub(lr.Upper),
  176. ur.Upper.Sub(lr.Upper),
  177. }
  178. // TODO(dh): if we don't truncate lengths to 0 we might be able to
  179. // easily detect slices with high < low. we'd need to treat -∞
  180. // specially, though.
  181. for i, l := range ls {
  182. if l.Sign() == -1 {
  183. ls[i] = NewZ(0)
  184. }
  185. }
  186. return SliceInterval{
  187. Length: NewIntInterval(MinZ(ls...), MaxZ(ls...)),
  188. }
  189. }
  190. func (c *ArraySliceConstraint) Eval(g *Graph) Range {
  191. lr := NewIntInterval(NewZ(0), NewZ(0))
  192. if c.Lower != nil {
  193. lr = g.Range(c.Lower).(IntInterval)
  194. }
  195. var l int64
  196. switch typ := c.X.Type().(type) {
  197. case *types.Array:
  198. l = typ.Len()
  199. case *types.Pointer:
  200. l = typ.Elem().(*types.Array).Len()
  201. }
  202. ur := NewIntInterval(NewZ(l), NewZ(l))
  203. if c.Upper != nil {
  204. ur = g.Range(c.Upper).(IntInterval)
  205. }
  206. if !lr.IsKnown() || !ur.IsKnown() {
  207. return SliceInterval{}
  208. }
  209. ls := []Z{
  210. ur.Lower.Sub(lr.Lower),
  211. ur.Upper.Sub(lr.Lower),
  212. ur.Lower.Sub(lr.Upper),
  213. ur.Upper.Sub(lr.Upper),
  214. }
  215. // TODO(dh): if we don't truncate lengths to 0 we might be able to
  216. // easily detect slices with high < low. we'd need to treat -∞
  217. // specially, though.
  218. for i, l := range ls {
  219. if l.Sign() == -1 {
  220. ls[i] = NewZ(0)
  221. }
  222. }
  223. return SliceInterval{
  224. Length: NewIntInterval(MinZ(ls...), MaxZ(ls...)),
  225. }
  226. }
  227. func (c *SliceIntersectionConstraint) Eval(g *Graph) Range {
  228. xi := g.Range(c.X).(SliceInterval)
  229. if !xi.IsKnown() {
  230. return c.I
  231. }
  232. return SliceInterval{
  233. Length: xi.Length.Intersection(c.I),
  234. }
  235. }
  236. func (c *SliceLengthConstraint) Eval(g *Graph) Range {
  237. i := g.Range(c.X).(SliceInterval).Length
  238. if !i.IsKnown() {
  239. return NewIntInterval(NewZ(0), PInfinity)
  240. }
  241. return i
  242. }
  243. func (c *MakeSliceConstraint) Eval(g *Graph) Range {
  244. i, ok := g.Range(c.Size).(IntInterval)
  245. if !ok {
  246. return SliceInterval{NewIntInterval(NewZ(0), PInfinity)}
  247. }
  248. if i.Lower.Sign() == -1 {
  249. i.Lower = NewZ(0)
  250. }
  251. return SliceInterval{i}
  252. }
  253. func (c *SliceIntervalConstraint) Eval(*Graph) Range { return SliceInterval{c.I} }