Source file src/cmd/compile/internal/noder/expr.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package noder
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"cmd/compile/internal/base"
    11  	"cmd/compile/internal/ir"
    12  	"cmd/compile/internal/syntax"
    13  	"cmd/compile/internal/typecheck"
    14  	"cmd/compile/internal/types"
    15  	"cmd/compile/internal/types2"
    16  	"cmd/internal/src"
    17  )
    18  
    19  func (g *irgen) expr(expr syntax.Expr) ir.Node {
    20  	expr = unparen(expr) // skip parens; unneeded after parse+typecheck
    21  
    22  	if expr == nil {
    23  		return nil
    24  	}
    25  
    26  	if expr, ok := expr.(*syntax.Name); ok && expr.Value == "_" {
    27  		return ir.BlankNode
    28  	}
    29  
    30  	tv, ok := g.info.Types[expr]
    31  	if !ok {
    32  		base.FatalfAt(g.pos(expr), "missing type for %v (%T)", expr, expr)
    33  	}
    34  	switch {
    35  	case tv.IsBuiltin():
    36  		// Qualified builtins, such as unsafe.Add and unsafe.Slice.
    37  		if expr, ok := expr.(*syntax.SelectorExpr); ok {
    38  			if name, ok := expr.X.(*syntax.Name); ok {
    39  				if _, ok := g.info.Uses[name].(*types2.PkgName); ok {
    40  					return g.use(expr.Sel)
    41  				}
    42  			}
    43  		}
    44  		return g.use(expr.(*syntax.Name))
    45  	case tv.IsType():
    46  		return ir.TypeNode(g.typ(tv.Type))
    47  	case tv.IsValue(), tv.IsVoid():
    48  		// ok
    49  	default:
    50  		base.FatalfAt(g.pos(expr), "unrecognized type-checker result")
    51  	}
    52  
    53  	base.Assert(g.exprStmtOK)
    54  
    55  	// The gc backend expects all expressions to have a concrete type, and
    56  	// types2 mostly satisfies this expectation already. But there are a few
    57  	// cases where the Go spec doesn't require converting to concrete type,
    58  	// and so types2 leaves them untyped. So we need to fix those up here.
    59  	typ := tv.Type
    60  	if basic, ok := typ.(*types2.Basic); ok && basic.Info()&types2.IsUntyped != 0 {
    61  		switch basic.Kind() {
    62  		case types2.UntypedNil:
    63  			// ok; can appear in type switch case clauses
    64  			// TODO(mdempsky): Handle as part of type switches instead?
    65  		case types2.UntypedBool:
    66  			typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
    67  		case types2.UntypedString:
    68  			typ = types2.Typ[types2.String] // argument to "append" or "copy" calls
    69  		default:
    70  			base.FatalfAt(g.pos(expr), "unexpected untyped type: %v", basic)
    71  		}
    72  	}
    73  
    74  	// Constant expression.
    75  	if tv.Value != nil {
    76  		typ := g.typ(typ)
    77  		value := FixValue(typ, tv.Value)
    78  		return OrigConst(g.pos(expr), typ, value, constExprOp(expr), syntax.String(expr))
    79  	}
    80  
    81  	n := g.expr0(typ, expr)
    82  	if n.Typecheck() != 1 && n.Typecheck() != 3 {
    83  		base.FatalfAt(g.pos(expr), "missed typecheck: %+v", n)
    84  	}
    85  	if n.Op() != ir.OFUNCINST && !g.match(n.Type(), typ, tv.HasOk()) {
    86  		base.FatalfAt(g.pos(expr), "expected %L to have type %v", n, typ)
    87  	}
    88  	return n
    89  }
    90  
    91  func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
    92  	pos := g.pos(expr)
    93  	assert(pos.IsKnown())
    94  
    95  	// Set base.Pos for transformation code that still uses base.Pos, rather than
    96  	// the pos of the node being converted.
    97  	base.Pos = pos
    98  
    99  	switch expr := expr.(type) {
   100  	case *syntax.Name:
   101  		if _, isNil := g.info.Uses[expr].(*types2.Nil); isNil {
   102  			return Nil(pos, g.typ(typ))
   103  		}
   104  		return g.use(expr)
   105  
   106  	case *syntax.CompositeLit:
   107  		return g.compLit(typ, expr)
   108  
   109  	case *syntax.FuncLit:
   110  		return g.funcLit(typ, expr)
   111  
   112  	case *syntax.AssertExpr:
   113  		return Assert(pos, g.expr(expr.X), g.typeExpr(expr.Type))
   114  
   115  	case *syntax.CallExpr:
   116  		fun := g.expr(expr.Fun)
   117  		return g.callExpr(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots)
   118  
   119  	case *syntax.IndexExpr:
   120  		args := unpackListExpr(expr.Index)
   121  		if len(args) == 1 {
   122  			tv, ok := g.info.Types[args[0]]
   123  			assert(ok)
   124  			if tv.IsValue() {
   125  				// This is just a normal index expression
   126  				n := Index(pos, g.typ(typ), g.expr(expr.X), g.expr(args[0]))
   127  				if !g.delayTransform() {
   128  					// transformIndex will modify n.Type() for OINDEXMAP.
   129  					transformIndex(n)
   130  				}
   131  				return n
   132  			}
   133  		}
   134  
   135  		// expr.Index is a list of type args, so we ignore it, since types2 has
   136  		// already provided this info with the Info.Instances map.
   137  		return g.expr(expr.X)
   138  
   139  	case *syntax.SelectorExpr:
   140  		// Qualified identifier.
   141  		if name, ok := expr.X.(*syntax.Name); ok {
   142  			if _, ok := g.info.Uses[name].(*types2.PkgName); ok {
   143  				return g.use(expr.Sel)
   144  			}
   145  		}
   146  		return g.selectorExpr(pos, typ, expr)
   147  
   148  	case *syntax.SliceExpr:
   149  		n := Slice(pos, g.typ(typ), g.expr(expr.X), g.expr(expr.Index[0]), g.expr(expr.Index[1]), g.expr(expr.Index[2]))
   150  		if !g.delayTransform() {
   151  			transformSlice(n)
   152  		}
   153  		return n
   154  
   155  	case *syntax.Operation:
   156  		if expr.Y == nil {
   157  			n := Unary(pos, g.typ(typ), g.op(expr.Op, unOps[:]), g.expr(expr.X))
   158  			if n.Op() == ir.OADDR && !g.delayTransform() {
   159  				transformAddr(n.(*ir.AddrExpr))
   160  			}
   161  			return n
   162  		}
   163  		switch op := g.op(expr.Op, binOps[:]); op {
   164  		case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
   165  			n := Compare(pos, g.typ(typ), op, g.expr(expr.X), g.expr(expr.Y))
   166  			if !g.delayTransform() {
   167  				transformCompare(n)
   168  			}
   169  			return n
   170  		case ir.OANDAND, ir.OOROR:
   171  			x := g.expr(expr.X)
   172  			y := g.expr(expr.Y)
   173  			return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y))
   174  		default:
   175  			n := Binary(pos, op, g.typ(typ), g.expr(expr.X), g.expr(expr.Y))
   176  			if op == ir.OADD && !g.delayTransform() {
   177  				return transformAdd(n)
   178  			}
   179  			return n
   180  		}
   181  
   182  	default:
   183  		g.unhandled("expression", expr)
   184  		panic("unreachable")
   185  	}
   186  }
   187  
   188  // substType does a normal type substition, but tparams is in the form of a field
   189  // list, and targs is in terms of a slice of type nodes. substType records any newly
   190  // instantiated types into g.instTypeList.
   191  func (g *irgen) substType(typ *types.Type, tparams *types.Type, targs []ir.Node) *types.Type {
   192  	fields := tparams.FieldSlice()
   193  	tparams1 := make([]*types.Type, len(fields))
   194  	for i, f := range fields {
   195  		tparams1[i] = f.Type
   196  	}
   197  	targs1 := make([]*types.Type, len(targs))
   198  	for i, n := range targs {
   199  		targs1[i] = n.Type()
   200  	}
   201  	ts := typecheck.Tsubster{
   202  		Tparams: tparams1,
   203  		Targs:   targs1,
   204  	}
   205  	newt := ts.Typ(typ)
   206  	return newt
   207  }
   208  
   209  // callExpr creates a call expression (which might be a type conversion, built-in
   210  // call, or a regular call) and does standard transforms, unless we are in a generic
   211  // function.
   212  func (g *irgen) callExpr(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node {
   213  	n := ir.NewCallExpr(pos, ir.OCALL, fun, args)
   214  	n.IsDDD = dots
   215  	typed(typ, n)
   216  
   217  	if fun.Op() == ir.OTYPE {
   218  		// Actually a type conversion, not a function call.
   219  		if !g.delayTransform() {
   220  			return transformConvCall(n)
   221  		}
   222  		return n
   223  	}
   224  
   225  	if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 {
   226  		if !g.delayTransform() {
   227  			return transformBuiltin(n)
   228  		}
   229  		return n
   230  	}
   231  
   232  	// Add information, now that we know that fun is actually being called.
   233  	switch fun := fun.(type) {
   234  	case *ir.SelectorExpr:
   235  		if fun.Op() == ir.OMETHVALUE {
   236  			op := ir.ODOTMETH
   237  			if fun.X.Type().IsInterface() {
   238  				op = ir.ODOTINTER
   239  			}
   240  			fun.SetOp(op)
   241  			// Set the type to include the receiver, since that's what
   242  			// later parts of the compiler expect
   243  			fun.SetType(fun.Selection.Type)
   244  		}
   245  	}
   246  
   247  	// A function instantiation (even if fully concrete) shouldn't be
   248  	// transformed yet, because we need to add the dictionary during the
   249  	// transformation.
   250  	if fun.Op() != ir.OFUNCINST && !g.delayTransform() {
   251  		transformCall(n)
   252  	}
   253  	return n
   254  }
   255  
   256  // selectorExpr resolves the choice of ODOT, ODOTPTR, OMETHVALUE (eventually
   257  // ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather
   258  // than in typecheck.go.
   259  func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.SelectorExpr) ir.Node {
   260  	x := g.expr(expr.X)
   261  	if x.Type().HasTParam() {
   262  		// Leave a method call on a type param as an OXDOT, since it can
   263  		// only be fully transformed once it has an instantiated type.
   264  		n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value))
   265  		typed(g.typ(typ), n)
   266  		return n
   267  	}
   268  
   269  	selinfo := g.info.Selections[expr]
   270  	// Everything up to the last selection is an implicit embedded field access,
   271  	// and the last selection is determined by selinfo.Kind().
   272  	index := selinfo.Index()
   273  	embeds, last := index[:len(index)-1], index[len(index)-1]
   274  
   275  	origx := x
   276  	for _, ix := range embeds {
   277  		x = Implicit(DotField(pos, x, ix))
   278  	}
   279  
   280  	kind := selinfo.Kind()
   281  	if kind == types2.FieldVal {
   282  		return DotField(pos, x, last)
   283  	}
   284  
   285  	var n ir.Node
   286  	method2 := selinfo.Obj().(*types2.Func)
   287  
   288  	if kind == types2.MethodExpr {
   289  		// OMETHEXPR is unusual in using directly the node and type of the
   290  		// original OTYPE node (origx) before passing through embedded
   291  		// fields, even though the method is selected from the type
   292  		// (x.Type()) reached after following the embedded fields. We will
   293  		// actually drop any ODOT nodes we created due to the embedded
   294  		// fields.
   295  		n = MethodExpr(pos, origx, x.Type(), last)
   296  	} else {
   297  		// Add implicit addr/deref for method values, if needed.
   298  		if x.Type().IsInterface() {
   299  			n = DotMethod(pos, x, last)
   300  		} else {
   301  			recvType2 := method2.Type().(*types2.Signature).Recv().Type()
   302  			_, wantPtr := recvType2.(*types2.Pointer)
   303  			havePtr := x.Type().IsPtr()
   304  
   305  			if havePtr != wantPtr {
   306  				if havePtr {
   307  					x = Implicit(Deref(pos, x.Type().Elem(), x))
   308  				} else {
   309  					x = Implicit(Addr(pos, x))
   310  				}
   311  			}
   312  			recvType2Base := recvType2
   313  			if wantPtr {
   314  				recvType2Base = types2.AsPointer(recvType2).Elem()
   315  			}
   316  			if recvType2Base.(*types2.Named).TypeParams().Len() > 0 {
   317  				// recvType2 is the original generic type that is
   318  				// instantiated for this method call.
   319  				// selinfo.Recv() is the instantiated type
   320  				recvType2 = recvType2Base
   321  				recvTypeSym := g.pkg(method2.Pkg()).Lookup(recvType2.(*types2.Named).Obj().Name())
   322  				recvType := recvTypeSym.Def.(*ir.Name).Type()
   323  				// method is the generic method associated with
   324  				// the base generic type. The instantiated type may not
   325  				// have method bodies filled in, if it was imported.
   326  				method := recvType.Methods().Index(last).Nname.(*ir.Name)
   327  				n = ir.NewSelectorExpr(pos, ir.OMETHVALUE, x, typecheck.Lookup(expr.Sel.Value))
   328  				n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type())
   329  				n.(*ir.SelectorExpr).Selection.Nname = method
   330  				typed(method.Type(), n)
   331  
   332  				xt := deref(x.Type())
   333  				targs := make([]ir.Node, len(xt.RParams()))
   334  				for i := range targs {
   335  					targs[i] = ir.TypeNode(xt.RParams()[i])
   336  				}
   337  
   338  				// Create function instantiation with the type
   339  				// args for the receiver type for the method call.
   340  				n = ir.NewInstExpr(pos, ir.OFUNCINST, n, targs)
   341  				typed(g.typ(typ), n)
   342  				return n
   343  			}
   344  
   345  			if !g.match(x.Type(), recvType2, false) {
   346  				base.FatalfAt(pos, "expected %L to have type %v", x, recvType2)
   347  			} else {
   348  				n = DotMethod(pos, x, last)
   349  			}
   350  		}
   351  	}
   352  	if have, want := n.Sym(), g.selector(method2); have != want {
   353  		base.FatalfAt(pos, "bad Sym: have %v, want %v", have, want)
   354  	}
   355  	return n
   356  }
   357  
   358  func (g *irgen) exprList(expr syntax.Expr) []ir.Node {
   359  	return g.exprs(unpackListExpr(expr))
   360  }
   361  
   362  func unpackListExpr(expr syntax.Expr) []syntax.Expr {
   363  	switch expr := expr.(type) {
   364  	case nil:
   365  		return nil
   366  	case *syntax.ListExpr:
   367  		return expr.ElemList
   368  	default:
   369  		return []syntax.Expr{expr}
   370  	}
   371  }
   372  
   373  func (g *irgen) exprs(exprs []syntax.Expr) []ir.Node {
   374  	nodes := make([]ir.Node, len(exprs))
   375  	for i, expr := range exprs {
   376  		nodes[i] = g.expr(expr)
   377  	}
   378  	return nodes
   379  }
   380  
   381  func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
   382  	if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
   383  		n := ir.NewAddrExpr(g.pos(lit), g.compLit(ptr.Elem(), lit))
   384  		n.SetOp(ir.OPTRLIT)
   385  		return typed(g.typ(typ), n)
   386  	}
   387  
   388  	_, isStruct := types2.CoreType(typ).(*types2.Struct)
   389  
   390  	exprs := make([]ir.Node, len(lit.ElemList))
   391  	for i, elem := range lit.ElemList {
   392  		switch elem := elem.(type) {
   393  		case *syntax.KeyValueExpr:
   394  			var key ir.Node
   395  			if isStruct {
   396  				key = ir.NewIdent(g.pos(elem.Key), g.name(elem.Key.(*syntax.Name)))
   397  			} else {
   398  				key = g.expr(elem.Key)
   399  			}
   400  			value := wrapname(g.pos(elem.Value), g.expr(elem.Value))
   401  			if value.Op() == ir.OPAREN {
   402  				// Make sure any PAREN node added by wrapper has a type
   403  				typed(value.(*ir.ParenExpr).X.Type(), value)
   404  			}
   405  			exprs[i] = ir.NewKeyExpr(g.pos(elem), key, value)
   406  		default:
   407  			exprs[i] = wrapname(g.pos(elem), g.expr(elem))
   408  			if exprs[i].Op() == ir.OPAREN {
   409  				// Make sure any PAREN node added by wrapper has a type
   410  				typed(exprs[i].(*ir.ParenExpr).X.Type(), exprs[i])
   411  			}
   412  		}
   413  	}
   414  
   415  	n := ir.NewCompLitExpr(g.pos(lit), ir.OCOMPLIT, nil, exprs)
   416  	typed(g.typ(typ), n)
   417  	var r ir.Node = n
   418  	if !g.delayTransform() {
   419  		r = transformCompLit(n)
   420  	}
   421  	return r
   422  }
   423  
   424  func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node {
   425  	fn := ir.NewClosureFunc(g.pos(expr), ir.CurFunc != nil)
   426  	ir.NameClosure(fn.OClosure, ir.CurFunc)
   427  
   428  	typ := g.typ(typ2)
   429  	typed(typ, fn.Nname)
   430  	typed(typ, fn.OClosure)
   431  	fn.SetTypecheck(1)
   432  
   433  	g.funcBody(fn, nil, expr.Type, expr.Body)
   434  
   435  	ir.FinishCaptureNames(fn.Pos(), ir.CurFunc, fn)
   436  
   437  	// TODO(mdempsky): ir.CaptureName should probably handle
   438  	// copying these fields from the canonical variable.
   439  	for _, cv := range fn.ClosureVars {
   440  		cv.SetType(cv.Canonical().Type())
   441  		cv.SetTypecheck(1)
   442  		cv.SetWalkdef(1)
   443  	}
   444  
   445  	if g.topFuncIsGeneric {
   446  		// Don't add any closure inside a generic function/method to the
   447  		// g.target.Decls list, even though it may not be generic itself.
   448  		// See issue #47514.
   449  		return ir.UseClosure(fn.OClosure, nil)
   450  	} else {
   451  		return ir.UseClosure(fn.OClosure, g.target)
   452  	}
   453  }
   454  
   455  func (g *irgen) typeExpr(typ syntax.Expr) *types.Type {
   456  	n := g.expr(typ)
   457  	if n.Op() != ir.OTYPE {
   458  		base.FatalfAt(g.pos(typ), "expected type: %L", n)
   459  	}
   460  	return n.Type()
   461  }
   462  
   463  // constExprOp returns an ir.Op that represents the outermost
   464  // operation of the given constant expression. It's intended for use
   465  // with ir.RawOrigExpr.
   466  func constExprOp(expr syntax.Expr) ir.Op {
   467  	switch expr := expr.(type) {
   468  	default:
   469  		panic(fmt.Sprintf("%s: unexpected expression: %T", expr.Pos(), expr))
   470  
   471  	case *syntax.BasicLit:
   472  		return ir.OLITERAL
   473  	case *syntax.Name, *syntax.SelectorExpr:
   474  		return ir.ONAME
   475  	case *syntax.CallExpr:
   476  		return ir.OCALL
   477  	case *syntax.Operation:
   478  		if expr.Y == nil {
   479  			return unOps[expr.Op]
   480  		}
   481  		return binOps[expr.Op]
   482  	}
   483  }
   484  
   485  func unparen(expr syntax.Expr) syntax.Expr {
   486  	for {
   487  		paren, ok := expr.(*syntax.ParenExpr)
   488  		if !ok {
   489  			return expr
   490  		}
   491  		expr = paren.X
   492  	}
   493  }
   494  

View as plain text