]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/noder: explicit receiver expression handling
authorMatthew Dempsky <mdempsky@google.com>
Sat, 6 Aug 2022 23:08:41 +0000 (16:08 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 10 Aug 2022 23:27:42 +0000 (23:27 +0000)
This CL adds a helper expression code for receiver addressing; i.e.,
the implicit addressing, dereferencing, and field selections involved
in changing the `x` in `x.M()` into an appropriate expression to pass
as an argument to the method.

Change-Id: I9be933e2a38c8f94f6a85d95b54f34164e5efb0a
Reviewed-on: https://go-review.googlesource.com/c/go/+/421820
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
src/cmd/compile/internal/noder/codes.go
src/cmd/compile/internal/noder/reader.go
src/cmd/compile/internal/noder/writer.go

index d8de1f483c86f312415cbec57326960f85e9e51a..fb4fb4a8865ee32aa2911e5560b0084ac0cabed0 100644 (file)
@@ -57,6 +57,7 @@ const (
        exprMake
        exprNil
        exprFuncInst
+       exprRecv
 )
 
 type codeAssign int
index 8c80c78c0b5afd75910244592ca5169e267a2ce3..3ab11399a5e28116779ce58756acbe4e2bf5719b 100644 (file)
@@ -1914,6 +1914,19 @@ func (r *reader) expr() (res ir.Node) {
                }
                return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
 
+       case exprRecv:
+               x := r.expr()
+               pos := r.pos()
+               for i, n := 0, r.Len(); i < n; i++ {
+                       x = Implicit(DotField(pos, x, r.Len()))
+               }
+               if r.Bool() { // needs deref
+                       x = Implicit(Deref(pos, x.Type().Elem(), x))
+               } else if r.Bool() { // needs addr
+                       x = Implicit(Addr(pos, x))
+               }
+               return x
+
        case exprCall:
                fun := r.expr()
                if r.Bool() { // method call
index 9cf914743dae5313ff0b5e7502ec70dcc322f553..ef84a53cf388f2a1613f4e3a56099384126aa76c 100644 (file)
@@ -1540,7 +1540,7 @@ func (w *writer) expr(expr syntax.Expr) {
 
                case types2.MethodVal:
                        w.Code(exprMethodVal)
-                       w.expr(expr.X)
+                       w.recvExpr(expr, sel)
                        w.pos(expr)
                        w.selector(sel.Obj())
 
@@ -1697,7 +1697,7 @@ func (w *writer) expr(expr syntax.Expr) {
                writeFunExpr := func() {
                        if selector, ok := unparen(expr.Fun).(*syntax.SelectorExpr); ok {
                                if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
-                                       w.expr(selector.X)
+                                       w.recvExpr(selector, sel)
                                        w.Bool(true) // method call
                                        w.pos(selector)
                                        w.selector(sel.Obj())
@@ -1741,6 +1741,40 @@ func (w *writer) optExpr(expr syntax.Expr) {
        }
 }
 
+// recvExpr writes out expr.X, but handles any implicit addressing,
+// dereferencing, and field selections.
+func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type {
+       index := sel.Index()
+       implicits := index[:len(index)-1]
+
+       w.Code(exprRecv)
+       w.expr(expr.X)
+       w.pos(expr)
+       w.Len(len(implicits))
+
+       typ := w.p.typeOf(expr.X)
+       for _, ix := range implicits {
+               typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
+               w.Len(ix)
+       }
+
+       isPtrTo := func(from, to types2.Type) bool {
+               if from, ok := from.(*types2.Pointer); ok {
+                       return types2.Identical(from.Elem(), to)
+               }
+               return false
+       }
+
+       recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
+       if w.Bool(isPtrTo(typ, recv)) { // needs deref
+               typ = recv
+       } else if w.Bool(isPtrTo(recv, typ)) { // needs addr
+               typ = recv
+       }
+
+       return typ
+}
+
 // multiExpr writes a sequence of expressions, where the i'th value is
 // implicitly converted to dstType(i). It also handles when exprs is a
 // single, multi-valued expression (e.g., the multi-valued argument in