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