return x>>b == 0
}
+func noLimit() limit {
+ return noLimitForBitsize(64)
+}
+
func noLimitForBitsize(bitsize uint) limit {
return limit{min: -(1 << (bitsize - 1)), max: 1<<(bitsize-1) - 1, umin: 0, umax: 1<<bitsize - 1}
}
return limit{min: int64r, max: int64r, umin: r, umax: r}
}
- r := noLimit
+ r := noLimit()
min, minOk := safeAdd(l.min, l2.min, b)
max, maxOk := safeAdd(l.max, l2.max, b)
if minOk && maxOk {
// same as add but for subtraction.
func (l limit) sub(l2 limit, b uint) limit {
- r := noLimit
+ r := noLimit()
min, minOk := safeSub(l.min, l2.max, b)
max, maxOk := safeSub(l.max, l2.min, b)
if minOk && maxOk {
// same as add but for multiplication.
func (l limit) mul(l2 limit, b uint) limit {
- r := noLimit
+ r := noLimit()
umaxhi, umaxlo := bits.Mul64(l.umax, l2.umax)
if umaxhi == 0 && fitsInBitsU(umaxlo, b) {
r.umax = umaxlo
// Similar to add, but compute 1 << l if it fits without overflow in b bits.
func (l limit) exp2(b uint) limit {
- r := noLimit
+ r := noLimit()
if l.umax < uint64(b) {
r.umin = 1 << l.umin
r.umax = 1 << l.umax
if l.umin&((1<<varying)-1) != 0 {
// there will always be at least one non-zero bit in the varying part
varying--
- return noLimit.unsignedMax(uint64(varying))
+ return noLimit().unsignedMax(uint64(varying))
}
- return noLimit.unsignedMax(uint64(min(uint(bits.TrailingZeros64(fixed)), b)))
+ return noLimit().unsignedMax(uint64(min(uint(bits.TrailingZeros64(fixed)), b)))
}
// Similar to add, but computes the Len of the limit for bitsize b.
func (l limit) bitlen(b uint) limit {
- return noLimit.unsignedMinMax(
+ return noLimit().unsignedMinMax(
uint64(bits.Len64(l.umin)),
uint64(bits.Len64(l.umax)),
)
min++
}
- return noLimit.unsignedMinMax(min, max)
+ return noLimit().unsignedMinMax(min, max)
}
-var noLimit = limit{math.MinInt64, math.MaxInt64, 0, math.MaxUint64}
-
// a limitFact is a limit known for a particular value.
type limitFact struct {
vid ID
ft.newLimit(v, limit{min: 0, max: 0, umin: 0, umax: 0})
}
func (ft *factsTable) pointerNonNil(v *Value) {
- l := noLimit
+ l := noLimit()
l.umin = 1
ft.newLimit(v, l)
}
case OpConstNil:
return limit{min: 0, max: 0, umin: 0, umax: 0}
case OpAddr, OpLocalAddr: // TODO: others?
- l := noLimit
+ l := noLimit()
l.umin = 1
return l
default:
- return noLimit
+ return noLimit()
}
}
if !v.Type.IsInteger() {
- return noLimit
+ return noLimit()
}
// Default limits based on type.
case OpDiv64u, OpDiv32u, OpDiv16u, OpDiv8u:
a := ft.limits[v.Args[0].ID]
b := ft.limits[v.Args[1].ID]
- lim := noLimit
+ lim := noLimit()
if b.umax > 0 {
lim = lim.unsignedMin(a.umin / b.umax)
}