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