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.
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"
19 func (g *irgen) expr(expr syntax.Expr) ir.Node {
20 expr = unparen(expr) // skip parens; unneeded after parse+typecheck
26 if expr, ok := expr.(*syntax.Name); ok && expr.Value == "_" {
30 tv := g.typeAndValue(expr)
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)
41 return g.use(expr.(*syntax.Name))
43 return ir.TypeNode(g.typ(tv.Type))
44 case tv.IsValue(), tv.IsVoid():
47 base.FatalfAt(g.pos(expr), "unrecognized type-checker result")
50 base.Assert(g.exprStmtOK)
54 base.FatalfAt(g.pos(expr), "unexpected untyped type: %v", tv.Type)
57 // Constant expression.
60 value := FixValue(typ, tv.Value)
61 return OrigConst(g.pos(expr), typ, value, constExprOp(expr), syntax.String(expr))
64 n := g.expr0(typ, expr)
65 if n.Typecheck() != 1 && n.Typecheck() != 3 {
66 base.FatalfAt(g.pos(expr), "missed typecheck: %+v", n)
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)
74 func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
78 // Set base.Pos for transformation code that still uses base.Pos, rather than
79 // the pos of the node being converted.
82 switch expr := expr.(type) {
84 if _, isNil := g.info.Uses[expr].(*types2.Nil); isNil {
85 return Nil(pos, g.typ(typ))
89 case *syntax.CompositeLit:
90 return g.compLit(typ, expr)
93 return g.funcLit(typ, expr)
95 case *syntax.AssertExpr:
96 return Assert(pos, g.expr(expr.X), g.typeExpr(expr.Type))
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)
102 case *syntax.IndexExpr:
103 args := unpackListExpr(expr.Index)
105 tv := g.typeAndValue(args[0])
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.
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)
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)
128 return g.selectorExpr(pos, typ, expr)
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() {
137 case *syntax.Operation:
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))
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() {
152 case ir.OANDAND, ir.OOROR:
155 return typed(x.Type(), ir.NewLogicalExpr(pos, op, x, y))
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)
165 g.unhandled("expression", expr)
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 {
179 targs1 := make([]*types.Type, len(targs))
180 for i, n := range targs {
183 ts := typecheck.Tsubster{
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
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)
199 if fun.Op() == ir.OTYPE {
200 // Actually a type conversion, not a function call.
201 if !g.delayTransform() {
202 return transformConvCall(n)
207 if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 {
208 if !g.delayTransform() {
209 return transformBuiltin(n)
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 {
219 if fun.X.Type().IsInterface() {
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)
229 // A function instantiation (even if fully concrete) shouldn't be
230 // transformed yet, because we need to add the dictionary during the
232 if fun.Op() != ir.OFUNCINST && !g.delayTransform() {
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 {
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))
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]
258 for _, ix := range embeds {
259 x = Implicit(DotField(pos, x, ix))
262 kind := selinfo.Kind()
263 if kind == types2.FieldVal {
264 return DotField(pos, x, last)
268 method2 := selinfo.Obj().(*types2.Func)
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
277 n = MethodExpr(pos, origx, x.Type(), last)
279 // Add implicit addr/deref for method values, if needed.
280 if x.Type().IsInterface() {
281 n = DotMethod(pos, x, last)
283 recvType2 := method2.Type().(*types2.Signature).Recv().Type()
284 _, wantPtr := recvType2.(*types2.Pointer)
285 havePtr := x.Type().IsPtr()
287 if havePtr != wantPtr {
289 x = Implicit(Deref(pos, x.Type().Elem(), x))
291 x = Implicit(Addr(pos, x))
294 recvType2Base := recvType2
296 recvType2Base = types2.AsPointer(recvType2).Elem()
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)
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])
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)
327 if !g.match(x.Type(), recvType2, false) {
328 base.FatalfAt(pos, "expected %L to have type %v", x, recvType2)
330 n = DotMethod(pos, x, last)
334 if have, want := n.Sym(), g.selector(method2); have != want {
335 base.FatalfAt(pos, "bad Sym: have %v, want %v", have, want)
340 func (g *irgen) exprList(expr syntax.Expr) []ir.Node {
341 return g.exprs(unpackListExpr(expr))
344 func unpackListExpr(expr syntax.Expr) []syntax.Expr {
345 switch expr := expr.(type) {
348 case *syntax.ListExpr:
351 return []syntax.Expr{expr}
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)
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))
367 return typed(g.typ(typ), n)
370 _, isStruct := types2.CoreType(typ).(*types2.Struct)
372 exprs := make([]ir.Node, len(lit.ElemList))
373 for i, elem := range lit.ElemList {
374 switch elem := elem.(type) {
375 case *syntax.KeyValueExpr:
378 key = ir.NewIdent(g.pos(elem.Key), g.name(elem.Key.(*syntax.Name)))
380 key = g.expr(elem.Key)
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)
387 exprs[i] = ir.NewKeyExpr(g.pos(elem), key, value)
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])
397 n := ir.NewCompLitExpr(g.pos(lit), ir.OCOMPLIT, nil, exprs)
400 if !g.delayTransform() {
401 r = transformCompLit(n)
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)
412 typed(typ, fn.OClosure)
415 g.funcBody(fn, nil, expr.Type, expr.Body)
417 ir.FinishCaptureNames(fn.Pos(), ir.CurFunc, fn)
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())
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.
430 return ir.UseClosure(fn.OClosure, nil)
432 return ir.UseClosure(fn.OClosure, g.target)
436 func (g *irgen) typeExpr(typ syntax.Expr) *types.Type {
438 if n.Op() != ir.OTYPE {
439 base.FatalfAt(g.pos(typ), "expected type: %L", n)
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) {
450 panic(fmt.Sprintf("%s: unexpected expression: %T", expr.Pos(), expr))
452 case *syntax.BasicLit:
454 case *syntax.Name, *syntax.SelectorExpr:
456 case *syntax.CallExpr:
458 case *syntax.Operation:
460 return unOps[expr.Op]
462 return binOps[expr.Op]
466 func unparen(expr syntax.Expr) syntax.Expr {
468 paren, ok := expr.(*syntax.ParenExpr)