mirror of
https://github.com/golang/go
synced 2024-11-18 21:44:45 -07:00
go.tools/ssa: fix regression in x<<y logic from CL 11011043
Details: - reintroduce interp.asUint64: it's not sound to use only the low 32 bits of y, which is what asInt gives us, when GOARCH=386. - instead, emit a uint64 conversion when y is not unsigned (i.e. a signed var, or an untyped constant). Tested on 386 & x86-64. R=gri CC=golang-dev https://golang.org/cl/11023043
This commit is contained in:
parent
2b6515094c
commit
06a43b8a0c
@ -38,6 +38,11 @@ func emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.
|
|||||||
switch op {
|
switch op {
|
||||||
case token.SHL, token.SHR:
|
case token.SHL, token.SHR:
|
||||||
x = emitConv(f, x, t)
|
x = emitConv(f, x, t)
|
||||||
|
// y may be signed or an 'untyped' constant.
|
||||||
|
// TODO(adonovan): whence signed values?
|
||||||
|
if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUnsigned == 0 {
|
||||||
|
y = emitConv(f, y, types.Typ[types.Uint64])
|
||||||
|
}
|
||||||
|
|
||||||
case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
|
case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
|
||||||
x = emitConv(f, x, t)
|
x = emitConv(f, x, t)
|
||||||
|
@ -30,6 +30,7 @@ func literalValue(l *ssa.Literal) value {
|
|||||||
// By destination type:
|
// By destination type:
|
||||||
switch t := l.Type().Underlying().(type) {
|
switch t := l.Type().Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
|
// TODO(adonovan): eliminate untyped literals from SSA form.
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case types.Bool, types.UntypedBool:
|
case types.Bool, types.UntypedBool:
|
||||||
return exact.BoolVal(l.Value)
|
return exact.BoolVal(l.Value)
|
||||||
@ -130,6 +131,26 @@ func asInt(x value) int {
|
|||||||
panic(fmt.Sprintf("cannot convert %T to int", x))
|
panic(fmt.Sprintf("cannot convert %T to int", x))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// asUint64 converts x, which must be an unsigned integer, to a uint64
|
||||||
|
// suitable for use as a bitwise shift count.
|
||||||
|
func asUint64(x value) uint64 {
|
||||||
|
switch x := x.(type) {
|
||||||
|
case uint:
|
||||||
|
return uint64(x)
|
||||||
|
case uint8:
|
||||||
|
return uint64(x)
|
||||||
|
case uint16:
|
||||||
|
return uint64(x)
|
||||||
|
case uint32:
|
||||||
|
return uint64(x)
|
||||||
|
case uint64:
|
||||||
|
return x
|
||||||
|
case uintptr:
|
||||||
|
return uint64(x)
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("cannot convert %T to uint64", x))
|
||||||
|
}
|
||||||
|
|
||||||
// zero returns a new "zero" value of the specified type.
|
// zero returns a new "zero" value of the specified type.
|
||||||
func zero(t types.Type) value {
|
func zero(t types.Type) value {
|
||||||
switch t := t.(type) {
|
switch t := t.(type) {
|
||||||
@ -543,7 +564,7 @@ func binop(op token.Token, x, y value) value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case token.SHL:
|
case token.SHL:
|
||||||
y := uint64(asInt(y))
|
y := asUint64(y)
|
||||||
switch x.(type) {
|
switch x.(type) {
|
||||||
case int:
|
case int:
|
||||||
return x.(int) << y
|
return x.(int) << y
|
||||||
@ -570,7 +591,7 @@ func binop(op token.Token, x, y value) value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case token.SHR:
|
case token.SHR:
|
||||||
y := uint64(asInt(y))
|
y := asUint64(y)
|
||||||
switch x.(type) {
|
switch x.(type) {
|
||||||
case int:
|
case int:
|
||||||
return x.(int) >> y
|
return x.(int) >> y
|
||||||
|
Loading…
Reference in New Issue
Block a user