builder.go (94823B)
1 // Copyright 2013 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 ssa 6 7 // This file defines the builder, which builds SSA-form IR for function bodies. 8 // 9 // SSA construction has two phases, "create" and "build". First, one 10 // or more packages are created in any order by a sequence of calls to 11 // CreatePackage, either from syntax or from mere type information. 12 // Each created package has a complete set of Members (const, var, 13 // type, func) that can be accessed through methods like 14 // Program.FuncValue. 15 // 16 // It is not necessary to call CreatePackage for all dependencies of 17 // each syntax package, only for its direct imports. (In future 18 // perhaps even this restriction may be lifted.) 19 // 20 // Second, packages created from syntax are built, by one or more 21 // calls to Package.Build, which may be concurrent; or by a call to 22 // Program.Build, which builds all packages in parallel. Building 23 // traverses the type-annotated syntax tree of each function body and 24 // creates SSA-form IR, a control-flow graph of instructions, 25 // populating fields such as Function.Body, .Params, and others. 26 // 27 // Building may create additional methods, including: 28 // - wrapper methods (e.g. for embedding, or implicit &recv) 29 // - bound method closures (e.g. for use(recv.f)) 30 // - thunks (e.g. for use(I.f) or use(T.f)) 31 // - generic instances (e.g. to produce f[int] from f[any]). 32 // As these methods are created, they are added to the build queue, 33 // and then processed in turn, until a fixed point is reached, 34 // Since these methods might belong to packages that were not 35 // created (by a call to CreatePackage), their Pkg field is unset. 36 // 37 // Instances of generic functions may be either instantiated (f[int] 38 // is a copy of f[T] with substitutions) or wrapped (f[int] delegates 39 // to f[T]), depending on the availability of generic syntax and the 40 // InstantiateGenerics mode flag. 41 // 42 // Each package has an initializer function named "init" that calls 43 // the initializer functions of each direct import, computes and 44 // assigns the initial value of each global variable, and calls each 45 // source-level function named "init". (These generate SSA functions 46 // named "init#1", "init#2", etc.) 47 // 48 // Runtime types 49 // 50 // Each MakeInterface operation is a conversion from a non-interface 51 // type to an interface type. The semantics of this operation requires 52 // a runtime type descriptor, which is the type portion of an 53 // interface, and the value abstracted by reflect.Type. 54 // 55 // The program accumulates all non-parameterized types that are 56 // encountered as MakeInterface operands, along with all types that 57 // may be derived from them using reflection. This set is available as 58 // Program.RuntimeTypes, and the methods of these types may be 59 // reachable via interface calls or reflection even if they are never 60 // referenced from the SSA IR. (In practice, algorithms such as RTA 61 // that compute reachability from package main perform their own 62 // tracking of runtime types at a finer grain, so this feature is not 63 // very useful.) 64 // 65 // Function literals 66 // 67 // Anonymous functions must be built as soon as they are encountered, 68 // as it may affect locals of the enclosing function, but they are not 69 // marked 'built' until the end of the outermost enclosing function. 70 // (Among other things, this causes them to be logged in top-down order.) 71 // 72 // The Function.build fields determines the algorithm for building the 73 // function body. It is cleared to mark that building is complete. 74 75 import ( 76 "fmt" 77 "go/ast" 78 "go/constant" 79 "go/token" 80 "go/types" 81 "os" 82 "runtime" 83 "sync" 84 85 "slices" 86 87 "golang.org/x/tools/internal/typeparams" 88 "golang.org/x/tools/internal/typesinternal" 89 "golang.org/x/tools/internal/versions" 90 ) 91 92 type opaqueType struct{ name string } 93 94 func (t *opaqueType) String() string { return t.name } 95 func (t *opaqueType) Underlying() types.Type { return t } 96 97 var ( 98 varOk = newVar("ok", tBool) 99 varIndex = newVar("index", tInt) 100 101 // Type constants. 102 tBool = types.Typ[types.Bool] 103 tByte = types.Typ[types.Byte] 104 tRune = types.Universe.Lookup("rune").Type() // prints as "rune" (Typ[Rune] is same as Int32) 105 tInt = types.Typ[types.Int] 106 tInvalid = types.Typ[types.Invalid] 107 tString = types.Typ[types.String] 108 tUntypedNil = types.Typ[types.UntypedNil] 109 110 tRangeIter = &opaqueType{"iter"} // the type of all "range" iterators 111 tDeferStack = types.NewPointer(&opaqueType{"deferStack"}) // the type of a "deferStack" from ssa:deferstack() 112 tEface = types.NewInterfaceType(nil, nil).Complete() 113 114 // SSA Value constants. 115 vZero = intConst(0) 116 vOne = intConst(1) 117 vTrue = NewConst(constant.MakeBool(true), tBool) 118 vFalse = NewConst(constant.MakeBool(false), tBool) 119 vNoReturn = NewConst(constant.MakeString("noreturn"), tString) 120 121 jReady = intConst(0) // range-over-func jump is READY 122 jBusy = intConst(-1) // range-over-func jump is BUSY 123 jDone = intConst(-2) // range-over-func jump is DONE 124 125 // The ssa:deferstack intrinsic returns the current function's defer stack. 126 vDeferStack = &Builtin{ 127 name: "ssa:deferstack", 128 sig: types.NewSignatureType(nil, nil, nil, nil, typesinternal.TupleOf(tDeferStack), false), 129 } 130 ) 131 132 // builder holds state associated with the package currently being built. 133 // Its methods contain all the logic for AST-to-SSA conversion. 134 // 135 // All Functions belong to the same Program. 136 // 137 // builders are not thread-safe. 138 type builder struct { 139 fns []*Function // Functions that have finished their CREATE phases. 140 141 finished int // finished is the length of the prefix of fns containing built functions. 142 143 // The task of building shared functions within the builder. 144 // Shared functions are ones the builder may either create or lookup. 145 // These may be built by other builders in parallel. 146 // The task is done when the builder has finished iterating, and it 147 // waits for all shared functions to finish building. 148 // nil implies there are no hared functions to wait on. 149 buildshared *task 150 } 151 152 // shared is done when the builder has built all of the 153 // enqueued functions to a fixed-point. 154 func (b *builder) shared() *task { 155 if b.buildshared == nil { // lazily-initialize 156 b.buildshared = &task{done: make(chan unit)} 157 } 158 return b.buildshared 159 } 160 161 // enqueue fn to be built by the builder. 162 func (b *builder) enqueue(fn *Function) { 163 b.fns = append(b.fns, fn) 164 } 165 166 // waitForSharedFunction indicates that the builder should wait until 167 // the potentially shared function fn has finished building. 168 // 169 // This should include any functions that may be built by other 170 // builders. 171 func (b *builder) waitForSharedFunction(fn *Function) { 172 if fn.buildshared != nil { // maybe need to wait? 173 s := b.shared() 174 s.addEdge(fn.buildshared) 175 } 176 } 177 178 // cond emits to fn code to evaluate boolean condition e and jump 179 // to t or f depending on its value, performing various simplifications. 180 // 181 // Postcondition: fn.currentBlock is nil. 182 func (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) { 183 switch e := e.(type) { 184 case *ast.ParenExpr: 185 b.cond(fn, e.X, t, f) 186 return 187 188 case *ast.BinaryExpr: 189 switch e.Op { 190 case token.LAND: 191 ltrue := fn.newBasicBlock("cond.true") 192 b.cond(fn, e.X, ltrue, f) 193 fn.currentBlock = ltrue 194 b.cond(fn, e.Y, t, f) 195 return 196 197 case token.LOR: 198 lfalse := fn.newBasicBlock("cond.false") 199 b.cond(fn, e.X, t, lfalse) 200 fn.currentBlock = lfalse 201 b.cond(fn, e.Y, t, f) 202 return 203 } 204 205 case *ast.UnaryExpr: 206 if e.Op == token.NOT { 207 b.cond(fn, e.X, f, t) 208 return 209 } 210 } 211 212 // A traditional compiler would simplify "if false" (etc) here 213 // but we do not, for better fidelity to the source code. 214 // 215 // The value of a constant condition may be platform-specific, 216 // and may cause blocks that are reachable in some configuration 217 // to be hidden from subsequent analyses such as bug-finding tools. 218 emitIf(fn, b.expr(fn, e), t, f) 219 } 220 221 // logicalBinop emits code to fn to evaluate e, a &&- or 222 // ||-expression whose reified boolean value is wanted. 223 // The value is returned. 224 func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value { 225 rhs := fn.newBasicBlock("binop.rhs") 226 done := fn.newBasicBlock("binop.done") 227 228 // T(e) = T(e.X) = T(e.Y) after untyped constants have been 229 // eliminated. 230 // TODO(adonovan): not true; MyBool==MyBool yields UntypedBool. 231 t := fn.typeOf(e) 232 233 var short Value // value of the short-circuit path 234 switch e.Op { 235 case token.LAND: 236 b.cond(fn, e.X, rhs, done) 237 short = NewConst(constant.MakeBool(false), t) 238 239 case token.LOR: 240 b.cond(fn, e.X, done, rhs) 241 short = NewConst(constant.MakeBool(true), t) 242 } 243 244 // Is rhs unreachable? 245 if rhs.Preds == nil { 246 // Simplify false&&y to false, true||y to true. 247 fn.currentBlock = done 248 return short 249 } 250 251 // Is done unreachable? 252 if done.Preds == nil { 253 // Simplify true&&y (or false||y) to y. 254 fn.currentBlock = rhs 255 return b.expr(fn, e.Y) 256 } 257 258 // All edges from e.X to done carry the short-circuit value. 259 var edges []Value 260 for range done.Preds { 261 edges = append(edges, short) 262 } 263 264 // The edge from e.Y to done carries the value of e.Y. 265 fn.currentBlock = rhs 266 edges = append(edges, b.expr(fn, e.Y)) 267 emitJump(fn, done) 268 fn.currentBlock = done 269 270 phi := &Phi{Edges: edges, Comment: e.Op.String()} 271 phi.pos = e.OpPos 272 phi.typ = t 273 return done.emit(phi) 274 } 275 276 // exprN lowers a multi-result expression e to SSA form, emitting code 277 // to fn and returning a single Value whose type is a *types.Tuple. 278 // The caller must access the components via Extract. 279 // 280 // Multi-result expressions include CallExprs in a multi-value 281 // assignment or return statement, and "value,ok" uses of 282 // TypeAssertExpr, IndexExpr (when X is a map), and UnaryExpr (when Op 283 // is token.ARROW). 284 func (b *builder) exprN(fn *Function, e ast.Expr) Value { 285 typ := fn.typeOf(e).(*types.Tuple) 286 switch e := e.(type) { 287 case *ast.ParenExpr: 288 return b.exprN(fn, e.X) 289 290 case *ast.CallExpr: 291 // Currently, no built-in function nor type conversion 292 // has multiple results, so we can avoid some of the 293 // cases for single-valued CallExpr. 294 var c Call 295 b.setCall(fn, e, &c.Call) 296 c.typ = typ 297 return emitCall(fn, &c) 298 299 case *ast.IndexExpr: 300 mapt := typeparams.CoreType(fn.typeOf(e.X)).(*types.Map) // ,ok must be a map. 301 lookup := &Lookup{ 302 X: b.expr(fn, e.X), 303 Index: emitConv(fn, b.expr(fn, e.Index), mapt.Key()), 304 CommaOk: true, 305 } 306 lookup.setType(typ) 307 lookup.setPos(e.Lbrack) 308 return fn.emit(lookup) 309 310 case *ast.TypeAssertExpr: 311 return emitTypeTest(fn, b.expr(fn, e.X), typ.At(0).Type(), e.Lparen) 312 313 case *ast.UnaryExpr: // must be receive <- 314 unop := &UnOp{ 315 Op: token.ARROW, 316 X: b.expr(fn, e.X), 317 CommaOk: true, 318 } 319 unop.setType(typ) 320 unop.setPos(e.OpPos) 321 return fn.emit(unop) 322 } 323 panic(fmt.Sprintf("exprN(%T) in %s", e, fn)) 324 } 325 326 // builtin emits to fn SSA instructions to implement a call to the 327 // built-in function obj with the specified arguments 328 // and return type. It returns the value defined by the result. 329 // 330 // The result is nil if no special handling was required; in this case 331 // the caller should treat this like an ordinary library function 332 // call. 333 func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value { 334 typ = fn.typ(typ) 335 switch obj.Name() { 336 case "make": 337 switch ct := typeparams.CoreType(typ).(type) { 338 case *types.Slice: 339 n := b.expr(fn, args[1]) 340 m := n 341 if len(args) == 3 { 342 m = b.expr(fn, args[2]) 343 } 344 if m, ok := m.(*Const); ok { 345 // treat make([]T, n, m) as new([m]T)[:n] 346 cap := m.Int64() 347 at := types.NewArray(ct.Elem(), cap) 348 v := &Slice{ 349 X: emitNew(fn, at, pos, "makeslice"), 350 High: n, 351 } 352 v.setPos(pos) 353 v.setType(typ) 354 return fn.emit(v) 355 } 356 v := &MakeSlice{ 357 Len: n, 358 Cap: m, 359 } 360 v.setPos(pos) 361 v.setType(typ) 362 return fn.emit(v) 363 364 case *types.Map: 365 var res Value 366 if len(args) == 2 { 367 res = b.expr(fn, args[1]) 368 } 369 v := &MakeMap{Reserve: res} 370 v.setPos(pos) 371 v.setType(typ) 372 return fn.emit(v) 373 374 case *types.Chan: 375 var sz Value = vZero 376 if len(args) == 2 { 377 sz = b.expr(fn, args[1]) 378 } 379 v := &MakeChan{Size: sz} 380 v.setPos(pos) 381 v.setType(typ) 382 return fn.emit(v) 383 } 384 385 case "new": 386 alloc := emitNew(fn, typeparams.MustDeref(typ), pos, "new") 387 if !fn.info.Types[args[0]].IsType() { 388 // new(expr), requires go1.26 389 v := b.expr(fn, args[0]) 390 emitStore(fn, alloc, v, pos) 391 } 392 return alloc 393 394 case "len", "cap": 395 // Special case: len or cap of an array or *array is 396 // based on the type, not the value which may be nil. 397 // We must still evaluate the value, though. (If it 398 // was side-effect free, the whole call would have 399 // been constant-folded.) 400 t := typeparams.Deref(fn.typeOf(args[0])) 401 if at, ok := typeparams.CoreType(t).(*types.Array); ok { 402 b.expr(fn, args[0]) // for effects only 403 return intConst(at.Len()) 404 } 405 // Otherwise treat as normal. 406 407 case "panic": 408 fn.emit(&Panic{ 409 X: emitConv(fn, b.expr(fn, args[0]), tEface), 410 pos: pos, 411 }) 412 fn.currentBlock = fn.newBasicBlock("unreachable") 413 return vTrue // any non-nil Value will do 414 } 415 return nil // treat all others as a regular function call 416 } 417 418 // addr lowers a single-result addressable expression e to SSA form, 419 // emitting code to fn and returning the location (an lvalue) defined 420 // by the expression. 421 // 422 // If escaping is true, addr marks the base variable of the 423 // addressable expression e as being a potentially escaping pointer 424 // value. For example, in this code: 425 // 426 // a := A{ 427 // b: [1]B{B{c: 1}} 428 // } 429 // return &a.b[0].c 430 // 431 // the application of & causes a.b[0].c to have its address taken, 432 // which means that ultimately the local variable a must be 433 // heap-allocated. This is a simple but very conservative escape 434 // analysis. 435 // 436 // Operations forming potentially escaping pointers include: 437 // - &x, including when implicit in method call or composite literals. 438 // - a[:] iff a is an array (not *array) 439 // - references to variables in lexically enclosing functions. 440 func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue { 441 switch e := e.(type) { 442 case *ast.Ident: 443 if isBlankIdent(e) { 444 return blank{} 445 } 446 obj := fn.objectOf(e).(*types.Var) 447 var v Value 448 if g := fn.Prog.packageLevelMember(obj); g != nil { 449 v = g.(*Global) // var (address) 450 } else { 451 v = fn.lookup(obj, escaping) 452 } 453 return &address{addr: v, pos: e.Pos(), expr: e} 454 455 case *ast.CompositeLit: 456 typ := typeparams.Deref(fn.typeOf(e)) 457 var v *Alloc 458 if escaping { 459 v = emitNew(fn, typ, e.Lbrace, "complit") 460 } else { 461 v = emitLocal(fn, typ, e.Lbrace, "complit") 462 } 463 var sb storebuf 464 b.compLit(fn, v, e, true, &sb) 465 sb.emit(fn) 466 return &address{addr: v, pos: e.Lbrace, expr: e} 467 468 case *ast.ParenExpr: 469 return b.addr(fn, e.X, escaping) 470 471 case *ast.SelectorExpr: 472 sel := fn.selection(e) 473 if sel == nil { 474 // qualified identifier 475 return b.addr(fn, e.Sel, escaping) 476 } 477 if sel.kind != types.FieldVal { 478 panic(sel) 479 } 480 wantAddr := true 481 v := b.receiver(fn, e.X, wantAddr, escaping, sel) 482 index := sel.index[len(sel.index)-1] 483 fld := fieldOf(typeparams.MustDeref(v.Type()), index) // v is an addr. 484 485 // Due to the two phases of resolving AssignStmt, a panic from x.f = p() 486 // when x is nil is required to come after the side-effects of 487 // evaluating x and p(). 488 emit := func(fn *Function) Value { 489 return emitFieldSelection(fn, v, index, true, e.Sel) 490 } 491 return &lazyAddress{addr: emit, t: fld.Type(), pos: e.Sel.Pos(), expr: e.Sel} 492 493 case *ast.IndexExpr: 494 xt := fn.typeOf(e.X) 495 elem, mode := indexType(xt) 496 var x Value 497 var et types.Type 498 switch mode { 499 case ixArrVar: // array, array|slice, array|*array, or array|*array|slice. 500 x = b.addr(fn, e.X, escaping).address(fn) 501 et = types.NewPointer(elem) 502 case ixVar: // *array, slice, *array|slice 503 x = b.expr(fn, e.X) 504 et = types.NewPointer(elem) 505 case ixMap: 506 mt := typeparams.CoreType(xt).(*types.Map) 507 return &element{ 508 m: b.expr(fn, e.X), 509 k: emitConv(fn, b.expr(fn, e.Index), mt.Key()), 510 t: mt.Elem(), 511 pos: e.Lbrack, 512 } 513 default: 514 panic("unexpected container type in IndexExpr: " + xt.String()) 515 } 516 index := b.expr(fn, e.Index) 517 if isUntyped(index.Type()) { 518 index = emitConv(fn, index, tInt) 519 } 520 // Due to the two phases of resolving AssignStmt, a panic from x[i] = p() 521 // when x is nil or i is out-of-bounds is required to come after the 522 // side-effects of evaluating x, i and p(). 523 emit := func(fn *Function) Value { 524 v := &IndexAddr{ 525 X: x, 526 Index: index, 527 } 528 v.setPos(e.Lbrack) 529 v.setType(et) 530 return fn.emit(v) 531 } 532 return &lazyAddress{addr: emit, t: typeparams.MustDeref(et), pos: e.Lbrack, expr: e} 533 534 case *ast.StarExpr: 535 return &address{addr: b.expr(fn, e.X), pos: e.Star, expr: e} 536 } 537 538 panic(fmt.Sprintf("unexpected address expression: %T", e)) 539 } 540 541 type store struct { 542 lhs lvalue 543 rhs Value 544 } 545 546 type storebuf struct{ stores []store } 547 548 func (sb *storebuf) store(lhs lvalue, rhs Value) { 549 sb.stores = append(sb.stores, store{lhs, rhs}) 550 } 551 552 func (sb *storebuf) emit(fn *Function) { 553 for _, s := range sb.stores { 554 s.lhs.store(fn, s.rhs) 555 } 556 } 557 558 // assign emits to fn code to initialize the lvalue loc with the value 559 // of expression e. If isZero is true, assign assumes that loc holds 560 // the zero value for its type. 561 // 562 // This is equivalent to loc.store(fn, b.expr(fn, e)), but may generate 563 // better code in some cases, e.g., for composite literals in an 564 // addressable location. 565 // 566 // If sb is not nil, assign generates code to evaluate expression e, but 567 // not to update loc. Instead, the necessary stores are appended to the 568 // storebuf sb so that they can be executed later. This allows correct 569 // in-place update of existing variables when the RHS is a composite 570 // literal that may reference parts of the LHS. 571 func (b *builder) assign(fn *Function, loc lvalue, e ast.Expr, isZero bool, sb *storebuf) { 572 // Can we initialize it in place? 573 if e, ok := ast.Unparen(e).(*ast.CompositeLit); ok { 574 // A CompositeLit never evaluates to a pointer, 575 // so if the type of the location is a pointer, 576 // an &-operation is implied. 577 if !is[blank](loc) && isPointerCore(loc.typ()) { // avoid calling blank.typ() 578 ptr := b.addr(fn, e, true).address(fn) 579 // copy address 580 if sb != nil { 581 sb.store(loc, ptr) 582 } else { 583 loc.store(fn, ptr) 584 } 585 return 586 } 587 } 588 589 // simple case: just copy 590 rhs := b.expr(fn, e) 591 if sb != nil { 592 sb.store(loc, rhs) 593 } else { 594 loc.store(fn, rhs) 595 } 596 } 597 598 // expr lowers a single-result expression e to SSA form, emitting code 599 // to fn and returning the Value defined by the expression. 600 func (b *builder) expr(fn *Function, e ast.Expr) Value { 601 e = ast.Unparen(e) 602 603 tv := fn.info.Types[e] 604 605 // Is expression a constant? 606 if tv.Value != nil { 607 return NewConst(tv.Value, fn.typ(tv.Type)) 608 } 609 610 var v Value 611 if tv.Addressable() { 612 // Prefer pointer arithmetic ({Index,Field}Addr) followed 613 // by Load over subelement extraction (e.g. Index, Field), 614 // to avoid large copies. 615 v = b.addr(fn, e, false).load(fn) 616 } else { 617 v = b.expr0(fn, e, tv) 618 } 619 if fn.debugInfo() { 620 emitDebugRef(fn, e, v, false) 621 } 622 return v 623 } 624 625 func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value { 626 switch e := e.(type) { 627 case *ast.BasicLit: 628 panic("non-constant BasicLit") // unreachable 629 630 case *ast.FuncLit: 631 /* function literal */ 632 anon := &Function{ 633 name: fmt.Sprintf("%s$%d", fn.Name(), 1+len(fn.AnonFuncs)), 634 Signature: fn.typeOf(e.Type).(*types.Signature), 635 pos: e.Type.Func, 636 parent: fn, 637 anonIdx: int32(len(fn.AnonFuncs)), 638 Pkg: fn.Pkg, 639 Prog: fn.Prog, 640 syntax: e, 641 info: fn.info, 642 goversion: fn.goversion, 643 build: (*builder).buildFromSyntax, 644 topLevelOrigin: nil, // use anonIdx to lookup an anon instance's origin. 645 typeparams: fn.typeparams, // share the parent's type parameters. 646 typeargs: fn.typeargs, // share the parent's type arguments. 647 subst: fn.subst, // share the parent's type substitutions. 648 uniq: fn.uniq, // start from parent's unique values 649 } 650 fn.AnonFuncs = append(fn.AnonFuncs, anon) 651 // Build anon immediately, as it may cause fn's locals to escape. 652 // (It is not marked 'built' until the end of the enclosing FuncDecl.) 653 anon.build(b, anon) 654 fn.uniq = anon.uniq // resume after anon's unique values 655 if anon.FreeVars == nil { 656 return anon 657 } 658 v := &MakeClosure{Fn: anon} 659 v.setType(fn.typ(tv.Type)) 660 for _, fv := range anon.FreeVars { 661 v.Bindings = append(v.Bindings, fv.outer) 662 fv.outer = nil 663 } 664 return fn.emit(v) 665 666 case *ast.TypeAssertExpr: // single-result form only 667 return emitTypeAssert(fn, b.expr(fn, e.X), fn.typ(tv.Type), e.Lparen) 668 669 case *ast.CallExpr: 670 if fn.info.Types[e.Fun].IsType() { 671 // Explicit type conversion, e.g. string(x) or big.Int(x) 672 x := b.expr(fn, e.Args[0]) 673 y := emitConv(fn, x, fn.typ(tv.Type)) 674 if y != x { 675 switch y := y.(type) { 676 case *Convert: 677 y.pos = e.Lparen 678 case *ChangeType: 679 y.pos = e.Lparen 680 case *MakeInterface: 681 y.pos = e.Lparen 682 case *SliceToArrayPointer: 683 y.pos = e.Lparen 684 case *UnOp: // conversion from slice to array. 685 y.pos = e.Lparen 686 } 687 } 688 return y 689 } 690 // Call to "intrinsic" built-ins, e.g. new, make, panic. 691 if id, ok := ast.Unparen(e.Fun).(*ast.Ident); ok { 692 if obj, ok := fn.info.Uses[id].(*types.Builtin); ok { 693 if v := b.builtin(fn, obj, e.Args, fn.typ(tv.Type), e.Lparen); v != nil { 694 return v 695 } 696 } 697 } 698 // Regular function call. 699 var v Call 700 b.setCall(fn, e, &v.Call) 701 v.setType(fn.typ(tv.Type)) 702 return emitCall(fn, &v) 703 704 case *ast.UnaryExpr: 705 switch e.Op { 706 case token.AND: // &X --- potentially escaping. 707 addr := b.addr(fn, e.X, true) 708 if _, ok := ast.Unparen(e.X).(*ast.StarExpr); ok { 709 // &*p must panic if p is nil (http://golang.org/s/go12nil). 710 // For simplicity, we'll just (suboptimally) rely 711 // on the side effects of a load. 712 // TODO(adonovan): emit dedicated nilcheck. 713 addr.load(fn) 714 } 715 return addr.address(fn) 716 case token.ADD: 717 return b.expr(fn, e.X) 718 case token.NOT, token.ARROW, token.SUB, token.XOR: // ! <- - ^ 719 v := &UnOp{ 720 Op: e.Op, 721 X: b.expr(fn, e.X), 722 } 723 v.setPos(e.OpPos) 724 v.setType(fn.typ(tv.Type)) 725 return fn.emit(v) 726 default: 727 panic(e.Op) 728 } 729 730 case *ast.BinaryExpr: 731 switch e.Op { 732 case token.LAND, token.LOR: 733 return b.logicalBinop(fn, e) 734 case token.SHL, token.SHR: 735 fallthrough 736 case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT: 737 return emitArith(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), fn.typ(tv.Type), e.OpPos) 738 739 case token.EQL, token.NEQ, token.GTR, token.LSS, token.LEQ, token.GEQ: 740 cmp := emitCompare(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), e.OpPos) 741 // The type of x==y may be UntypedBool. 742 return emitConv(fn, cmp, types.Default(fn.typ(tv.Type))) 743 default: 744 panic("illegal op in BinaryExpr: " + e.Op.String()) 745 } 746 747 case *ast.SliceExpr: 748 var low, high, max Value 749 var x Value 750 xtyp := fn.typeOf(e.X) 751 switch typeparams.CoreType(xtyp).(type) { 752 case *types.Array: 753 // Potentially escaping. 754 x = b.addr(fn, e.X, true).address(fn) 755 case *types.Basic, *types.Slice, *types.Pointer: // *array 756 x = b.expr(fn, e.X) 757 default: 758 // core type exception? 759 if isBytestring(xtyp) { 760 x = b.expr(fn, e.X) // bytestring is handled as string and []byte. 761 } else { 762 panic("unexpected sequence type in SliceExpr") 763 } 764 } 765 if e.Low != nil { 766 low = b.expr(fn, e.Low) 767 } 768 if e.High != nil { 769 high = b.expr(fn, e.High) 770 } 771 if e.Slice3 { 772 max = b.expr(fn, e.Max) 773 } 774 v := &Slice{ 775 X: x, 776 Low: low, 777 High: high, 778 Max: max, 779 } 780 v.setPos(e.Lbrack) 781 v.setType(fn.typ(tv.Type)) 782 return fn.emit(v) 783 784 case *ast.Ident: 785 obj := fn.info.Uses[e] 786 // Universal built-in or nil? 787 switch obj := obj.(type) { 788 case *types.Builtin: 789 return &Builtin{name: obj.Name(), sig: fn.instanceType(e).(*types.Signature)} 790 case *types.Nil: 791 return zeroConst(fn.instanceType(e)) 792 } 793 794 // Package-level func or var? 795 // (obj must belong to same package or a direct import.) 796 if v := fn.Prog.packageLevelMember(obj); v != nil { 797 if g, ok := v.(*Global); ok { 798 return emitLoad(fn, g) // var (address) 799 } 800 callee := v.(*Function) // (func) 801 if callee.typeparams.Len() > 0 { 802 targs := fn.subtargs(e) 803 callee = callee.instance(nil, targs, b) 804 } 805 return callee 806 } 807 // Local var. 808 return emitLoad(fn, fn.lookup(obj.(*types.Var), false)) // var (address) 809 810 case *ast.SelectorExpr: 811 sel := fn.selection(e) 812 if sel == nil { 813 // builtin unsafe.{Add,Slice} 814 if obj, ok := fn.info.Uses[e.Sel].(*types.Builtin); ok { 815 return &Builtin{name: obj.Name(), sig: fn.typ(tv.Type).(*types.Signature)} 816 } 817 // qualified identifier 818 return b.expr(fn, e.Sel) 819 } 820 switch sel.kind { 821 case types.MethodExpr: 822 // (*T).f or T.f, the method f from the method-set of type T. 823 // The result is a "thunk". 824 targs := fn.subtargs(e.Sel) 825 thunk := createThunk(fn.Prog, sel, targs) 826 b.enqueue(thunk) 827 return thunk 828 829 case types.MethodVal: 830 // e.f where e is an expression and f is a method. 831 // The result is a "bound". 832 m := sel.obj.(*types.Func) 833 rt := fn.typ(recvType(m)) 834 wantAddr := isPointer(rt) 835 escaping := true 836 v := b.receiver(fn, e.X, wantAddr, escaping, sel) 837 838 if types.IsInterface(rt) { 839 // If v may be an interface type I (after instantiating), 840 // we must emit a check that v is non-nil. 841 if recv, ok := types.Unalias(sel.recv).(*types.TypeParam); ok { 842 // Emit a nil check if any possible instantiation of the 843 // type parameter is an interface type. 844 if !typeSetIsEmpty(recv) { 845 // recv has a concrete term its typeset. 846 // So it cannot be instantiated as an interface. 847 // 848 // Example: 849 // func _[T interface{~int; Foo()}] () { 850 // var v T 851 // _ = v.Foo // <-- MethodVal 852 // } 853 } else { 854 // rt may be instantiated as an interface. 855 // Emit nil check: typeassert (any(v)).(any). 856 emitTypeAssert(fn, emitConv(fn, v, tEface), tEface, token.NoPos) 857 } 858 } else { 859 // non-type param interface 860 // Emit nil check: typeassert v.(I). 861 emitTypeAssert(fn, v, rt, e.Sel.Pos()) 862 } 863 } 864 865 if rtargs := fn.subrtargs(m); len(rtargs) > 0 { 866 m = fn.Prog.canon.instantiateMethod(m, rtargs, fn.Prog.ctxt) 867 } 868 869 targs := fn.subtargs(e.Sel) 870 bound := createBound(fn.Prog, m, targs) 871 b.enqueue(bound) 872 873 // The assignment may widen a type parameter to its 874 // interface bound (case #3 of go.dev/issue.78110). 875 v = emitConv(fn, v, bound.FreeVars[0].Type()) 876 877 c := &MakeClosure{ 878 Fn: bound, 879 Bindings: []Value{v}, 880 } 881 c.setPos(e.Sel.Pos()) 882 c.setType(bound.Signature) 883 return fn.emit(c) 884 885 case types.FieldVal: 886 indices := sel.index 887 last := len(indices) - 1 888 v := b.expr(fn, e.X) 889 v = emitImplicitSelections(fn, v, indices[:last], e.Pos()) 890 v = emitFieldSelection(fn, v, indices[last], false, e.Sel) 891 return v 892 } 893 894 panic("unexpected expression-relative selector") 895 896 case *ast.IndexListExpr: 897 // f[X, Y] must be a generic function 898 if !instance(fn.info, e.X) { 899 panic("unexpected expression-could not match index list to instantiation") 900 } 901 return b.expr(fn, e.X) // Handle instantiation within the *Ident or *SelectorExpr cases. 902 903 case *ast.IndexExpr: 904 if instance(fn.info, e.X) { 905 return b.expr(fn, e.X) // Handle instantiation within the *Ident or *SelectorExpr cases. 906 } 907 // not a generic instantiation. 908 xt := fn.typeOf(e.X) 909 switch et, mode := indexType(xt); mode { 910 case ixVar: 911 // Addressable slice/array; use IndexAddr and Load. 912 return b.addr(fn, e, false).load(fn) 913 914 case ixArrVar, ixValue: 915 // An array in a register, a string or a combined type that contains 916 // either an [_]array (ixArrVar) or string (ixValue). 917 918 // Note: for ixArrVar and CoreType(xt)==nil can be IndexAddr and Load. 919 index := b.expr(fn, e.Index) 920 if isUntyped(index.Type()) { 921 index = emitConv(fn, index, tInt) 922 } 923 v := &Index{ 924 X: b.expr(fn, e.X), 925 Index: index, 926 } 927 v.setPos(e.Lbrack) 928 v.setType(et) 929 return fn.emit(v) 930 931 case ixMap: 932 ct := typeparams.CoreType(xt).(*types.Map) 933 v := &Lookup{ 934 X: b.expr(fn, e.X), 935 Index: emitConv(fn, b.expr(fn, e.Index), ct.Key()), 936 } 937 v.setPos(e.Lbrack) 938 v.setType(ct.Elem()) 939 return fn.emit(v) 940 default: 941 panic("unexpected container type in IndexExpr: " + xt.String()) 942 } 943 944 case *ast.CompositeLit, *ast.StarExpr: 945 // Addressable types (lvalues) 946 return b.addr(fn, e, false).load(fn) 947 } 948 949 panic(fmt.Sprintf("unexpected expr: %T", e)) 950 } 951 952 // stmtList emits to fn code for all statements in list. 953 func (b *builder) stmtList(fn *Function, list []ast.Stmt) { 954 for _, s := range list { 955 b.stmt(fn, s) 956 } 957 } 958 959 // receiver emits to fn code for expression e in the "receiver" 960 // position of selection e.f (where f may be a field or a method) and 961 // returns the effective receiver after applying the implicit field 962 // selections of sel. 963 // 964 // wantAddr requests that the result is an address. If 965 // !sel.indirect, this may require that e be built in addr() mode; it 966 // must thus be addressable. 967 // 968 // escaping is defined as per builder.addr(). 969 func (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, sel *selection) Value { 970 var v Value 971 if wantAddr && !sel.indirect && !isPointerCore(fn.typeOf(e)) { 972 v = b.addr(fn, e, escaping).address(fn) 973 } else { 974 v = b.expr(fn, e) 975 } 976 977 last := len(sel.index) - 1 978 // The position of implicit selection is the position of the inducing receiver expression. 979 v = emitImplicitSelections(fn, v, sel.index[:last], e.Pos()) 980 if types.IsInterface(v.Type()) { 981 // When v is an interface, sel.Kind()==MethodValue and v.f is invoked. 982 // So v is not loaded, even if v has a pointer core type. 983 } else if !wantAddr && isPointerCore(v.Type()) { 984 v = emitLoad(fn, v) 985 } 986 return v 987 } 988 989 // setCallFunc populates the function parts of a CallCommon structure 990 // (Func, Method, Recv, Args[0]) based on the kind of invocation 991 // occurring in e. 992 func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) { 993 c.pos = e.Lparen 994 995 // Is this a (possibly generic) method call? 996 m := ast.Unparen(e.Fun) 997 switch e := m.(type) { 998 case *ast.IndexExpr: 999 m = e.X 1000 case *ast.IndexListExpr: 1001 m = e.X 1002 } 1003 if selector, ok := m.(*ast.SelectorExpr); ok { 1004 sel := fn.selection(selector) 1005 if sel != nil && sel.kind == types.MethodVal { 1006 obj := sel.obj.(*types.Func) 1007 recv := recvType(obj) 1008 1009 wantAddr := isPointer(recv) 1010 escaping := true 1011 v := b.receiver(fn, selector.X, wantAddr, escaping, sel) 1012 if types.IsInterface(recv) { 1013 // Invoke-mode call. 1014 c.Value = v // possibly type param 1015 c.Method = obj 1016 } else { 1017 // "Call"-mode call. 1018 targs := fn.subtargs(selector.Sel) 1019 c.Value = fn.Prog.objectMethod(obj, targs, b) 1020 c.Args = append(c.Args, v) 1021 } 1022 return 1023 } 1024 1025 // sel.kind==MethodExpr indicates T.f() or (*T).f(): 1026 // a statically dispatched call to the method f in the 1027 // method-set of T or *T. T may be an interface. 1028 // 1029 // e.Fun would evaluate to a concrete method, interface 1030 // wrapper function, or promotion wrapper. 1031 // 1032 // For now, we evaluate it in the usual way. 1033 // 1034 // TODO(adonovan): opt: inline expr() here, to make the 1035 // call static and to avoid generation of wrappers. 1036 // It's somewhat tricky as it may consume the first 1037 // actual parameter if the call is "invoke" mode. 1038 // 1039 // Examples: 1040 // type T struct{}; func (T) f() {} // "call" mode 1041 // type T interface { f() } // "invoke" mode 1042 // 1043 // type S struct{ T } 1044 // 1045 // var s S 1046 // S.f(s) 1047 // (*S).f(&s) 1048 // 1049 // Suggested approach: 1050 // - consume the first actual parameter expression 1051 // and build it with b.expr(). 1052 // - apply implicit field selections. 1053 // - use MethodVal logic to populate fields of c. 1054 } 1055 1056 // Evaluate the function operand in the usual way. 1057 c.Value = b.expr(fn, e.Fun) 1058 } 1059 1060 // emitCallArgs emits to f code for the actual parameters of call e to 1061 // a (possibly built-in) function of effective type sig. 1062 // The argument values are appended to args, which is then returned. 1063 func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value { 1064 // f(x, y, z...): pass slice z straight through. 1065 if e.Ellipsis != 0 { 1066 for i, arg := range e.Args { 1067 v := emitConv(fn, b.expr(fn, arg), sig.Params().At(i).Type()) 1068 args = append(args, v) 1069 } 1070 return args 1071 } 1072 1073 offset := len(args) // 1 if call has receiver, 0 otherwise 1074 1075 // Evaluate actual parameter expressions. 1076 // 1077 // If this is a chained call of the form f(g()) where g has 1078 // multiple return values (MRV), they are flattened out into 1079 // args; a suffix of them may end up in a varargs slice. 1080 for _, arg := range e.Args { 1081 v := b.expr(fn, arg) 1082 if ttuple, ok := v.Type().(*types.Tuple); ok { // MRV chain 1083 for i, n := 0, ttuple.Len(); i < n; i++ { 1084 args = append(args, emitExtract(fn, v, i)) 1085 } 1086 } else { 1087 args = append(args, v) 1088 } 1089 } 1090 1091 // Actual->formal assignability conversions for normal parameters. 1092 np := sig.Params().Len() // number of normal parameters 1093 if sig.Variadic() { 1094 np-- 1095 } 1096 for i := 0; i < np; i++ { 1097 args[offset+i] = emitConv(fn, args[offset+i], sig.Params().At(i).Type()) 1098 } 1099 1100 // Actual->formal assignability conversions for variadic parameter, 1101 // and construction of slice. 1102 if sig.Variadic() { 1103 varargs := args[offset+np:] 1104 st := sig.Params().At(np).Type().(*types.Slice) 1105 vt := st.Elem() 1106 if len(varargs) == 0 { 1107 args = append(args, zeroConst(st)) 1108 } else { 1109 // Replace a suffix of args with a slice containing it. 1110 at := types.NewArray(vt, int64(len(varargs))) 1111 a := emitNew(fn, at, token.NoPos, "varargs") 1112 a.setPos(e.Rparen) 1113 for i, arg := range varargs { 1114 iaddr := &IndexAddr{ 1115 X: a, 1116 Index: intConst(int64(i)), 1117 } 1118 iaddr.setType(types.NewPointer(vt)) 1119 fn.emit(iaddr) 1120 emitStore(fn, iaddr, arg, arg.Pos()) 1121 } 1122 s := &Slice{X: a} 1123 s.setType(st) 1124 args[offset+np] = fn.emit(s) 1125 args = args[:offset+np+1] 1126 } 1127 } 1128 return args 1129 } 1130 1131 // setCall emits to fn code to evaluate all the parameters of a function 1132 // call e, and populates *c with those values. 1133 func (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) { 1134 // First deal with the f(...) part and optional receiver. 1135 b.setCallFunc(fn, e, c) 1136 1137 // Then append the other actual parameters. 1138 sig, _ := typeparams.CoreType(fn.typeOf(e.Fun)).(*types.Signature) 1139 if sig == nil { 1140 panic(fmt.Sprintf("no signature for call of %s", e.Fun)) 1141 } 1142 c.Args = b.emitCallArgs(fn, sig, e, c.Args) 1143 } 1144 1145 // assignOp emits to fn code to perform loc <op>= val. 1146 func (b *builder) assignOp(fn *Function, loc lvalue, val Value, op token.Token, pos token.Pos) { 1147 loc.store(fn, emitArith(fn, op, loc.load(fn), val, loc.typ(), pos)) 1148 } 1149 1150 // localValueSpec emits to fn code to define all of the vars in the 1151 // function-local ValueSpec, spec. 1152 func (b *builder) localValueSpec(fn *Function, spec *ast.ValueSpec) { 1153 switch { 1154 case len(spec.Values) == len(spec.Names): 1155 // e.g. var x, y = 0, 1 1156 // 1:1 assignment 1157 for i, id := range spec.Names { 1158 if !isBlankIdent(id) { 1159 emitLocalVar(fn, identVar(fn, id)) 1160 } 1161 lval := b.addr(fn, id, false) // non-escaping 1162 b.assign(fn, lval, spec.Values[i], true, nil) 1163 } 1164 1165 case len(spec.Values) == 0: 1166 // e.g. var x, y int 1167 // Locals are implicitly zero-initialized. 1168 for _, id := range spec.Names { 1169 if !isBlankIdent(id) { 1170 lhs := emitLocalVar(fn, identVar(fn, id)) 1171 if fn.debugInfo() { 1172 emitDebugRef(fn, id, lhs, true) 1173 } 1174 } 1175 } 1176 1177 default: 1178 // e.g. var x, y = pos() 1179 tuple := b.exprN(fn, spec.Values[0]) 1180 for i, id := range spec.Names { 1181 if !isBlankIdent(id) { 1182 emitLocalVar(fn, identVar(fn, id)) 1183 lhs := b.addr(fn, id, false) // non-escaping 1184 lhs.store(fn, emitExtract(fn, tuple, i)) 1185 } 1186 } 1187 } 1188 } 1189 1190 // assignStmt emits code to fn for a parallel assignment of rhss to lhss. 1191 // isDef is true if this is a short variable declaration (:=). 1192 // 1193 // Note the similarity with localValueSpec. 1194 func (b *builder) assignStmt(fn *Function, lhss, rhss []ast.Expr, isDef bool) { 1195 // Side effects of all LHSs and RHSs must occur in left-to-right order. 1196 lvals := make([]lvalue, len(lhss)) 1197 isZero := make([]bool, len(lhss)) 1198 for i, lhs := range lhss { 1199 var lval lvalue = blank{} 1200 if !isBlankIdent(lhs) { 1201 if isDef { 1202 if obj, ok := fn.info.Defs[lhs.(*ast.Ident)].(*types.Var); ok { 1203 emitLocalVar(fn, obj) 1204 isZero[i] = true 1205 } 1206 } 1207 lval = b.addr(fn, lhs, false) // non-escaping 1208 } 1209 lvals[i] = lval 1210 } 1211 if len(lhss) == len(rhss) { 1212 // Simple assignment: x = f() (!isDef) 1213 // Parallel assignment: x, y = f(), g() (!isDef) 1214 // or short var decl: x, y := f(), g() (isDef) 1215 // 1216 // In all cases, the RHSs may refer to the LHSs, 1217 // so we need a storebuf. 1218 var sb storebuf 1219 for i := range rhss { 1220 b.assign(fn, lvals[i], rhss[i], isZero[i], &sb) 1221 } 1222 sb.emit(fn) 1223 } else { 1224 // e.g. x, y = pos() 1225 tuple := b.exprN(fn, rhss[0]) 1226 emitDebugRef(fn, rhss[0], tuple, false) 1227 for i, lval := range lvals { 1228 lval.store(fn, emitExtract(fn, tuple, i)) 1229 } 1230 } 1231 } 1232 1233 // arrayLen returns the length of the array whose composite literal elements are elts. 1234 func (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 { 1235 var max int64 = -1 1236 var i int64 = -1 1237 for _, e := range elts { 1238 if kv, ok := e.(*ast.KeyValueExpr); ok { 1239 i = b.expr(fn, kv.Key).(*Const).Int64() 1240 } else { 1241 i++ 1242 } 1243 if i > max { 1244 max = i 1245 } 1246 } 1247 return max + 1 1248 } 1249 1250 // compLit emits to fn code to initialize a composite literal e at 1251 // address addr with type typ. 1252 // 1253 // Nested composite literals are recursively initialized in place 1254 // where possible. If isZero is true, compLit assumes that addr 1255 // holds the zero value for typ. 1256 // 1257 // Because the elements of a composite literal may refer to the 1258 // variables being updated, as in the second line below, 1259 // 1260 // x := T{a: 1} 1261 // x = T{a: x.a} 1262 // 1263 // all the reads must occur before all the writes. Thus all stores to 1264 // loc are emitted to the storebuf sb for later execution. 1265 // 1266 // A CompositeLit may have pointer type only in the recursive (nested) 1267 // case when the type name is implicit. e.g. in []*T{{}}, the inner 1268 // literal has type *T behaves like &T{}. 1269 // In that case, addr must hold a T, not a *T. 1270 func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero bool, sb *storebuf) { 1271 typ := typeparams.Deref(fn.typeOf(e)) // retain the named/alias/param type, if any 1272 switch t := typeparams.CoreType(typ).(type) { 1273 case *types.Struct: 1274 if !isZero && len(e.Elts) != t.NumFields() { 1275 // memclear 1276 zt := typeparams.MustDeref(addr.Type()) 1277 sb.store(&address{addr, e.Lbrace, nil}, zeroConst(zt)) 1278 isZero = true 1279 } 1280 var fIndices []int 1281 for i, e := range e.Elts { 1282 var ( 1283 pos token.Pos 1284 fType types.Type 1285 ) 1286 1287 if kv, ok := e.(*ast.KeyValueExpr); ok { // tagged field 1288 fname := kv.Key.(*ast.Ident).Name 1289 obj, index, _ := types.LookupFieldOrMethod(t, true, fn.declaredPackage().Pkg, fname) 1290 fIndices = append(fIndices[:0], index...) 1291 pos = kv.Colon 1292 e = kv.Value 1293 fType = obj.Type() 1294 } else { // untagged field 1295 fIndices = append(fIndices[:0], i) 1296 pos = e.Pos() 1297 fType = t.Field(i).Type() 1298 } 1299 1300 last := len(fIndices) - 1 1301 v := emitImplicitSelections(fn, addr, fIndices[:last], pos) 1302 1303 faddr := &FieldAddr{ 1304 X: v, 1305 Field: fIndices[last], 1306 } 1307 faddr.setPos(pos) 1308 faddr.setType(types.NewPointer(fType)) 1309 fn.emit(faddr) 1310 b.assign(fn, &address{addr: faddr, pos: pos, expr: e}, e, isZero, sb) 1311 } 1312 1313 case *types.Array, *types.Slice: 1314 var at *types.Array 1315 var array Value 1316 switch t := t.(type) { 1317 case *types.Slice: 1318 at = types.NewArray(t.Elem(), b.arrayLen(fn, e.Elts)) 1319 array = emitNew(fn, at, e.Lbrace, "slicelit") 1320 case *types.Array: 1321 at = t 1322 array = addr 1323 1324 if !isZero && int64(len(e.Elts)) != at.Len() { 1325 // memclear 1326 zt := typeparams.MustDeref(array.Type()) 1327 sb.store(&address{array, e.Lbrace, nil}, zeroConst(zt)) 1328 } 1329 } 1330 1331 var idx *Const 1332 for _, e := range e.Elts { 1333 pos := e.Pos() 1334 if kv, ok := e.(*ast.KeyValueExpr); ok { 1335 idx = b.expr(fn, kv.Key).(*Const) 1336 pos = kv.Colon 1337 e = kv.Value 1338 } else { 1339 var idxval int64 1340 if idx != nil { 1341 idxval = idx.Int64() + 1 1342 } 1343 idx = intConst(idxval) 1344 } 1345 iaddr := &IndexAddr{ 1346 X: array, 1347 Index: idx, 1348 } 1349 iaddr.setType(types.NewPointer(at.Elem())) 1350 fn.emit(iaddr) 1351 if t != at { // slice 1352 // backing array is unaliased => storebuf not needed. 1353 b.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, nil) 1354 } else { 1355 b.assign(fn, &address{addr: iaddr, pos: pos, expr: e}, e, true, sb) 1356 } 1357 } 1358 1359 if t != at { // slice 1360 s := &Slice{X: array} 1361 s.setPos(e.Lbrace) 1362 s.setType(typ) 1363 sb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, fn.emit(s)) 1364 } 1365 1366 case *types.Map: 1367 m := &MakeMap{Reserve: intConst(int64(len(e.Elts)))} 1368 m.setPos(e.Lbrace) 1369 m.setType(typ) 1370 fn.emit(m) 1371 for _, e := range e.Elts { 1372 e := e.(*ast.KeyValueExpr) 1373 1374 // If a key expression in a map literal is itself a 1375 // composite literal, the type may be omitted. 1376 // For example: 1377 // map[*struct{}]bool{{}: true} 1378 // An &-operation may be implied: 1379 // map[*struct{}]bool{&struct{}{}: true} 1380 wantAddr := false 1381 if _, ok := ast.Unparen(e.Key).(*ast.CompositeLit); ok { 1382 wantAddr = isPointerCore(t.Key()) 1383 } 1384 1385 var key Value 1386 if wantAddr { 1387 // A CompositeLit never evaluates to a pointer, 1388 // so if the type of the location is a pointer, 1389 // an &-operation is implied. 1390 key = b.addr(fn, e.Key, true).address(fn) 1391 } else { 1392 key = b.expr(fn, e.Key) 1393 } 1394 1395 loc := element{ 1396 m: m, 1397 k: emitConv(fn, key, t.Key()), 1398 t: t.Elem(), 1399 pos: e.Colon, 1400 } 1401 1402 // We call assign() only because it takes care 1403 // of any &-operation required in the recursive 1404 // case, e.g., 1405 // map[int]*struct{}{0: {}} implies &struct{}{}. 1406 // In-place update is of course impossible, 1407 // and no storebuf is needed. 1408 b.assign(fn, &loc, e.Value, true, nil) 1409 } 1410 sb.store(&address{addr: addr, pos: e.Lbrace, expr: e}, m) 1411 1412 default: 1413 panic("unexpected CompositeLit type: " + typ.String()) 1414 } 1415 } 1416 1417 // switchStmt emits to fn code for the switch statement s, optionally 1418 // labelled by label. 1419 func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) { 1420 // We treat SwitchStmt like a sequential if-else chain. 1421 // Multiway dispatch can be recovered later by ssautil.Switches() 1422 // to those cases that are free of side effects. 1423 if s.Init != nil { 1424 b.stmt(fn, s.Init) 1425 } 1426 var tag Value = vTrue 1427 if s.Tag != nil { 1428 tag = b.expr(fn, s.Tag) 1429 } 1430 done := fn.newBasicBlock("switch.done") 1431 if label != nil { 1432 label._break = done 1433 } 1434 // We pull the default case (if present) down to the end. 1435 // But each fallthrough label must point to the next 1436 // body block in source order, so we preallocate a 1437 // body block (fallthru) for the next case. 1438 // Unfortunately this makes for a confusing block order. 1439 var dfltBody *[]ast.Stmt 1440 var dfltFallthrough *BasicBlock 1441 var fallthru, dfltBlock *BasicBlock 1442 ncases := len(s.Body.List) 1443 for i, clause := range s.Body.List { 1444 body := fallthru 1445 if body == nil { 1446 body = fn.newBasicBlock("switch.body") // first case only 1447 } 1448 1449 // Preallocate body block for the next case. 1450 fallthru = done 1451 if i+1 < ncases { 1452 fallthru = fn.newBasicBlock("switch.body") 1453 } 1454 1455 cc := clause.(*ast.CaseClause) 1456 if cc.List == nil { 1457 // Default case. 1458 dfltBody = &cc.Body 1459 dfltFallthrough = fallthru 1460 dfltBlock = body 1461 continue 1462 } 1463 1464 var nextCond *BasicBlock 1465 for _, cond := range cc.List { 1466 nextCond = fn.newBasicBlock("switch.next") 1467 // For boolean switches, emit short-circuit control flow, 1468 // just like an if/else-chain. 1469 if tag == vTrue && !isNonTypeParamInterface(fn.info.Types[cond].Type) { 1470 b.cond(fn, cond, body, nextCond) 1471 } else { 1472 c := emitCompare(fn, token.EQL, tag, b.expr(fn, cond), cond.Pos()) 1473 emitIf(fn, c, body, nextCond) 1474 } 1475 fn.currentBlock = nextCond 1476 } 1477 fn.currentBlock = body 1478 fn.targets = &targets{ 1479 tail: fn.targets, 1480 _break: done, 1481 _fallthrough: fallthru, 1482 } 1483 b.stmtList(fn, cc.Body) 1484 fn.targets = fn.targets.tail 1485 emitJump(fn, done) 1486 fn.currentBlock = nextCond 1487 } 1488 if dfltBlock != nil { 1489 emitJump(fn, dfltBlock) 1490 fn.currentBlock = dfltBlock 1491 fn.targets = &targets{ 1492 tail: fn.targets, 1493 _break: done, 1494 _fallthrough: dfltFallthrough, 1495 } 1496 b.stmtList(fn, *dfltBody) 1497 fn.targets = fn.targets.tail 1498 } 1499 emitJump(fn, done) 1500 fn.currentBlock = done 1501 } 1502 1503 // typeSwitchStmt emits to fn code for the type switch statement s, optionally 1504 // labelled by label. 1505 func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) { 1506 // We treat TypeSwitchStmt like a sequential if-else chain. 1507 // Multiway dispatch can be recovered later by ssautil.Switches(). 1508 1509 // Typeswitch lowering: 1510 // 1511 // var x X 1512 // switch y := x.(type) { 1513 // case T1, T2: S1 // >1 (y := x) 1514 // case nil: SN // nil (y := x) 1515 // default: SD // 0 types (y := x) 1516 // case T3: S3 // 1 type (y := x.(T3)) 1517 // } 1518 // 1519 // ...s.Init... 1520 // x := eval x 1521 // .caseT1: 1522 // t1, ok1 := typeswitch,ok x <T1> 1523 // if ok1 then goto S1 else goto .caseT2 1524 // .caseT2: 1525 // t2, ok2 := typeswitch,ok x <T2> 1526 // if ok2 then goto S1 else goto .caseNil 1527 // .S1: 1528 // y := x 1529 // ...S1... 1530 // goto done 1531 // .caseNil: 1532 // if t2, ok2 := typeswitch,ok x <T2> 1533 // if x == nil then goto SN else goto .caseT3 1534 // .SN: 1535 // y := x 1536 // ...SN... 1537 // goto done 1538 // .caseT3: 1539 // t3, ok3 := typeswitch,ok x <T3> 1540 // if ok3 then goto S3 else goto default 1541 // .S3: 1542 // y := t3 1543 // ...S3... 1544 // goto done 1545 // .default: 1546 // y := x 1547 // ...SD... 1548 // goto done 1549 // .done: 1550 if s.Init != nil { 1551 b.stmt(fn, s.Init) 1552 } 1553 1554 var x Value 1555 switch ass := s.Assign.(type) { 1556 case *ast.ExprStmt: // x.(type) 1557 x = b.expr(fn, ast.Unparen(ass.X).(*ast.TypeAssertExpr).X) 1558 case *ast.AssignStmt: // y := x.(type) 1559 x = b.expr(fn, ast.Unparen(ass.Rhs[0]).(*ast.TypeAssertExpr).X) 1560 } 1561 1562 done := fn.newBasicBlock("typeswitch.done") 1563 if label != nil { 1564 label._break = done 1565 } 1566 var default_ *ast.CaseClause 1567 for _, clause := range s.Body.List { 1568 cc := clause.(*ast.CaseClause) 1569 if cc.List == nil { 1570 default_ = cc 1571 continue 1572 } 1573 body := fn.newBasicBlock("typeswitch.body") 1574 var next *BasicBlock 1575 var casetype types.Type 1576 var ti Value // ti, ok := typeassert,ok x <Ti> 1577 for _, cond := range cc.List { 1578 next = fn.newBasicBlock("typeswitch.next") 1579 casetype = fn.typeOf(cond) 1580 var condv Value 1581 if casetype == tUntypedNil { 1582 condv = emitCompare(fn, token.EQL, x, zeroConst(x.Type()), cond.Pos()) 1583 ti = x 1584 } else { 1585 yok := emitTypeTest(fn, x, casetype, cc.Case) 1586 ti = emitExtract(fn, yok, 0) 1587 condv = emitExtract(fn, yok, 1) 1588 } 1589 emitIf(fn, condv, body, next) 1590 fn.currentBlock = next 1591 } 1592 if len(cc.List) != 1 { 1593 ti = x 1594 } 1595 fn.currentBlock = body 1596 b.typeCaseBody(fn, cc, ti, done) 1597 fn.currentBlock = next 1598 } 1599 if default_ != nil { 1600 b.typeCaseBody(fn, default_, x, done) 1601 } else { 1602 emitJump(fn, done) 1603 } 1604 fn.currentBlock = done 1605 } 1606 1607 func (b *builder) typeCaseBody(fn *Function, cc *ast.CaseClause, x Value, done *BasicBlock) { 1608 if obj, ok := fn.info.Implicits[cc].(*types.Var); ok { 1609 // In a switch y := x.(type), each case clause 1610 // implicitly declares a distinct object y. 1611 // In a single-type case, y has that type. 1612 // In multi-type cases, 'case nil' and default, 1613 // y has the same type as the interface operand. 1614 emitStore(fn, emitLocalVar(fn, obj), x, obj.Pos()) 1615 } 1616 fn.targets = &targets{ 1617 tail: fn.targets, 1618 _break: done, 1619 } 1620 b.stmtList(fn, cc.Body) 1621 fn.targets = fn.targets.tail 1622 emitJump(fn, done) 1623 } 1624 1625 // selectStmt emits to fn code for the select statement s, optionally 1626 // labelled by label. 1627 func (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) { 1628 // A blocking select of a single case degenerates to a 1629 // simple send or receive. 1630 // TODO(adonovan): opt: is this optimization worth its weight? 1631 if len(s.Body.List) == 1 { 1632 clause := s.Body.List[0].(*ast.CommClause) 1633 if clause.Comm != nil { 1634 b.stmt(fn, clause.Comm) 1635 done := fn.newBasicBlock("select.done") 1636 if label != nil { 1637 label._break = done 1638 } 1639 fn.targets = &targets{ 1640 tail: fn.targets, 1641 _break: done, 1642 } 1643 b.stmtList(fn, clause.Body) 1644 fn.targets = fn.targets.tail 1645 emitJump(fn, done) 1646 fn.currentBlock = done 1647 return 1648 } 1649 } 1650 1651 // First evaluate all channels in all cases, and find 1652 // the directions of each state. 1653 var states []*SelectState 1654 blocking := true 1655 debugInfo := fn.debugInfo() 1656 for _, clause := range s.Body.List { 1657 var st *SelectState 1658 switch comm := clause.(*ast.CommClause).Comm.(type) { 1659 case nil: // default case 1660 blocking = false 1661 continue 1662 1663 case *ast.SendStmt: // ch<- i 1664 ch := b.expr(fn, comm.Chan) 1665 chtyp := typeparams.CoreType(fn.typ(ch.Type())).(*types.Chan) 1666 st = &SelectState{ 1667 Dir: types.SendOnly, 1668 Chan: ch, 1669 Send: emitConv(fn, b.expr(fn, comm.Value), chtyp.Elem()), 1670 Pos: comm.Arrow, 1671 } 1672 if debugInfo { 1673 st.DebugNode = comm 1674 } 1675 1676 case *ast.AssignStmt: // x := <-ch 1677 recv := ast.Unparen(comm.Rhs[0]).(*ast.UnaryExpr) 1678 st = &SelectState{ 1679 Dir: types.RecvOnly, 1680 Chan: b.expr(fn, recv.X), 1681 Pos: recv.OpPos, 1682 } 1683 if debugInfo { 1684 st.DebugNode = recv 1685 } 1686 1687 case *ast.ExprStmt: // <-ch 1688 recv := ast.Unparen(comm.X).(*ast.UnaryExpr) 1689 st = &SelectState{ 1690 Dir: types.RecvOnly, 1691 Chan: b.expr(fn, recv.X), 1692 Pos: recv.OpPos, 1693 } 1694 if debugInfo { 1695 st.DebugNode = recv 1696 } 1697 } 1698 states = append(states, st) 1699 } 1700 1701 // We dispatch on the (fair) result of Select using a 1702 // sequential if-else chain, in effect: 1703 // 1704 // idx, recvOk, r0...r_n-1 := select(...) 1705 // if idx == 0 { // receive on channel 0 (first receive => r0) 1706 // x, ok := r0, recvOk 1707 // ...state0... 1708 // } else if v == 1 { // send on channel 1 1709 // ...state1... 1710 // } else { 1711 // ...default... 1712 // } 1713 sel := &Select{ 1714 States: states, 1715 Blocking: blocking, 1716 } 1717 sel.setPos(s.Select) 1718 var vars []*types.Var 1719 vars = append(vars, varIndex, varOk) 1720 for _, st := range states { 1721 if st.Dir == types.RecvOnly { 1722 chtyp := typeparams.CoreType(fn.typ(st.Chan.Type())).(*types.Chan) 1723 vars = append(vars, newVar("", chtyp.Elem())) 1724 } 1725 } 1726 sel.setType(types.NewTuple(vars...)) 1727 1728 fn.emit(sel) 1729 idx := emitExtract(fn, sel, 0) 1730 1731 done := fn.newBasicBlock("select.done") 1732 if label != nil { 1733 label._break = done 1734 } 1735 1736 var defaultBody *[]ast.Stmt 1737 state := 0 1738 r := 2 // index in 'sel' tuple of value; increments if st.Dir==RECV 1739 for _, cc := range s.Body.List { 1740 clause := cc.(*ast.CommClause) 1741 if clause.Comm == nil { 1742 defaultBody = &clause.Body 1743 continue 1744 } 1745 body := fn.newBasicBlock("select.body") 1746 next := fn.newBasicBlock("select.next") 1747 emitIf(fn, emitCompare(fn, token.EQL, idx, intConst(int64(state)), token.NoPos), body, next) 1748 fn.currentBlock = body 1749 fn.targets = &targets{ 1750 tail: fn.targets, 1751 _break: done, 1752 } 1753 switch comm := clause.Comm.(type) { 1754 case *ast.ExprStmt: // <-ch 1755 if debugInfo { 1756 v := emitExtract(fn, sel, r) 1757 emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false) 1758 } 1759 r++ 1760 1761 case *ast.AssignStmt: // x := <-states[state].Chan 1762 if comm.Tok == token.DEFINE { 1763 emitLocalVar(fn, identVar(fn, comm.Lhs[0].(*ast.Ident))) 1764 } 1765 x := b.addr(fn, comm.Lhs[0], false) // non-escaping 1766 v := emitExtract(fn, sel, r) 1767 if debugInfo { 1768 emitDebugRef(fn, states[state].DebugNode.(ast.Expr), v, false) 1769 } 1770 x.store(fn, v) 1771 1772 if len(comm.Lhs) == 2 { // x, ok := ... 1773 if comm.Tok == token.DEFINE { 1774 emitLocalVar(fn, identVar(fn, comm.Lhs[1].(*ast.Ident))) 1775 } 1776 ok := b.addr(fn, comm.Lhs[1], false) // non-escaping 1777 ok.store(fn, emitExtract(fn, sel, 1)) 1778 } 1779 r++ 1780 } 1781 b.stmtList(fn, clause.Body) 1782 fn.targets = fn.targets.tail 1783 emitJump(fn, done) 1784 fn.currentBlock = next 1785 state++ 1786 } 1787 if defaultBody != nil { 1788 fn.targets = &targets{ 1789 tail: fn.targets, 1790 _break: done, 1791 } 1792 b.stmtList(fn, *defaultBody) 1793 fn.targets = fn.targets.tail 1794 } else { 1795 // A blocking select must match some case. 1796 // (This should really be a runtime.errorString, not a string.) 1797 fn.emit(&Panic{ 1798 X: emitConv(fn, stringConst("blocking select matched no case"), tEface), 1799 }) 1800 fn.currentBlock = fn.newBasicBlock("unreachable") 1801 } 1802 emitJump(fn, done) 1803 fn.currentBlock = done 1804 } 1805 1806 // forStmt emits to fn code for the for statement s, optionally 1807 // labelled by label. 1808 func (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) { 1809 // Use forStmtGo122 instead if it applies. 1810 if s.Init != nil { 1811 if assign, ok := s.Init.(*ast.AssignStmt); ok && assign.Tok == token.DEFINE { 1812 if versions.AtLeast(fn.goversion, versions.Go1_22) { 1813 b.forStmtGo122(fn, s, label) 1814 return 1815 } 1816 } 1817 } 1818 1819 // ...init... 1820 // jump loop 1821 // loop: 1822 // if cond goto body else done 1823 // body: 1824 // ...body... 1825 // jump post 1826 // post: (target of continue) 1827 // ...post... 1828 // jump loop 1829 // done: (target of break) 1830 if s.Init != nil { 1831 b.stmt(fn, s.Init) 1832 } 1833 1834 body := fn.newBasicBlock("for.body") 1835 done := fn.newBasicBlock("for.done") // target of 'break' 1836 loop := body // target of back-edge 1837 if s.Cond != nil { 1838 loop = fn.newBasicBlock("for.loop") 1839 } 1840 cont := loop // target of 'continue' 1841 if s.Post != nil { 1842 cont = fn.newBasicBlock("for.post") 1843 } 1844 if label != nil { 1845 label._break = done 1846 label._continue = cont 1847 } 1848 emitJump(fn, loop) 1849 fn.currentBlock = loop 1850 if loop != body { 1851 b.cond(fn, s.Cond, body, done) 1852 fn.currentBlock = body 1853 } 1854 fn.targets = &targets{ 1855 tail: fn.targets, 1856 _break: done, 1857 _continue: cont, 1858 } 1859 b.stmt(fn, s.Body) 1860 fn.targets = fn.targets.tail 1861 emitJump(fn, cont) 1862 1863 if s.Post != nil { 1864 fn.currentBlock = cont 1865 b.stmt(fn, s.Post) 1866 emitJump(fn, loop) // back-edge 1867 } 1868 fn.currentBlock = done 1869 } 1870 1871 // forStmtGo122 emits to fn code for the for statement s, optionally 1872 // labelled by label. s must define its variables. 1873 // 1874 // This allocates once per loop iteration. This is only correct in 1875 // GoVersions >= go1.22. 1876 func (b *builder) forStmtGo122(fn *Function, s *ast.ForStmt, label *lblock) { 1877 // i_outer = alloc[T] 1878 // *i_outer = ...init... // under objects[i] = i_outer 1879 // jump loop 1880 // loop: 1881 // i = phi [head: i_outer, loop: i_next] 1882 // ...cond... // under objects[i] = i 1883 // if cond goto body else done 1884 // body: 1885 // ...body... // under objects[i] = i (same as loop) 1886 // jump post 1887 // post: 1888 // tmp = *i 1889 // i_next = alloc[T] 1890 // *i_next = tmp 1891 // ...post... // under objects[i] = i_next 1892 // goto loop 1893 // done: 1894 1895 init := s.Init.(*ast.AssignStmt) 1896 startingBlocks := len(fn.Blocks) 1897 1898 pre := fn.currentBlock // current block before starting 1899 loop := fn.newBasicBlock("for.loop") // target of back-edge 1900 body := fn.newBasicBlock("for.body") 1901 post := fn.newBasicBlock("for.post") // target of 'continue' 1902 done := fn.newBasicBlock("for.done") // target of 'break' 1903 1904 // For each of the n loop variables, we create five SSA values, 1905 // outer, phi, next, load, and store in pre, loop, and post. 1906 // There is no limit on n. 1907 type loopVar struct { 1908 obj *types.Var 1909 outer *Alloc 1910 phi *Phi 1911 load *UnOp 1912 next *Alloc 1913 store *Store 1914 } 1915 vars := make([]loopVar, len(init.Lhs)) 1916 for i, lhs := range init.Lhs { 1917 v := identVar(fn, lhs.(*ast.Ident)) 1918 typ := fn.typ(v.Type()) 1919 1920 fn.currentBlock = pre 1921 outer := emitLocal(fn, typ, v.Pos(), v.Name()) 1922 1923 fn.currentBlock = loop 1924 phi := &Phi{Comment: v.Name()} 1925 phi.pos = v.Pos() 1926 phi.typ = outer.Type() 1927 fn.emit(phi) 1928 1929 fn.currentBlock = post 1930 // If next is local, it reuses the address and zeroes the old value so 1931 // load before allocating next. 1932 load := emitLoad(fn, phi) 1933 next := emitLocal(fn, typ, v.Pos(), v.Name()) 1934 store := emitStore(fn, next, load, token.NoPos) 1935 1936 phi.Edges = []Value{outer, next} // pre edge is emitted before post edge. 1937 1938 vars[i] = loopVar{v, outer, phi, load, next, store} 1939 } 1940 1941 // ...init... under fn.objects[v] = i_outer 1942 fn.currentBlock = pre 1943 for _, v := range vars { 1944 fn.vars[v.obj] = v.outer 1945 } 1946 const isDef = false // assign to already-allocated outers 1947 b.assignStmt(fn, init.Lhs, init.Rhs, isDef) 1948 if label != nil { 1949 label._break = done 1950 label._continue = post 1951 } 1952 emitJump(fn, loop) 1953 1954 // ...cond... under fn.objects[v] = i 1955 fn.currentBlock = loop 1956 for _, v := range vars { 1957 fn.vars[v.obj] = v.phi 1958 } 1959 if s.Cond != nil { 1960 b.cond(fn, s.Cond, body, done) 1961 } else { 1962 emitJump(fn, body) 1963 } 1964 1965 // ...body... under fn.objects[v] = i 1966 fn.currentBlock = body 1967 fn.targets = &targets{ 1968 tail: fn.targets, 1969 _break: done, 1970 _continue: post, 1971 } 1972 b.stmt(fn, s.Body) 1973 fn.targets = fn.targets.tail 1974 emitJump(fn, post) 1975 1976 // ...post... under fn.objects[v] = i_next 1977 for _, v := range vars { 1978 fn.vars[v.obj] = v.next 1979 } 1980 fn.currentBlock = post 1981 if s.Post != nil { 1982 b.stmt(fn, s.Post) 1983 } 1984 emitJump(fn, loop) // back-edge 1985 fn.currentBlock = done 1986 1987 // For each loop variable that does not escape, 1988 // (the common case), fuse its next cells into its 1989 // (local) outer cell as they have disjoint live ranges. 1990 // 1991 // It is sufficient to test whether i_next escapes, 1992 // because its Heap flag will be marked true if either 1993 // the cond or post expression causes i to escape 1994 // (because escape distributes over phi). 1995 var nlocals int 1996 for _, v := range vars { 1997 if !v.next.Heap { 1998 nlocals++ 1999 } 2000 } 2001 if nlocals > 0 { 2002 replace := make(map[Value]Value, 2*nlocals) 2003 dead := make(map[Instruction]bool, 4*nlocals) 2004 for _, v := range vars { 2005 if !v.next.Heap { 2006 replace[v.next] = v.outer 2007 replace[v.phi] = v.outer 2008 dead[v.phi], dead[v.next], dead[v.load], dead[v.store] = true, true, true, true 2009 } 2010 } 2011 2012 // Replace all uses of i_next and phi with i_outer. 2013 // Referrers have not been built for fn yet so only update Instruction operands. 2014 // We need only look within the blocks added by the loop. 2015 var operands []*Value // recycle storage 2016 for _, b := range fn.Blocks[startingBlocks:] { 2017 for _, instr := range b.Instrs { 2018 operands = instr.Operands(operands[:0]) 2019 for _, ptr := range operands { 2020 k := *ptr 2021 if v := replace[k]; v != nil { 2022 *ptr = v 2023 } 2024 } 2025 } 2026 } 2027 2028 // Remove instructions for phi, load, and store. 2029 // lift() will remove the unused i_next *Alloc. 2030 isDead := func(i Instruction) bool { return dead[i] } 2031 loop.Instrs = slices.DeleteFunc(loop.Instrs, isDead) 2032 post.Instrs = slices.DeleteFunc(post.Instrs, isDead) 2033 } 2034 } 2035 2036 // rangeIndexed emits to fn the header for an integer-indexed loop 2037 // over array, *array or slice value x. 2038 // The v result is defined only if tv is non-nil. 2039 // forPos is the position of the "for" token. 2040 func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) { 2041 // 2042 // length = len(x) 2043 // index = -1 2044 // loop: (target of continue) 2045 // index++ 2046 // if index < length goto body else done 2047 // body: 2048 // k = index 2049 // v = x[index] 2050 // ...body... 2051 // jump loop 2052 // done: (target of break) 2053 2054 // Determine number of iterations. 2055 var length Value 2056 dt := typeparams.Deref(x.Type()) 2057 if arr, ok := typeparams.CoreType(dt).(*types.Array); ok { 2058 // For array or *array, the number of iterations is 2059 // known statically thanks to the type. We avoid a 2060 // data dependence upon x, permitting later dead-code 2061 // elimination if x is pure, static unrolling, etc. 2062 // Ranging over a nil *array may have >0 iterations. 2063 // We still generate code for x, in case it has effects. 2064 length = intConst(arr.Len()) 2065 } else { 2066 // length = len(x). 2067 var c Call 2068 c.Call.Value = makeLen(x.Type()) 2069 c.Call.Args = []Value{x} 2070 c.setType(tInt) 2071 length = fn.emit(&c) 2072 } 2073 2074 index := emitLocal(fn, tInt, token.NoPos, "rangeindex") 2075 emitStore(fn, index, intConst(-1), pos) 2076 2077 loop = fn.newBasicBlock("rangeindex.loop") 2078 emitJump(fn, loop) 2079 fn.currentBlock = loop 2080 2081 incr := &BinOp{ 2082 Op: token.ADD, 2083 X: emitLoad(fn, index), 2084 Y: vOne, 2085 } 2086 incr.setType(tInt) 2087 emitStore(fn, index, fn.emit(incr), pos) 2088 2089 body := fn.newBasicBlock("rangeindex.body") 2090 done = fn.newBasicBlock("rangeindex.done") 2091 emitIf(fn, emitCompare(fn, token.LSS, incr, length, token.NoPos), body, done) 2092 fn.currentBlock = body 2093 2094 k = emitLoad(fn, index) 2095 if tv != nil { 2096 switch t := typeparams.CoreType(x.Type()).(type) { 2097 case *types.Array: 2098 instr := &Index{ 2099 X: x, 2100 Index: k, 2101 } 2102 instr.setType(t.Elem()) 2103 instr.setPos(x.Pos()) 2104 v = fn.emit(instr) 2105 2106 case *types.Pointer: // *array 2107 instr := &IndexAddr{ 2108 X: x, 2109 Index: k, 2110 } 2111 instr.setType(types.NewPointer(t.Elem().Underlying().(*types.Array).Elem())) 2112 instr.setPos(x.Pos()) 2113 v = emitLoad(fn, fn.emit(instr)) 2114 2115 case *types.Slice: 2116 instr := &IndexAddr{ 2117 X: x, 2118 Index: k, 2119 } 2120 instr.setType(types.NewPointer(t.Elem())) 2121 instr.setPos(x.Pos()) 2122 v = emitLoad(fn, fn.emit(instr)) 2123 2124 default: 2125 panic("rangeIndexed x:" + t.String()) 2126 } 2127 } 2128 return 2129 } 2130 2131 // rangeIter emits to fn the header for a loop using 2132 // Range/Next/Extract to iterate over map or string value x. 2133 // tk and tv are the types of the key/value results k and v, or nil 2134 // if the respective component is not wanted. 2135 func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) { 2136 // 2137 // it = range x 2138 // loop: (target of continue) 2139 // okv = next it (ok, key, value) 2140 // ok = extract okv #0 2141 // if ok goto body else done 2142 // body: 2143 // k = extract okv #1 2144 // v = extract okv #2 2145 // ...body... 2146 // jump loop 2147 // done: (target of break) 2148 // 2149 2150 rng := &Range{X: x} 2151 rng.setPos(pos) 2152 rng.setType(tRangeIter) 2153 it := fn.emit(rng) 2154 2155 loop = fn.newBasicBlock("rangeiter.loop") 2156 emitJump(fn, loop) 2157 fn.currentBlock = loop 2158 2159 var ak, av types.Type 2160 isString := false 2161 if m, ok := typeparams.CoreType(x.Type()).(*types.Map); ok { 2162 ak, av = m.Key(), m.Elem() 2163 } else { 2164 isString = true 2165 ak, av = tInt, tRune 2166 } 2167 if tk == nil { 2168 ak = tInvalid 2169 } 2170 if tv == nil { 2171 av = tInvalid 2172 } 2173 2174 okv := &Next{ 2175 Iter: it, 2176 IsString: isString, 2177 } 2178 okv.setType(types.NewTuple( 2179 varOk, 2180 newVar("k", ak), 2181 newVar("v", av), 2182 )) 2183 fn.emit(okv) 2184 2185 body := fn.newBasicBlock("rangeiter.body") 2186 done = fn.newBasicBlock("rangeiter.done") 2187 emitIf(fn, emitExtract(fn, okv, 0), body, done) 2188 fn.currentBlock = body 2189 2190 // The assignment may widen a map or string 2191 // key/value to a variable's interface type 2192 // (cases #1 and #2 of go.dev/issue/78110). 2193 if tk != nil { 2194 k = emitConv(fn, emitExtract(fn, okv, 1), tk) 2195 } 2196 if tv != nil { 2197 v = emitConv(fn, emitExtract(fn, okv, 2), tv) 2198 } 2199 return 2200 } 2201 2202 // rangeChan emits to fn the header for a loop that receives from 2203 // channel x until it fails. 2204 // tk is the channel's element type, or nil if the k result is 2205 // not wanted 2206 // pos is the position of the '=' or ':=' token. 2207 func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) { 2208 // 2209 // loop: (target of continue) 2210 // ko = <-x (key, ok) 2211 // ok = extract ko #1 2212 // if ok goto body else done 2213 // body: 2214 // k = extract ko #0 2215 // ...body... 2216 // goto loop 2217 // done: (target of break) 2218 2219 loop = fn.newBasicBlock("rangechan.loop") 2220 emitJump(fn, loop) 2221 fn.currentBlock = loop 2222 recv := &UnOp{ 2223 Op: token.ARROW, 2224 X: x, 2225 CommaOk: true, 2226 } 2227 recv.setPos(pos) 2228 recv.setType(types.NewTuple( 2229 newVar("k", typeparams.CoreType(x.Type()).(*types.Chan).Elem()), 2230 varOk, 2231 )) 2232 ko := fn.emit(recv) 2233 body := fn.newBasicBlock("rangechan.body") 2234 done = fn.newBasicBlock("rangechan.done") 2235 emitIf(fn, emitExtract(fn, ko, 1), body, done) 2236 fn.currentBlock = body 2237 if tk != nil { 2238 k = emitExtract(fn, ko, 0) 2239 } 2240 return 2241 } 2242 2243 // rangeInt emits to fn the header for a range loop with an integer operand. 2244 // tk is the key value's type, or nil if the k result is not wanted. 2245 // pos is the position of the "for" token. 2246 func (b *builder) rangeInt(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) { 2247 // 2248 // iter = 0 2249 // if 0 < x goto body else done 2250 // loop: (target of continue) 2251 // iter++ 2252 // if iter < x goto body else done 2253 // body: 2254 // k = x 2255 // ...body... 2256 // jump loop 2257 // done: (target of break) 2258 2259 if isUntyped(x.Type()) { 2260 x = emitConv(fn, x, tInt) 2261 } 2262 2263 T := x.Type() 2264 iter := emitLocal(fn, T, token.NoPos, "rangeint.iter") 2265 // x may be unsigned. Avoid initializing x to -1. 2266 2267 body := fn.newBasicBlock("rangeint.body") 2268 done = fn.newBasicBlock("rangeint.done") 2269 emitIf(fn, emitCompare(fn, token.LSS, zeroConst(T), x, token.NoPos), body, done) 2270 2271 loop = fn.newBasicBlock("rangeint.loop") 2272 fn.currentBlock = loop 2273 2274 incr := &BinOp{ 2275 Op: token.ADD, 2276 X: emitLoad(fn, iter), 2277 Y: emitConv(fn, vOne, T), 2278 } 2279 incr.setType(T) 2280 emitStore(fn, iter, fn.emit(incr), pos) 2281 emitIf(fn, emitCompare(fn, token.LSS, incr, x, token.NoPos), body, done) 2282 fn.currentBlock = body 2283 2284 if tk != nil { 2285 // Integer types (int, uint8, etc.) are named and 2286 // we know that k is assignable to x when tk != nil. 2287 // This implies tk and T are identical so no conversion is needed. 2288 k = emitLoad(fn, iter) 2289 } 2290 2291 return 2292 } 2293 2294 // rangeStmt emits to fn code for the range statement s, optionally 2295 // labelled by label. 2296 func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) { 2297 var tk, tv types.Type 2298 if s.Key != nil && !isBlankIdent(s.Key) { 2299 tk = fn.typeOf(s.Key) 2300 } 2301 if s.Value != nil && !isBlankIdent(s.Value) { 2302 tv = fn.typeOf(s.Value) 2303 } 2304 2305 // create locals for s.Key and s.Value. 2306 createVars := func() { 2307 // Unlike a short variable declaration, a RangeStmt 2308 // using := never redeclares an existing variable; it 2309 // always creates a new one. 2310 if tk != nil { 2311 emitLocalVar(fn, identVar(fn, s.Key.(*ast.Ident))) 2312 } 2313 if tv != nil { 2314 emitLocalVar(fn, identVar(fn, s.Value.(*ast.Ident))) 2315 } 2316 } 2317 2318 afterGo122 := versions.AtLeast(fn.goversion, versions.Go1_22) 2319 if s.Tok == token.DEFINE && !afterGo122 { 2320 // pre-go1.22: If iteration variables are defined (:=), this 2321 // occurs once outside the loop. 2322 createVars() 2323 } 2324 2325 x := b.expr(fn, s.X) 2326 2327 var k, v Value 2328 var loop, done *BasicBlock 2329 switch rt := typeparams.CoreType(x.Type()).(type) { 2330 case *types.Slice, *types.Array, *types.Pointer: // *array 2331 k, v, loop, done = b.rangeIndexed(fn, x, tv, s.For) 2332 2333 case *types.Chan: 2334 k, loop, done = b.rangeChan(fn, x, tk, s.For) 2335 2336 case *types.Map: 2337 k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For) 2338 2339 case *types.Basic: 2340 switch { 2341 case rt.Info()&types.IsString != 0: 2342 k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For) 2343 2344 case rt.Info()&types.IsInteger != 0: 2345 k, loop, done = b.rangeInt(fn, x, tk, s.For) 2346 2347 default: 2348 panic("Cannot range over basic type: " + rt.String()) 2349 } 2350 2351 case *types.Signature: 2352 // Special case rewrite (fn.goversion >= go1.23): 2353 // for x := range f { ... } 2354 // into 2355 // f(func(x T) bool { ... }) 2356 b.rangeFunc(fn, x, s, label) 2357 return 2358 2359 default: 2360 panic("Cannot range over: " + rt.String()) 2361 } 2362 2363 if s.Tok == token.DEFINE && afterGo122 { 2364 // go1.22: If iteration variables are defined (:=), this occurs inside the loop. 2365 createVars() 2366 } 2367 2368 // Evaluate both LHS expressions before we update either. 2369 var kl, vl lvalue 2370 if tk != nil { 2371 kl = b.addr(fn, s.Key, false) // non-escaping 2372 } 2373 if tv != nil { 2374 vl = b.addr(fn, s.Value, false) // non-escaping 2375 } 2376 if tk != nil { 2377 kl.store(fn, k) 2378 } 2379 if tv != nil { 2380 vl.store(fn, v) 2381 } 2382 2383 if label != nil { 2384 label._break = done 2385 label._continue = loop 2386 } 2387 2388 fn.targets = &targets{ 2389 tail: fn.targets, 2390 _break: done, 2391 _continue: loop, 2392 } 2393 b.stmt(fn, s.Body) 2394 fn.targets = fn.targets.tail 2395 emitJump(fn, loop) // back-edge 2396 fn.currentBlock = done 2397 } 2398 2399 // rangeFunc emits to fn code for the range-over-func rng.Body of the iterator 2400 // function x, optionally labelled by label. It creates a new anonymous function 2401 // yield for rng and builds the function. 2402 func (b *builder) rangeFunc(fn *Function, x Value, rng *ast.RangeStmt, label *lblock) { 2403 // Consider the SSA code for the outermost range-over-func in fn: 2404 // 2405 // func fn(...) (ret R) { 2406 // ... 2407 // for k, v = range x { 2408 // ... 2409 // } 2410 // ... 2411 // } 2412 // 2413 // The code emitted into fn will look something like this. 2414 // 2415 // loop: 2416 // jump := READY 2417 // y := make closure yield [ret, deferstack, jump, k, v] 2418 // x(y) 2419 // switch jump { 2420 // [see resuming execution] 2421 // } 2422 // goto done 2423 // done: 2424 // ... 2425 // 2426 // where yield is a new synthetic yield function: 2427 // 2428 // func yield(_k tk, _v tv) bool 2429 // free variables: [ret, stack, jump, k, v] 2430 // { 2431 // entry: 2432 // if jump != READY then goto invalid else valid 2433 // invalid: 2434 // panic("iterator called when it is not in a ready state") 2435 // valid: 2436 // jump = BUSY 2437 // k = _k 2438 // v = _v 2439 // ... 2440 // cont: 2441 // jump = READY 2442 // return true 2443 // } 2444 // 2445 // Yield state: 2446 // 2447 // Each range loop has an associated jump variable that records 2448 // the state of the iterator. A yield function is initially 2449 // in a READY (0) and callable state. If the yield function is called 2450 // and is not in READY state, it panics. When it is called in a callable 2451 // state, it becomes BUSY. When execution reaches the end of the body 2452 // of the loop (or a continue statement targeting the loop is executed), 2453 // the yield function returns true and resumes being in a READY state. 2454 // After the iterator function x(y) returns, then if the yield function 2455 // is in a READY state, the yield enters the DONE state. 2456 // 2457 // Each lowered control statement (break X, continue X, goto Z, or return) 2458 // that exits the loop sets the variable to a unique positive EXIT value, 2459 // before returning false from the yield function. 2460 // 2461 // If the yield function returns abruptly due to a panic or GoExit, 2462 // it remains in a BUSY state. The generated code asserts that, after 2463 // the iterator call x(y) returns normally, the jump variable state 2464 // is DONE. 2465 // 2466 // Resuming execution: 2467 // 2468 // The code generated for the range statement checks the jump 2469 // variable to determine how to resume execution. 2470 // 2471 // switch jump { 2472 // case BUSY: panic("...") 2473 // case DONE: goto done 2474 // case READY: state = DONE; goto done 2475 // case 123: ... // action for exit 123. 2476 // case 456: ... // action for exit 456. 2477 // ... 2478 // } 2479 // 2480 // Forward goto statements within a yield are jumps to labels that 2481 // have not yet been traversed in fn. They may be in the Body of the 2482 // function. What we emit for these is: 2483 // 2484 // goto target 2485 // target: 2486 // ... 2487 // 2488 // We leave an unresolved exit in yield.exits to check at the end 2489 // of building yield if it encountered target in the body. If it 2490 // encountered target, no additional work is required. Otherwise, 2491 // the yield emits a new early exit in the basic block for target. 2492 // We expect that blockopt will fuse the early exit into the case 2493 // block later. The unresolved exit is then added to yield.parent.exits. 2494 2495 loop := fn.newBasicBlock("rangefunc.loop") 2496 done := fn.newBasicBlock("rangefunc.done") 2497 2498 // These are targets within y. 2499 fn.targets = &targets{ 2500 tail: fn.targets, 2501 _break: done, 2502 // _continue is within y. 2503 } 2504 if label != nil { 2505 label._break = done 2506 // _continue is within y 2507 } 2508 2509 emitJump(fn, loop) 2510 fn.currentBlock = loop 2511 2512 // loop: 2513 // jump := READY 2514 2515 anonIdx := len(fn.AnonFuncs) 2516 2517 jump := newVar(fmt.Sprintf("jump$%d", anonIdx+1), tInt) 2518 emitLocalVar(fn, jump) // zero value is READY 2519 2520 xsig := typeparams.CoreType(x.Type()).(*types.Signature) 2521 ysig := typeparams.CoreType(xsig.Params().At(0).Type()).(*types.Signature) 2522 2523 /* synthetic yield function for body of range-over-func loop */ 2524 y := &Function{ 2525 name: fmt.Sprintf("%s$%d", fn.Name(), anonIdx+1), 2526 Signature: ysig, 2527 Synthetic: "range-over-func yield", 2528 pos: rng.Range, 2529 parent: fn, 2530 anonIdx: int32(len(fn.AnonFuncs)), 2531 Pkg: fn.Pkg, 2532 Prog: fn.Prog, 2533 syntax: rng, 2534 info: fn.info, 2535 goversion: fn.goversion, 2536 build: (*builder).buildYieldFunc, 2537 topLevelOrigin: nil, 2538 typeparams: fn.typeparams, 2539 typeargs: fn.typeargs, 2540 subst: fn.subst, 2541 jump: jump, 2542 deferstack: fn.deferstack, 2543 returnVars: fn.returnVars, // use the parent's return variables 2544 uniq: fn.uniq, // start from parent's unique values 2545 } 2546 2547 // If the RangeStmt has a label, this is how it is passed to buildYieldFunc. 2548 if label != nil { 2549 y.lblocks = map[*types.Label]*lblock{label.label: nil} 2550 } 2551 fn.AnonFuncs = append(fn.AnonFuncs, y) 2552 2553 // Build y immediately. It may: 2554 // * cause fn's locals to escape, and 2555 // * create new exit nodes in exits. 2556 // (y is not marked 'built' until the end of the enclosing FuncDecl.) 2557 unresolved := len(fn.exits) 2558 y.build(b, y) 2559 fn.uniq = y.uniq // resume after y's unique values 2560 2561 // Emit the call of y. 2562 // c := MakeClosure y 2563 // x(c) 2564 c := &MakeClosure{Fn: y} 2565 c.setType(ysig) 2566 for _, fv := range y.FreeVars { 2567 c.Bindings = append(c.Bindings, fv.outer) 2568 fv.outer = nil 2569 } 2570 fn.emit(c) 2571 call := Call{ 2572 Call: CallCommon{ 2573 Value: x, 2574 Args: []Value{c}, 2575 pos: token.NoPos, 2576 }, 2577 } 2578 call.setType(xsig.Results()) 2579 fn.emit(&call) 2580 2581 exits := fn.exits[unresolved:] 2582 b.buildYieldResume(fn, jump, exits, done) 2583 2584 emitJump(fn, done) 2585 fn.currentBlock = done 2586 // pop the stack for the range-over-func 2587 fn.targets = fn.targets.tail 2588 } 2589 2590 // buildYieldResume emits to fn code for how to resume execution once a call to 2591 // the iterator function over the yield function returns x(y). It does this by building 2592 // a switch over the value of jump for when it is READY, BUSY, or EXIT(id). 2593 func (b *builder) buildYieldResume(fn *Function, jump *types.Var, exits []*exit, done *BasicBlock) { 2594 // v := *jump 2595 // switch v { 2596 // case BUSY: panic("...") 2597 // case READY: jump = DONE; goto done 2598 // case EXIT(a): ... 2599 // case EXIT(b): ... 2600 // ... 2601 // } 2602 v := emitLoad(fn, fn.lookup(jump, false)) 2603 2604 // case BUSY: panic("...") 2605 isbusy := fn.newBasicBlock("rangefunc.resume.busy") 2606 ifready := fn.newBasicBlock("rangefunc.resume.ready.check") 2607 emitIf(fn, emitCompare(fn, token.EQL, v, jBusy, token.NoPos), isbusy, ifready) 2608 fn.currentBlock = isbusy 2609 fn.emit(&Panic{ 2610 X: emitConv(fn, stringConst("iterator call did not preserve panic"), tEface), 2611 }) 2612 fn.currentBlock = ifready 2613 2614 // case READY: jump = DONE; goto done 2615 isready := fn.newBasicBlock("rangefunc.resume.ready") 2616 ifexit := fn.newBasicBlock("rangefunc.resume.exits") 2617 emitIf(fn, emitCompare(fn, token.EQL, v, jReady, token.NoPos), isready, ifexit) 2618 fn.currentBlock = isready 2619 storeVar(fn, jump, jDone, token.NoPos) 2620 emitJump(fn, done) 2621 fn.currentBlock = ifexit 2622 2623 for _, e := range exits { 2624 id := intConst(e.id) 2625 2626 // case EXIT(id): { /* do e */ } 2627 cond := emitCompare(fn, token.EQL, v, id, e.pos) 2628 matchb := fn.newBasicBlock("rangefunc.resume.match") 2629 cndb := fn.newBasicBlock("rangefunc.resume.cnd") 2630 emitIf(fn, cond, matchb, cndb) 2631 fn.currentBlock = matchb 2632 2633 // Cases to fill in the { /* do e */ } bit. 2634 switch { 2635 case e.label != nil: // forward goto? 2636 // case EXIT(id): goto lb // label 2637 lb := fn.lblockOf(e.label) 2638 // Do not mark lb as resolved. 2639 // If fn does not contain label, lb remains unresolved and 2640 // fn must itself be a range-over-func function. lb will be: 2641 // lb: 2642 // fn.jump = id 2643 // return false 2644 emitJump(fn, lb._goto) 2645 2646 case e.to != fn: // e jumps to an ancestor of fn? 2647 // case EXIT(id): { fn.jump = id; return false } 2648 // fn is a range-over-func function. 2649 storeVar(fn, fn.jump, id, token.NoPos) 2650 fn.emit(&Return{Results: []Value{vFalse}, pos: e.pos}) 2651 2652 case e.block == nil && e.label == nil: // return from fn? 2653 // case EXIT(id): { return ... } 2654 fn.emit(new(RunDefers)) 2655 results := make([]Value, len(fn.results)) 2656 for i, r := range fn.results { 2657 results[i] = emitLoad(fn, r) 2658 } 2659 fn.emit(&Return{Results: results, pos: e.pos}) 2660 2661 case e.block != nil: 2662 // case EXIT(id): goto block 2663 emitJump(fn, e.block) 2664 2665 default: 2666 panic("unreachable") 2667 } 2668 fn.currentBlock = cndb 2669 } 2670 } 2671 2672 // stmt lowers statement s to SSA form, emitting code to fn. 2673 func (b *builder) stmt(fn *Function, _s ast.Stmt) { 2674 // The label of the current statement. If non-nil, its _goto 2675 // target is always set; its _break and _continue are set only 2676 // within the body of switch/typeswitch/select/for/range. 2677 // It is effectively an additional default-nil parameter of stmt(). 2678 var label *lblock 2679 start: 2680 switch s := _s.(type) { 2681 case *ast.EmptyStmt: 2682 // ignore. (Usually removed by gofmt.) 2683 2684 case *ast.DeclStmt: // Con, Var or Typ 2685 d := s.Decl.(*ast.GenDecl) 2686 if d.Tok == token.VAR { 2687 for _, spec := range d.Specs { 2688 if vs, ok := spec.(*ast.ValueSpec); ok { 2689 b.localValueSpec(fn, vs) 2690 } 2691 } 2692 } 2693 2694 case *ast.LabeledStmt: 2695 if s.Label.Name == "_" { 2696 // Blank labels can't be the target of a goto, break, 2697 // or continue statement, so we don't need a new block. 2698 _s = s.Stmt 2699 goto start 2700 } 2701 label = fn.lblockOf(fn.label(s.Label)) 2702 label.resolved = true 2703 emitJump(fn, label._goto) 2704 fn.currentBlock = label._goto 2705 _s = s.Stmt 2706 goto start // effectively: tailcall stmt(fn, s.Stmt, label) 2707 2708 case *ast.ExprStmt: 2709 b.expr(fn, s.X) 2710 2711 case *ast.SendStmt: 2712 chtyp := typeparams.CoreType(fn.typeOf(s.Chan)).(*types.Chan) 2713 fn.emit(&Send{ 2714 Chan: b.expr(fn, s.Chan), 2715 X: emitConv(fn, b.expr(fn, s.Value), chtyp.Elem()), 2716 pos: s.Arrow, 2717 }) 2718 2719 case *ast.IncDecStmt: 2720 op := token.ADD 2721 if s.Tok == token.DEC { 2722 op = token.SUB 2723 } 2724 loc := b.addr(fn, s.X, false) 2725 b.assignOp(fn, loc, NewConst(constant.MakeInt64(1), loc.typ()), op, s.Pos()) 2726 2727 case *ast.AssignStmt: 2728 switch s.Tok { 2729 case token.ASSIGN, token.DEFINE: 2730 b.assignStmt(fn, s.Lhs, s.Rhs, s.Tok == token.DEFINE) 2731 2732 default: // +=, etc. 2733 op := s.Tok + token.ADD - token.ADD_ASSIGN 2734 b.assignOp(fn, b.addr(fn, s.Lhs[0], false), b.expr(fn, s.Rhs[0]), op, s.Pos()) 2735 } 2736 2737 case *ast.GoStmt: 2738 // The "intrinsics" new/make/len/cap are forbidden here. 2739 // panic is treated like an ordinary function call. 2740 v := Go{pos: s.Go} 2741 b.setCall(fn, s.Call, &v.Call) 2742 fn.emit(&v) 2743 2744 case *ast.DeferStmt: 2745 // The "intrinsics" new/make/len/cap are forbidden here. 2746 // panic is treated like an ordinary function call. 2747 deferstack := emitLoad(fn, fn.lookup(fn.deferstack, false)) 2748 v := Defer{pos: s.Defer, DeferStack: deferstack} 2749 b.setCall(fn, s.Call, &v.Call) 2750 fn.emit(&v) 2751 2752 // A deferred call can cause recovery from panic, 2753 // and control resumes at the Recover block. 2754 createRecoverBlock(fn.source) 2755 2756 case *ast.ReturnStmt: 2757 b.returnStmt(fn, s) 2758 2759 case *ast.BranchStmt: 2760 b.branchStmt(fn, s) 2761 2762 case *ast.BlockStmt: 2763 b.stmtList(fn, s.List) 2764 2765 case *ast.IfStmt: 2766 if s.Init != nil { 2767 b.stmt(fn, s.Init) 2768 } 2769 then := fn.newBasicBlock("if.then") 2770 done := fn.newBasicBlock("if.done") 2771 els := done 2772 if s.Else != nil { 2773 els = fn.newBasicBlock("if.else") 2774 } 2775 b.cond(fn, s.Cond, then, els) 2776 fn.currentBlock = then 2777 b.stmt(fn, s.Body) 2778 emitJump(fn, done) 2779 2780 if s.Else != nil { 2781 fn.currentBlock = els 2782 b.stmt(fn, s.Else) 2783 emitJump(fn, done) 2784 } 2785 2786 fn.currentBlock = done 2787 2788 case *ast.SwitchStmt: 2789 b.switchStmt(fn, s, label) 2790 2791 case *ast.TypeSwitchStmt: 2792 b.typeSwitchStmt(fn, s, label) 2793 2794 case *ast.SelectStmt: 2795 b.selectStmt(fn, s, label) 2796 2797 case *ast.ForStmt: 2798 b.forStmt(fn, s, label) 2799 2800 case *ast.RangeStmt: 2801 b.rangeStmt(fn, s, label) 2802 2803 default: 2804 panic(fmt.Sprintf("unexpected statement kind: %T", s)) 2805 } 2806 } 2807 2808 func (b *builder) branchStmt(fn *Function, s *ast.BranchStmt) { 2809 var block *BasicBlock 2810 if s.Label == nil { 2811 block = targetedBlock(fn, s.Tok) 2812 } else { 2813 target := fn.label(s.Label) 2814 block = labelledBlock(fn, target, s.Tok) 2815 if block == nil { // forward goto 2816 lb := fn.lblockOf(target) 2817 block = lb._goto // jump to lb._goto 2818 if fn.jump != nil { 2819 // fn is a range-over-func and the goto may exit fn. 2820 // Create an exit and resolve it at the end of 2821 // builder.buildYieldFunc. 2822 labelExit(fn, target, s.Pos()) 2823 } 2824 } 2825 } 2826 to := block.parent 2827 2828 if to == fn { 2829 emitJump(fn, block) 2830 } else { // break outside of fn. 2831 // fn must be a range-over-func 2832 e := blockExit(fn, block, s.Pos()) 2833 storeVar(fn, fn.jump, intConst(e.id), e.pos) 2834 fn.emit(&Return{Results: []Value{vFalse}, pos: e.pos}) 2835 } 2836 fn.currentBlock = fn.newBasicBlock("unreachable") 2837 } 2838 2839 func (b *builder) returnStmt(fn *Function, s *ast.ReturnStmt) { 2840 var results []Value 2841 2842 sig := fn.source.Signature // signature of the enclosing source function 2843 2844 // Convert return operands to result type. 2845 if len(s.Results) == 1 && sig.Results().Len() > 1 { 2846 // Return of one expression in a multi-valued function. 2847 tuple := b.exprN(fn, s.Results[0]) 2848 ttuple := tuple.Type().(*types.Tuple) 2849 for i, n := 0, ttuple.Len(); i < n; i++ { 2850 results = append(results, 2851 emitConv(fn, emitExtract(fn, tuple, i), 2852 sig.Results().At(i).Type())) 2853 } 2854 } else { 2855 // 1:1 return, or no-arg return in non-void function. 2856 for i, r := range s.Results { 2857 v := emitConv(fn, b.expr(fn, r), sig.Results().At(i).Type()) 2858 results = append(results, v) 2859 } 2860 } 2861 2862 // Store the results. 2863 for i, r := range results { 2864 var result Value // fn.source.result[i] conceptually 2865 if fn == fn.source { 2866 result = fn.results[i] 2867 } else { // lookup needed? 2868 result = fn.lookup(fn.returnVars[i], false) 2869 } 2870 emitStore(fn, result, r, s.Return) 2871 } 2872 2873 if fn.jump != nil { 2874 // Return from body of a range-over-func. 2875 // The return statement is syntactically within the loop, 2876 // but the generated code is in the 'switch jump {...}' after it. 2877 e := returnExit(fn, s.Pos()) 2878 storeVar(fn, fn.jump, intConst(e.id), e.pos) 2879 fn.emit(&Return{Results: []Value{vFalse}, pos: e.pos}) 2880 fn.currentBlock = fn.newBasicBlock("unreachable") 2881 return 2882 } 2883 2884 // Run function calls deferred in this 2885 // function when explicitly returning from it. 2886 fn.emit(new(RunDefers)) 2887 // Reload (potentially) named result variables to form the result tuple. 2888 results = results[:0] 2889 for _, nr := range fn.results { 2890 results = append(results, emitLoad(fn, nr)) 2891 } 2892 fn.emit(&Return{Results: results, pos: s.Return}) 2893 fn.currentBlock = fn.newBasicBlock("unreachable") 2894 } 2895 2896 // A buildFunc is a strategy for building the SSA body for a function. 2897 type buildFunc = func(*builder, *Function) 2898 2899 // iterate causes all created but unbuilt functions to be built. As 2900 // this may create new methods, the process is iterated until it 2901 // converges. 2902 // 2903 // Waits for any dependencies to finish building. 2904 func (b *builder) iterate() { 2905 for ; b.finished < len(b.fns); b.finished++ { 2906 fn := b.fns[b.finished] 2907 b.buildFunction(fn) 2908 } 2909 2910 b.buildshared.markDone() 2911 b.buildshared.wait() 2912 } 2913 2914 // buildFunction builds SSA code for the body of function fn. Idempotent. 2915 func (b *builder) buildFunction(fn *Function) { 2916 if fn.build != nil { 2917 assert(fn.parent == nil, "anonymous functions should not be built by buildFunction()") 2918 2919 if fn.Prog.mode&LogSource != 0 { 2920 defer logStack("build %s @ %s", fn, fn.Prog.Fset.Position(fn.pos))() 2921 } 2922 fn.build(b, fn) 2923 fn.done() 2924 } 2925 } 2926 2927 // buildParamsOnly builds fn.Params from fn.Signature, but does not build fn.Body. 2928 func (b *builder) buildParamsOnly(fn *Function) { 2929 // For external (C, asm) functions or functions loaded from 2930 // export data, we must set fn.Params even though there is no 2931 // body code to reference them. 2932 if recv := fn.Signature.Recv(); recv != nil { 2933 fn.addParamVar(recv) 2934 } 2935 params := fn.Signature.Params() 2936 for i, n := 0, params.Len(); i < n; i++ { 2937 fn.addParamVar(params.At(i)) 2938 } 2939 2940 // clear out other function state (keep consistent with finishBody) 2941 fn.subst = nil 2942 } 2943 2944 // buildFromSyntax builds fn.Body from fn.syntax, which must be non-nil. 2945 func (b *builder) buildFromSyntax(fn *Function) { 2946 var ( 2947 recvField *ast.FieldList 2948 body *ast.BlockStmt 2949 functype *ast.FuncType 2950 ) 2951 switch syntax := fn.syntax.(type) { 2952 case *ast.FuncDecl: 2953 functype = syntax.Type 2954 recvField = syntax.Recv 2955 body = syntax.Body 2956 if body == nil { 2957 b.buildParamsOnly(fn) // no body (non-Go function) 2958 return 2959 } 2960 case *ast.FuncLit: 2961 functype = syntax.Type 2962 body = syntax.Body 2963 case nil: 2964 panic("no syntax") 2965 default: 2966 panic(syntax) // unexpected syntax 2967 } 2968 fn.source = fn 2969 fn.startBody() 2970 fn.createSyntacticParams(recvField, functype) 2971 fn.createDeferStack() 2972 b.stmt(fn, body) 2973 if cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) { 2974 // Control fell off the end of the function's body block. 2975 // 2976 // Block optimizations eliminate the current block, if 2977 // unreachable. It is a builder invariant that 2978 // if this no-arg return is ill-typed for 2979 // fn.Signature.Results, this block must be 2980 // unreachable. The sanity checker checks this. 2981 fn.emit(new(RunDefers)) 2982 fn.emit(new(Return)) 2983 } 2984 fn.finishBody() 2985 } 2986 2987 // buildYieldFunc builds the body of the yield function created 2988 // from a range-over-func *ast.RangeStmt. 2989 func (b *builder) buildYieldFunc(fn *Function) { 2990 // See builder.rangeFunc for detailed documentation on how fn is set up. 2991 // 2992 // In pseudo-Go this roughly builds: 2993 // func yield(_k tk, _v tv) bool { 2994 // if jump != READY { panic("yield function called after range loop exit") } 2995 // jump = BUSY 2996 // k, v = _k, _v // assign the iterator variable (if needed) 2997 // ... // rng.Body 2998 // continue: 2999 // jump = READY 3000 // return true 3001 // } 3002 s := fn.syntax.(*ast.RangeStmt) 3003 fn.source = fn.parent.source 3004 fn.startBody() 3005 params := fn.Signature.Params() 3006 for v := range params.Variables() { 3007 fn.addParamVar(v) 3008 } 3009 3010 // Initial targets 3011 ycont := fn.newBasicBlock("yield-continue") 3012 // lblocks is either {} or is {label: nil} where label is the label of syntax. 3013 for label := range fn.lblocks { 3014 fn.lblocks[label] = &lblock{ 3015 label: label, 3016 resolved: true, 3017 _goto: ycont, 3018 _continue: ycont, 3019 // `break label` statement targets fn.parent.targets._break 3020 } 3021 } 3022 fn.targets = &targets{ 3023 tail: fn.targets, 3024 _continue: ycont, 3025 // `break` statement targets fn.parent.targets._break. 3026 } 3027 3028 // continue: 3029 // jump = READY 3030 // return true 3031 saved := fn.currentBlock 3032 fn.currentBlock = ycont 3033 storeVar(fn, fn.jump, jReady, s.Body.Rbrace) 3034 // A yield function's own deferstack is always empty, so rundefers is not needed. 3035 fn.emit(&Return{Results: []Value{vTrue}, pos: token.NoPos}) 3036 3037 // Emit header: 3038 // 3039 // if jump != READY { panic("yield iterator accessed after exit") } 3040 // jump = BUSY 3041 // k, v = _k, _v 3042 fn.currentBlock = saved 3043 yloop := fn.newBasicBlock("yield-loop") 3044 invalid := fn.newBasicBlock("yield-invalid") 3045 3046 jumpVal := emitLoad(fn, fn.lookup(fn.jump, true)) 3047 emitIf(fn, emitCompare(fn, token.EQL, jumpVal, jReady, token.NoPos), yloop, invalid) 3048 fn.currentBlock = invalid 3049 fn.emit(&Panic{ 3050 X: emitConv(fn, stringConst("yield function called after range loop exit"), tEface), 3051 }) 3052 3053 fn.currentBlock = yloop 3054 storeVar(fn, fn.jump, jBusy, s.Body.Rbrace) 3055 3056 // Initialize k and v from params. 3057 var tk, tv types.Type 3058 if s.Key != nil && !isBlankIdent(s.Key) { 3059 tk = fn.typeOf(s.Key) // fn.parent.typeOf is identical 3060 } 3061 if s.Value != nil && !isBlankIdent(s.Value) { 3062 tv = fn.typeOf(s.Value) 3063 } 3064 if s.Tok == token.DEFINE { 3065 if tk != nil { 3066 emitLocalVar(fn, identVar(fn, s.Key.(*ast.Ident))) 3067 } 3068 if tv != nil { 3069 emitLocalVar(fn, identVar(fn, s.Value.(*ast.Ident))) 3070 } 3071 } 3072 var k, v Value 3073 if len(fn.Params) > 0 { 3074 k = fn.Params[0] 3075 } 3076 if len(fn.Params) > 1 { 3077 v = fn.Params[1] 3078 } 3079 var kl, vl lvalue 3080 if tk != nil { 3081 kl = b.addr(fn, s.Key, false) // non-escaping 3082 } 3083 if tv != nil { 3084 vl = b.addr(fn, s.Value, false) // non-escaping 3085 } 3086 if tk != nil { 3087 kl.store(fn, k) 3088 } 3089 if tv != nil { 3090 vl.store(fn, v) 3091 } 3092 3093 // Build the body of the range loop. 3094 b.stmt(fn, s.Body) 3095 if cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) { 3096 // Control fell off the end of the function's body block. 3097 // Block optimizations eliminate the current block, if 3098 // unreachable. 3099 emitJump(fn, ycont) 3100 } 3101 // pop the stack for the yield function 3102 fn.targets = fn.targets.tail 3103 3104 // Clean up exits and promote any unresolved exits to fn.parent. 3105 for _, e := range fn.exits { 3106 if e.label != nil { 3107 lb := fn.lblocks[e.label] 3108 if lb.resolved { 3109 // label was resolved. Do not turn lb into an exit. 3110 // e does not need to be handled by the parent. 3111 continue 3112 } 3113 3114 // _goto becomes an exit. 3115 // _goto: 3116 // jump = id 3117 // return false 3118 fn.currentBlock = lb._goto 3119 id := intConst(e.id) 3120 storeVar(fn, fn.jump, id, e.pos) 3121 fn.emit(&Return{Results: []Value{vFalse}, pos: e.pos}) 3122 } 3123 3124 if e.to != fn { // e needs to be handled by the parent too. 3125 fn.parent.exits = append(fn.parent.exits, e) 3126 } 3127 } 3128 3129 fn.finishBody() 3130 } 3131 3132 // addMakeInterfaceType records non-interface type t as the type of 3133 // the operand a MakeInterface operation, for [Program.RuntimeTypes]. 3134 // 3135 // Acquires prog.makeInterfaceTypesMu. 3136 func addMakeInterfaceType(prog *Program, t types.Type) { 3137 prog.makeInterfaceTypesMu.Lock() 3138 defer prog.makeInterfaceTypesMu.Unlock() 3139 if prog.makeInterfaceTypes == nil { 3140 prog.makeInterfaceTypes = make(map[types.Type]unit) 3141 } 3142 prog.makeInterfaceTypes[t] = unit{} 3143 } 3144 3145 // Build calls Package.Build for each package in prog. 3146 // Building occurs in parallel unless the BuildSerially mode flag was set. 3147 // 3148 // Build is intended for whole-program analysis; a typical compiler 3149 // need only build a single package. 3150 // 3151 // Build is idempotent and thread-safe. 3152 func (prog *Program) Build() { 3153 var wg sync.WaitGroup 3154 for _, p := range prog.packages { 3155 if prog.mode&BuildSerially != 0 { 3156 p.Build() 3157 } else { 3158 wg.Add(1) 3159 cpuLimit <- unit{} // acquire a token 3160 go func(p *Package) { 3161 p.Build() 3162 wg.Done() 3163 <-cpuLimit // release a token 3164 }(p) 3165 } 3166 } 3167 wg.Wait() 3168 } 3169 3170 // cpuLimit is a counting semaphore to limit CPU parallelism. 3171 var cpuLimit = make(chan unit, runtime.GOMAXPROCS(0)) 3172 3173 // Build builds SSA code for all functions and vars in package p. 3174 // 3175 // CreatePackage must have been called for all of p's direct imports 3176 // (and hence its direct imports must have been error-free). It is not 3177 // necessary to call CreatePackage for indirect dependencies. 3178 // Functions will be created for all necessary methods in those 3179 // packages on demand. 3180 // 3181 // Build is idempotent and thread-safe. 3182 func (p *Package) Build() { p.buildOnce.Do(p.build) } 3183 3184 func (p *Package) build() { 3185 if p.info == nil { 3186 return // synthetic package, e.g. "testmain" 3187 } 3188 if p.Prog.mode&LogSource != 0 { 3189 defer logStack("build %s", p)() 3190 } 3191 3192 b := builder{fns: p.created} 3193 b.iterate() 3194 3195 // We no longer need transient information: ASTs or go/types deductions. 3196 p.info = nil 3197 p.created = nil 3198 p.files = nil 3199 p.initVersion = nil 3200 3201 if p.Prog.mode&SanityCheckFunctions != 0 { 3202 sanityCheckPackage(p) 3203 } 3204 } 3205 3206 // buildPackageInit builds fn.Body for the synthetic package initializer. 3207 func (b *builder) buildPackageInit(fn *Function) { 3208 p := fn.Pkg 3209 fn.startBody() 3210 3211 var done *BasicBlock 3212 3213 if p.Prog.mode&BareInits == 0 { 3214 // Make init() skip if package is already initialized. 3215 initguard := p.Var("init$guard") 3216 doinit := fn.newBasicBlock("init.start") 3217 done = fn.newBasicBlock("init.done") 3218 emitIf(fn, emitLoad(fn, initguard), done, doinit) 3219 fn.currentBlock = doinit 3220 emitStore(fn, initguard, vTrue, token.NoPos) 3221 3222 // Call the init() function of each package we import. 3223 for _, pkg := range p.Pkg.Imports() { 3224 prereq := p.Prog.packages[pkg] 3225 if prereq == nil { 3226 panic(fmt.Sprintf("Package(%q).Build(): unsatisfied import: Program.CreatePackage(%q) was not called", p.Pkg.Path(), pkg.Path())) 3227 } 3228 var v Call 3229 v.Call.Value = prereq.init 3230 v.Call.pos = fn.pos 3231 v.setType(types.NewTuple()) 3232 fn.emit(&v) 3233 } 3234 } 3235 3236 // Initialize package-level vars in correct order. 3237 if len(p.info.InitOrder) > 0 && len(p.files) == 0 { 3238 panic("no source files provided for package. cannot initialize globals") 3239 } 3240 3241 for _, varinit := range p.info.InitOrder { 3242 if fn.Prog.mode&LogSource != 0 { 3243 fmt.Fprintf(os.Stderr, "build global initializer %v @ %s\n", 3244 varinit.Lhs, p.Prog.Fset.Position(varinit.Rhs.Pos())) 3245 } 3246 // Initializers for global vars are evaluated in dependency 3247 // order, but may come from arbitrary files of the package 3248 // with different versions, so we transiently update 3249 // fn.goversion for each one. (Since init is a synthetic 3250 // function it has no syntax of its own that needs a version.) 3251 fn.goversion = p.initVersion[varinit.Rhs] 3252 if len(varinit.Lhs) == 1 { 3253 // 1:1 initialization: var x, y = a(), b() 3254 var lval lvalue 3255 if v := varinit.Lhs[0]; v.Name() != "_" { 3256 lval = &address{addr: p.objects[v].(*Global), pos: v.Pos()} 3257 } else { 3258 lval = blank{} 3259 } 3260 b.assign(fn, lval, varinit.Rhs, true, nil) 3261 } else { 3262 // n:1 initialization: var x, y := f() 3263 tuple := b.exprN(fn, varinit.Rhs) 3264 for i, v := range varinit.Lhs { 3265 if v.Name() == "_" { 3266 continue 3267 } 3268 emitStore(fn, p.objects[v].(*Global), emitExtract(fn, tuple, i), v.Pos()) 3269 } 3270 } 3271 } 3272 3273 // The rest of the init function is synthetic: 3274 // no syntax, info, goversion. 3275 fn.info = nil 3276 fn.goversion = "" 3277 3278 // Call all of the declared init() functions in source order. 3279 for _, file := range p.files { 3280 for _, decl := range file.Decls { 3281 if decl, ok := decl.(*ast.FuncDecl); ok { 3282 id := decl.Name 3283 if !isBlankIdent(id) && id.Name == "init" && decl.Recv == nil { 3284 declaredInit := p.objects[p.info.Defs[id]].(*Function) 3285 var v Call 3286 v.Call.Value = declaredInit 3287 v.setType(types.NewTuple()) 3288 p.init.emit(&v) 3289 } 3290 } 3291 } 3292 } 3293 3294 // Finish up init(). 3295 if p.Prog.mode&BareInits == 0 { 3296 emitJump(fn, done) 3297 fn.currentBlock = done 3298 } 3299 fn.emit(new(Return)) 3300 fn.finishBody() 3301 }