mirror of
				https://github.com/golang/go.git
				synced 2025-10-31 00:30:57 +00:00 
			
		
		
		
	[dev.typeparams] cmd/compile: rewrite method call into method expression during escape analysis
CL 330331 extended escape analysis to analyze method expression calls the same as normal method calls. We can now simply desugar method calls into function calls in escape analysis. To do this, two things must be changed: - Folding the rewrite method call to method expression call into an export function in typecheck package, so others can re-use it. - walkCall now have to call usemethod for method expression calls. (It seems to me this is a bug in current tip, because if one write (*rtype).Method(typ, i) in package "reflect", then the function won't be marked with AttrReflectMethod) Passes toolstash -cmp. Change-Id: I4745ab6110b417c7fd32949cc799811a882cd2ec Reviewed-on: https://go-review.googlesource.com/c/go/+/330671 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
							
								
									f190a9280d
								
							
						
					
					
						commit
						2493c72742
					
				
					 4 changed files with 23 additions and 16 deletions
				
			
		|  | @ -50,7 +50,6 @@ func Call(call *ir.CallExpr) { | |||
| 		if base.Flag.LowerM != 0 { | ||||
| 			base.WarnfAt(call.Pos(), "devirtualizing %v to %v", sel, typ) | ||||
| 		} | ||||
| 		call.SetOp(ir.OCALLMETH) | ||||
| 		call.X = x | ||||
| 	case ir.ODOTINTER: | ||||
| 		// Promoted method from embedded interface-typed field (#42279). | ||||
|  |  | |||
|  | @ -46,6 +46,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir | |||
| 	case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: | ||||
| 		call := call.(*ir.CallExpr) | ||||
| 		typecheck.FixVariadicCall(call) | ||||
| 		typecheck.FixMethodCall(call) | ||||
| 
 | ||||
| 		// Pick out the function callee, if statically known. | ||||
| 		// | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ import ( | |||
| 	"go/token" | ||||
| ) | ||||
| 
 | ||||
| // package all the arguments that match a ... T parameter into a []T. | ||||
| // MakeDotArgs package all the arguments that match a ... T parameter into a []T. | ||||
| func MakeDotArgs(pos src.XPos, typ *types.Type, args []ir.Node) ir.Node { | ||||
| 	var n ir.Node | ||||
| 	if len(args) == 0 { | ||||
|  | @ -57,6 +57,25 @@ func FixVariadicCall(call *ir.CallExpr) { | |||
| 	call.IsDDD = true | ||||
| } | ||||
| 
 | ||||
| // FixMethodCall rewrites a method call t.M(...) into a function call T.M(t, ...). | ||||
| func FixMethodCall(call *ir.CallExpr) { | ||||
| 	if call.X.Op() != ir.ODOTMETH { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	dot := call.X.(*ir.SelectorExpr) | ||||
| 
 | ||||
| 	fn := Expr(ir.NewSelectorExpr(dot.Pos(), ir.OXDOT, ir.TypeNode(dot.X.Type()), dot.Selection.Sym)) | ||||
| 
 | ||||
| 	args := make([]ir.Node, 1+len(call.Args)) | ||||
| 	args[0] = dot.X | ||||
| 	copy(args[1:], call.Args) | ||||
| 
 | ||||
| 	call.SetOp(ir.OCALLFUNC) | ||||
| 	call.X = fn | ||||
| 	call.Args = args | ||||
| } | ||||
| 
 | ||||
| // ClosureType returns the struct type used to hold all the information | ||||
| // needed in the closure for clo (clo must be a OCLOSURE node). | ||||
| // The address of a variable of the returned type can be cast to a func. | ||||
|  |  | |||
|  | @ -489,7 +489,7 @@ func walkAddString(n *ir.AddStringExpr, init *ir.Nodes) ir.Node { | |||
| 
 | ||||
| // walkCall walks an OCALLFUNC, OCALLINTER, or OCALLMETH node. | ||||
| func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node { | ||||
| 	if n.Op() == ir.OCALLINTER || n.Op() == ir.OCALLMETH { | ||||
| 	if n.Op() == ir.OCALLINTER || n.X.Op() == ir.OMETHEXPR { | ||||
| 		// We expect both interface call reflect.Type.Method and concrete | ||||
| 		// call reflect.(*rtype).Method. | ||||
| 		usemethod(n) | ||||
|  | @ -549,20 +549,8 @@ func walkCall1(n *ir.CallExpr, init *ir.Nodes) { | |||
| 	} | ||||
| 	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) | ||||
| 		typecheck.FixMethodCall(n) | ||||
| 	} | ||||
| 
 | ||||
| 	args := n.Args | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Cuong Manh Le
						Cuong Manh Le