aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/stackalloc.go
diff options
context:
space:
mode:
authorDavid Chase <drchase@google.com>2021-02-19 17:11:40 -0500
committerDavid Chase <drchase@google.com>2021-03-04 16:19:12 +0000
commita2d92b5143ad6ed1b55b71032c5c1f468ba76fd4 (patch)
tree303c0fae9984d9e23366e183825d0dd5421dc7ae /src/cmd/compile/internal/ssa/stackalloc.go
parent868a110c568591d9085996ba05c94593809a437a (diff)
downloadgo-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.go41
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
+}