Don't do direct loads from argument slots if the sizes don't match.
This prevents us from loading from a float32 using a uint64 load
during expressions like uint64(math.float32Bits(f)) where f is a float32 arg.
Fixes #25335
Change-Id: I3887d76f78c844ba546243e7721d811c3d4a9700
Reviewed-on: https://go-review.googlesource.com/112637
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/131276
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
// Load args directly into the register class where it will be used.
// We do this by just modifying the type of the Arg.
-(MOVQf2i <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym})
-(MOVLf2i <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym})
-(MOVQi2f <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym})
-(MOVLi2f <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym})
+(MOVQf2i <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg <t> [off] {sym})
+(MOVLf2i <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg <t> [off] {sym})
+(MOVQi2f <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg <t> [off] {sym})
+(MOVLi2f <t> (Arg <u> [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg <t> [off] {sym})
{name: "MOVQi2f", argLength: 1, reg: gpfp, typ: "Float64"}, // move 64 bits from int to float reg
{name: "MOVQf2i", argLength: 1, reg: fpgp, typ: "UInt64"}, // move 64 bits from float to int reg
{name: "MOVLi2f", argLength: 1, reg: gpfp, typ: "Float32"}, // move 32 bits from int to float reg
- {name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg
+ {name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg, zero extend
{name: "PXOR", argLength: 2, reg: fp21, asm: "PXOR", commutative: true, resultInArg0: true}, // exclusive or, applied to X regs for float negation.
func rewriteValueAMD64_OpAMD64MOVLf2i_0(v *Value) bool {
b := v.Block
_ = b
- // match: (MOVLf2i <t> (Arg [off] {sym}))
- // cond:
+ // match: (MOVLf2i <t> (Arg <u> [off] {sym}))
+ // cond: t.Size() == u.Size()
// result: @b.Func.Entry (Arg <t> [off] {sym})
for {
t := v.Type
if v_0.Op != OpArg {
break
}
+ u := v_0.Type
off := v_0.AuxInt
sym := v_0.Aux
+ if !(t.Size() == u.Size()) {
+ break
+ }
b = b.Func.Entry
v0 := b.NewValue0(v.Pos, OpArg, t)
v.reset(OpCopy)
func rewriteValueAMD64_OpAMD64MOVLi2f_0(v *Value) bool {
b := v.Block
_ = b
- // match: (MOVLi2f <t> (Arg [off] {sym}))
- // cond:
+ // match: (MOVLi2f <t> (Arg <u> [off] {sym}))
+ // cond: t.Size() == u.Size()
// result: @b.Func.Entry (Arg <t> [off] {sym})
for {
t := v.Type
if v_0.Op != OpArg {
break
}
+ u := v_0.Type
off := v_0.AuxInt
sym := v_0.Aux
+ if !(t.Size() == u.Size()) {
+ break
+ }
b = b.Func.Entry
v0 := b.NewValue0(v.Pos, OpArg, t)
v.reset(OpCopy)
func rewriteValueAMD64_OpAMD64MOVQf2i_0(v *Value) bool {
b := v.Block
_ = b
- // match: (MOVQf2i <t> (Arg [off] {sym}))
- // cond:
+ // match: (MOVQf2i <t> (Arg <u> [off] {sym}))
+ // cond: t.Size() == u.Size()
// result: @b.Func.Entry (Arg <t> [off] {sym})
for {
t := v.Type
if v_0.Op != OpArg {
break
}
+ u := v_0.Type
off := v_0.AuxInt
sym := v_0.Aux
+ if !(t.Size() == u.Size()) {
+ break
+ }
b = b.Func.Entry
v0 := b.NewValue0(v.Pos, OpArg, t)
v.reset(OpCopy)
func rewriteValueAMD64_OpAMD64MOVQi2f_0(v *Value) bool {
b := v.Block
_ = b
- // match: (MOVQi2f <t> (Arg [off] {sym}))
- // cond:
+ // match: (MOVQi2f <t> (Arg <u> [off] {sym}))
+ // cond: t.Size() == u.Size()
// result: @b.Func.Entry (Arg <t> [off] {sym})
for {
t := v.Type
if v_0.Op != OpArg {
break
}
+ u := v_0.Type
off := v_0.AuxInt
sym := v_0.Aux
+ if !(t.Size() == u.Size()) {
+ break
+ }
b = b.Func.Entry
v0 := b.NewValue0(v.Pos, OpArg, t)
v.reset(OpCopy)
--- /dev/null
+// cmpout
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Missing zero extension when converting a float32
+// to a uint64.
+
+package main
+
+import (
+ "fmt"
+ "math"
+)
+
+func Foo(v float32) {
+ fmt.Printf("%x\n", uint64(math.Float32bits(v)))
+}
+
+func main() {
+ Foo(2.0)
+}