github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/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 "github.com/shogo82148/std/cmd/compile/internal/types" 9 "github.com/shogo82148/std/cmd/internal/obj" 10 "github.com/shogo82148/std/cmd/internal/src" 11 "github.com/shogo82148/std/go/constant" 12 ) 13 14 // An Expr is a Node that can appear as an expression. 15 type Expr interface { 16 Node 17 isExpr() 18 } 19 20 // An AddStringExpr is a string concatenation List[0] + List[1] + ... + List[len(List)-1]. 21 type AddStringExpr struct { 22 miniExpr 23 List Nodes 24 Prealloc *Name 25 } 26 27 func NewAddStringExpr(pos src.XPos, list []Node) *AddStringExpr 28 29 // An AddrExpr is an address-of expression &X. 30 // It may end up being a normal address-of or an allocation of a composite literal. 31 type AddrExpr struct { 32 miniExpr 33 X Node 34 Prealloc *Name 35 } 36 37 func NewAddrExpr(pos src.XPos, x Node) *AddrExpr 38 39 func (n *AddrExpr) Implicit() bool 40 func (n *AddrExpr) SetImplicit(b bool) 41 42 func (n *AddrExpr) SetOp(op Op) 43 44 // A BasicLit is a literal of basic type. 45 type BasicLit struct { 46 miniExpr 47 val constant.Value 48 } 49 50 // NewBasicLit returns an OLITERAL representing val with the given type. 51 func NewBasicLit(pos src.XPos, typ *types.Type, val constant.Value) Node 52 53 func (n *BasicLit) Val() constant.Value 54 func (n *BasicLit) SetVal(val constant.Value) 55 56 // NewConstExpr returns an OLITERAL representing val, copying the 57 // position and type from orig. 58 func NewConstExpr(val constant.Value, orig Node) Node 59 60 // A BinaryExpr is a binary expression X Op Y, 61 // or Op(X, Y) for builtin functions that do not become calls. 62 type BinaryExpr struct { 63 miniExpr 64 X Node 65 Y Node 66 RType Node `mknode:"-"` 67 } 68 69 func NewBinaryExpr(pos src.XPos, op Op, x, y Node) *BinaryExpr 70 71 func (n *BinaryExpr) SetOp(op Op) 72 73 // A CallExpr is a function call Fun(Args). 74 type CallExpr struct { 75 miniExpr 76 Fun Node 77 Args Nodes 78 DeferAt Node 79 RType Node `mknode:"-"` 80 KeepAlive []*Name 81 IsDDD bool 82 GoDefer bool 83 NoInline bool 84 } 85 86 func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr 87 88 func (n *CallExpr) SetOp(op Op) 89 90 // A ClosureExpr is a function literal expression. 91 type ClosureExpr struct { 92 miniExpr 93 Func *Func `mknode:"-"` 94 Prealloc *Name 95 IsGoWrap bool 96 } 97 98 // A CompLitExpr is a composite literal Type{Vals}. 99 // Before type-checking, the type is Ntype. 100 type CompLitExpr struct { 101 miniExpr 102 List Nodes 103 RType Node `mknode:"-"` 104 Prealloc *Name 105 // For OSLICELIT, Len is the backing array length. 106 // For OMAPLIT, Len is the number of entries that we've removed from List and 107 // generated explicit mapassign calls for. This is used to inform the map alloc hint. 108 Len int64 109 } 110 111 func NewCompLitExpr(pos src.XPos, op Op, typ *types.Type, list []Node) *CompLitExpr 112 113 func (n *CompLitExpr) Implicit() bool 114 func (n *CompLitExpr) SetImplicit(b bool) 115 116 func (n *CompLitExpr) SetOp(op Op) 117 118 // A ConvExpr is a conversion Type(X). 119 // It may end up being a value or a type. 120 type ConvExpr struct { 121 miniExpr 122 X Node 123 124 // For implementing OCONVIFACE expressions. 125 // 126 // TypeWord is an expression yielding a *runtime._type or 127 // *runtime.itab value to go in the type word of the iface/eface 128 // result. See reflectdata.ConvIfaceTypeWord for further details. 129 // 130 // SrcRType is an expression yielding a *runtime._type value for X, 131 // if it's not pointer-shaped and needs to be heap allocated. 132 TypeWord Node `mknode:"-"` 133 SrcRType Node `mknode:"-"` 134 135 // For -d=checkptr instrumentation of conversions from 136 // unsafe.Pointer to *Elem or *[Len]Elem. 137 // 138 // TODO(mdempsky): We only ever need one of these, but currently we 139 // don't decide which one until walk. Longer term, it probably makes 140 // sense to have a dedicated IR op for `(*[Len]Elem)(ptr)[:n:m]` 141 // expressions. 142 ElemRType Node `mknode:"-"` 143 ElemElemRType Node `mknode:"-"` 144 } 145 146 func NewConvExpr(pos src.XPos, op Op, typ *types.Type, x Node) *ConvExpr 147 148 func (n *ConvExpr) Implicit() bool 149 func (n *ConvExpr) SetImplicit(b bool) 150 func (n *ConvExpr) CheckPtr() bool 151 func (n *ConvExpr) SetCheckPtr(b bool) 152 153 func (n *ConvExpr) SetOp(op Op) 154 155 // An IndexExpr is an index expression X[Index]. 156 type IndexExpr struct { 157 miniExpr 158 X Node 159 Index Node 160 RType Node `mknode:"-"` 161 Assigned bool 162 } 163 164 func NewIndexExpr(pos src.XPos, x, index Node) *IndexExpr 165 166 func (n *IndexExpr) SetOp(op Op) 167 168 // A KeyExpr is a Key: Value composite literal key. 169 type KeyExpr struct { 170 miniExpr 171 Key Node 172 Value Node 173 } 174 175 func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr 176 177 // A StructKeyExpr is a Field: Value composite literal key. 178 type StructKeyExpr struct { 179 miniExpr 180 Field *types.Field 181 Value Node 182 } 183 184 func NewStructKeyExpr(pos src.XPos, field *types.Field, value Node) *StructKeyExpr 185 186 func (n *StructKeyExpr) Sym() *types.Sym 187 188 // An InlinedCallExpr is an inlined function call. 189 type InlinedCallExpr struct { 190 miniExpr 191 Body Nodes 192 ReturnVars Nodes 193 } 194 195 func NewInlinedCallExpr(pos src.XPos, body, retvars []Node) *InlinedCallExpr 196 197 func (n *InlinedCallExpr) SingleResult() Node 198 199 // A LogicalExpr is an expression X Op Y where Op is && or ||. 200 // It is separate from BinaryExpr to make room for statements 201 // that must be executed before Y but after X. 202 type LogicalExpr struct { 203 miniExpr 204 X Node 205 Y Node 206 } 207 208 func NewLogicalExpr(pos src.XPos, op Op, x, y Node) *LogicalExpr 209 210 func (n *LogicalExpr) SetOp(op Op) 211 212 // A MakeExpr is a make expression: make(Type[, Len[, Cap]]). 213 // Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY, 214 // but *not* OMAKE (that's a pre-typechecking CallExpr). 215 type MakeExpr struct { 216 miniExpr 217 RType Node `mknode:"-"` 218 Len Node 219 Cap Node 220 } 221 222 func NewMakeExpr(pos src.XPos, op Op, len, cap Node) *MakeExpr 223 224 func (n *MakeExpr) SetOp(op Op) 225 226 // A NilExpr represents the predefined untyped constant nil. 227 type NilExpr struct { 228 miniExpr 229 } 230 231 func NewNilExpr(pos src.XPos, typ *types.Type) *NilExpr 232 233 // A ParenExpr is a parenthesized expression (X). 234 // It may end up being a value or a type. 235 type ParenExpr struct { 236 miniExpr 237 X Node 238 } 239 240 func NewParenExpr(pos src.XPos, x Node) *ParenExpr 241 242 func (n *ParenExpr) Implicit() bool 243 func (n *ParenExpr) SetImplicit(b bool) 244 245 // A ResultExpr represents a direct access to a result. 246 type ResultExpr struct { 247 miniExpr 248 Index int64 249 } 250 251 func NewResultExpr(pos src.XPos, typ *types.Type, index int64) *ResultExpr 252 253 // A LinksymOffsetExpr refers to an offset within a global variable. 254 // It is like a SelectorExpr but without the field name. 255 type LinksymOffsetExpr struct { 256 miniExpr 257 Linksym *obj.LSym 258 Offset_ int64 259 } 260 261 func NewLinksymOffsetExpr(pos src.XPos, lsym *obj.LSym, offset int64, typ *types.Type) *LinksymOffsetExpr 262 263 // NewLinksymExpr is NewLinksymOffsetExpr, but with offset fixed at 0. 264 func NewLinksymExpr(pos src.XPos, lsym *obj.LSym, typ *types.Type) *LinksymOffsetExpr 265 266 // NewNameOffsetExpr is NewLinksymOffsetExpr, but taking a *Name 267 // representing a global variable instead of an *obj.LSym directly. 268 func NewNameOffsetExpr(pos src.XPos, name *Name, offset int64, typ *types.Type) *LinksymOffsetExpr 269 270 // A SelectorExpr is a selector expression X.Sel. 271 type SelectorExpr struct { 272 miniExpr 273 X Node 274 // Sel is the name of the field or method being selected, without (in the 275 // case of methods) any preceding type specifier. If the field/method is 276 // exported, than the Sym uses the local package regardless of the package 277 // of the containing type. 278 Sel *types.Sym 279 // The actual selected field - may not be filled in until typechecking. 280 Selection *types.Field 281 Prealloc *Name 282 } 283 284 func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr 285 286 func (n *SelectorExpr) SetOp(op Op) 287 288 func (n *SelectorExpr) Sym() *types.Sym 289 func (n *SelectorExpr) Implicit() bool 290 func (n *SelectorExpr) SetImplicit(b bool) 291 func (n *SelectorExpr) Offset() int64 292 293 func (n *SelectorExpr) FuncName() *Name 294 295 // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max]. 296 type SliceExpr struct { 297 miniExpr 298 X Node 299 Low Node 300 High Node 301 Max Node 302 } 303 304 func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr 305 306 func (n *SliceExpr) SetOp(op Op) 307 308 // IsSlice3 reports whether o is a slice3 op (OSLICE3, OSLICE3ARR). 309 // o must be a slicing op. 310 func (o Op) IsSlice3() bool 311 312 // A SliceHeader expression constructs a slice header from its parts. 313 type SliceHeaderExpr struct { 314 miniExpr 315 Ptr Node 316 Len Node 317 Cap Node 318 } 319 320 func NewSliceHeaderExpr(pos src.XPos, typ *types.Type, ptr, len, cap Node) *SliceHeaderExpr 321 322 // A StringHeaderExpr expression constructs a string header from its parts. 323 type StringHeaderExpr struct { 324 miniExpr 325 Ptr Node 326 Len Node 327 } 328 329 func NewStringHeaderExpr(pos src.XPos, ptr, len Node) *StringHeaderExpr 330 331 // A StarExpr is a dereference expression *X. 332 // It may end up being a value or a type. 333 type StarExpr struct { 334 miniExpr 335 X Node 336 } 337 338 func NewStarExpr(pos src.XPos, x Node) *StarExpr 339 340 func (n *StarExpr) Implicit() bool 341 func (n *StarExpr) SetImplicit(b bool) 342 343 // A TypeAssertionExpr is a selector expression X.(Type). 344 // Before type-checking, the type is Ntype. 345 type TypeAssertExpr struct { 346 miniExpr 347 X Node 348 349 // Runtime type information provided by walkDotType for 350 // assertions from non-empty interface to concrete type. 351 ITab Node `mknode:"-"` 352 353 // An internal/abi.TypeAssert descriptor to pass to the runtime. 354 Descriptor *obj.LSym 355 } 356 357 func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr 358 359 func (n *TypeAssertExpr) SetOp(op Op) 360 361 // A DynamicTypeAssertExpr asserts that X is of dynamic type RType. 362 type DynamicTypeAssertExpr struct { 363 miniExpr 364 X Node 365 366 // SrcRType is an expression that yields a *runtime._type value 367 // representing X's type. It's used in failed assertion panic 368 // messages. 369 SrcRType Node 370 371 // RType is an expression that yields a *runtime._type value 372 // representing the asserted type. 373 // 374 // BUG(mdempsky): If ITab is non-nil, RType may be nil. 375 RType Node 376 377 // ITab is an expression that yields a *runtime.itab value 378 // representing the asserted type within the assertee expression's 379 // original interface type. 380 // 381 // ITab is only used for assertions from non-empty interface type to 382 // a concrete (i.e., non-interface) type. For all other assertions, 383 // ITab is nil. 384 ITab Node 385 } 386 387 func NewDynamicTypeAssertExpr(pos src.XPos, op Op, x, rtype Node) *DynamicTypeAssertExpr 388 389 func (n *DynamicTypeAssertExpr) SetOp(op Op) 390 391 // A UnaryExpr is a unary expression Op X, 392 // or Op(X) for a builtin function that does not end up being a call. 393 type UnaryExpr struct { 394 miniExpr 395 X Node 396 } 397 398 func NewUnaryExpr(pos src.XPos, op Op, x Node) *UnaryExpr 399 400 func (n *UnaryExpr) SetOp(op Op) 401 402 func IsZero(n Node) bool 403 404 // lvalue etc 405 func IsAddressable(n Node) bool 406 407 // StaticValue analyzes n to find the earliest expression that always 408 // evaluates to the same value as n, which might be from an enclosing 409 // function. 410 // 411 // For example, given: 412 // 413 // var x int = g() 414 // func() { 415 // y := x 416 // *p = int(y) 417 // } 418 // 419 // calling StaticValue on the "int(y)" expression returns the outer 420 // "g()" expression. 421 func StaticValue(n Node) Node 422 423 // Reassigned takes an ONAME node, walks the function in which it is 424 // defined, and returns a boolean indicating whether the name has any 425 // assignments other than its declaration. 426 // NB: global variables are always considered to be re-assigned. 427 // TODO: handle initial declaration not including an assignment and 428 // followed by a single assignment? 429 // NOTE: any changes made here should also be made in the corresponding 430 // code in the ReassignOracle.Init method. 431 func Reassigned(name *Name) bool 432 433 // StaticCalleeName returns the ONAME/PFUNC for n, if known. 434 func StaticCalleeName(n Node) *Name 435 436 // IsIntrinsicCall reports whether the compiler back end will treat the call as an intrinsic operation. 437 var IsIntrinsicCall = func(*CallExpr) bool { return false } 438 439 // SameSafeExpr checks whether it is safe to reuse one of l and r 440 // instead of computing both. SameSafeExpr assumes that l and r are 441 // used in the same statement or expression. In order for it to be 442 // safe to reuse l or r, they must: 443 // - be the same expression 444 // - not have side-effects (no function calls, no channel ops); 445 // however, panics are ok 446 // - not cause inappropriate aliasing; e.g. two string to []byte 447 // conversions, must result in two distinct slices 448 // 449 // The handling of OINDEXMAP is subtle. OINDEXMAP can occur both 450 // as an lvalue (map assignment) and an rvalue (map access). This is 451 // currently OK, since the only place SameSafeExpr gets used on an 452 // lvalue expression is for OSLICE and OAPPEND optimizations, and it 453 // is correct in those settings. 454 func SameSafeExpr(l Node, r Node) bool 455 456 // ShouldCheckPtr reports whether pointer checking should be enabled for 457 // function fn at a given level. See debugHelpFooter for defined 458 // levels. 459 func ShouldCheckPtr(fn *Func, level int) bool 460 461 // ShouldAsanCheckPtr reports whether pointer checking should be enabled for 462 // function fn when -asan is enabled. 463 func ShouldAsanCheckPtr(fn *Func) bool 464 465 // IsReflectHeaderDataField reports whether l is an expression p.Data 466 // where p has type reflect.SliceHeader or reflect.StringHeader. 467 func IsReflectHeaderDataField(l Node) bool 468 469 func ParamNames(ft *types.Type) []Node 470 471 // MethodSym returns the method symbol representing a method name 472 // associated with a specific receiver type. 473 // 474 // Method symbols can be used to distinguish the same method appearing 475 // in different method sets. For example, T.M and (*T).M have distinct 476 // method symbols. 477 // 478 // The returned symbol will be marked as a function. 479 func MethodSym(recv *types.Type, msym *types.Sym) *types.Sym 480 481 // MethodSymSuffix is like MethodSym, but allows attaching a 482 // distinguisher suffix. To avoid collisions, the suffix must not 483 // start with a letter, number, or period. 484 func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym 485 486 // LookupMethodSelector returns the types.Sym of the selector for a method 487 // named in local symbol name, as well as the types.Sym of the receiver. 488 // 489 // TODO(prattmic): this does not attempt to handle method suffixes (wrappers). 490 func LookupMethodSelector(pkg *types.Pkg, name string) (typ, meth *types.Sym, err error) 491 492 // MethodExprName returns the ONAME representing the method 493 // referenced by expression n, which must be a method selector, 494 // method expression, or method value. 495 func MethodExprName(n Node) *Name 496 497 // MethodExprFunc is like MethodExprName, but returns the types.Field instead. 498 func MethodExprFunc(n Node) *types.Field