}
n.SetWalked(true)
- // If this is a method call t.M(...),
- // rewrite into a function call T.M(t, ...).
// TODO(mdempsky): Do this right after type checking.
- if n.Op() == ir.OCALLMETH {
- withRecv := make([]ir.Node, len(n.Args)+1)
- dot := n.X.(*ir.SelectorExpr)
- withRecv[0] = dot.X
- copy(withRecv[1:], n.Args)
- n.Args = withRecv
-
- dot = ir.NewSelectorExpr(dot.Pos(), ir.OXDOT, ir.TypeNode(dot.X.Type()), dot.Selection.Sym)
-
- n.SetOp(ir.OCALLFUNC)
- n.X = typecheck.Expr(dot)
- }
+ rewriteMethodCall(n)
args := n.Args
params := n.X.Type().Params()
n.Args = args
}
+// rewriteMethodCall rewrites a method call t.M(...) into a function call T.M(t, ...).
+func rewriteMethodCall(n *ir.CallExpr) {
+ if n.Op() != ir.OCALLMETH {
+ return
+ }
+ withRecv := make([]ir.Node, len(n.Args)+1)
+ dot := n.X.(*ir.SelectorExpr)
+ withRecv[0] = dot.X
+ copy(withRecv[1:], n.Args)
+ n.Args = withRecv
+
+ dot = ir.NewSelectorExpr(dot.Pos(), ir.OXDOT, ir.TypeNode(dot.X.Type()), dot.Selection.Sym)
+
+ n.SetOp(ir.OCALLFUNC)
+ n.X = typecheck.Expr(dot)
+}
+
// walkDivMod walks an ODIV or OMOD node.
func walkDivMod(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
n.X = walkExpr(n.X, init)
init.Append(ir.TakeInit(n)...)
}
+ // TODO(mdempsky): Do this right after type checking.
+ rewriteMethodCall(n)
+
isBuiltinCall := n.Op() != ir.OCALLFUNC && n.Op() != ir.OCALLMETH && n.Op() != ir.OCALLINTER
// Turn f(a, b, []T{c, d, e}...) back into f(a, b, c, d, e).
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 {
+ runtime.GC()
+ runtime.GC()
+
+ if *(*string)(unsafe.Pointer(p)) != "ok" {
+ panic(s + ": p failed")
+ }
+ if *(*string)(unsafe.Pointer(q)) != "ok" {
+ panic(s + ": q failed")
+ }
+ for _, r := range rest {
+ if *(*string)(unsafe.Pointer(r)) != "ok" {
+ panic(s + ": r[i] failed")
+ }
+ }
+
+ done <- true
+ return 0
+}
+
func main() {
test("normal", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
<-done
}()
<-done
+ func() {
+ s := &S{}
+ defer s.test("method call", uintptr(setup()), uintptr(setup()))
+ }()
+ <-done
+
f()
<-done
}
--- /dev/null
+// compile
+
+// 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.
+
+// +build windows
+
+package p
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+var dllKernel = syscall.NewLazyDLL("Kernel32.dll")
+
+func Call() {
+ procLocalFree := dllKernel.NewProc("LocalFree")
+ defer procLocalFree.Call(uintptr(unsafe.Pointer(nil)))
+}