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