mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
c5a1c2276e
commit
a2f7067233
1 changed files with 18 additions and 0 deletions
|
|
@ -123,6 +123,24 @@ func (a *abiSeq) stepsForValue(i int) []abiStep {
|
||||||
func (a *abiSeq) addArg(t *rtype) *abiStep {
|
func (a *abiSeq) addArg(t *rtype) *abiStep {
|
||||||
pStart := len(a.steps)
|
pStart := len(a.steps)
|
||||||
a.valueStart = append(a.valueStart, pStart)
|
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) {
|
if !a.regAssign(t, 0) {
|
||||||
a.steps = a.steps[:pStart]
|
a.steps = a.steps[:pStart]
|
||||||
a.stackAssign(t.size, uintptr(t.align))
|
a.stackAssign(t.size, uintptr(t.align))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue