// 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, []*Value) {
+ if x.debug {
+ x.indent(3)
+ defer x.indent(-3)
+ x.Printf("rewriteArgs(%s; %d)\n", v.LongString(), firstArg)
+ }
// Thread the stores on the memory arg
aux := v.Aux.(*AuxCall)
pos := v.Pos.WithNotStmt()
aOffset = aux.OffsetOfArg(auxI)
}
if x.debug {
- x.Printf("storeArg %s, %v, %d\n", a.LongString(), aType, aOffset)
+ x.Printf("...storeArg %s, %v, %d\n", a.LongString(), aType, aOffset)
}
rc.init(aRegs, aux.abiInfo, result, x.sp)
mem = x.storeArgOrLoad(pos, v.Block, a, mem, aType, aOffset, 0, rc)
}
}
if isBlockMultiValueExit(b) {
+ x.indent(3)
// Very similar to code in rewriteArgs, but results instead of args.
v := b.Controls[0]
m0 := v.MemoryArg()
aux := f.OwnAux
pos := v.Pos.WithNotStmt()
allResults := []*Value{}
+ if x.debug {
+ x.Printf("multiValueExit rewriting %s\n", v.LongString())
+ }
+ var oldArgs []*Value
for j, a := range v.Args[:len(v.Args)-1] {
+ oldArgs = append(oldArgs, a)
i := int64(j)
auxType := aux.TypeOfResult(i)
auxBase := b.NewValue2A(v.Pos, OpLocalAddr, types.NewPtr(auxType), aux.NameOfResult(i), x.sp, mem)
v.AddArg(mem)
v.Type = types.NewResults(append(abi.RegisterTypes(aux.abiInfo.OutParams()), types.TypeMem))
b.SetControl(v)
+ for _, a := range oldArgs {
+ if a.Uses == 0 {
+ if x.debug {
+ x.Printf("...marking %v unused\n", a.LongString())
+ }
+ a.reset(OpInvalid)
+ }
+ }
+ if x.debug {
+ x.Printf("...multiValueExit new result %s\n", v.LongString())
+ }
+ x.indent(-3)
}
}
--- /dev/null
+// run
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type patchlist struct {
+ head, tail uint32
+}
+
+type frag struct {
+ i uint32
+ out patchlist
+}
+
+//go:noinline
+//go:registerparams
+func patch(l patchlist, i uint32) {
+}
+
+//go:noinline
+//go:registerparams
+func badbad(f1, f2 frag) frag {
+ // concat of failure is failure
+ if f1.i == 0 || f2.i == 0 { // internal compiler error: 'badbad': incompatible OpArgIntReg [4]: v42 and v26
+ return frag{}
+ }
+ patch(f1.out, f2.i)
+ return frag{f1.i, f2.out}
+}
+
+func main() {
+ badbad(frag{i: 2}, frag{i: 3})
+}