diff options
author | Than McIntosh <thanm@google.com> | 2021-04-29 11:47:18 -0400 |
---|---|---|
committer | Than McIntosh <thanm@google.com> | 2021-04-30 19:38:25 +0000 |
commit | d19eece91f7825556eadfef08e7011e22a719ec0 (patch) | |
tree | 96eb94726ed249cb5e40a4d4835ecc70a58b264f /src/cmd/compile/internal/test | |
parent | 162d4f9c92cb618e8b434e445a842351160fb84d (diff) | |
download | go-d19eece91f7825556eadfef08e7011e22a719ec0.tar.gz go-d19eece91f7825556eadfef08e7011e22a719ec0.zip |
cmd/compile: handle field padding for register-passed structs
When constructing multi-piece DWARF location expressions for
struct-typed parameters using the register ABI, make sure that the
location expressions generated properly reflect padding between
elements (this is required by debuggers). Example:
type small struct { x uint16 ; y uint8 ; z int32 }
func ABC(p1 int, p2 small, f1 float32) {
...
In the DWARF location expression for "p2" on entry to the routine, we
need pieces for each field, but for debuggers (such as GDB) to work
properly, we also need to describe the padding between elements. Thus
instead of
<rbx> DW_OP_piece 2 <rcx> DW_OP_piece 1 <rdi> DW_OP_piece 4
we need to emit
<rbx> DW_OP_piece 2 <rcx> DW_OP_piece 1 DW_OP_piece 1 <rdi> DW_OP_piece 4
This patch adds a new helper routine in abiutils to compute the
correct padding amounts for a struct type, a unit test for the helper,
and updates the debug generation code to call the helper and insert
apadding "piece" ops in the right spots.
Updates #40724.
Updates #45720.
Change-Id: Ie208bee25776b9eb70642041869e65e4fa65a005
Reviewed-on: https://go-review.googlesource.com/c/go/+/315071
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/compile/internal/test')
-rw-r--r-- | src/cmd/compile/internal/test/abiutils_test.go | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/test/abiutils_test.go b/src/cmd/compile/internal/test/abiutils_test.go index daff99a799..b752c48612 100644 --- a/src/cmd/compile/internal/test/abiutils_test.go +++ b/src/cmd/compile/internal/test/abiutils_test.go @@ -14,6 +14,7 @@ import ( "cmd/internal/obj" "cmd/internal/obj/x86" "cmd/internal/src" + "fmt" "os" "testing" ) @@ -359,3 +360,38 @@ func TestABINumParamRegs(t *testing.T) { nrtest(t, a, 12) } + +func TestABIUtilsComputePadding(t *testing.T) { + // type s1 { f1 int8; f2 int16; f3 struct{}; f4 int32; f5 int64 } + i8 := types.Types[types.TINT8] + i16 := types.Types[types.TINT16] + i32 := types.Types[types.TINT32] + i64 := types.Types[types.TINT64] + emptys := mkstruct([]*types.Type{}) + s1 := mkstruct([]*types.Type{i8, i16, emptys, i32, i64}) + // func (p1 int32, p2 s1, p3 emptys, p4 [1]int32) + a1 := types.NewArray(i32, 1) + ft := mkFuncType(nil, []*types.Type{i32, s1, emptys, a1}, []*types.Type{}) + + // Run abitest() just to document what we're expected to see. + exp := makeExpectedDump(` + IN 0: R{ I0 } spilloffset: 0 typ: int32 + IN 1: R{ I1 I2 I3 I4 } spilloffset: 8 typ: struct { int8; int16; struct {}; int32; int64 } + IN 2: R{ } offset: 0 typ: struct {} + IN 3: R{ I5 } spilloffset: 24 typ: [1]int32 + offsetToSpillArea: 0 spillAreaSize: 32 +`) + abitest(t, ft, exp) + + // Analyze with full set of registers, then call ComputePadding + // on the second param, verifying the results. + regRes := configAMD64.ABIAnalyze(ft, false) + padding := make([]uint64, 32) + parm := regRes.InParams()[1] + padding = parm.ComputePadding(padding) + want := "[1 1 1 0]" + got := fmt.Sprintf("%+v", padding) + if got != want { + t.Errorf("padding mismatch: wanted %q got %q\n", got, want) + } +} |