Keep track of the outargs size needed at each call.
Compute the size of the outargs section of the stack frame. It's just
the max of the outargs size at all the callsites in the function.
Change-Id: I3d0640f654f01307633b1a5f75bab16e211ea6c0
Reviewed-on: https://go-review.googlesource.com/12178
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
entry := s.newValue2(ssa.OpLoad, s.config.Uintptr, closure, s.mem())
call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, entry, closure, s.mem())
}
+ dowidth(n.Left.Type)
+ call.AuxInt = n.Left.Type.Argwid // call operations carry the argsize of the callee along with them
b := s.endBlock()
b.Kind = ssa.BlockCall
b.Control = call
- Make calls clobber all registers
StackAlloc:
- - Compute size of outargs section correctly
- Sort variables so all ptr-containing ones are first (so stack
maps are smaller)
- Reuse stack slots for noninterfering and type-compatible variables
(If (SETB cmp) yes no) -> (ULT cmp yes no)
(If cond yes no) && cond.Op == OpAMD64MOVBload -> (NE (TESTB <TypeFlags> cond cond) yes no)
-(StaticCall {target} mem) -> (CALLstatic {target} mem)
-(ClosureCall entry closure mem) -> (CALLclosure entry closure mem)
+(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
+(ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
// Rules below here apply some simple optimizations after lowering.
// TODO: Should this be a separate pass?
endf8ca12fe79290bc82b11cfa463bc9413:
;
case OpClosureCall:
- // match: (ClosureCall entry closure mem)
+ // match: (ClosureCall [argwid] entry closure mem)
// cond:
- // result: (CALLclosure entry closure mem)
+ // result: (CALLclosure [argwid] entry closure mem)
{
+ argwid := v.AuxInt
entry := v.Args[0]
closure := v.Args[1]
mem := v.Args[2]
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
+ v.AuxInt = argwid
v.AddArg(entry)
v.AddArg(closure)
v.AddArg(mem)
return true
}
- goto endee26da781e813a3c602ccb4f7ade98c7
- endee26da781e813a3c602ccb4f7ade98c7:
+ goto endfd75d26316012d86cb71d0dd1214259b
+ endfd75d26316012d86cb71d0dd1214259b:
;
case OpConst:
// match: (Const <t> [val])
end78e66b6fc298684ff4ac8aec5ce873c9:
;
case OpStaticCall:
- // match: (StaticCall {target} mem)
+ // match: (StaticCall [argwid] {target} mem)
// cond:
- // result: (CALLstatic {target} mem)
+ // result: (CALLstatic [argwid] {target} mem)
{
+ argwid := v.AuxInt
target := v.Aux
mem := v.Args[0]
v.Op = OpAMD64CALLstatic
v.AuxInt = 0
v.Aux = nil
v.resetArgs()
+ v.AuxInt = argwid
v.Aux = target
v.AddArg(mem)
return true
}
- goto end1948857a7cfc2a4f905045e58d3b9ec1
- end1948857a7cfc2a4f905045e58d3b9ec1:
+ goto end32c5cbec813d1c2ae94fc9b1090e4b2a
+ end32c5cbec813d1c2ae94fc9b1090e4b2a:
;
case OpStore:
// match: (Store ptr val mem)
func stackalloc(f *Func) {
home := f.RegAlloc
- // First compute the size of the outargs section.
- n := int64(16) //TODO: compute max of all callsites
-
- // Include one slot for deferreturn.
- if false && n < f.Config.ptrSize { //TODO: check for deferreturn
- n = f.Config.ptrSize
+ // Start with space for callee arguments/returns.
+ var n int64
+ for _, b := range f.Blocks {
+ if b.Kind != BlockCall {
+ continue
+ }
+ v := b.Control
+ if n < v.AuxInt {
+ n = v.AuxInt
+ }
}
// TODO: group variables by ptr/nonptr, size, etc. Emit ptr vars last