1
0
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:
Alan Donovan 2013-07-09 10:21:25 -04:00
parent 2b6515094c
commit 06a43b8a0c
2 changed files with 28 additions and 2 deletions

View File

@ -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)

View File

@ -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