github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/ir/name.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/bir3/gocompiler/src/cmd/compile/internal/base" 9 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 10 "github.com/bir3/gocompiler/src/cmd/internal/obj" 11 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 12 "github.com/bir3/gocompiler/src/cmd/internal/src" 13 "fmt" 14 15 "github.com/bir3/gocompiler/src/go/constant" 16 ) 17 18 // An Ident is an identifier, possibly qualified. 19 type Ident struct { 20 miniExpr 21 sym *types.Sym 22 } 23 24 func NewIdent(pos src.XPos, sym *types.Sym) *Ident { 25 n := new(Ident) 26 n.op = ONONAME 27 n.pos = pos 28 n.sym = sym 29 return n 30 } 31 32 func (n *Ident) Sym() *types.Sym { return n.sym } 33 34 // Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL). 35 type Name struct { 36 miniExpr 37 BuiltinOp Op // uint8 38 Class Class // uint8 39 pragma PragmaFlag // int16 40 flags bitset16 41 DictIndex uint16 // index of the dictionary entry describing the type of this variable declaration plus 1 42 sym *types.Sym 43 Func *Func // TODO(austin): nil for I.M, eqFor, hashfor, and hashmem 44 Offset_ int64 45 val constant.Value 46 Opt interface{} // for use by escape analysis 47 Embed *[]Embed // list of embedded files, for ONAME var 48 49 // For a local variable (not param) or extern, the initializing assignment (OAS or OAS2). 50 // For a closure var, the ONAME node of the outer captured variable. 51 // For the case-local variables of a type switch, the type switch guard (OTYPESW). 52 // For a range variable, the range statement (ORANGE) 53 // For a recv variable in a case of a select statement, the receive assignment (OSELRECV2) 54 // For the name of a function, points to corresponding Func node. 55 Defn Node 56 57 // The function, method, or closure in which local variable or param is declared. 58 Curfn *Func 59 60 Heapaddr *Name // temp holding heap address of param 61 62 // ONAME closure linkage 63 // Consider: 64 // 65 // func f() { 66 // x := 1 // x1 67 // func() { 68 // use(x) // x2 69 // func() { 70 // use(x) // x3 71 // --- parser is here --- 72 // }() 73 // }() 74 // } 75 // 76 // There is an original declaration of x and then a chain of mentions of x 77 // leading into the current function. Each time x is mentioned in a new closure, 78 // we create a variable representing x for use in that specific closure, 79 // since the way you get to x is different in each closure. 80 // 81 // Let's number the specific variables as shown in the code: 82 // x1 is the original x, x2 is when mentioned in the closure, 83 // and x3 is when mentioned in the closure in the closure. 84 // 85 // We keep these linked (assume N > 1): 86 // 87 // - x1.Defn = original declaration statement for x (like most variables) 88 // - x1.Innermost = current innermost closure x (in this case x3), or nil for none 89 // - x1.IsClosureVar() = false 90 // 91 // - xN.Defn = x1, N > 1 92 // - xN.IsClosureVar() = true, N > 1 93 // - x2.Outer = nil 94 // - xN.Outer = x(N-1), N > 2 95 // 96 // 97 // When we look up x in the symbol table, we always get x1. 98 // Then we can use x1.Innermost (if not nil) to get the x 99 // for the innermost known closure function, 100 // but the first reference in a closure will find either no x1.Innermost 101 // or an x1.Innermost with .Funcdepth < Funcdepth. 102 // In that case, a new xN must be created, linked in with: 103 // 104 // xN.Defn = x1 105 // xN.Outer = x1.Innermost 106 // x1.Innermost = xN 107 // 108 // When we finish the function, we'll process its closure variables 109 // and find xN and pop it off the list using: 110 // 111 // x1 := xN.Defn 112 // x1.Innermost = xN.Outer 113 // 114 // We leave x1.Innermost set so that we can still get to the original 115 // variable quickly. Not shown here, but once we're 116 // done parsing a function and no longer need xN.Outer for the 117 // lexical x reference links as described above, funcLit 118 // recomputes xN.Outer as the semantic x reference link tree, 119 // even filling in x in intermediate closures that might not 120 // have mentioned it along the way to inner closures that did. 121 // See funcLit for details. 122 // 123 // During the eventual compilation, then, for closure variables we have: 124 // 125 // xN.Defn = original variable 126 // xN.Outer = variable captured in next outward scope 127 // to make closure where xN appears 128 // 129 // Because of the sharding of pieces of the node, x.Defn means x.Name.Defn 130 // and x.Innermost/Outer means x.Name.Param.Innermost/Outer. 131 Innermost *Name 132 Outer *Name 133 } 134 135 func (n *Name) isExpr() {} 136 137 func (n *Name) copy() Node { panic(n.no("copy")) } 138 func (n *Name) doChildren(do func(Node) bool) bool { return false } 139 func (n *Name) editChildren(edit func(Node) Node) {} 140 func (n *Name) editChildrenWithHidden(edit func(Node) Node) {} 141 142 // RecordFrameOffset records the frame offset for the name. 143 // It is used by package types when laying out function arguments. 144 func (n *Name) RecordFrameOffset(offset int64) { 145 n.SetFrameOffset(offset) 146 } 147 148 // NewNameAt returns a new ONAME Node associated with symbol s at position pos. 149 // The caller is responsible for setting Curfn. 150 func NewNameAt(pos src.XPos, sym *types.Sym) *Name { 151 if sym == nil { 152 base.Fatalf("NewNameAt nil") 153 } 154 return newNameAt(pos, ONAME, sym) 155 } 156 157 // NewDeclNameAt returns a new Name associated with symbol s at position pos. 158 // The caller is responsible for setting Curfn. 159 func NewDeclNameAt(pos src.XPos, op Op, sym *types.Sym) *Name { 160 if sym == nil { 161 base.Fatalf("NewDeclNameAt nil") 162 } 163 switch op { 164 case ONAME, OTYPE, OLITERAL: 165 // ok 166 default: 167 base.Fatalf("NewDeclNameAt op %v", op) 168 } 169 return newNameAt(pos, op, sym) 170 } 171 172 // NewConstAt returns a new OLITERAL Node associated with symbol s at position pos. 173 func NewConstAt(pos src.XPos, sym *types.Sym, typ *types.Type, val constant.Value) *Name { 174 if sym == nil { 175 base.Fatalf("NewConstAt nil") 176 } 177 n := newNameAt(pos, OLITERAL, sym) 178 n.SetType(typ) 179 n.SetVal(val) 180 return n 181 } 182 183 // newNameAt is like NewNameAt but allows sym == nil. 184 func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name { 185 n := new(Name) 186 n.op = op 187 n.pos = pos 188 n.sym = sym 189 return n 190 } 191 192 func (n *Name) Name() *Name { return n } 193 func (n *Name) Sym() *types.Sym { return n.sym } 194 func (n *Name) SetSym(x *types.Sym) { n.sym = x } 195 func (n *Name) SubOp() Op { return n.BuiltinOp } 196 func (n *Name) SetSubOp(x Op) { n.BuiltinOp = x } 197 func (n *Name) SetFunc(x *Func) { n.Func = x } 198 func (n *Name) Offset() int64 { panic("Name.Offset") } 199 func (n *Name) SetOffset(x int64) { 200 if x != 0 { 201 panic("Name.SetOffset") 202 } 203 } 204 func (n *Name) FrameOffset() int64 { return n.Offset_ } 205 func (n *Name) SetFrameOffset(x int64) { n.Offset_ = x } 206 207 func (n *Name) Linksym() *obj.LSym { return n.sym.Linksym() } 208 func (n *Name) LinksymABI(abi obj.ABI) *obj.LSym { return n.sym.LinksymABI(abi) } 209 210 func (*Name) CanBeNtype() {} 211 func (*Name) CanBeAnSSASym() {} 212 func (*Name) CanBeAnSSAAux() {} 213 214 // Pragma returns the PragmaFlag for p, which must be for an OTYPE. 215 func (n *Name) Pragma() PragmaFlag { return n.pragma } 216 217 // SetPragma sets the PragmaFlag for p, which must be for an OTYPE. 218 func (n *Name) SetPragma(flag PragmaFlag) { n.pragma = flag } 219 220 // Alias reports whether p, which must be for an OTYPE, is a type alias. 221 func (n *Name) Alias() bool { return n.flags&nameAlias != 0 } 222 223 // SetAlias sets whether p, which must be for an OTYPE, is a type alias. 224 func (n *Name) SetAlias(alias bool) { n.flags.set(nameAlias, alias) } 225 226 const ( 227 nameReadonly = 1 << iota 228 nameByval // is the variable captured by value or by reference 229 nameNeedzero // if it contains pointers, needs to be zeroed on function entry 230 nameAutoTemp // is the variable a temporary (implies no dwarf info. reset if escapes to heap) 231 nameUsed // for variable declared and not used error 232 nameIsClosureVar // PAUTOHEAP closure pseudo-variable; original (if any) at n.Defn 233 nameIsOutputParamHeapAddr // pointer to a result parameter's heap copy 234 nameIsOutputParamInRegisters // output parameter in registers spills as an auto 235 nameAddrtaken // address taken, even if not moved to heap 236 nameInlFormal // PAUTO created by inliner, derived from callee formal 237 nameInlLocal // PAUTO created by inliner, derived from callee local 238 nameOpenDeferSlot // if temporary var storing info for open-coded defers 239 nameLibfuzzer8BitCounter // if PEXTERN should be assigned to __sancov_cntrs section 240 nameCoverageCounter // instrumentation counter var for cmd/cover 241 nameCoverageAuxVar // instrumentation pkg ID variable cmd/cover 242 nameAlias // is type name an alias 243 ) 244 245 func (n *Name) Readonly() bool { return n.flags&nameReadonly != 0 } 246 func (n *Name) Needzero() bool { return n.flags&nameNeedzero != 0 } 247 func (n *Name) AutoTemp() bool { return n.flags&nameAutoTemp != 0 } 248 func (n *Name) Used() bool { return n.flags&nameUsed != 0 } 249 func (n *Name) IsClosureVar() bool { return n.flags&nameIsClosureVar != 0 } 250 func (n *Name) IsOutputParamHeapAddr() bool { return n.flags&nameIsOutputParamHeapAddr != 0 } 251 func (n *Name) IsOutputParamInRegisters() bool { return n.flags&nameIsOutputParamInRegisters != 0 } 252 func (n *Name) Addrtaken() bool { return n.flags&nameAddrtaken != 0 } 253 func (n *Name) InlFormal() bool { return n.flags&nameInlFormal != 0 } 254 func (n *Name) InlLocal() bool { return n.flags&nameInlLocal != 0 } 255 func (n *Name) OpenDeferSlot() bool { return n.flags&nameOpenDeferSlot != 0 } 256 func (n *Name) Libfuzzer8BitCounter() bool { return n.flags&nameLibfuzzer8BitCounter != 0 } 257 func (n *Name) CoverageCounter() bool { return n.flags&nameCoverageCounter != 0 } 258 func (n *Name) CoverageAuxVar() bool { return n.flags&nameCoverageAuxVar != 0 } 259 260 func (n *Name) setReadonly(b bool) { n.flags.set(nameReadonly, b) } 261 func (n *Name) SetNeedzero(b bool) { n.flags.set(nameNeedzero, b) } 262 func (n *Name) SetAutoTemp(b bool) { n.flags.set(nameAutoTemp, b) } 263 func (n *Name) SetUsed(b bool) { n.flags.set(nameUsed, b) } 264 func (n *Name) SetIsClosureVar(b bool) { n.flags.set(nameIsClosureVar, b) } 265 func (n *Name) SetIsOutputParamHeapAddr(b bool) { n.flags.set(nameIsOutputParamHeapAddr, b) } 266 func (n *Name) SetIsOutputParamInRegisters(b bool) { n.flags.set(nameIsOutputParamInRegisters, b) } 267 func (n *Name) SetAddrtaken(b bool) { n.flags.set(nameAddrtaken, b) } 268 func (n *Name) SetInlFormal(b bool) { n.flags.set(nameInlFormal, b) } 269 func (n *Name) SetInlLocal(b bool) { n.flags.set(nameInlLocal, b) } 270 func (n *Name) SetOpenDeferSlot(b bool) { n.flags.set(nameOpenDeferSlot, b) } 271 func (n *Name) SetLibfuzzer8BitCounter(b bool) { n.flags.set(nameLibfuzzer8BitCounter, b) } 272 func (n *Name) SetCoverageCounter(b bool) { n.flags.set(nameCoverageCounter, b) } 273 func (n *Name) SetCoverageAuxVar(b bool) { n.flags.set(nameCoverageAuxVar, b) } 274 275 // OnStack reports whether variable n may reside on the stack. 276 func (n *Name) OnStack() bool { 277 if n.Op() == ONAME { 278 switch n.Class { 279 case PPARAM, PPARAMOUT, PAUTO: 280 return n.Esc() != EscHeap 281 case PEXTERN, PAUTOHEAP: 282 return false 283 } 284 } 285 // Note: fmt.go:dumpNodeHeader calls all "func() bool"-typed 286 // methods, but it can only recover from panics, not Fatalf. 287 panic(fmt.Sprintf("%v: not a variable: %v", base.FmtPos(n.Pos()), n)) 288 } 289 290 // MarkReadonly indicates that n is an ONAME with readonly contents. 291 func (n *Name) MarkReadonly() { 292 if n.Op() != ONAME { 293 base.Fatalf("Node.MarkReadonly %v", n.Op()) 294 } 295 n.setReadonly(true) 296 // Mark the linksym as readonly immediately 297 // so that the SSA backend can use this information. 298 // It will be overridden later during dumpglobls. 299 n.Linksym().Type = objabi.SRODATA 300 } 301 302 // Val returns the constant.Value for the node. 303 func (n *Name) Val() constant.Value { 304 if n.val == nil { 305 return constant.MakeUnknown() 306 } 307 return n.val 308 } 309 310 // SetVal sets the constant.Value for the node. 311 func (n *Name) SetVal(v constant.Value) { 312 if n.op != OLITERAL { 313 panic(n.no("SetVal")) 314 } 315 AssertValidTypeForConst(n.Type(), v) 316 n.val = v 317 } 318 319 // Canonical returns the logical declaration that n represents. If n 320 // is a closure variable, then Canonical returns the original Name as 321 // it appears in the function that immediately contains the 322 // declaration. Otherwise, Canonical simply returns n itself. 323 func (n *Name) Canonical() *Name { 324 if n.IsClosureVar() && n.Defn != nil { 325 n = n.Defn.(*Name) 326 } 327 return n 328 } 329 330 func (n *Name) SetByval(b bool) { 331 if n.Canonical() != n { 332 base.Fatalf("SetByval called on non-canonical variable: %v", n) 333 } 334 n.flags.set(nameByval, b) 335 } 336 337 func (n *Name) Byval() bool { 338 // We require byval to be set on the canonical variable, but we 339 // allow it to be accessed from any instance. 340 return n.Canonical().flags&nameByval != 0 341 } 342 343 // NewClosureVar returns a new closure variable for fn to refer to 344 // outer variable n. 345 func NewClosureVar(pos src.XPos, fn *Func, n *Name) *Name { 346 switch n.Class { 347 case PAUTO, PPARAM, PPARAMOUT, PAUTOHEAP: 348 // ok 349 default: 350 // Prevent mistaken capture of global variables. 351 base.Fatalf("NewClosureVar: %+v", n) 352 } 353 354 c := NewNameAt(pos, n.Sym()) 355 c.Curfn = fn 356 c.Class = PAUTOHEAP 357 c.SetIsClosureVar(true) 358 c.Defn = n.Canonical() 359 c.Outer = n 360 361 c.SetType(n.Type()) 362 c.SetTypecheck(n.Typecheck()) 363 364 fn.ClosureVars = append(fn.ClosureVars, c) 365 366 return c 367 } 368 369 // NewHiddenParam returns a new hidden parameter for fn with the given 370 // name and type. 371 func NewHiddenParam(pos src.XPos, fn *Func, sym *types.Sym, typ *types.Type) *Name { 372 if fn.OClosure != nil { 373 base.FatalfAt(fn.Pos(), "cannot add hidden parameters to closures") 374 } 375 376 fn.SetNeedctxt(true) 377 378 // Create a fake parameter, disassociated from any real function, to 379 // pretend to capture. 380 fake := NewNameAt(pos, sym) 381 fake.Class = PPARAM 382 fake.SetType(typ) 383 fake.SetByval(true) 384 385 return NewClosureVar(pos, fn, fake) 386 } 387 388 // CaptureName returns a Name suitable for referring to n from within function 389 // fn or from the package block if fn is nil. If n is a free variable declared 390 // within a function that encloses fn, then CaptureName returns the closure 391 // variable that refers to n within fn, creating it if necessary. 392 // Otherwise, it simply returns n. 393 func CaptureName(pos src.XPos, fn *Func, n *Name) *Name { 394 if n.Op() != ONAME || n.Curfn == nil { 395 return n // okay to use directly 396 } 397 if n.IsClosureVar() { 398 base.FatalfAt(pos, "misuse of CaptureName on closure variable: %v", n) 399 } 400 401 c := n.Innermost 402 if c == nil { 403 c = n 404 } 405 if c.Curfn == fn { 406 return c 407 } 408 409 if fn == nil { 410 base.FatalfAt(pos, "package-block reference to %v, declared in %v", n, n.Curfn) 411 } 412 413 // Do not have a closure var for the active closure yet; make one. 414 c = NewClosureVar(pos, fn, c) 415 416 // Link into list of active closure variables. 417 // Popped from list in FinishCaptureNames. 418 n.Innermost = c 419 420 return c 421 } 422 423 // FinishCaptureNames handles any work leftover from calling CaptureName 424 // earlier. outerfn should be the function that immediately encloses fn. 425 func FinishCaptureNames(pos src.XPos, outerfn, fn *Func) { 426 // closure-specific variables are hanging off the 427 // ordinary ones; see CaptureName above. 428 // unhook them. 429 // make the list of pointers for the closure call. 430 for _, cv := range fn.ClosureVars { 431 // Unlink from n; see comment above on type Name for these fields. 432 n := cv.Defn.(*Name) 433 n.Innermost = cv.Outer 434 435 // If the closure usage of n is not dense, we need to make it 436 // dense by recapturing n within the enclosing function. 437 // 438 // That is, suppose we just finished parsing the innermost 439 // closure f4 in this code: 440 // 441 // func f() { 442 // n := 1 443 // func() { // f2 444 // use(n) 445 // func() { // f3 446 // func() { // f4 447 // use(n) 448 // }() 449 // }() 450 // }() 451 // } 452 // 453 // At this point cv.Outer is f2's n; there is no n for f3. To 454 // construct the closure f4 from within f3, we need to use f3's 455 // n and in this case we need to create f3's n with CaptureName. 456 // 457 // We'll decide later in walk whether to use v directly or &v. 458 cv.Outer = CaptureName(pos, outerfn, n) 459 } 460 } 461 462 // SameSource reports whether two nodes refer to the same source 463 // element. 464 // 465 // It exists to help incrementally migrate the compiler towards 466 // allowing the introduction of IdentExpr (#42990). Once we have 467 // IdentExpr, it will no longer be safe to directly compare Node 468 // values to tell if they refer to the same Name. Instead, code will 469 // need to explicitly get references to the underlying Name object(s), 470 // and compare those instead. 471 // 472 // It will still be safe to compare Nodes directly for checking if two 473 // nodes are syntactically the same. The SameSource function exists to 474 // indicate code that intentionally compares Nodes for syntactic 475 // equality as opposed to code that has yet to be updated in 476 // preparation for IdentExpr. 477 func SameSource(n1, n2 Node) bool { 478 return n1 == n2 479 } 480 481 // Uses reports whether expression x is a (direct) use of the given 482 // variable. 483 func Uses(x Node, v *Name) bool { 484 if v == nil || v.Op() != ONAME { 485 base.Fatalf("RefersTo bad Name: %v", v) 486 } 487 return x.Op() == ONAME && x.Name() == v 488 } 489 490 // DeclaredBy reports whether expression x refers (directly) to a 491 // variable that was declared by the given statement. 492 func DeclaredBy(x, stmt Node) bool { 493 if stmt == nil { 494 base.Fatalf("DeclaredBy nil") 495 } 496 return x.Op() == ONAME && SameSource(x.Name().Defn, stmt) 497 } 498 499 // The Class of a variable/function describes the "storage class" 500 // of a variable or function. During parsing, storage classes are 501 // called declaration contexts. 502 type Class uint8 503 504 //go:generate stringer -type=Class name.go 505 const ( 506 Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables 507 PEXTERN // global variables 508 PAUTO // local variables 509 PAUTOHEAP // local variables or parameters moved to heap 510 PPARAM // input arguments 511 PPARAMOUT // output results 512 PTYPEPARAM // type params 513 PFUNC // global functions 514 515 // Careful: Class is stored in three bits in Node.flags. 516 _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3) 517 ) 518 519 type Embed struct { 520 Pos src.XPos 521 Patterns []string 522 }