[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>
This commit is contained in:
Cuong Manh Le 2021-06-27 22:25:21 +07:00
parent a8861b907d
commit f99b3fe2ab
2 changed files with 79 additions and 81 deletions

View file

@ -218,86 +218,6 @@ func fnpkg(fn *ir.Name) *types.Pkg {
return fn.Sym().Pkg
}
// 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 Target.Decls.
//
// TODO(mdempsky): Move into walk. This isn't part of type checking.
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,
NewFuncParams(t0.Params(), true),
NewFuncParams(t0.Results(), false))
fn := DeclFunc(sym, tfn)
fn.SetDupok(true)
fn.SetNeedctxt(true)
fn.SetWrapper(true)
// Declare and initialize variable holding receiver.
ptr := ir.NewNameAt(base.Pos, 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}
FinishFuncBody()
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
Stmts(fn.Body)
sym.Def = fn
Target.Decls = append(Target.Decls, fn)
ir.CurFunc = savecurfn
base.Pos = saveLineNo
return fn
}
// tcClosure typechecks an OCLOSURE node. It also creates the named
// function associated with the closure.
// TODO: This creation of the named function should probably really be done in a

View file

@ -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
}