diff options
author | Cuong Manh Le <cuong.manhle.vn@gmail.com> | 2021-06-27 22:25:21 +0700 |
---|---|---|
committer | Cuong Manh Le <cuong.manhle.vn@gmail.com> | 2021-06-28 02:00:50 +0000 |
commit | f99b3fe2ab6b142bc49b653c6547655cb7114625 (patch) | |
tree | 604114b449ed583b30c653caa9fbe809ea3f6e37 /src/cmd/compile/internal/walk | |
parent | a8861b907dc9d6fece2d515e45dc5091ffd4be63 (diff) | |
download | go-f99b3fe2ab6b142bc49b653c6547655cb7114625.tar.gz go-f99b3fe2ab6b142bc49b653c6547655cb7114625.zip |
[dev.typeparams] cmd/compile: move MethodValueWrapper to walk
walk is the only pass that use the function, so un-export it, too.
Change-Id: I32ec64d1c15fda7bb54bd8efa528ed32c102876d
Reviewed-on: https://go-review.googlesource.com/c/go/+/330841
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/walk')
-rw-r--r-- | src/cmd/compile/internal/walk/closure.go | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/walk/closure.go b/src/cmd/compile/internal/walk/closure.go index f399a26689..a86ed2ab80 100644 --- a/src/cmd/compile/internal/walk/closure.go +++ b/src/cmd/compile/internal/walk/closure.go @@ -179,7 +179,7 @@ func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { clos := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil) clos.SetEsc(n.Esc()) - clos.List = []ir.Node{ir.NewUnaryExpr(base.Pos, ir.OCFUNC, typecheck.MethodValueWrapper(n).Nname), n.X} + clos.List = []ir.Node{ir.NewUnaryExpr(base.Pos, ir.OCFUNC, methodValueWrapper(n).Nname), n.X} addr := typecheck.NodAddr(clos) addr.SetEsc(n.Esc()) @@ -198,3 +198,81 @@ func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node { return walkExpr(cfn, init) } + +// methodValueWrapper returns the DCLFUNC node representing the +// wrapper function (*-fm) needed for the given method value. If the +// wrapper function hasn't already been created yet, it's created and +// added to typecheck.Target.Decls. +func methodValueWrapper(dot *ir.SelectorExpr) *ir.Func { + if dot.Op() != ir.OMETHVALUE { + base.Fatalf("methodValueWrapper: unexpected %v (%v)", dot, dot.Op()) + } + + t0 := dot.Type() + meth := dot.Sel + rcvrtype := dot.X.Type() + sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm") + + if sym.Uniq() { + return sym.Def.(*ir.Func) + } + sym.SetUniq(true) + + savecurfn := ir.CurFunc + saveLineNo := base.Pos + ir.CurFunc = nil + + // Set line number equal to the line number where the method is declared. + if pos := dot.Selection.Pos; pos.IsKnown() { + base.Pos = pos + } + // Note: !dot.Selection.Pos.IsKnown() happens for method expressions where + // the method is implicitly declared. The Error method of the + // built-in error type is one such method. We leave the line + // number at the use of the method expression in this + // case. See issue 29389. + + tfn := ir.NewFuncType(base.Pos, nil, + typecheck.NewFuncParams(t0.Params(), true), + typecheck.NewFuncParams(t0.Results(), false)) + + fn := typecheck.DeclFunc(sym, tfn) + fn.SetDupok(true) + fn.SetNeedctxt(true) + fn.SetWrapper(true) + + // Declare and initialize variable holding receiver. + ptr := ir.NewNameAt(base.Pos, typecheck.Lookup(".this")) + ptr.Class = ir.PAUTOHEAP + ptr.SetType(rcvrtype) + ptr.Curfn = fn + ptr.SetIsClosureVar(true) + ptr.SetByval(true) + fn.ClosureVars = append(fn.ClosureVars, ptr) + + call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil) + call.Args = ir.ParamNames(tfn.Type()) + call.IsDDD = tfn.Type().IsVariadic() + + var body ir.Node = call + if t0.NumResults() != 0 { + ret := ir.NewReturnStmt(base.Pos, nil) + ret.Results = []ir.Node{call} + body = ret + } + + fn.Body = []ir.Node{body} + typecheck.FinishFuncBody() + + typecheck.Func(fn) + // Need to typecheck the body of the just-generated wrapper. + // typecheckslice() requires that Curfn is set when processing an ORETURN. + ir.CurFunc = fn + typecheck.Stmts(fn.Body) + sym.Def = fn + typecheck.Target.Decls = append(typecheck.Target.Decls, fn) + ir.CurFunc = savecurfn + base.Pos = saveLineNo + + return fn +} |