go.tools/ssa: avoid redundant uint64 conversion of right operand of <<, >>.
Also: add sanity check that no Instruction yields a Value of 'untyped' type. R=golang-dev, gri CC=golang-dev https://golang.org/cl/11011043
This commit is contained in:
parent
1aa0484f4b
commit
8846992823
|
|
@ -38,7 +38,6 @@ 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 = 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)
|
||||||
|
|
|
||||||
|
|
@ -130,26 +130,6 @@ 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) {
|
||||||
|
|
@ -563,7 +543,7 @@ func binop(op token.Token, x, y value) value {
|
||||||
}
|
}
|
||||||
|
|
||||||
case token.SHL:
|
case token.SHL:
|
||||||
y := asUint64(y)
|
y := uint64(asInt(y))
|
||||||
switch x.(type) {
|
switch x.(type) {
|
||||||
case int:
|
case int:
|
||||||
return x.(int) << y
|
return x.(int) << y
|
||||||
|
|
@ -590,7 +570,7 @@ func binop(op token.Token, x, y value) value {
|
||||||
}
|
}
|
||||||
|
|
||||||
case token.SHR:
|
case token.SHR:
|
||||||
y := asUint64(y)
|
y := uint64(asInt(y))
|
||||||
switch x.(type) {
|
switch x.(type) {
|
||||||
case int:
|
case int:
|
||||||
return x.(int) >> y
|
return x.(int) >> y
|
||||||
|
|
|
||||||
|
|
@ -270,6 +270,16 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mybool bool
|
||||||
|
|
||||||
|
func (mybool) f() {}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var x, y int
|
||||||
|
var b mybool = x == y // x==y is an untyped bool
|
||||||
|
b.f()
|
||||||
|
}
|
||||||
|
|
||||||
// Simple closures.
|
// Simple closures.
|
||||||
func init() {
|
func init() {
|
||||||
b := 3
|
b := 3
|
||||||
|
|
|
||||||
|
|
@ -160,11 +160,23 @@ func (s *sanity) checkInstr(idx int, instr Instruction) {
|
||||||
panic(fmt.Sprintf("Unknown instruction type: %T", instr))
|
panic(fmt.Sprintf("Unknown instruction type: %T", instr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that value-defining instructions have valid types.
|
||||||
if v, ok := instr.(Value); ok {
|
if v, ok := instr.(Value); ok {
|
||||||
if v.Type() == nil {
|
t := v.Type()
|
||||||
|
if t == nil {
|
||||||
s.errorf("no type: %s = %s", v.Name(), v)
|
s.errorf("no type: %s = %s", v.Name(), v)
|
||||||
|
} else if t == tRangeIter {
|
||||||
|
// not a proper type; ignore.
|
||||||
|
} else if b, ok := t.Underlying().(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
|
||||||
|
s.errorf("instruction has 'untyped' result: %s = %s : %s", v.Name(), v, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): sanity-check Literals used as instruction Operands(),
|
||||||
|
// e.g. reject Literals with "untyped" types.
|
||||||
|
//
|
||||||
|
// All other non-Instruction Values can be found via their
|
||||||
|
// enclosing Function or Package.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sanity) checkFinalInstr(idx int, instr Instruction) {
|
func (s *sanity) checkFinalInstr(idx int, instr Instruction) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue