mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
When using softfloat, floating point ops are rewritten to integer ops. The types of store ops were not rewritten. This may lower to floating point stores, which are problematic. This CL fixes this by rewriting the store types as well. This fixes test/fixedbugs/issue28688.go on Wasm. Softfloat mode is not used by default on Wasm, and it is not needed as Wasm spec supports floating points. But it is nice to have the correct types. Change-Id: Ib5e19e19fa9491b15c2f60320f8724cace5cefb5 Reviewed-on: https://go-review.googlesource.com/c/149965 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
// Copyright 2017 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.
|
|
|
|
package ssa
|
|
|
|
import (
|
|
"cmd/compile/internal/types"
|
|
"math"
|
|
)
|
|
|
|
func softfloat(f *Func) {
|
|
if !f.Config.SoftFloat {
|
|
return
|
|
}
|
|
newInt64 := false
|
|
|
|
for _, b := range f.Blocks {
|
|
for _, v := range b.Values {
|
|
if v.Type.IsFloat() {
|
|
switch v.Op {
|
|
case OpPhi, OpLoad, OpArg:
|
|
if v.Type.Size() == 4 {
|
|
v.Type = f.Config.Types.UInt32
|
|
} else {
|
|
v.Type = f.Config.Types.UInt64
|
|
}
|
|
case OpConst32F:
|
|
v.Op = OpConst32
|
|
v.Type = f.Config.Types.UInt32
|
|
v.AuxInt = int64(int32(math.Float32bits(auxTo32F(v.AuxInt))))
|
|
case OpConst64F:
|
|
v.Op = OpConst64
|
|
v.Type = f.Config.Types.UInt64
|
|
case OpNeg32F:
|
|
arg0 := v.Args[0]
|
|
v.reset(OpXor32)
|
|
v.Type = f.Config.Types.UInt32
|
|
v.AddArg(arg0)
|
|
mask := v.Block.NewValue0(v.Pos, OpConst32, v.Type)
|
|
mask.AuxInt = -0x80000000
|
|
v.AddArg(mask)
|
|
case OpNeg64F:
|
|
arg0 := v.Args[0]
|
|
v.reset(OpXor64)
|
|
v.Type = f.Config.Types.UInt64
|
|
v.AddArg(arg0)
|
|
mask := v.Block.NewValue0(v.Pos, OpConst64, v.Type)
|
|
mask.AuxInt = -0x8000000000000000
|
|
v.AddArg(mask)
|
|
case OpRound32F:
|
|
v.Op = OpCopy
|
|
v.Type = f.Config.Types.UInt32
|
|
case OpRound64F:
|
|
v.Op = OpCopy
|
|
v.Type = f.Config.Types.UInt64
|
|
}
|
|
newInt64 = newInt64 || v.Type.Size() == 8
|
|
} else if (v.Op == OpStore || v.Op == OpZero || v.Op == OpMove) && v.Aux.(*types.Type).IsFloat() {
|
|
switch size := v.Aux.(*types.Type).Size(); size {
|
|
case 4:
|
|
v.Aux = f.Config.Types.UInt32
|
|
case 8:
|
|
v.Aux = f.Config.Types.UInt64
|
|
default:
|
|
v.Fatalf("bad float type with size %d", size)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if newInt64 && f.Config.RegSize == 4 {
|
|
// On 32bit arch, decompose Uint64 introduced in the switch above.
|
|
decomposeBuiltIn(f)
|
|
applyRewrite(f, rewriteBlockdec64, rewriteValuedec64)
|
|
}
|
|
|
|
}
|