[dev.ssa] cmd/compile: start arguments as spilled
Declare a function's arguments as having already been
spilled so their use just requires a restore.
Allow spill locations to be portions of larger objects the stack.
Required to load portions of compound input arguments.
Rename the memory input to InputMem. Use Arg for the
pre-spilled argument values.
Change-Id: I8fe2a03ffbba1022d98bfae2052b376b96d32dda
Reviewed-on: https://go-review.googlesource.com/16536
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 5a8e43d..2c935b7 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -97,7 +97,7 @@
// Allocate starting values
s.labels = map[string]*ssaLabel{}
s.labeledNodes = map[*Node]*ssaLabel{}
- s.startmem = s.entryNewValue0(ssa.OpArg, ssa.TypeMem)
+ s.startmem = s.entryNewValue0(ssa.OpInitMem, ssa.TypeMem)
s.sp = s.entryNewValue0(ssa.OpSP, Types[TUINTPTR]) // TODO: use generic pointer type (unsafe.Pointer?) instead
s.sb = s.entryNewValue0(ssa.OpSB, Types[TUINTPTR])
@@ -3168,6 +3168,12 @@
if name == &memVar {
return s.startmem
}
+ if canSSA(name) {
+ v := s.entryNewValue0A(ssa.OpArg, t, name)
+ // v starts with AuxInt == 0.
+ s.addNamedValue(name, v)
+ return v
+ }
// variable is live at the entry block. Load it.
addr := s.decladdrs[name]
if addr == nil {
@@ -3239,18 +3245,21 @@
// Don't track autotmp_ variables.
return
}
- if n.Class == PPARAM || n.Class == PPARAMOUT {
- // TODO: Remove this
+ if n.Class == PAUTO && (v.Type.IsString() || v.Type.IsSlice() || v.Type.IsInterface()) {
+ // TODO: can't handle auto compound objects with pointers yet.
+ // The live variable analysis barfs because we don't put VARDEF
+ // pseudos in the right place when we spill to these nodes.
return
}
if n.Class == PAUTO && n.Xoffset != 0 {
s.Fatalf("AUTO var with offset %s %d", n, n.Xoffset)
}
- values, ok := s.f.NamedValues[n]
+ loc := ssa.LocalSlot{N: n, Type: n.Type, Off: 0}
+ values, ok := s.f.NamedValues[loc]
if !ok {
- s.f.Names = append(s.f.Names, n)
+ s.f.Names = append(s.f.Names, loc)
}
- s.f.NamedValues[n] = append(values, v)
+ s.f.NamedValues[loc] = append(values, v)
}
// an unresolved branch
@@ -3873,11 +3882,17 @@
return
}
p := Prog(movSizeByType(v.Type))
- n := autoVar(v.Args[0])
+ n, off := autoVar(v.Args[0])
p.From.Type = obj.TYPE_MEM
- p.From.Name = obj.NAME_AUTO
p.From.Node = n
p.From.Sym = Linksym(n.Sym)
+ p.From.Offset = off
+ if n.Class == PPARAM {
+ p.From.Name = obj.NAME_PARAM
+ p.From.Offset += n.Xoffset
+ } else {
+ p.From.Name = obj.NAME_AUTO
+ }
p.To.Type = obj.TYPE_REG
p.To.Reg = regnum(v)
@@ -3889,11 +3904,17 @@
p := Prog(movSizeByType(v.Type))
p.From.Type = obj.TYPE_REG
p.From.Reg = regnum(v.Args[0])
- n := autoVar(v)
+ n, off := autoVar(v)
p.To.Type = obj.TYPE_MEM
- p.To.Name = obj.NAME_AUTO
p.To.Node = n
p.To.Sym = Linksym(n.Sym)
+ p.To.Offset = off
+ if n.Class == PPARAM {
+ p.To.Name = obj.NAME_PARAM
+ p.To.Offset += n.Xoffset
+ } else {
+ p.To.Name = obj.NAME_AUTO
+ }
case ssa.OpPhi:
// just check to make sure regalloc and stackalloc did it right
if v.Type.IsMemory() {
@@ -3912,9 +3933,10 @@
v.Fatalf("const value %v shouldn't have a location", v)
}
- case ssa.OpArg:
+ case ssa.OpInitMem:
// memory arg needs no code
- // TODO: check that only mem arg goes here.
+ case ssa.OpArg:
+ // input args need no code
case ssa.OpAMD64LoweredGetClosurePtr:
// Output is hardwired to DX only,
// and DX contains the closure pointer on
@@ -4476,9 +4498,11 @@
return ssaRegToReg[reg.(*ssa.Register).Num]
}
-// autoVar returns a *Node representing the auto variable assigned to v.
-func autoVar(v *ssa.Value) *Node {
- return v.Block.Func.RegAlloc[v.ID].(*ssa.LocalSlot).N.(*Node)
+// autoVar returns a *Node and int64 representing the auto variable and offset within it
+// where v should be spilled.
+func autoVar(v *ssa.Value) (*Node, int64) {
+ loc := v.Block.Func.RegAlloc[v.ID].(ssa.LocalSlot)
+ return loc.N.(*Node), loc.Off
}
// ssaExport exports a bunch of compiler services for the ssa backend.