mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
77505c25d8
commit
c015f76acb
5 changed files with 190 additions and 26 deletions
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue