github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/noder/expr.go (about)

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