diff options
author | David Chase <drchase@google.com> | 2021-02-23 20:00:31 -0500 |
---|---|---|
committer | David Chase <drchase@google.com> | 2021-03-04 20:18:16 +0000 |
commit | c015f76acb73990d4cb7fb056165b64d79b1b037 (patch) | |
tree | 264fdffc93c704fea2aee0da55072196d02ea4bd /src/cmd/compile/internal/abi/abiutils.go | |
parent | 77505c25d83a2130011736d6a2a915eaa3ae230a (diff) | |
download | go-c015f76acb73990d4cb7fb056165b64d79b1b037.tar.gz go-c015f76acb73990d4cb7fb056165b64d79b1b037.zip |
cmd/compile: implement too-big-to-SSA struct passing in registers
Added a test that exercises named results
Change-Id: Ie228b68f4f846266595a95e0f65a6e4b8bf79635
Reviewed-on: https://go-review.googlesource.com/c/go/+/297029
Trust: David Chase <drchase@google.com>
Run-TryBot: David Chase <drchase@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src/cmd/compile/internal/abi/abiutils.go')
-rw-r--r-- | src/cmd/compile/internal/abi/abiutils.go | 59 |
1 files changed, 52 insertions, 7 deletions
diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index ffa709965c..3c07be62e0 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -118,12 +118,22 @@ func RegisterTypes(apa []ABIParamAssignment) []*types.Type { if len(pa.Registers) == 0 { continue } - rts = appendParamRegs(rts, pa.Type) + rts = appendParamTypes(rts, pa.Type) } return rts } -func appendParamRegs(rts []*types.Type, t *types.Type) []*types.Type { +func (pa *ABIParamAssignment) RegisterTypesAndOffsets() ([]*types.Type, []int64) { + l := len(pa.Registers) + if l == 0 { + return nil, nil + } + typs := make([]*types.Type, 0, l) + offs := make([]int64, 0, l) + return appendParamTypes(typs, pa.Type), appendParamOffsets(offs, 0, pa.Type) +} + +func appendParamTypes(rts []*types.Type, t *types.Type) []*types.Type { if t.IsScalar() || t.IsPtrShaped() { if t.IsComplex() { c := types.FloatForComplex(t) @@ -146,25 +156,60 @@ func appendParamRegs(rts []*types.Type, t *types.Type) []*types.Type { switch typ { case types.TARRAY: for i := int64(0); i < t.Size(); i++ { // 0 gets no registers, plus future-proofing. - rts = appendParamRegs(rts, t.Elem()) + rts = appendParamTypes(rts, t.Elem()) } case types.TSTRUCT: for _, f := range t.FieldSlice() { if f.Type.Size() > 0 { // embedded zero-width types receive no registers - rts = appendParamRegs(rts, f.Type) + rts = appendParamTypes(rts, f.Type) } } case types.TSLICE: - return appendParamRegs(rts, synthSlice) + return appendParamTypes(rts, synthSlice) case types.TSTRING: - return appendParamRegs(rts, synthString) + return appendParamTypes(rts, synthString) case types.TINTER: - return appendParamRegs(rts, synthIface) + return appendParamTypes(rts, synthIface) } } return rts } +// appendParamOffsets appends the offset(s) of type t, starting from "at", +// to input offsets, and returns the longer slice. +func appendParamOffsets(offsets []int64, at int64, t *types.Type) []int64 { + at = align(at, t) + if t.IsScalar() || t.IsPtrShaped() { + if t.IsComplex() || int(t.Width) > types.RegSize { // complex and *int64 on 32-bit + s := t.Width / 2 + return append(offsets, at, at+s) + } else { + return append(offsets, at) + } + } else { + typ := t.Kind() + switch typ { + case types.TARRAY: + for i := int64(0); i < t.NumElem(); i++ { + offsets = appendParamOffsets(offsets, at, t.Elem()) + } + return offsets + case types.TSTRUCT: + for _, f := range t.FieldSlice() { + offsets = appendParamOffsets(offsets, at, f.Type) + at += f.Type.Width + } + case types.TSLICE: + return appendParamOffsets(offsets, at, synthSlice) + case types.TSTRING: + return appendParamOffsets(offsets, at, synthString) + case types.TINTER: + return appendParamOffsets(offsets, at, synthIface) + } + } + return offsets +} + // SpillOffset returns the offset *within the spill area* for the parameter that "a" describes. // Registers will be spilled here; if a memory home is needed (for a pointer method e.g.) // then that will be the address. |