1
0
mirror of https://github.com/golang/go synced 2024-11-08 00:16:14 -07:00

cmd/compile: pass arguments as register parameters to StaticCall.

Additional register-parameter plumbing, not all the way to the end;
if you test register parameter-passing, it fails mid-compilation.

For #40724.

Change-Id: Ibb675022c9156779a451726329890e52fca1cb33
Reviewed-on: https://go-review.googlesource.com/c/go/+/293398
Trust: David Chase <drchase@google.com>
Run-TryBot: David Chase <drchase@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
This commit is contained in:
David Chase 2021-02-17 18:01:52 -05:00
parent 04a4dca2ac
commit 95ff296a11

View File

@ -806,7 +806,6 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value,
s := mem
if storeRc.hasRegs() {
// TODO(register args)
storeRc.addArg(source)
} else {
dst := x.offsetFrom(storeRc.storeDest, offset, types.NewPtr(t))
@ -821,21 +820,15 @@ func (x *expandState) storeArgOrLoad(pos src.XPos, b *Block, source, mem *Value,
// rewriteArgs removes all the Args from a call and converts the call args into appropriate
// stores (or later, register movement). Extra args for interface and closure calls are ignored,
// but removed.
func (x *expandState) rewriteArgs(v *Value, firstArg int) *Value {
func (x *expandState) rewriteArgs(v *Value, firstArg int) (*Value, []*Value) {
// Thread the stores on the memory arg
aux := v.Aux.(*AuxCall)
pos := v.Pos.WithNotStmt()
m0 := v.MemoryArg()
mem := m0
allResults := []*Value{}
for i, a := range v.Args {
if i < firstArg {
continue
}
if a == m0 { // mem is last.
break
}
auxI := int64(i - firstArg)
for i, a := range v.Args[firstArg : len(v.Args)-1] { // skip leading non-parameter SSA Args and trailing mem SSA Arg.
auxI := int64(i)
aRegs := aux.RegsOfArg(auxI)
aType := aux.TypeOfArg(auxI)
if a.Op == OpDereference {
@ -863,11 +856,10 @@ func (x *expandState) rewriteArgs(v *Value, firstArg int) *Value {
}
rc.init(aRegs, aux.abiInfo, result, x.sp)
mem = x.storeArgOrLoad(pos, v.Block, a, mem, aType, aOffset, 0, rc)
// TODO append mem to Result, update type
}
}
v.resetArgs()
return mem
return mem, allResults
}
// expandCalls converts LE (Late Expansion) calls that act like they receive value args into a lower-level form
@ -921,17 +913,30 @@ func expandCalls(f *Func) {
for _, v := range b.Values {
switch v.Op {
case OpStaticLECall:
mem := x.rewriteArgs(v, 0)
v.SetArgs1(mem)
mem, results := x.rewriteArgs(v, 0)
v.AddArgs(results...)
v.AddArg(mem)
case OpClosureLECall:
code := v.Args[0]
context := v.Args[1]
mem := x.rewriteArgs(v, 2)
v.SetArgs3(code, context, mem)
mem, results := x.rewriteArgs(v, 2)
if len(results) == 0 {
v.SetArgs3(code, context, mem)
} else {
v.SetArgs2(code, context)
v.AddArgs(results...)
v.AddArg(mem)
}
case OpInterLECall:
code := v.Args[0]
mem := x.rewriteArgs(v, 1)
v.SetArgs2(code, mem)
mem, results := x.rewriteArgs(v, 1)
if len(results) == 0 {
v.SetArgs2(code, mem)
} else {
v.SetArgs1(code)
v.AddArgs(results...)
v.AddArg(mem)
}
}
}
if isBlockMultiValueExit(b) {
@ -942,11 +947,8 @@ func expandCalls(f *Func) {
aux := f.OwnAux
pos := v.Pos.WithNotStmt()
allResults := []*Value{}
for j, a := range v.Args {
for j, a := range v.Args[:len(v.Args)-1] {
i := int64(j)
if a == m0 {
break
}
auxType := aux.TypeOfResult(i)
auxBase := b.NewValue2A(v.Pos, OpLocalAddr, types.NewPtr(auxType), aux.results[i].Name, x.sp, mem)
auxOffset := int64(0)
@ -978,11 +980,10 @@ func expandCalls(f *Func) {
result = &allResults
}
rc.init(aRegs, aux.abiInfo, result, auxBase)
// TODO REGISTER
mem = x.storeArgOrLoad(v.Pos, b, a, mem, aux.TypeOfResult(i), auxOffset, 0, rc)
// TODO append mem to Result, update type
}
}
// TODO REGISTER -- keep the Result for block control, splice in contents of AllResults
b.SetControl(mem)
v.reset(OpInvalid) // otherwise it can have a mem operand which will fail check(), even though it is dead.
}