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