From 382851c1fd135a99efbe128a3be0ce466d42506f Mon Sep 17 00:00:00 2001 From: David Chase Date: Sun, 7 Mar 2021 14:00:10 -0500 Subject: cmd/compile: fix failure to communicate between ABIinfo producer&consumer ABI info producer and consumer had different ideas for register order for parameters. Includes a test, includes improvements to debugging output. Updates #44816. Change-Id: I4812976f7a6c08d6fc02aac1ec0544b1f141cca6 Reviewed-on: https://go-review.googlesource.com/c/go/+/299570 Trust: David Chase Reviewed-by: Than McIntosh --- src/cmd/compile/internal/abi/abiutils.go | 77 +++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 21 deletions(-) (limited to 'src/cmd/compile/internal/abi/abiutils.go') diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index 7d5de1d528..ecde34313a 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -477,9 +477,9 @@ func (c *RegAmounts) regString(r RegIndex) string { return fmt.Sprintf("%d", r) } -// toString method renders an ABIParamAssignment in human-readable +// ToString method renders an ABIParamAssignment in human-readable // form, suitable for debugging or unit testing. -func (ri *ABIParamAssignment) toString(config *ABIConfig) string { +func (ri *ABIParamAssignment) ToString(config *ABIConfig, extra bool) string { regs := "R{" offname := "spilloffset" // offset is for spill for register(s) if len(ri.Registers) == 0 { @@ -487,19 +487,25 @@ func (ri *ABIParamAssignment) toString(config *ABIConfig) string { } for _, r := range ri.Registers { regs += " " + config.regAmounts.regString(r) + if extra { + regs += fmt.Sprintf("(%d)", r) + } + } + if extra { + regs += fmt.Sprintf(" | #I=%d, #F=%d", config.regAmounts.intRegs, config.regAmounts.floatRegs) } return fmt.Sprintf("%s } %s: %d typ: %v", regs, offname, ri.offset, ri.Type) } -// toString method renders an ABIParamResultInfo in human-readable +// String method renders an ABIParamResultInfo in human-readable // form, suitable for debugging or unit testing. func (ri *ABIParamResultInfo) String() string { res := "" for k, p := range ri.inparams { - res += fmt.Sprintf("IN %d: %s\n", k, p.toString(ri.config)) + res += fmt.Sprintf("IN %d: %s\n", k, p.ToString(ri.config, false)) } for k, r := range ri.outparams { - res += fmt.Sprintf("OUT %d: %s\n", k, r.toString(ri.config)) + res += fmt.Sprintf("OUT %d: %s\n", k, r.ToString(ri.config, false)) } res += fmt.Sprintf("offsetToSpillArea: %d spillAreaSize: %d", ri.offsetToSpillArea, ri.spillAreaSize) @@ -537,25 +543,54 @@ func (state *assignState) stackSlot(t *types.Type) int64 { return rv } -// allocateRegs returns a set of register indices for a parameter or result +// allocateRegs returns an ordered list of register indices for a parameter or result // that we've just determined to be register-assignable. The number of registers // needed is assumed to be stored in state.pUsed. -func (state *assignState) allocateRegs() []RegIndex { - regs := []RegIndex{} - - // integer - for r := state.rUsed.intRegs; r < state.rUsed.intRegs+state.pUsed.intRegs; r++ { - regs = append(regs, RegIndex(r)) +func (state *assignState) allocateRegs(regs []RegIndex, t *types.Type) []RegIndex { + if t.Width == 0 { + return regs } - state.rUsed.intRegs += state.pUsed.intRegs - - // floating - for r := state.rUsed.floatRegs; r < state.rUsed.floatRegs+state.pUsed.floatRegs; r++ { - regs = append(regs, RegIndex(r+state.rTotal.intRegs)) + ri := state.rUsed.intRegs + rf := state.rUsed.floatRegs + if t.IsScalar() || t.IsPtrShaped() { + if t.IsComplex() { + regs = append(regs, RegIndex(rf+state.rTotal.intRegs), RegIndex(rf+1+state.rTotal.intRegs)) + rf += 2 + } else if t.IsFloat() { + regs = append(regs, RegIndex(rf+state.rTotal.intRegs)) + rf += 1 + } else { + n := (int(t.Size()) + types.RegSize - 1) / types.RegSize + for i := 0; i < n; i++ { // looking ahead to really big integers + regs = append(regs, RegIndex(ri)) + ri += 1 + } + } + state.rUsed.intRegs = ri + state.rUsed.floatRegs = rf + return regs + } else { + typ := t.Kind() + switch typ { + case types.TARRAY: + for i := int64(0); i < t.NumElem(); i++ { + regs = state.allocateRegs(regs, t.Elem()) + } + return regs + case types.TSTRUCT: + for _, f := range t.FieldSlice() { + regs = state.allocateRegs(regs, f.Type) + } + return regs + case types.TSLICE: + return state.allocateRegs(regs, synthSlice) + case types.TSTRING: + return state.allocateRegs(regs, synthString) + case types.TINTER: + return state.allocateRegs(regs, synthIface) + } } - state.rUsed.floatRegs += state.pUsed.floatRegs - - return regs + panic(fmt.Errorf("Was not expecting type %s", t)) } // regAllocate creates a register ABIParamAssignment object for a param @@ -571,7 +606,7 @@ func (state *assignState) regAllocate(t *types.Type, name types.Object, isReturn return ABIParamAssignment{ Type: t, Name: name, - Registers: state.allocateRegs(), + Registers: state.allocateRegs([]RegIndex{}, t), offset: int32(spillLoc), } } -- cgit v1.2.3-54-g00ecf