From 80ddc17ae1b3ffacc42c19b999956f9ccef3ddd1 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 23 Feb 2021 20:48:22 -0500 Subject: [PATCH] cmd/compile/internal-abi: fix ABI0-equivalence for zero-sized values This fixes a bug in the internal ABI specification that made it not equivalent to ABI0 even with zero architectural argument registers in the case of a zero-sized argument with alignment > 1. In ABI0, even zero-sized arguments cause alignment padding in the stack frame. Currently, in the internal ABI, zero-sized arguments get register-assigned even if there are no registers because they don't consume any registers. Hence, they don't create alignment padding in the stack frame. Fix this by stack-assigning zero-sized arguments. For #40724. Change-Id: I1f5a95a94fed8b5313a360e5e76875701ba5f562 Reviewed-on: https://go-review.googlesource.com/c/go/+/295791 Trust: Austin Clements Reviewed-by: Cherry Zhang Reviewed-by: Than McIntosh --- src/cmd/compile/internal-abi.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/cmd/compile/internal-abi.md b/src/cmd/compile/internal-abi.md index 0e5d8ce260..b457f6ee74 100644 --- a/src/cmd/compile/internal-abi.md +++ b/src/cmd/compile/internal-abi.md @@ -153,6 +153,7 @@ Assigning a receiver, argument, or result V of underlying type T works as follows: 1. Remember I and FP. +1. If T has zero size, add T to the stack sequence S and return. 1. Try to register-assign V. 1. If step 2 failed, reset I and FP to the values from step 1, add T to the stack sequence S, and assign V to this field in S. @@ -295,6 +296,15 @@ An architecture may still define register meanings that aren’t compatible with ABI0, but these differences should be easy to account for in the compiler. +The assignment algorithm assigns zero-sized values to the stack +(assignment step 2) in order to support ABI0-equivalence. +While these values take no space themselves, they do result in +alignment padding on the stack in ABI0. +Without this step, the internal ABI would register-assign zero-sized +values even on architectures that provide no argument registers +because they don't consume any registers, and hence not add alignment +padding to the stack. + The algorithm reserves spill space for arguments in the caller’s frame so that the compiler can generate a stack growth path that spills into this reserved space.