mirror of
https://github.com/golang/go
synced 2024-09-04 15:34:21 +00:00
[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:
parent
a8861b907d
commit
f99b3fe2ab
|
@ -218,86 +218,6 @@ func fnpkg(fn *ir.Name) *types.Pkg {
|
||||||
return fn.Sym().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
|
// tcClosure typechecks an OCLOSURE node. It also creates the named
|
||||||
// function associated with the closure.
|
// function associated with the closure.
|
||||||
// TODO: This creation of the named function should probably really be done in a
|
// TODO: This creation of the named function should probably really be done in a
|
||||||
|
|
|
@ -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 := ir.NewCompLitExpr(base.Pos, ir.OCOMPLIT, ir.TypeNode(typ), nil)
|
||||||
clos.SetEsc(n.Esc())
|
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 := typecheck.NodAddr(clos)
|
||||||
addr.SetEsc(n.Esc())
|
addr.SetEsc(n.Esc())
|
||||||
|
@ -198,3 +198,81 @@ func walkMethodValue(n *ir.SelectorExpr, init *ir.Nodes) ir.Node {
|
||||||
|
|
||||||
return walkExpr(cfn, init)
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue