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 }