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
5package noder
6
7import (
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
19func (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
91func (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 Call(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.
191func (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// selectorExpr resolves the choice of ODOT, ODOTPTR, OMETHVALUE (eventually
210// ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather
211// than in typecheck.go.
212func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.SelectorExpr) ir.Node {
213	x := g.expr(expr.X)
214	if x.Type().HasTParam() {
215		// Leave a method call on a type param as an OXDOT, since it can
216		// only be fully transformed once it has an instantiated type.
217		n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value))
218		typed(g.typ(typ), n)
219		return n
220	}
221
222	selinfo := g.info.Selections[expr]
223	// Everything up to the last selection is an implicit embedded field access,
224	// and the last selection is determined by selinfo.Kind().
225	index := selinfo.Index()
226	embeds, last := index[:len(index)-1], index[len(index)-1]
227
228	origx := x
229	for _, ix := range embeds {
230		x = Implicit(DotField(pos, x, ix))
231	}
232
233	kind := selinfo.Kind()
234	if kind == types2.FieldVal {
235		return DotField(pos, x, last)
236	}
237
238	var n ir.Node
239	method2 := selinfo.Obj().(*types2.Func)
240
241	if kind == types2.MethodExpr {
242		// OMETHEXPR is unusual in using directly the node and type of the
243		// original OTYPE node (origx) before passing through embedded
244		// fields, even though the method is selected from the type
245		// (x.Type()) reached after following the embedded fields. We will
246		// actually drop any ODOT nodes we created due to the embedded
247		// fields.
248		n = MethodExpr(pos, origx, x.Type(), last)
249	} else {
250		// Add implicit addr/deref for method values, if needed.
251		if x.Type().IsInterface() {
252			n = DotMethod(pos, x, last)
253		} else {
254			recvType2 := method2.Type().(*types2.Signature).Recv().Type()
255			_, wantPtr := recvType2.(*types2.Pointer)
256			havePtr := x.Type().IsPtr()
257
258			if havePtr != wantPtr {
259				if havePtr {
260					x = Implicit(Deref(pos, x.Type().Elem(), x))
261				} else {
262					x = Implicit(Addr(pos, x))
263				}
264			}
265			recvType2Base := recvType2
266			if wantPtr {
267				recvType2Base = types2.AsPointer(recvType2).Elem()
268			}
269			if recvType2Base.(*types2.Named).TypeParams().Len() > 0 {
270				// recvType2 is the original generic type that is
271				// instantiated for this method call.
272				// selinfo.Recv() is the instantiated type
273				recvType2 = recvType2Base
274				recvTypeSym := g.pkg(method2.Pkg()).Lookup(recvType2.(*types2.Named).Obj().Name())
275				recvType := recvTypeSym.Def.(*ir.Name).Type()
276				// method is the generic method associated with
277				// the base generic type. The instantiated type may not
278				// have method bodies filled in, if it was imported.
279				method := recvType.Methods().Index(last).Nname.(*ir.Name)
280				n = ir.NewSelectorExpr(pos, ir.OMETHVALUE, x, typecheck.Lookup(expr.Sel.Value))
281				n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type())
282				n.(*ir.SelectorExpr).Selection.Nname = method
283				typed(method.Type(), n)
284
285				xt := deref(x.Type())
286				targs := make([]ir.Node, len(xt.RParams()))
287				for i := range targs {
288					targs[i] = ir.TypeNode(xt.RParams()[i])
289				}
290
291				// Create function instantiation with the type
292				// args for the receiver type for the method call.
293				n = ir.NewInstExpr(pos, ir.OFUNCINST, n, targs)
294				typed(g.typ(typ), n)
295				return n
296			}
297
298			if !g.match(x.Type(), recvType2, false) {
299				base.FatalfAt(pos, "expected %L to have type %v", x, recvType2)
300			} else {
301				n = DotMethod(pos, x, last)
302			}
303		}
304	}
305	if have, want := n.Sym(), g.selector(method2); have != want {
306		base.FatalfAt(pos, "bad Sym: have %v, want %v", have, want)
307	}
308	return n
309}
310
311func (g *irgen) exprList(expr syntax.Expr) []ir.Node {
312	return g.exprs(unpackListExpr(expr))
313}
314
315func unpackListExpr(expr syntax.Expr) []syntax.Expr {
316	switch expr := expr.(type) {
317	case nil:
318		return nil
319	case *syntax.ListExpr:
320		return expr.ElemList
321	default:
322		return []syntax.Expr{expr}
323	}
324}
325
326func (g *irgen) exprs(exprs []syntax.Expr) []ir.Node {
327	nodes := make([]ir.Node, len(exprs))
328	for i, expr := range exprs {
329		nodes[i] = g.expr(expr)
330	}
331	return nodes
332}
333
334func (g *irgen) compLit(typ types2.Type, lit *syntax.CompositeLit) ir.Node {
335	if ptr, ok := typ.Underlying().(*types2.Pointer); ok {
336		n := ir.NewAddrExpr(g.pos(lit), g.compLit(ptr.Elem(), lit))
337		n.SetOp(ir.OPTRLIT)
338		return typed(g.typ(typ), n)
339	}
340
341	_, isStruct := types2.StructuralType(typ).(*types2.Struct)
342
343	exprs := make([]ir.Node, len(lit.ElemList))
344	for i, elem := range lit.ElemList {
345		switch elem := elem.(type) {
346		case *syntax.KeyValueExpr:
347			var key ir.Node
348			if isStruct {
349				key = ir.NewIdent(g.pos(elem.Key), g.name(elem.Key.(*syntax.Name)))
350			} else {
351				key = g.expr(elem.Key)
352			}
353			value := wrapname(g.pos(elem.Value), g.expr(elem.Value))
354			if value.Op() == ir.OPAREN {
355				// Make sure any PAREN node added by wrapper has a type
356				typed(value.(*ir.ParenExpr).X.Type(), value)
357			}
358			exprs[i] = ir.NewKeyExpr(g.pos(elem), key, value)
359		default:
360			exprs[i] = wrapname(g.pos(elem), g.expr(elem))
361			if exprs[i].Op() == ir.OPAREN {
362				// Make sure any PAREN node added by wrapper has a type
363				typed(exprs[i].(*ir.ParenExpr).X.Type(), exprs[i])
364			}
365		}
366	}
367
368	n := ir.NewCompLitExpr(g.pos(lit), ir.OCOMPLIT, nil, exprs)
369	typed(g.typ(typ), n)
370	var r ir.Node = n
371	if !g.delayTransform() {
372		r = transformCompLit(n)
373	}
374	return r
375}
376
377func (g *irgen) funcLit(typ2 types2.Type, expr *syntax.FuncLit) ir.Node {
378	fn := ir.NewClosureFunc(g.pos(expr), ir.CurFunc != nil)
379	ir.NameClosure(fn.OClosure, ir.CurFunc)
380
381	typ := g.typ(typ2)
382	typed(typ, fn.Nname)
383	typed(typ, fn.OClosure)
384	fn.SetTypecheck(1)
385
386	g.funcBody(fn, nil, expr.Type, expr.Body)
387
388	ir.FinishCaptureNames(fn.Pos(), ir.CurFunc, fn)
389
390	// TODO(mdempsky): ir.CaptureName should probably handle
391	// copying these fields from the canonical variable.
392	for _, cv := range fn.ClosureVars {
393		cv.SetType(cv.Canonical().Type())
394		cv.SetTypecheck(1)
395		cv.SetWalkdef(1)
396	}
397
398	if g.topFuncIsGeneric {
399		// Don't add any closure inside a generic function/method to the
400		// g.target.Decls list, even though it may not be generic itself.
401		// See issue #47514.
402		return ir.UseClosure(fn.OClosure, nil)
403	} else {
404		return ir.UseClosure(fn.OClosure, g.target)
405	}
406}
407
408func (g *irgen) typeExpr(typ syntax.Expr) *types.Type {
409	n := g.expr(typ)
410	if n.Op() != ir.OTYPE {
411		base.FatalfAt(g.pos(typ), "expected type: %L", n)
412	}
413	return n.Type()
414}
415
416// constExprOp returns an ir.Op that represents the outermost
417// operation of the given constant expression. It's intended for use
418// with ir.RawOrigExpr.
419func constExprOp(expr syntax.Expr) ir.Op {
420	switch expr := expr.(type) {
421	default:
422		panic(fmt.Sprintf("%s: unexpected expression: %T", expr.Pos(), expr))
423
424	case *syntax.BasicLit:
425		return ir.OLITERAL
426	case *syntax.Name, *syntax.SelectorExpr:
427		return ir.ONAME
428	case *syntax.CallExpr:
429		return ir.OCALL
430	case *syntax.Operation:
431		if expr.Y == nil {
432			return unOps[expr.Op]
433		}
434		return binOps[expr.Op]
435	}
436}
437
438func unparen(expr syntax.Expr) syntax.Expr {
439	for {
440		paren, ok := expr.(*syntax.ParenExpr)
441		if !ok {
442			return expr
443		}
444		expr = paren.X
445	}
446}
447