aboutsummaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2021-02-18 17:33:01 +0000
committerMichael Knyszek <mknyszek@google.com>2021-03-05 15:34:32 +0000
commita2f70672334ecc71c81bd1f424e1734485d8cb83 (patch)
treed9de8f0be7b1d57cb02bb037854644cfe5c0acb4 /src/reflect
parentc5a1c2276ee41a65cce93b7e443d333dfa29aba7 (diff)
downloadgo-a2f70672334ecc71c81bd1f424e1734485d8cb83.tar.gz
go-a2f70672334ecc71c81bd1f424e1734485d8cb83.zip
reflect: include the alignment of zero-sized types in stack offsets
This change modifies the reflect ABI assignment algorithm to catch zero-sized types at the top level of each argument and faux-stack-assign them. It doesn't actually generate an ABI step, which is unnecessary, but it ensures that the offsets of further stack-assigned arguments are aligned to the alignment of that zero-sized argument. This change is necessary to have the register ABI assignment algorithm gracefully degrade to ABI0 when no registers are present in the ABI. Fixes #44377. Change-Id: Ia95571688a61259302bb3c6d5fb33fbb6b5e8db8 Reviewed-on: https://go-review.googlesource.com/c/go/+/293789 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com> Trust: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/abi.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/reflect/abi.go b/src/reflect/abi.go
index 618efd0980..50e6312172 100644
--- a/src/reflect/abi.go
+++ b/src/reflect/abi.go
@@ -123,6 +123,24 @@ func (a *abiSeq) stepsForValue(i int) []abiStep {
func (a *abiSeq) addArg(t *rtype) *abiStep {
pStart := len(a.steps)
a.valueStart = append(a.valueStart, pStart)
+ if t.size == 0 {
+ // If the size of the argument type is zero, then
+ // in order to degrade gracefully into ABI0, we need
+ // to stack-assign this type. The reason is that
+ // although zero-sized types take up no space on the
+ // stack, they do cause the next argument to be aligned.
+ // So just do that here, but don't bother actually
+ // generating a new ABI step for it (there's nothing to
+ // actually copy).
+ //
+ // We cannot handle this in the recursive case of
+ // regAssign because zero-sized *fields* of a
+ // non-zero-sized struct do not cause it to be
+ // stack-assigned. So we need a special case here
+ // at the top.
+ a.stackBytes = align(a.stackBytes, uintptr(t.align))
+ return nil
+ }
if !a.regAssign(t, 0) {
a.steps = a.steps[:pStart]
a.stackAssign(t.size, uintptr(t.align))