diff options
author | David Chase <drchase@google.com> | 2021-02-22 21:51:35 -0500 |
---|---|---|
committer | David Chase <drchase@google.com> | 2021-03-04 19:45:11 +0000 |
commit | 9d88a9e2bf89068238ed02a0c960e58f547bb102 (patch) | |
tree | 97b23a5d25fbd2f5fd3e3060b1d7b581b99c19f7 /src/cmd/compile/internal/abi/abiutils.go | |
parent | 2d30c94874c127d9028e29b77fadeb284c23e89a (diff) | |
download | go-9d88a9e2bf89068238ed02a0c960e58f547bb102.tar.gz go-9d88a9e2bf89068238ed02a0c960e58f547bb102.zip |
cmd/compile: implement simple register results
at least for ints and strings
includes simple test
For #40724.
Change-Id: Ib8484e5b957b08f961574a67cfd93d3d26551558
Reviewed-on: https://go-review.googlesource.com/c/go/+/295309
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 | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index f84f8f8e01..ffa709965c 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -101,6 +101,70 @@ func (a *ABIParamAssignment) Offset() int32 { return a.offset } +// RegisterTypes returns a slice of the types of the registers +// corresponding to a slice of parameters. The returned slice +// has capacity for one more, likely a memory type. +func RegisterTypes(apa []ABIParamAssignment) []*types.Type { + rcount := 0 + for _, pa := range apa { + rcount += len(pa.Registers) + } + if rcount == 0 { + // Note that this catches top-level struct{} and [0]Foo, which are stack allocated. + return make([]*types.Type, 0, 1) + } + rts := make([]*types.Type, 0, rcount+1) + for _, pa := range apa { + if len(pa.Registers) == 0 { + continue + } + rts = appendParamRegs(rts, pa.Type) + } + return rts +} + +func appendParamRegs(rts []*types.Type, t *types.Type) []*types.Type { + if t.IsScalar() || t.IsPtrShaped() { + if t.IsComplex() { + c := types.FloatForComplex(t) + return append(rts, c, c) + } else { + if int(t.Size()) <= types.RegSize { + return append(rts, t) + } + // assume 64bit int on 32-bit machine + // TODO endianness? Should high-order (sign bits) word come first? + if t.IsSigned() { + rts = append(rts, types.Types[types.TINT32]) + } else { + rts = append(rts, types.Types[types.TUINT32]) + } + return append(rts, types.Types[types.TUINT32]) + } + } else { + typ := t.Kind() + 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()) + } + 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) + } + } + case types.TSLICE: + return appendParamRegs(rts, synthSlice) + case types.TSTRING: + return appendParamRegs(rts, synthString) + case types.TINTER: + return appendParamRegs(rts, synthIface) + } + } + return rts +} + // 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. |