diff options
author | David Chase <drchase@google.com> | 2021-02-19 17:11:40 -0500 |
---|---|---|
committer | David Chase <drchase@google.com> | 2021-03-04 16:19:12 +0000 |
commit | a2d92b5143ad6ed1b55b71032c5c1f468ba76fd4 (patch) | |
tree | 303c0fae9984d9e23366e183825d0dd5421dc7ae /src/cmd/compile/internal/ssa/stackalloc.go | |
parent | 868a110c568591d9085996ba05c94593809a437a (diff) | |
download | go-a2d92b5143ad6ed1b55b71032c5c1f468ba76fd4.tar.gz go-a2d92b5143ad6ed1b55b71032c5c1f468ba76fd4.zip |
cmd/compile: register abi, morestack work and mole whacking
Morestack works for non-pointer register parameters
Within a function body, pointer-typed parameters are correctly
tracked.
Results still not hooked up.
For #40724.
Change-Id: Icaee0b51d0da54af983662d945d939b756088746
Reviewed-on: https://go-review.googlesource.com/c/go/+/294410
Trust: David Chase <drchase@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/stackalloc.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/stackalloc.go | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/src/cmd/compile/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go index 041e7855f6..45058d4e72 100644 --- a/src/cmd/compile/internal/ssa/stackalloc.go +++ b/src/cmd/compile/internal/ssa/stackalloc.go @@ -112,7 +112,7 @@ func (s *stackAllocState) init(f *Func, spillLive [][]ID) { for _, v := range b.Values { s.values[v.ID].typ = v.Type s.values[v.ID].needSlot = !v.Type.IsMemory() && !v.Type.IsVoid() && !v.Type.IsFlags() && f.getHome(v.ID) == nil && !v.rematerializeable() && !v.OnWasmStack - s.values[v.ID].isArg = v.Op == OpArg + s.values[v.ID].isArg = hasAnyArgOp(v) if f.pass.debug > stackDebug && s.values[v.ID].needSlot { fmt.Printf("%s needs a stack slot\n", v) } @@ -151,28 +151,29 @@ func (s *stackAllocState) stackalloc() { // Allocate args to their assigned locations. for _, v := range f.Entry.Values { - if v.Op != OpArg { // && v.Op != OpArgFReg && v.Op != OpArgIReg { + if !hasAnyArgOp(v) { continue } if v.Aux == nil { f.Fatalf("%s has nil Aux\n", v.LongString()) } - var loc LocalSlot - var name *ir.Name - var offset int64 if v.Op == OpArg { - name = v.Aux.(*ir.Name) - offset = v.AuxInt - } else { - nameOff := v.Aux.(*AuxNameOffset) - name = nameOff.Name - offset = nameOff.Offset + loc := LocalSlot{N: v.Aux.(*ir.Name), Type: v.Type, Off: v.AuxInt} + if f.pass.debug > stackDebug { + fmt.Printf("stackalloc OpArg %s to %s\n", v, loc) + } + f.setHome(v, loc) + continue } - loc = LocalSlot{N: name, Type: v.Type, Off: offset} + + nameOff := v.Aux.(*AuxNameOffset) + loc := LocalSlot{N: nameOff.Name, Type: v.Type, Off: nameOff.Offset} if f.pass.debug > stackDebug { - fmt.Printf("stackalloc %s to %s\n", v, loc) + fmt.Printf("stackalloc Op%s %s to %s\n", v.Op, v, loc) } - f.setHome(v, loc) + // register args already allocated to registers, but need to know the stack allocation for later + reg := f.getHome(v.ID).(*Register) + f.RegArgs = append(f.RegArgs, ArgPair{reg: reg, mem: loc}) } // For each type, we keep track of all the stack slots we @@ -209,7 +210,7 @@ func (s *stackAllocState) stackalloc() { s.nNotNeed++ continue } - if v.Op == OpArg { + if hasAnyArgOp(v) { s.nArgSlot++ continue // already picked } @@ -396,7 +397,7 @@ func (s *stackAllocState) buildInterferenceGraph() { for _, id := range live.contents() { // Note: args can have different types and still interfere // (with each other or with other values). See issue 23522. - if s.values[v.ID].typ.Compare(s.values[id].typ) == types.CMPeq || v.Op == OpArg || s.values[id].isArg { + if s.values[v.ID].typ.Compare(s.values[id].typ) == types.CMPeq || hasAnyArgOp(v) || s.values[id].isArg { s.interfere[v.ID] = append(s.interfere[v.ID], id) s.interfere[id] = append(s.interfere[id], v.ID) } @@ -407,13 +408,15 @@ func (s *stackAllocState) buildInterferenceGraph() { live.add(a.ID) } } - if v.Op == OpArg && s.values[v.ID].needSlot { + if hasAnyArgOp(v) && s.values[v.ID].needSlot { // OpArg is an input argument which is pre-spilled. // We add back v.ID here because we want this value // to appear live even before this point. Being live // all the way to the start of the entry block prevents other // values from being allocated to the same slot and clobbering // the input value before we have a chance to load it. + + // TODO(register args) this is apparently not wrong for register args -- is it necessary? live.add(v.ID) } } @@ -430,3 +433,7 @@ func (s *stackAllocState) buildInterferenceGraph() { } } } + +func hasAnyArgOp(v *Value) bool { + return v.Op == OpArg || v.Op == OpArgIntReg || v.Op == OpArgFloatReg +} |