aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/value.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2021-09-03 21:35:59 +0000
committerMichael Knyszek <mknyszek@google.com>2021-09-09 16:48:19 +0000
commitea434450c26431332c4cc376996e2b917fd09873 (patch)
treed6b96f2ca2222e60c345544bf491acf545f565fb /src/reflect/value.go
parenta53e3d5f885ca7a0df1cd6cf65faa5b63a802dce (diff)
downloadgo-ea434450c26431332c4cc376996e2b917fd09873.tar.gz
go-ea434450c26431332c4cc376996e2b917fd09873.zip
reflect: add hooks for dealing with narrow width floats
Currently on amd64 and arm64, float32 values just live in the bottom 32 bits of the register, so reflect simply places them there in a RegArgs for reflectcall to load them. This works fine because both of these platforms don't care what the upper 32 bits are, and have instructions to operate on float32 values specifically that we use. In sum, the representation of the float32 in memory is identical to that of the representation in a register. On other platforms, however, the representation of FP values differ depending on whether they're in memory or in a register. For instance, on ppc64, all floating point values get promoted to a float64 when loaded to a register (i.e. there's only one set of FP instructions). As another example, on riscv64, narrow-width floats in registers need to be NaN-boxed. What all this means is that for supporting the register ABI on these platforms, reflect needs to do a little extra work to ensure that the representation of FP values in a RegArgs matches the representation it takes on in a register. For this purpose, this change abstracts away the action of storing values into a RegArgs a little bit and adds a platform-specific hook which currently does nothing but copy the value. For #40724. Change-Id: I65dcc7d86d5602a584f86026ac204564617f4c5a Reviewed-on: https://go-review.googlesource.com/c/go/+/347566 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/reflect/value.go')
-rw-r--r--src/reflect/value.go24
1 files changed, 12 insertions, 12 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 3c2172135e..bf29d1bb3a 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -508,7 +508,7 @@ func (v Value) call(op string, in []Value) []Value {
// Copy values to "integer registers."
if v.flag&flagIndir != 0 {
offset := add(v.ptr, st.offset, "precomputed value offset")
- memmove(regArgs.IntRegArgAddr(st.ireg, st.size), offset, st.size)
+ intToReg(&regArgs, st.ireg, st.size, offset)
} else {
if st.kind == abiStepPointer {
// Duplicate this pointer in the pointer area of the
@@ -524,7 +524,7 @@ func (v Value) call(op string, in []Value) []Value {
panic("attempted to copy pointer to FP register")
}
offset := add(v.ptr, st.offset, "precomputed value offset")
- memmove(regArgs.FloatRegArgAddr(st.freg, st.size), offset, st.size)
+ floatToReg(&regArgs, st.freg, st.size, offset)
default:
panic("unknown ABI part kind")
}
@@ -610,13 +610,13 @@ func (v Value) call(op string, in []Value) []Value {
switch st.kind {
case abiStepIntReg:
offset := add(s, st.offset, "precomputed value offset")
- memmove(offset, regArgs.IntRegArgAddr(st.ireg, st.size), st.size)
+ intFromReg(&regArgs, st.ireg, st.size, offset)
case abiStepPointer:
s := add(s, st.offset, "precomputed value offset")
*((*unsafe.Pointer)(s)) = regArgs.Ptrs[st.ireg]
case abiStepFloatReg:
offset := add(s, st.offset, "precomputed value offset")
- memmove(offset, regArgs.FloatRegArgAddr(st.freg, st.size), st.size)
+ floatFromReg(&regArgs, st.freg, st.size, offset)
case abiStepStack:
panic("register-based return value has stack component")
default:
@@ -698,13 +698,13 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs
switch st.kind {
case abiStepIntReg:
offset := add(v.ptr, st.offset, "precomputed value offset")
- memmove(offset, regs.IntRegArgAddr(st.ireg, st.size), st.size)
+ intFromReg(regs, st.ireg, st.size, offset)
case abiStepPointer:
s := add(v.ptr, st.offset, "precomputed value offset")
*((*unsafe.Pointer)(s)) = regs.Ptrs[st.ireg]
case abiStepFloatReg:
offset := add(v.ptr, st.offset, "precomputed value offset")
- memmove(offset, regs.FloatRegArgAddr(st.freg, st.size), st.size)
+ floatFromReg(regs, st.freg, st.size, offset)
case abiStepStack:
panic("register-based return value has stack component")
default:
@@ -784,7 +784,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs
// Copy values to "integer registers."
if v.flag&flagIndir != 0 {
offset := add(v.ptr, st.offset, "precomputed value offset")
- memmove(regs.IntRegArgAddr(st.ireg, st.size), offset, st.size)
+ intToReg(regs, st.ireg, st.size, offset)
} else {
// Only populate the Ints space on the return path.
// This is safe because out is kept alive until the
@@ -799,7 +799,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs
panic("attempted to copy pointer to FP register")
}
offset := add(v.ptr, st.offset, "precomputed value offset")
- memmove(regs.FloatRegArgAddr(st.freg, st.size), offset, st.size)
+ floatToReg(regs, st.freg, st.size, offset)
default:
panic("unknown ABI part kind")
}
@@ -982,9 +982,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a
methodRegs.Ptrs[mStep.ireg] = *(*unsafe.Pointer)(from)
fallthrough // We need to make sure this ends up in Ints, too.
case abiStepIntReg:
- memmove(methodRegs.IntRegArgAddr(mStep.ireg, mStep.size), from, mStep.size)
+ intToReg(&methodRegs, mStep.ireg, mStep.size, from)
case abiStepFloatReg:
- memmove(methodRegs.FloatRegArgAddr(mStep.freg, mStep.size), from, mStep.size)
+ floatToReg(&methodRegs, mStep.freg, mStep.size, from)
default:
panic("unexpected method step")
}
@@ -1000,9 +1000,9 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a
// Do the pointer copy directly so we get a write barrier.
*(*unsafe.Pointer)(to) = valueRegs.Ptrs[vStep.ireg]
case abiStepIntReg:
- memmove(to, valueRegs.IntRegArgAddr(vStep.ireg, vStep.size), vStep.size)
+ intFromReg(valueRegs, vStep.ireg, vStep.size, to)
case abiStepFloatReg:
- memmove(to, valueRegs.FloatRegArgAddr(vStep.freg, vStep.size), vStep.size)
+ floatFromReg(valueRegs, vStep.freg, vStep.size, to)
default:
panic("unexpected value step")
}