github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/ir/expr.go (about) 1 // Copyright 2020 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 ir 6 7 import ( 8 "bytes" 9 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 10 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 11 "github.com/bir3/gocompiler/src/cmd/internal/obj" 12 "github.com/bir3/gocompiler/src/cmd/internal/src" 13 "fmt" 14 "github.com/bir3/gocompiler/src/go/constant" 15 "github.com/bir3/gocompiler/src/go/token" 16 ) 17 18 // An Expr is a Node that can appear as an expression. 19 type Expr interface { 20 Node 21 isExpr() 22 } 23 24 // A miniExpr is a miniNode with extra fields common to expressions. 25 // TODO(rsc): Once we are sure about the contents, compact the bools 26 // into a bit field and leave extra bits available for implementations 27 // embedding miniExpr. Right now there are ~60 unused bits sitting here. 28 type miniExpr struct { 29 miniNode 30 typ *types.Type 31 init Nodes // TODO(rsc): Don't require every Node to have an init 32 flags bitset8 33 } 34 35 const ( 36 miniExprNonNil = 1 << iota 37 miniExprTransient 38 miniExprBounded 39 miniExprImplicit // for use by implementations; not supported by every Expr 40 miniExprCheckPtr 41 ) 42 43 func (*miniExpr) isExpr() {} 44 45 func (n *miniExpr) Type() *types.Type { return n.typ } 46 func (n *miniExpr) SetType(x *types.Type) { n.typ = x } 47 func (n *miniExpr) NonNil() bool { return n.flags&miniExprNonNil != 0 } 48 func (n *miniExpr) MarkNonNil() { n.flags |= miniExprNonNil } 49 func (n *miniExpr) Transient() bool { return n.flags&miniExprTransient != 0 } 50 func (n *miniExpr) SetTransient(b bool) { n.flags.set(miniExprTransient, b) } 51 func (n *miniExpr) Bounded() bool { return n.flags&miniExprBounded != 0 } 52 func (n *miniExpr) SetBounded(b bool) { n.flags.set(miniExprBounded, b) } 53 func (n *miniExpr) Init() Nodes { return n.init } 54 func (n *miniExpr) PtrInit() *Nodes { return &n.init } 55 func (n *miniExpr) SetInit(x Nodes) { n.init = x } 56 57 // An AddStringExpr is a string concatenation Expr[0] + Exprs[1] + ... + Expr[len(Expr)-1]. 58 type AddStringExpr struct { 59 miniExpr 60 List Nodes 61 Prealloc *Name 62 } 63 64 func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr { 65 n := &AddStringExpr{} 66 n.pos = pos 67 n.op = OADDSTR 68 n.List = list 69 return n 70 } 71 72 // An AddrExpr is an address-of expression &X. 73 // It may end up being a normal address-of or an allocation of a composite literal. 74 type AddrExpr struct { 75 miniExpr 76 X Node 77 Prealloc *Name // preallocated storage if any 78 } 79 80 func NewAddrExpr(pos src.XPos, x Node) *AddrExpr { 81 n := &AddrExpr{X: x} 82 n.op = OADDR 83 n.pos = pos 84 return n 85 } 86 87 func (n *AddrExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 88 func (n *AddrExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 89 90 func (n *AddrExpr) SetOp(op Op) { 91 switch op { 92 default: 93 panic(n.no("SetOp " + op.String())) 94 case OADDR, OPTRLIT: 95 n.op = op 96 } 97 } 98 99 // A BasicLit is a literal of basic type. 100 type BasicLit struct { 101 miniExpr 102 val constant.Value 103 } 104 105 func NewBasicLit(pos src.XPos, val constant.Value) Node { 106 n := &BasicLit{val: val} 107 n.op = OLITERAL 108 n.pos = pos 109 if k := val.Kind(); k != constant.Unknown { 110 n.SetType(idealType(k)) 111 } 112 return n 113 } 114 115 func (n *BasicLit) Val() constant.Value { return n.val } 116 func (n *BasicLit) SetVal(val constant.Value) { n.val = val } 117 118 // A BinaryExpr is a binary expression X Op Y, 119 // or Op(X, Y) for builtin functions that do not become calls. 120 type BinaryExpr struct { 121 miniExpr 122 X Node 123 Y Node 124 RType Node `mknode:"-"` // see reflectdata/helpers.go 125 } 126 127 func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr { 128 n := &BinaryExpr{X: x, Y: y} 129 n.pos = pos 130 n.SetOp(op) 131 return n 132 } 133 134 func (n *BinaryExpr) SetOp(op Op) { 135 switch op { 136 default: 137 panic(n.no("SetOp " + op.String())) 138 case OADD, OADDSTR, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, 139 OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR, 140 OCOPY, OCOMPLEX, OUNSAFEADD, OUNSAFESLICE, OUNSAFESTRING, 141 OEFACE: 142 n.op = op 143 } 144 } 145 146 // A CallExpr is a function call X(Args). 147 type CallExpr struct { 148 miniExpr 149 origNode 150 X Node 151 Args Nodes 152 RType Node `mknode:"-"` // see reflectdata/helpers.go 153 KeepAlive []*Name // vars to be kept alive until call returns 154 IsDDD bool 155 NoInline bool 156 } 157 158 func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr { 159 n := &CallExpr{X: fun} 160 n.pos = pos 161 n.orig = n 162 n.SetOp(op) 163 n.Args = args 164 return n 165 } 166 167 func (*CallExpr) isStmt() {} 168 169 func (n *CallExpr) SetOp(op Op) { 170 switch op { 171 default: 172 panic(n.no("SetOp " + op.String())) 173 case OAPPEND, 174 OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, 175 ODELETE, 176 OGETG, OGETCALLERPC, OGETCALLERSP, 177 OMAKE, OPRINT, OPRINTN, 178 ORECOVER, ORECOVERFP: 179 n.op = op 180 } 181 } 182 183 // A ClosureExpr is a function literal expression. 184 type ClosureExpr struct { 185 miniExpr 186 Func *Func `mknode:"-"` 187 Prealloc *Name 188 IsGoWrap bool // whether this is wrapper closure of a go statement 189 } 190 191 // A CompLitExpr is a composite literal Type{Vals}. 192 // Before type-checking, the type is Ntype. 193 type CompLitExpr struct { 194 miniExpr 195 origNode 196 List Nodes // initialized values 197 RType Node `mknode:"-"` // *runtime._type for OMAPLIT map types 198 Prealloc *Name 199 // For OSLICELIT, Len is the backing array length. 200 // For OMAPLIT, Len is the number of entries that we've removed from List and 201 // generated explicit mapassign calls for. This is used to inform the map alloc hint. 202 Len int64 203 } 204 205 func NewCompLitExpr(pos src.XPos, op Op, typ *types.Type, list []Node) *CompLitExpr { 206 n := &CompLitExpr{List: list} 207 n.pos = pos 208 n.SetOp(op) 209 if typ != nil { 210 n.SetType(typ) 211 } 212 n.orig = n 213 return n 214 } 215 216 func (n *CompLitExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 217 func (n *CompLitExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 218 219 func (n *CompLitExpr) SetOp(op Op) { 220 switch op { 221 default: 222 panic(n.no("SetOp " + op.String())) 223 case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT: 224 n.op = op 225 } 226 } 227 228 type ConstExpr struct { 229 miniExpr 230 origNode 231 val constant.Value 232 } 233 234 func NewConstExpr(val constant.Value, orig Node) Node { 235 n := &ConstExpr{val: val} 236 n.op = OLITERAL 237 n.pos = orig.Pos() 238 n.orig = orig 239 n.SetType(orig.Type()) 240 n.SetTypecheck(orig.Typecheck()) 241 return n 242 } 243 244 func (n *ConstExpr) Sym() *types.Sym { return n.orig.Sym() } 245 func (n *ConstExpr) Val() constant.Value { return n.val } 246 247 // A ConvExpr is a conversion Type(X). 248 // It may end up being a value or a type. 249 type ConvExpr struct { 250 miniExpr 251 X Node 252 253 // For implementing OCONVIFACE expressions. 254 // 255 // TypeWord is an expression yielding a *runtime._type or 256 // *runtime.itab value to go in the type word of the iface/eface 257 // result. See reflectdata.ConvIfaceTypeWord for further details. 258 // 259 // SrcRType is an expression yielding a *runtime._type value for X, 260 // if it's not pointer-shaped and needs to be heap allocated. 261 TypeWord Node `mknode:"-"` 262 SrcRType Node `mknode:"-"` 263 264 // For -d=checkptr instrumentation of conversions from 265 // unsafe.Pointer to *Elem or *[Len]Elem. 266 // 267 // TODO(mdempsky): We only ever need one of these, but currently we 268 // don't decide which one until walk. Longer term, it probably makes 269 // sense to have a dedicated IR op for `(*[Len]Elem)(ptr)[:n:m]` 270 // expressions. 271 ElemRType Node `mknode:"-"` 272 ElemElemRType Node `mknode:"-"` 273 } 274 275 func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr { 276 n := &ConvExpr{X: x} 277 n.pos = pos 278 n.typ = typ 279 n.SetOp(op) 280 return n 281 } 282 283 func (n *ConvExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 284 func (n *ConvExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 285 func (n *ConvExpr) CheckPtr() bool { return n.flags&miniExprCheckPtr != 0 } 286 func (n *ConvExpr) SetCheckPtr(b bool) { n.flags.set(miniExprCheckPtr, b) } 287 288 func (n *ConvExpr) SetOp(op Op) { 289 switch op { 290 default: 291 panic(n.no("SetOp " + op.String())) 292 case OCONV, OCONVIFACE, OCONVIDATA, OCONVNOP, OBYTES2STR, OBYTES2STRTMP, ORUNES2STR, OSTR2BYTES, OSTR2BYTESTMP, OSTR2RUNES, ORUNESTR, OSLICE2ARR, OSLICE2ARRPTR: 293 n.op = op 294 } 295 } 296 297 // An IndexExpr is an index expression X[Index]. 298 type IndexExpr struct { 299 miniExpr 300 X Node 301 Index Node 302 RType Node `mknode:"-"` // see reflectdata/helpers.go 303 Assigned bool 304 } 305 306 func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr { 307 n := &IndexExpr{X: x, Index: index} 308 n.pos = pos 309 n.op = OINDEX 310 return n 311 } 312 313 func (n *IndexExpr) SetOp(op Op) { 314 switch op { 315 default: 316 panic(n.no("SetOp " + op.String())) 317 case OINDEX, OINDEXMAP: 318 n.op = op 319 } 320 } 321 322 // A KeyExpr is a Key: Value composite literal key. 323 type KeyExpr struct { 324 miniExpr 325 Key Node 326 Value Node 327 } 328 329 func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr { 330 n := &KeyExpr{Key: key, Value: value} 331 n.pos = pos 332 n.op = OKEY 333 return n 334 } 335 336 // A StructKeyExpr is an Field: Value composite literal key. 337 type StructKeyExpr struct { 338 miniExpr 339 Field *types.Field 340 Value Node 341 } 342 343 func NewStructKeyExpr(pos src.XPos, field *types.Field, value Node) *StructKeyExpr { 344 n := &StructKeyExpr{Field: field, Value: value} 345 n.pos = pos 346 n.op = OSTRUCTKEY 347 return n 348 } 349 350 func (n *StructKeyExpr) Sym() *types.Sym { return n.Field.Sym } 351 352 // An InlinedCallExpr is an inlined function call. 353 type InlinedCallExpr struct { 354 miniExpr 355 Body Nodes 356 ReturnVars Nodes // must be side-effect free 357 } 358 359 func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr { 360 n := &InlinedCallExpr{} 361 n.pos = pos 362 n.op = OINLCALL 363 n.Body = body 364 n.ReturnVars = retvars 365 return n 366 } 367 368 func (n *InlinedCallExpr) SingleResult() Node { 369 if have := len(n.ReturnVars); have != 1 { 370 base.FatalfAt(n.Pos(), "inlined call has %v results, expected 1", have) 371 } 372 if !n.Type().HasShape() && n.ReturnVars[0].Type().HasShape() { 373 // If the type of the call is not a shape, but the type of the return value 374 // is a shape, we need to do an implicit conversion, so the real type 375 // of n is maintained. 376 r := NewConvExpr(n.Pos(), OCONVNOP, n.Type(), n.ReturnVars[0]) 377 r.SetTypecheck(1) 378 return r 379 } 380 return n.ReturnVars[0] 381 } 382 383 // A LogicalExpr is a expression X Op Y where Op is && or ||. 384 // It is separate from BinaryExpr to make room for statements 385 // that must be executed before Y but after X. 386 type LogicalExpr struct { 387 miniExpr 388 X Node 389 Y Node 390 } 391 392 func NewLogicalExpr(pos src.XPos, op Op, x, y Node) *LogicalExpr { 393 n := &LogicalExpr{X: x, Y: y} 394 n.pos = pos 395 n.SetOp(op) 396 return n 397 } 398 399 func (n *LogicalExpr) SetOp(op Op) { 400 switch op { 401 default: 402 panic(n.no("SetOp " + op.String())) 403 case OANDAND, OOROR: 404 n.op = op 405 } 406 } 407 408 // A MakeExpr is a make expression: make(Type[, Len[, Cap]]). 409 // Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY, 410 // but *not* OMAKE (that's a pre-typechecking CallExpr). 411 type MakeExpr struct { 412 miniExpr 413 RType Node `mknode:"-"` // see reflectdata/helpers.go 414 Len Node 415 Cap Node 416 } 417 418 func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr { 419 n := &MakeExpr{Len: len, Cap: cap} 420 n.pos = pos 421 n.SetOp(op) 422 return n 423 } 424 425 func (n *MakeExpr) SetOp(op Op) { 426 switch op { 427 default: 428 panic(n.no("SetOp " + op.String())) 429 case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY: 430 n.op = op 431 } 432 } 433 434 // A NilExpr represents the predefined untyped constant nil. 435 // (It may be copied and assigned a type, though.) 436 type NilExpr struct { 437 miniExpr 438 } 439 440 func NewNilExpr(pos src.XPos) *NilExpr { 441 n := &NilExpr{} 442 n.pos = pos 443 n.op = ONIL 444 return n 445 } 446 447 // A ParenExpr is a parenthesized expression (X). 448 // It may end up being a value or a type. 449 type ParenExpr struct { 450 miniExpr 451 X Node 452 } 453 454 func NewParenExpr(pos src.XPos, x Node) *ParenExpr { 455 n := &ParenExpr{X: x} 456 n.op = OPAREN 457 n.pos = pos 458 return n 459 } 460 461 func (n *ParenExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 462 func (n *ParenExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 463 464 // A RawOrigExpr represents an arbitrary Go expression as a string value. 465 // When printed in diagnostics, the string value is written out exactly as-is. 466 type RawOrigExpr struct { 467 miniExpr 468 Raw string 469 } 470 471 func NewRawOrigExpr(pos src.XPos, op Op, raw string) *RawOrigExpr { 472 n := &RawOrigExpr{Raw: raw} 473 n.pos = pos 474 n.op = op 475 return n 476 } 477 478 // A ResultExpr represents a direct access to a result. 479 type ResultExpr struct { 480 miniExpr 481 Index int64 // index of the result expr. 482 } 483 484 func NewResultExpr(pos src.XPos, typ *types.Type, index int64) *ResultExpr { 485 n := &ResultExpr{Index: index} 486 n.pos = pos 487 n.op = ORESULT 488 n.typ = typ 489 return n 490 } 491 492 // A LinksymOffsetExpr refers to an offset within a global variable. 493 // It is like a SelectorExpr but without the field name. 494 type LinksymOffsetExpr struct { 495 miniExpr 496 Linksym *obj.LSym 497 Offset_ int64 498 } 499 500 func NewLinksymOffsetExpr(pos src.XPos, lsym *obj.LSym, offset int64, typ *types.Type) *LinksymOffsetExpr { 501 n := &LinksymOffsetExpr{Linksym: lsym, Offset_: offset} 502 n.typ = typ 503 n.op = OLINKSYMOFFSET 504 return n 505 } 506 507 // NewLinksymExpr is NewLinksymOffsetExpr, but with offset fixed at 0. 508 func NewLinksymExpr(pos src.XPos, lsym *obj.LSym, typ *types.Type) *LinksymOffsetExpr { 509 return NewLinksymOffsetExpr(pos, lsym, 0, typ) 510 } 511 512 // NewNameOffsetExpr is NewLinksymOffsetExpr, but taking a *Name 513 // representing a global variable instead of an *obj.LSym directly. 514 func NewNameOffsetExpr(pos src.XPos, name *Name, offset int64, typ *types.Type) *LinksymOffsetExpr { 515 if name == nil || IsBlank(name) || !(name.Op() == ONAME && name.Class == PEXTERN) { 516 base.FatalfAt(pos, "cannot take offset of nil, blank name or non-global variable: %v", name) 517 } 518 return NewLinksymOffsetExpr(pos, name.Linksym(), offset, typ) 519 } 520 521 // A SelectorExpr is a selector expression X.Sel. 522 type SelectorExpr struct { 523 miniExpr 524 X Node 525 // Sel is the name of the field or method being selected, without (in the 526 // case of methods) any preceding type specifier. If the field/method is 527 // exported, than the Sym uses the local package regardless of the package 528 // of the containing type. 529 Sel *types.Sym 530 // The actual selected field - may not be filled in until typechecking. 531 Selection *types.Field 532 Prealloc *Name // preallocated storage for OMETHVALUE, if any 533 } 534 535 func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr { 536 n := &SelectorExpr{X: x, Sel: sel} 537 n.pos = pos 538 n.SetOp(op) 539 return n 540 } 541 542 func (n *SelectorExpr) SetOp(op Op) { 543 switch op { 544 default: 545 panic(n.no("SetOp " + op.String())) 546 case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OMETHVALUE, OMETHEXPR: 547 n.op = op 548 } 549 } 550 551 func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } 552 func (n *SelectorExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 553 func (n *SelectorExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 554 func (n *SelectorExpr) Offset() int64 { return n.Selection.Offset } 555 556 func (n *SelectorExpr) FuncName() *Name { 557 if n.Op() != OMETHEXPR { 558 panic(n.no("FuncName")) 559 } 560 fn := NewNameAt(n.Selection.Pos, MethodSym(n.X.Type(), n.Sel)) 561 fn.Class = PFUNC 562 fn.SetType(n.Type()) 563 if n.Selection.Nname != nil { 564 // TODO(austin): Nname is nil for interface method 565 // expressions (I.M), so we can't attach a Func to 566 // those here. reflectdata.methodWrapper generates the 567 // Func. 568 fn.Func = n.Selection.Nname.(*Name).Func 569 } 570 return fn 571 } 572 573 // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max]. 574 type SliceExpr struct { 575 miniExpr 576 X Node 577 Low Node 578 High Node 579 Max Node 580 } 581 582 func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr { 583 n := &SliceExpr{X: x, Low: low, High: high, Max: max} 584 n.pos = pos 585 n.op = op 586 return n 587 } 588 589 func (n *SliceExpr) SetOp(op Op) { 590 switch op { 591 default: 592 panic(n.no("SetOp " + op.String())) 593 case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR: 594 n.op = op 595 } 596 } 597 598 // IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR). 599 // o must be a slicing op. 600 func (o Op) IsSlice3() bool { 601 switch o { 602 case OSLICE, OSLICEARR, OSLICESTR: 603 return false 604 case OSLICE3, OSLICE3ARR: 605 return true 606 } 607 base.Fatalf("IsSlice3 op %v", o) 608 return false 609 } 610 611 // A SliceHeader expression constructs a slice header from its parts. 612 type SliceHeaderExpr struct { 613 miniExpr 614 Ptr Node 615 Len Node 616 Cap Node 617 } 618 619 func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr { 620 n := &SliceHeaderExpr{Ptr: ptr, Len: len, Cap: cap} 621 n.pos = pos 622 n.op = OSLICEHEADER 623 n.typ = typ 624 return n 625 } 626 627 // A StringHeaderExpr expression constructs a string header from its parts. 628 type StringHeaderExpr struct { 629 miniExpr 630 Ptr Node 631 Len Node 632 } 633 634 func NewStringHeaderExpr(pos src.XPos, ptr, len Node) *StringHeaderExpr { 635 n := &StringHeaderExpr{Ptr: ptr, Len: len} 636 n.pos = pos 637 n.op = OSTRINGHEADER 638 n.typ = types.Types[types.TSTRING] 639 return n 640 } 641 642 // A StarExpr is a dereference expression *X. 643 // It may end up being a value or a type. 644 type StarExpr struct { 645 miniExpr 646 X Node 647 } 648 649 func NewStarExpr(pos src.XPos, x Node) *StarExpr { 650 n := &StarExpr{X: x} 651 n.op = ODEREF 652 n.pos = pos 653 return n 654 } 655 656 func (n *StarExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 657 func (n *StarExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 658 659 // A TypeAssertionExpr is a selector expression X.(Type). 660 // Before type-checking, the type is Ntype. 661 type TypeAssertExpr struct { 662 miniExpr 663 X Node 664 665 // Runtime type information provided by walkDotType for 666 // assertions from non-empty interface to concrete type. 667 ITab Node `mknode:"-"` // *runtime.itab for Type implementing X's type 668 } 669 670 func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr { 671 n := &TypeAssertExpr{X: x} 672 n.pos = pos 673 n.op = ODOTTYPE 674 if typ != nil { 675 n.SetType(typ) 676 } 677 return n 678 } 679 680 func (n *TypeAssertExpr) SetOp(op Op) { 681 switch op { 682 default: 683 panic(n.no("SetOp " + op.String())) 684 case ODOTTYPE, ODOTTYPE2: 685 n.op = op 686 } 687 } 688 689 // A DynamicTypeAssertExpr asserts that X is of dynamic type RType. 690 type DynamicTypeAssertExpr struct { 691 miniExpr 692 X Node 693 694 // SrcRType is an expression that yields a *runtime._type value 695 // representing X's type. It's used in failed assertion panic 696 // messages. 697 SrcRType Node 698 699 // RType is an expression that yields a *runtime._type value 700 // representing the asserted type. 701 // 702 // BUG(mdempsky): If ITab is non-nil, RType may be nil. 703 RType Node 704 705 // ITab is an expression that yields a *runtime.itab value 706 // representing the asserted type within the assertee expression's 707 // original interface type. 708 // 709 // ITab is only used for assertions from non-empty interface type to 710 // a concrete (i.e., non-interface) type. For all other assertions, 711 // ITab is nil. 712 ITab Node 713 } 714 715 func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, rtype Node) *DynamicTypeAssertExpr { 716 n := &DynamicTypeAssertExpr{X: x, RType: rtype} 717 n.pos = pos 718 n.op = op 719 return n 720 } 721 722 func (n *DynamicTypeAssertExpr) SetOp(op Op) { 723 switch op { 724 default: 725 panic(n.no("SetOp " + op.String())) 726 case ODYNAMICDOTTYPE, ODYNAMICDOTTYPE2: 727 n.op = op 728 } 729 } 730 731 // A UnaryExpr is a unary expression Op X, 732 // or Op(X) for a builtin function that does not end up being a call. 733 type UnaryExpr struct { 734 miniExpr 735 X Node 736 } 737 738 func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr { 739 n := &UnaryExpr{X: x} 740 n.pos = pos 741 n.SetOp(op) 742 return n 743 } 744 745 func (n *UnaryExpr) SetOp(op Op) { 746 switch op { 747 default: 748 panic(n.no("SetOp " + op.String())) 749 case OBITNOT, ONEG, ONOT, OPLUS, ORECV, 750 OALIGNOF, OCAP, OCLOSE, OIMAG, OLEN, ONEW, 751 OOFFSETOF, OPANIC, OREAL, OSIZEOF, 752 OCHECKNIL, OCFUNC, OIDATA, OITAB, OSPTR, 753 OUNSAFESTRINGDATA, OUNSAFESLICEDATA: 754 n.op = op 755 } 756 } 757 758 // Probably temporary: using Implicit() flag to mark generic function nodes that 759 // are called to make getGfInfo analysis easier in one pre-order pass. 760 func (n *InstExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 761 func (n *InstExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 762 763 // An InstExpr is a generic function or type instantiation. 764 type InstExpr struct { 765 miniExpr 766 X Node 767 Targs []Ntype 768 } 769 770 func NewInstExpr(pos src.XPos, op Op, x Node, targs []Ntype) *InstExpr { 771 n := &InstExpr{X: x, Targs: targs} 772 n.pos = pos 773 n.op = op 774 return n 775 } 776 777 func IsZero(n Node) bool { 778 switch n.Op() { 779 case ONIL: 780 return true 781 782 case OLITERAL: 783 switch u := n.Val(); u.Kind() { 784 case constant.String: 785 return constant.StringVal(u) == "" 786 case constant.Bool: 787 return !constant.BoolVal(u) 788 default: 789 return constant.Sign(u) == 0 790 } 791 792 case OARRAYLIT: 793 n := n.(*CompLitExpr) 794 for _, n1 := range n.List { 795 if n1.Op() == OKEY { 796 n1 = n1.(*KeyExpr).Value 797 } 798 if !IsZero(n1) { 799 return false 800 } 801 } 802 return true 803 804 case OSTRUCTLIT: 805 n := n.(*CompLitExpr) 806 for _, n1 := range n.List { 807 n1 := n1.(*StructKeyExpr) 808 if !IsZero(n1.Value) { 809 return false 810 } 811 } 812 return true 813 } 814 815 return false 816 } 817 818 // lvalue etc 819 func IsAddressable(n Node) bool { 820 switch n.Op() { 821 case OINDEX: 822 n := n.(*IndexExpr) 823 if n.X.Type() != nil && n.X.Type().IsArray() { 824 return IsAddressable(n.X) 825 } 826 if n.X.Type() != nil && n.X.Type().IsString() { 827 return false 828 } 829 fallthrough 830 case ODEREF, ODOTPTR: 831 return true 832 833 case ODOT: 834 n := n.(*SelectorExpr) 835 return IsAddressable(n.X) 836 837 case ONAME: 838 n := n.(*Name) 839 if n.Class == PFUNC { 840 return false 841 } 842 return true 843 844 case OLINKSYMOFFSET: 845 return true 846 } 847 848 return false 849 } 850 851 func StaticValue(n Node) Node { 852 for { 853 if n.Op() == OCONVNOP { 854 n = n.(*ConvExpr).X 855 continue 856 } 857 858 if n.Op() == OINLCALL { 859 n = n.(*InlinedCallExpr).SingleResult() 860 continue 861 } 862 863 n1 := staticValue1(n) 864 if n1 == nil { 865 return n 866 } 867 n = n1 868 } 869 } 870 871 // staticValue1 implements a simple SSA-like optimization. If n is a local variable 872 // that is initialized and never reassigned, staticValue1 returns the initializer 873 // expression. Otherwise, it returns nil. 874 func staticValue1(nn Node) Node { 875 if nn.Op() != ONAME { 876 return nil 877 } 878 n := nn.(*Name) 879 if n.Class != PAUTO { 880 return nil 881 } 882 883 defn := n.Defn 884 if defn == nil { 885 return nil 886 } 887 888 var rhs Node 889 FindRHS: 890 switch defn.Op() { 891 case OAS: 892 defn := defn.(*AssignStmt) 893 rhs = defn.Y 894 case OAS2: 895 defn := defn.(*AssignListStmt) 896 for i, lhs := range defn.Lhs { 897 if lhs == n { 898 rhs = defn.Rhs[i] 899 break FindRHS 900 } 901 } 902 base.Fatalf("%v missing from LHS of %v", n, defn) 903 default: 904 return nil 905 } 906 if rhs == nil { 907 base.Fatalf("RHS is nil: %v", defn) 908 } 909 910 if reassigned(n) { 911 return nil 912 } 913 914 return rhs 915 } 916 917 // reassigned takes an ONAME node, walks the function in which it is defined, and returns a boolean 918 // indicating whether the name has any assignments other than its declaration. 919 // The second return value is the first such assignment encountered in the walk, if any. It is mostly 920 // useful for -m output documenting the reason for inhibited optimizations. 921 // NB: global variables are always considered to be re-assigned. 922 // TODO: handle initial declaration not including an assignment and followed by a single assignment? 923 func reassigned(name *Name) bool { 924 if name.Op() != ONAME { 925 base.Fatalf("reassigned %v", name) 926 } 927 // no way to reliably check for no-reassignment of globals, assume it can be 928 if name.Curfn == nil { 929 return true 930 } 931 932 // TODO(mdempsky): This is inefficient and becoming increasingly 933 // unwieldy. Figure out a way to generalize escape analysis's 934 // reassignment detection for use by inlining and devirtualization. 935 936 // isName reports whether n is a reference to name. 937 isName := func(x Node) bool { 938 n, ok := x.(*Name) 939 return ok && n.Canonical() == name 940 } 941 942 var do func(n Node) bool 943 do = func(n Node) bool { 944 switch n.Op() { 945 case OAS: 946 n := n.(*AssignStmt) 947 if isName(n.X) && n != name.Defn { 948 return true 949 } 950 case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV, OSELRECV2: 951 n := n.(*AssignListStmt) 952 for _, p := range n.Lhs { 953 if isName(p) && n != name.Defn { 954 return true 955 } 956 } 957 case OADDR: 958 n := n.(*AddrExpr) 959 if isName(OuterValue(n.X)) { 960 return true 961 } 962 case ORANGE: 963 n := n.(*RangeStmt) 964 if isName(n.Key) || isName(n.Value) { 965 return true 966 } 967 case OCLOSURE: 968 n := n.(*ClosureExpr) 969 if Any(n.Func, do) { 970 return true 971 } 972 } 973 return false 974 } 975 return Any(name.Curfn, do) 976 } 977 978 // IsIntrinsicCall reports whether the compiler back end will treat the call as an intrinsic operation. 979 var IsIntrinsicCall = func(*CallExpr) bool { return false } 980 981 // SameSafeExpr checks whether it is safe to reuse one of l and r 982 // instead of computing both. SameSafeExpr assumes that l and r are 983 // used in the same statement or expression. In order for it to be 984 // safe to reuse l or r, they must: 985 // - be the same expression 986 // - not have side-effects (no function calls, no channel ops); 987 // however, panics are ok 988 // - not cause inappropriate aliasing; e.g. two string to []byte 989 // conversions, must result in two distinct slices 990 // 991 // The handling of OINDEXMAP is subtle. OINDEXMAP can occur both 992 // as an lvalue (map assignment) and an rvalue (map access). This is 993 // currently OK, since the only place SameSafeExpr gets used on an 994 // lvalue expression is for OSLICE and OAPPEND optimizations, and it 995 // is correct in those settings. 996 func SameSafeExpr(l Node, r Node) bool { 997 for l.Op() == OCONVNOP { 998 l = l.(*ConvExpr).X 999 } 1000 for r.Op() == OCONVNOP { 1001 r = r.(*ConvExpr).X 1002 } 1003 if l.Op() != r.Op() || !types.Identical(l.Type(), r.Type()) { 1004 return false 1005 } 1006 1007 switch l.Op() { 1008 case ONAME: 1009 return l == r 1010 1011 case ODOT, ODOTPTR: 1012 l := l.(*SelectorExpr) 1013 r := r.(*SelectorExpr) 1014 return l.Sel != nil && r.Sel != nil && l.Sel == r.Sel && SameSafeExpr(l.X, r.X) 1015 1016 case ODEREF: 1017 l := l.(*StarExpr) 1018 r := r.(*StarExpr) 1019 return SameSafeExpr(l.X, r.X) 1020 1021 case ONOT, OBITNOT, OPLUS, ONEG: 1022 l := l.(*UnaryExpr) 1023 r := r.(*UnaryExpr) 1024 return SameSafeExpr(l.X, r.X) 1025 1026 case OCONV: 1027 l := l.(*ConvExpr) 1028 r := r.(*ConvExpr) 1029 // Some conversions can't be reused, such as []byte(str). 1030 // Allow only numeric-ish types. This is a bit conservative. 1031 return types.IsSimple[l.Type().Kind()] && SameSafeExpr(l.X, r.X) 1032 1033 case OINDEX, OINDEXMAP: 1034 l := l.(*IndexExpr) 1035 r := r.(*IndexExpr) 1036 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Index, r.Index) 1037 1038 case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD: 1039 l := l.(*BinaryExpr) 1040 r := r.(*BinaryExpr) 1041 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Y, r.Y) 1042 1043 case OLITERAL: 1044 return constant.Compare(l.Val(), token.EQL, r.Val()) 1045 1046 case ONIL: 1047 return true 1048 } 1049 1050 return false 1051 } 1052 1053 // ShouldCheckPtr reports whether pointer checking should be enabled for 1054 // function fn at a given level. See debugHelpFooter for defined 1055 // levels. 1056 func ShouldCheckPtr(fn *Func, level int) bool { 1057 return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0 1058 } 1059 1060 // ShouldAsanCheckPtr reports whether pointer checking should be enabled for 1061 // function fn when -asan is enabled. 1062 func ShouldAsanCheckPtr(fn *Func) bool { 1063 return base.Flag.ASan && fn.Pragma&NoCheckPtr == 0 1064 } 1065 1066 // IsReflectHeaderDataField reports whether l is an expression p.Data 1067 // where p has type reflect.SliceHeader or reflect.StringHeader. 1068 func IsReflectHeaderDataField(l Node) bool { 1069 if l.Type() != types.Types[types.TUINTPTR] { 1070 return false 1071 } 1072 1073 var tsym *types.Sym 1074 switch l.Op() { 1075 case ODOT: 1076 l := l.(*SelectorExpr) 1077 tsym = l.X.Type().Sym() 1078 case ODOTPTR: 1079 l := l.(*SelectorExpr) 1080 tsym = l.X.Type().Elem().Sym() 1081 default: 1082 return false 1083 } 1084 1085 if tsym == nil || l.Sym().Name != "Data" || tsym.Pkg.Path != "reflect" { 1086 return false 1087 } 1088 return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader" 1089 } 1090 1091 func ParamNames(ft *types.Type) []Node { 1092 args := make([]Node, ft.NumParams()) 1093 for i, f := range ft.Params().FieldSlice() { 1094 args[i] = AsNode(f.Nname) 1095 } 1096 return args 1097 } 1098 1099 // MethodSym returns the method symbol representing a method name 1100 // associated with a specific receiver type. 1101 // 1102 // Method symbols can be used to distinguish the same method appearing 1103 // in different method sets. For example, T.M and (*T).M have distinct 1104 // method symbols. 1105 // 1106 // The returned symbol will be marked as a function. 1107 func MethodSym(recv *types.Type, msym *types.Sym) *types.Sym { 1108 sym := MethodSymSuffix(recv, msym, "") 1109 sym.SetFunc(true) 1110 return sym 1111 } 1112 1113 // MethodSymSuffix is like methodsym, but allows attaching a 1114 // distinguisher suffix. To avoid collisions, the suffix must not 1115 // start with a letter, number, or period. 1116 func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym { 1117 if msym.IsBlank() { 1118 base.Fatalf("blank method name") 1119 } 1120 1121 rsym := recv.Sym() 1122 if recv.IsPtr() { 1123 if rsym != nil { 1124 base.Fatalf("declared pointer receiver type: %v", recv) 1125 } 1126 rsym = recv.Elem().Sym() 1127 } 1128 1129 // Find the package the receiver type appeared in. For 1130 // anonymous receiver types (i.e., anonymous structs with 1131 // embedded fields), use the "go" pseudo-package instead. 1132 rpkg := Pkgs.Go 1133 if rsym != nil { 1134 rpkg = rsym.Pkg 1135 } 1136 1137 var b bytes.Buffer 1138 if recv.IsPtr() { 1139 // The parentheses aren't really necessary, but 1140 // they're pretty traditional at this point. 1141 fmt.Fprintf(&b, "(%-S)", recv) 1142 } else { 1143 fmt.Fprintf(&b, "%-S", recv) 1144 } 1145 1146 // A particular receiver type may have multiple non-exported 1147 // methods with the same name. To disambiguate them, include a 1148 // package qualifier for names that came from a different 1149 // package than the receiver type. 1150 if !types.IsExported(msym.Name) && msym.Pkg != rpkg { 1151 b.WriteString(".") 1152 b.WriteString(msym.Pkg.Prefix) 1153 } 1154 1155 b.WriteString(".") 1156 b.WriteString(msym.Name) 1157 b.WriteString(suffix) 1158 return rpkg.LookupBytes(b.Bytes()) 1159 } 1160 1161 // MethodExprName returns the ONAME representing the method 1162 // referenced by expression n, which must be a method selector, 1163 // method expression, or method value. 1164 func MethodExprName(n Node) *Name { 1165 name, _ := MethodExprFunc(n).Nname.(*Name) 1166 return name 1167 } 1168 1169 // MethodExprFunc is like MethodExprName, but returns the types.Field instead. 1170 func MethodExprFunc(n Node) *types.Field { 1171 switch n.Op() { 1172 case ODOTMETH, OMETHEXPR, OMETHVALUE: 1173 return n.(*SelectorExpr).Selection 1174 } 1175 base.Fatalf("unexpected node: %v (%v)", n, n.Op()) 1176 panic("unreachable") 1177 }