github.com/bir3/gocompiler@v0.9.2202/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 List[0] + List[1] + ... + List[len(List)-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 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 117 func (n *AddrExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 118 func (n *AddrExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 119 120 func (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. 130 type BasicLit struct { 131 miniExpr 132 val constant.Value 133 } 134 135 // NewBasicLit returns an OLITERAL representing val with the given type. 136 func 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 147 func (n *BasicLit) Val() constant.Value { return n.val } 148 func (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. 152 func 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. 158 type BinaryExpr struct { 159 miniExpr 160 X Node 161 Y Node 162 RType Node `mknode:"-"` // see reflectdata/helpers.go 163 } 164 165 func 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 172 func (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). 185 type 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 197 func 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 205 func (*CallExpr) isStmt() {} 206 207 func (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. 222 type 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. 231 type 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 242 func 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 252 func (n *CompLitExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 253 func (n *CompLitExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 254 255 func (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. 266 type 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 292 func 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 300 func (n *ConvExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 301 func (n *ConvExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 302 func (n *ConvExpr) CheckPtr() bool { return n.flags&miniExprCheckPtr != 0 } 303 func (n *ConvExpr) SetCheckPtr(b bool) { n.flags.set(miniExprCheckPtr, b) } 304 305 func (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]. 315 type IndexExpr struct { 316 miniExpr 317 X Node 318 Index Node 319 RType Node `mknode:"-"` // see reflectdata/helpers.go 320 Assigned bool 321 } 322 323 func 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 330 func (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. 340 type KeyExpr struct { 341 miniExpr 342 Key Node 343 Value Node 344 } 345 346 func 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. 354 type StructKeyExpr struct { 355 miniExpr 356 Field *types.Field 357 Value Node 358 } 359 360 func 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 367 func (n *StructKeyExpr) Sym() *types.Sym { return n.Field.Sym } 368 369 // An InlinedCallExpr is an inlined function call. 370 type InlinedCallExpr struct { 371 miniExpr 372 Body Nodes 373 ReturnVars Nodes // must be side-effect free 374 } 375 376 func 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 385 func (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. 403 type LogicalExpr struct { 404 miniExpr 405 X Node 406 Y Node 407 } 408 409 func 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 416 func (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). 428 type MakeExpr struct { 429 miniExpr 430 RType Node `mknode:"-"` // see reflectdata/helpers.go 431 Len Node 432 Cap Node 433 } 434 435 func 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 442 func (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. 452 type NilExpr struct { 453 miniExpr 454 } 455 456 func 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. 470 type ParenExpr struct { 471 miniExpr 472 X Node 473 } 474 475 func 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 482 func (n *ParenExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 483 func (n *ParenExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 484 485 // A ResultExpr represents a direct access to a result. 486 type ResultExpr struct { 487 miniExpr 488 Index int64 // index of the result expr. 489 } 490 491 func 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. 501 type LinksymOffsetExpr struct { 502 miniExpr 503 Linksym *obj.LSym 504 Offset_ int64 505 } 506 507 func 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. 519 func 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. 525 func 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. 533 type 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 546 func 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 553 func (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 562 func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } 563 func (n *SelectorExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 564 func (n *SelectorExpr) SetImplicit(b bool) { n.flags.set(miniExprImplicit, b) } 565 func (n *SelectorExpr) Offset() int64 { return n.Selection.Offset } 566 567 func (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]. 583 type SliceExpr struct { 584 miniExpr 585 X Node 586 Low Node 587 High Node 588 Max Node 589 } 590 591 func 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 598 func (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. 609 func (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. 621 type SliceHeaderExpr struct { 622 miniExpr 623 Ptr Node 624 Len Node 625 Cap Node 626 } 627 628 func 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. 637 type StringHeaderExpr struct { 638 miniExpr 639 Ptr Node 640 Len Node 641 } 642 643 func 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. 653 type StarExpr struct { 654 miniExpr 655 X Node 656 } 657 658 func 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 665 func (n *StarExpr) Implicit() bool { return n.flags&miniExprImplicit != 0 } 666 func (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. 670 type 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 682 func 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 692 func (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. 702 type 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 727 func 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 734 func (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. 745 type UnaryExpr struct { 746 miniExpr 747 X Node 748 } 749 750 func 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 757 func (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 769 func 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 811 func 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. 857 func StaticValue(n Node) Node { 858 for { 859 if n.Op() == OCONVNOP { 860 n = n.(*ConvExpr).X 861 continue 862 } 863 864 if n.Op() == OINLCALL { 865 n = n.(*InlinedCallExpr).SingleResult() 866 continue 867 } 868 869 n1 := staticValue1(n) 870 if n1 == nil { 871 return n 872 } 873 n = n1 874 } 875 } 876 877 func staticValue1(nn Node) Node { 878 if nn.Op() != ONAME { 879 return nil 880 } 881 n := nn.(*Name).Canonical() 882 if n.Class != PAUTO { 883 return nil 884 } 885 886 defn := n.Defn 887 if defn == nil { 888 return nil 889 } 890 891 var rhs Node 892 FindRHS: 893 switch defn.Op() { 894 case OAS: 895 defn := defn.(*AssignStmt) 896 rhs = defn.Y 897 case OAS2: 898 defn := defn.(*AssignListStmt) 899 for i, lhs := range defn.Lhs { 900 if lhs == n { 901 rhs = defn.Rhs[i] 902 break FindRHS 903 } 904 } 905 base.Fatalf("%v missing from LHS of %v", n, defn) 906 default: 907 return nil 908 } 909 if rhs == nil { 910 base.Fatalf("RHS is nil: %v", defn) 911 } 912 913 if Reassigned(n) { 914 return nil 915 } 916 917 return rhs 918 } 919 920 // Reassigned takes an ONAME node, walks the function in which it is 921 // defined, and returns a boolean indicating whether the name has any 922 // assignments other than its declaration. 923 // NB: global variables are always considered to be re-assigned. 924 // TODO: handle initial declaration not including an assignment and 925 // followed by a single assignment? 926 // NOTE: any changes made here should also be made in the corresponding 927 // code in the ReassignOracle.Init method. 928 func Reassigned(name *Name) bool { 929 if name.Op() != ONAME { 930 base.Fatalf("reassigned %v", name) 931 } 932 // no way to reliably check for no-reassignment of globals, assume it can be 933 if name.Curfn == nil { 934 return true 935 } 936 937 if name.Addrtaken() { 938 return true // conservatively assume it's reassigned indirectly 939 } 940 941 // TODO(mdempsky): This is inefficient and becoming increasingly 942 // unwieldy. Figure out a way to generalize escape analysis's 943 // reassignment detection for use by inlining and devirtualization. 944 945 // isName reports whether n is a reference to name. 946 isName := func(x Node) bool { 947 if x == nil { 948 return false 949 } 950 n, ok := OuterValue(x).(*Name) 951 return ok && n.Canonical() == name 952 } 953 954 var do func(n Node) bool 955 do = func(n Node) bool { 956 switch n.Op() { 957 case OAS: 958 n := n.(*AssignStmt) 959 if isName(n.X) && n != name.Defn { 960 return true 961 } 962 case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV, OSELRECV2: 963 n := n.(*AssignListStmt) 964 for _, p := range n.Lhs { 965 if isName(p) && n != name.Defn { 966 return true 967 } 968 } 969 case OASOP: 970 n := n.(*AssignOpStmt) 971 if isName(n.X) { 972 return true 973 } 974 case OADDR: 975 n := n.(*AddrExpr) 976 if isName(n.X) { 977 base.FatalfAt(n.Pos(), "%v not marked addrtaken", name) 978 } 979 case ORANGE: 980 n := n.(*RangeStmt) 981 if isName(n.Key) || isName(n.Value) { 982 return true 983 } 984 case OCLOSURE: 985 n := n.(*ClosureExpr) 986 if Any(n.Func, do) { 987 return true 988 } 989 } 990 return false 991 } 992 return Any(name.Curfn, do) 993 } 994 995 // StaticCalleeName returns the ONAME/PFUNC for n, if known. 996 func StaticCalleeName(n Node) *Name { 997 switch n.Op() { 998 case OMETHEXPR: 999 n := n.(*SelectorExpr) 1000 return MethodExprName(n) 1001 case ONAME: 1002 n := n.(*Name) 1003 if n.Class == PFUNC { 1004 return n 1005 } 1006 case OCLOSURE: 1007 return n.(*ClosureExpr).Func.Nname 1008 } 1009 return nil 1010 } 1011 1012 // IsIntrinsicCall reports whether the compiler back end will treat the call as an intrinsic operation. 1013 var IsIntrinsicCall = func(*CallExpr) bool { return false } 1014 1015 // SameSafeExpr checks whether it is safe to reuse one of l and r 1016 // instead of computing both. SameSafeExpr assumes that l and r are 1017 // used in the same statement or expression. In order for it to be 1018 // safe to reuse l or r, they must: 1019 // - be the same expression 1020 // - not have side-effects (no function calls, no channel ops); 1021 // however, panics are ok 1022 // - not cause inappropriate aliasing; e.g. two string to []byte 1023 // conversions, must result in two distinct slices 1024 // 1025 // The handling of OINDEXMAP is subtle. OINDEXMAP can occur both 1026 // as an lvalue (map assignment) and an rvalue (map access). This is 1027 // currently OK, since the only place SameSafeExpr gets used on an 1028 // lvalue expression is for OSLICE and OAPPEND optimizations, and it 1029 // is correct in those settings. 1030 func SameSafeExpr(l Node, r Node) bool { 1031 for l.Op() == OCONVNOP { 1032 l = l.(*ConvExpr).X 1033 } 1034 for r.Op() == OCONVNOP { 1035 r = r.(*ConvExpr).X 1036 } 1037 if l.Op() != r.Op() || !types.Identical(l.Type(), r.Type()) { 1038 return false 1039 } 1040 1041 switch l.Op() { 1042 case ONAME: 1043 return l == r 1044 1045 case ODOT, ODOTPTR: 1046 l := l.(*SelectorExpr) 1047 r := r.(*SelectorExpr) 1048 return l.Sel != nil && r.Sel != nil && l.Sel == r.Sel && SameSafeExpr(l.X, r.X) 1049 1050 case ODEREF: 1051 l := l.(*StarExpr) 1052 r := r.(*StarExpr) 1053 return SameSafeExpr(l.X, r.X) 1054 1055 case ONOT, OBITNOT, OPLUS, ONEG: 1056 l := l.(*UnaryExpr) 1057 r := r.(*UnaryExpr) 1058 return SameSafeExpr(l.X, r.X) 1059 1060 case OCONV: 1061 l := l.(*ConvExpr) 1062 r := r.(*ConvExpr) 1063 // Some conversions can't be reused, such as []byte(str). 1064 // Allow only numeric-ish types. This is a bit conservative. 1065 return types.IsSimple[l.Type().Kind()] && SameSafeExpr(l.X, r.X) 1066 1067 case OINDEX, OINDEXMAP: 1068 l := l.(*IndexExpr) 1069 r := r.(*IndexExpr) 1070 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Index, r.Index) 1071 1072 case OADD, OSUB, OOR, OXOR, OMUL, OLSH, ORSH, OAND, OANDNOT, ODIV, OMOD: 1073 l := l.(*BinaryExpr) 1074 r := r.(*BinaryExpr) 1075 return SameSafeExpr(l.X, r.X) && SameSafeExpr(l.Y, r.Y) 1076 1077 case OLITERAL: 1078 return constant.Compare(l.Val(), token.EQL, r.Val()) 1079 1080 case ONIL: 1081 return true 1082 } 1083 1084 return false 1085 } 1086 1087 // ShouldCheckPtr reports whether pointer checking should be enabled for 1088 // function fn at a given level. See debugHelpFooter for defined 1089 // levels. 1090 func ShouldCheckPtr(fn *Func, level int) bool { 1091 return base.Debug.Checkptr >= level && fn.Pragma&NoCheckPtr == 0 1092 } 1093 1094 // ShouldAsanCheckPtr reports whether pointer checking should be enabled for 1095 // function fn when -asan is enabled. 1096 func ShouldAsanCheckPtr(fn *Func) bool { 1097 return base.Flag.ASan && fn.Pragma&NoCheckPtr == 0 1098 } 1099 1100 // IsReflectHeaderDataField reports whether l is an expression p.Data 1101 // where p has type reflect.SliceHeader or reflect.StringHeader. 1102 func IsReflectHeaderDataField(l Node) bool { 1103 if l.Type() != types.Types[types.TUINTPTR] { 1104 return false 1105 } 1106 1107 var tsym *types.Sym 1108 switch l.Op() { 1109 case ODOT: 1110 l := l.(*SelectorExpr) 1111 tsym = l.X.Type().Sym() 1112 case ODOTPTR: 1113 l := l.(*SelectorExpr) 1114 tsym = l.X.Type().Elem().Sym() 1115 default: 1116 return false 1117 } 1118 1119 if tsym == nil || l.Sym().Name != "Data" || tsym.Pkg.Path != "reflect" { 1120 return false 1121 } 1122 return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader" 1123 } 1124 1125 func ParamNames(ft *types.Type) []Node { 1126 args := make([]Node, ft.NumParams()) 1127 for i, f := range ft.Params() { 1128 args[i] = f.Nname.(*Name) 1129 } 1130 return args 1131 } 1132 1133 // MethodSym returns the method symbol representing a method name 1134 // associated with a specific receiver type. 1135 // 1136 // Method symbols can be used to distinguish the same method appearing 1137 // in different method sets. For example, T.M and (*T).M have distinct 1138 // method symbols. 1139 // 1140 // The returned symbol will be marked as a function. 1141 func MethodSym(recv *types.Type, msym *types.Sym) *types.Sym { 1142 sym := MethodSymSuffix(recv, msym, "") 1143 sym.SetFunc(true) 1144 return sym 1145 } 1146 1147 // MethodSymSuffix is like MethodSym, but allows attaching a 1148 // distinguisher suffix. To avoid collisions, the suffix must not 1149 // start with a letter, number, or period. 1150 func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym { 1151 if msym.IsBlank() { 1152 base.Fatalf("blank method name") 1153 } 1154 1155 rsym := recv.Sym() 1156 if recv.IsPtr() { 1157 if rsym != nil { 1158 base.Fatalf("declared pointer receiver type: %v", recv) 1159 } 1160 rsym = recv.Elem().Sym() 1161 } 1162 1163 // Find the package the receiver type appeared in. For 1164 // anonymous receiver types (i.e., anonymous structs with 1165 // embedded fields), use the "go" pseudo-package instead. 1166 rpkg := Pkgs.Go 1167 if rsym != nil { 1168 rpkg = rsym.Pkg 1169 } 1170 1171 var b bytes.Buffer 1172 if recv.IsPtr() { 1173 // The parentheses aren't really necessary, but 1174 // they're pretty traditional at this point. 1175 fmt.Fprintf(&b, "(%-S)", recv) 1176 } else { 1177 fmt.Fprintf(&b, "%-S", recv) 1178 } 1179 1180 // A particular receiver type may have multiple non-exported 1181 // methods with the same name. To disambiguate them, include a 1182 // package qualifier for names that came from a different 1183 // package than the receiver type. 1184 if !types.IsExported(msym.Name) && msym.Pkg != rpkg { 1185 b.WriteString(".") 1186 b.WriteString(msym.Pkg.Prefix) 1187 } 1188 1189 b.WriteString(".") 1190 b.WriteString(msym.Name) 1191 b.WriteString(suffix) 1192 return rpkg.LookupBytes(b.Bytes()) 1193 } 1194 1195 // LookupMethodSelector returns the types.Sym of the selector for a method 1196 // named in local symbol name, as well as the types.Sym of the receiver. 1197 // 1198 // TODO(prattmic): this does not attempt to handle method suffixes (wrappers). 1199 func LookupMethodSelector(pkg *types.Pkg, name string) (typ, meth *types.Sym, err error) { 1200 typeName, methName := splitType(name) 1201 if typeName == "" { 1202 return nil, nil, fmt.Errorf("%s doesn't contain type split", name) 1203 } 1204 1205 if len(typeName) > 3 && typeName[:2] == "(*" && typeName[len(typeName)-1] == ')' { 1206 // Symbol name is for a pointer receiver method. We just want 1207 // the base type name. 1208 typeName = typeName[2 : len(typeName)-1] 1209 } 1210 1211 typ = pkg.Lookup(typeName) 1212 meth = pkg.Selector(methName) 1213 return typ, meth, nil 1214 } 1215 1216 // splitType splits a local symbol name into type and method (fn). If this a 1217 // free function, typ == "". 1218 // 1219 // N.B. closures and methods can be ambiguous (e.g., bar.func1). These cases 1220 // are returned as methods. 1221 func splitType(name string) (typ, fn string) { 1222 // Types are split on the first dot, ignoring everything inside 1223 // brackets (instantiation of type parameter, usually including 1224 // "go.shape"). 1225 bracket := 0 1226 for i, r := range name { 1227 if r == '.' && bracket == 0 { 1228 return name[:i], name[i+1:] 1229 } 1230 if r == '[' { 1231 bracket++ 1232 } 1233 if r == ']' { 1234 bracket-- 1235 } 1236 } 1237 return "", name 1238 } 1239 1240 // MethodExprName returns the ONAME representing the method 1241 // referenced by expression n, which must be a method selector, 1242 // method expression, or method value. 1243 func MethodExprName(n Node) *Name { 1244 name, _ := MethodExprFunc(n).Nname.(*Name) 1245 return name 1246 } 1247 1248 // MethodExprFunc is like MethodExprName, but returns the types.Field instead. 1249 func MethodExprFunc(n Node) *types.Field { 1250 switch n.Op() { 1251 case ODOTMETH, OMETHEXPR, OMETHVALUE: 1252 return n.(*SelectorExpr).Selection 1253 } 1254 base.Fatalf("unexpected node: %v (%v)", n, n.Op()) 1255 panic("unreachable") 1256 }