From a2f70672334ecc71c81bd1f424e1734485d8cb83 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 18 Feb 2021 17:33:01 +0000 Subject: [PATCH] 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 TryBot-Result: Go Bot Reviewed-by: Than McIntosh Reviewed-by: Cherry Zhang Trust: Than McIntosh --- src/reflect/abi.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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)) -- 2.50.0