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