}
}
+ wrapArgs := n.List.Slice()
+ // If there's a receiver argument, it needs to be passed through the wrapper too.
+ if n.Op == OCALLMETH || n.Op == OCALLINTER {
+ recv := n.Left.Left
+ wrapArgs = append([]*Node{recv}, wrapArgs...)
+ }
+
// origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion.
- origArgs := make([]*Node, n.List.Len())
+ origArgs := make([]*Node, len(wrapArgs))
t := nod(OTFUNC, nil, nil)
- for i, arg := range n.List.Slice() {
+ for i, arg := range wrapArgs {
s := lookupN("a", i)
if !isBuiltinCall && arg.Op == OCONVNOP && arg.Type.IsUintptr() && arg.Left.Type.IsUnsafePtr() {
origArgs[i] = arg
arg = arg.Left
- n.List.SetIndex(i, arg)
+ wrapArgs[i] = arg
}
t.List.Append(symfield(s, arg.Type))
}
arg.Type = origArg.Type
args[i] = arg
}
+ if n.Op == OCALLMETH || n.Op == OCALLINTER {
+ // Move wrapped receiver argument back to its appropriate place.
+ recv := typecheck(args[0], ctxExpr)
+ n.Left.Left = recv
+ args = args[1:]
+ }
call := nod(n.Op, nil, nil)
if !isBuiltinCall {
call.Op = OCALL
call = nod(OCALL, nil, nil)
call.Left = fn.Func.Nname
- call.List.Set(n.List.Slice())
+ call.List.Set(wrapArgs)
call = typecheck(call, ctxStmt)
call = walkexpr(call, init)
return call
return test("return", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
}
+type S struct{}
+
+//go:noinline
+//go:uintptrescapes
+func (S) test(s string, p, q uintptr, rest ...uintptr) int {
+ return test(s, p, q, rest...)
+}
+
func main() {
test("normal", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
<-done
}()
<-done
+ func() {
+ for {
+ defer test("defer in for loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
+ break
+ }
+ }()
+
+ <-done
+ func() {
+ s := &S{}
+ defer s.test("method call", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
+ }()
+ <-done
+
+ func() {
+ s := &S{}
+ for {
+ defer s.test("defer method loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
+ break
+ }
+ }()
+ <-done
+
f()
<-done
}