aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/abi/abiutils.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/abi/abiutils.go')
-rw-r--r--src/cmd/compile/internal/abi/abiutils.go77
1 files changed, 56 insertions, 21 deletions
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),
}
}