aboutsummaryrefslogtreecommitdiff
path: root/go/ssa/interp/ops.go
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2022-03-29 00:50:59 -0700
committerDan Willemsen <dwillemsen@google.com>2022-03-29 00:52:27 -0700
commitf10932f763d058b0dcb3acfb795c869996fef47b (patch)
tree7e04d345c214f3efac3c4b86c7ec3e831c500437 /go/ssa/interp/ops.go
parentd6d1ab63f7e2d16fb9a1f1d29755d12da90aa0bb (diff)
parente693fb417253d14786976bd29a456961aa8b6343 (diff)
downloadgolang-x-tools-f10932f763d058b0dcb3acfb795c869996fef47b.tar.gz
Merge commit 'e693fb417253d14786976bd29a456961aa8b6343'
Change-Id: I65e50880732e718fa2264e47ef7cc19e37cc2f05
Diffstat (limited to 'go/ssa/interp/ops.go')
-rw-r--r--go/ssa/interp/ops.go32
1 files changed, 30 insertions, 2 deletions
diff --git a/go/ssa/interp/ops.go b/go/ssa/interp/ops.go
index 6af7847c0..3bc6a4e32 100644
--- a/go/ssa/interp/ops.go
+++ b/go/ssa/interp/ops.go
@@ -137,6 +137,26 @@ func asUint64(x value) uint64 {
panic(fmt.Sprintf("cannot convert %T to uint64", x))
}
+// asUnsigned returns the value of x, which must be an integer type, as its equivalent unsigned type,
+// and returns true if x is non-negative.
+func asUnsigned(x value) (value, bool) {
+ switch x := x.(type) {
+ case int:
+ return uint(x), x >= 0
+ case int8:
+ return uint8(x), x >= 0
+ case int16:
+ return uint16(x), x >= 0
+ case int32:
+ return uint32(x), x >= 0
+ case int64:
+ return uint64(x), x >= 0
+ case uint, uint8, uint32, uint64, uintptr:
+ return x, true
+ }
+ panic(fmt.Sprintf("cannot convert %T to unsigned", x))
+}
+
// zero returns a new "zero" value of the specified type.
func zero(t types.Type) value {
switch t := t.(type) {
@@ -576,7 +596,11 @@ func binop(op token.Token, t types.Type, x, y value) value {
}
case token.SHL:
- y := asUint64(y)
+ u, ok := asUnsigned(y)
+ if !ok {
+ panic("negative shift amount")
+ }
+ y := asUint64(u)
switch x.(type) {
case int:
return x.(int) << y
@@ -603,7 +627,11 @@ func binop(op token.Token, t types.Type, x, y value) value {
}
case token.SHR:
- y := asUint64(y)
+ u, ok := asUnsigned(y)
+ if !ok {
+ panic("negative shift amount")
+ }
+ y := asUint64(u)
switch x.(type) {
case int:
return x.(int) >> y