type opaqueType … func (t *opaqueType) String() string { … } func (t *opaqueType) Underlying() types.Type { … } var varOk … var varIndex … var tBool … var tByte … var tInt … var tInvalid … var tString … var tUntypedNil … var tRangeIter … var tDeferStack … var tEface … var vZero … var vOne … var vTrue … var vFalse … var jReady … var jBusy … var jDone … var vDeferStack … type builder … // shared is done when the builder has built all of the // enqueued functions to a fixed-point. func (b *builder) shared() *task { … } // enqueue fn to be built by the builder. func (b *builder) enqueue(fn *Function) { … } // waitForSharedFunction indicates that the builder should wait until // the potentially shared function fn has finished building. // // This should include any functions that may be built by other // builders. func (b *builder) waitForSharedFunction(fn *Function) { … } // cond emits to fn code to evaluate boolean condition e and jump // to t or f depending on its value, performing various simplifications. // // Postcondition: fn.currentBlock is nil. func (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) { … } // logicalBinop emits code to fn to evaluate e, a &&- or // ||-expression whose reified boolean value is wanted. // The value is returned. func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value { … } // exprN lowers a multi-result expression e to SSA form, emitting code // to fn and returning a single Value whose type is a *types.Tuple. // The caller must access the components via Extract. // // Multi-result expressions include CallExprs in a multi-value // assignment or return statement, and "value,ok" uses of // TypeAssertExpr, IndexExpr (when X is a map), and UnaryExpr (when Op // is token.ARROW). func (b *builder) exprN(fn *Function, e ast.Expr) Value { … } // builtin emits to fn SSA instructions to implement a call to the // built-in function obj with the specified arguments // and return type. It returns the value defined by the result. // // The result is nil if no special handling was required; in this case // the caller should treat this like an ordinary library function // call. func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value { … } // addr lowers a single-result addressable expression e to SSA form, // emitting code to fn and returning the location (an lvalue) defined // by the expression. // // If escaping is true, addr marks the base variable of the // addressable expression e as being a potentially escaping pointer // value. For example, in this code: // // a := A{ // b: [1]B{B{c: 1}} // } // return &a.b[0].c // // the application of & causes a.b[0].c to have its address taken, // which means that ultimately the local variable a must be // heap-allocated. This is a simple but very conservative escape // analysis. // // Operations forming potentially escaping pointers include: // - &x, including when implicit in method call or composite literals. // - a[:] iff a is an array (not *array) // - references to variables in lexically enclosing functions. func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue { … } type store … type storebuf … func (sb *storebuf) store(lhs lvalue, rhs Value) { … } func (sb *storebuf) emit(fn *Function) { … } // assign emits to fn code to initialize the lvalue loc with the value // of expression e. If isZero is true, assign assumes that loc holds // the zero value for its type. // // This is equivalent to loc.store(fn, b.expr(fn, e)), but may generate // better code in some cases, e.g., for composite literals in an // addressable location. // // If sb is not nil, assign generates code to evaluate expression e, but // not to update loc. Instead, the necessary stores are appended to the // storebuf sb so that they can be executed later. This allows correct // in-place update of existing variables when the RHS is a composite // literal that may reference parts of the LHS. func (b *builder) assign(fn *Function, loc lvalue, e ast.Expr, isZero bool, sb *storebuf) { … } // expr lowers a single-result expression e to SSA form, emitting code // to fn and returning the Value defined by the expression. func (b *builder) expr(fn *Function, e ast.Expr) Value { … } func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value { … } // stmtList emits to fn code for all statements in list. func (b *builder) stmtList(fn *Function, list []ast.Stmt) { … } // receiver emits to fn code for expression e in the "receiver" // position of selection e.f (where f may be a field or a method) and // returns the effective receiver after applying the implicit field // selections of sel. // // wantAddr requests that the result is an address. If // !sel.indirect, this may require that e be built in addr() mode; it // must thus be addressable. // // escaping is defined as per builder.addr(). func (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, sel *selection) Value { … } // setCallFunc populates the function parts of a CallCommon structure // (Func, Method, Recv, Args[0]) based on the kind of invocation // occurring in e. func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) { … } // emitCallArgs emits to f code for the actual parameters of call e to // a (possibly built-in) function of effective type sig. // The argument values are appended to args, which is then returned. func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value { … } // setCall emits to fn code to evaluate all the parameters of a function // call e, and populates *c with those values. func (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) { … } // assignOp emits to fn code to perform loc <op>= val. func (b *builder) assignOp(fn *Function, loc lvalue, val Value, op token.Token, pos token.Pos) { … } // localValueSpec emits to fn code to define all of the vars in the // function-local ValueSpec, spec. func (b *builder) localValueSpec(fn *Function, spec *ast.ValueSpec) { … } // assignStmt emits code to fn for a parallel assignment of rhss to lhss. // isDef is true if this is a short variable declaration (:=). // // Note the similarity with localValueSpec. func (b *builder) assignStmt(fn *Function, lhss, rhss []ast.Expr, isDef bool) { … } // arrayLen returns the length of the array whose composite literal elements are elts. func (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 { … } // compLit emits to fn code to initialize a composite literal e at // address addr with type typ. // // Nested composite literals are recursively initialized in place // where possible. If isZero is true, compLit assumes that addr // holds the zero value for typ. // // Because the elements of a composite literal may refer to the // variables being updated, as in the second line below, // // x := T{a: 1} // x = T{a: x.a} // // all the reads must occur before all the writes. Thus all stores to // loc are emitted to the storebuf sb for later execution. // // A CompositeLit may have pointer type only in the recursive (nested) // case when the type name is implicit. e.g. in []*T{{}}, the inner // literal has type *T behaves like &T{}. // In that case, addr must hold a T, not a *T. func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero bool, sb *storebuf) { … } // switchStmt emits to fn code for the switch statement s, optionally // labelled by label. func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) { … } // typeSwitchStmt emits to fn code for the type switch statement s, optionally // labelled by label. func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) { … } func (b *builder) typeCaseBody(fn *Function, cc *ast.CaseClause, x Value, done *BasicBlock) { … } // selectStmt emits to fn code for the select statement s, optionally // labelled by label. func (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) { … } // forStmt emits to fn code for the for statement s, optionally // labelled by label. func (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) { … } // forStmtGo122 emits to fn code for the for statement s, optionally // labelled by label. s must define its variables. // // This allocates once per loop iteration. This is only correct in // GoVersions >= go1.22. func (b *builder) forStmtGo122(fn *Function, s *ast.ForStmt, label *lblock) { … } // rangeIndexed emits to fn the header for an integer-indexed loop // over array, *array or slice value x. // The v result is defined only if tv is non-nil. // forPos is the position of the "for" token. func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) { … } // rangeIter emits to fn the header for a loop using // Range/Next/Extract to iterate over map or string value x. // tk and tv are the types of the key/value results k and v, or nil // if the respective component is not wanted. func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) { … } // rangeChan emits to fn the header for a loop that receives from // channel x until it fails. // tk is the channel's element type, or nil if the k result is // not wanted // pos is the position of the '=' or ':=' token. func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) { … } // rangeInt emits to fn the header for a range loop with an integer operand. // tk is the key value's type, or nil if the k result is not wanted. // pos is the position of the "for" token. func (b *builder) rangeInt(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) { … } // rangeStmt emits to fn code for the range statement s, optionally // labelled by label. func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) { … } // rangeFunc emits to fn code for the range-over-func rng.Body of the iterator // function x, optionally labelled by label. It creates a new anonymous function // yield for rng and builds the function. func (b *builder) rangeFunc(fn *Function, x Value, tk, tv types.Type, rng *ast.RangeStmt, label *lblock) { … } // buildYieldResume emits to fn code for how to resume execution once a call to // the iterator function over the yield function returns x(y). It does this by building // a switch over the value of jump for when it is READY, BUSY, or EXIT(id). func (b *builder) buildYieldResume(fn *Function, jump *types.Var, exits []*exit, done *BasicBlock) { … } // stmt lowers statement s to SSA form, emitting code to fn. func (b *builder) stmt(fn *Function, _s ast.Stmt) { … } func (b *builder) branchStmt(fn *Function, s *ast.BranchStmt) { … } func (b *builder) returnStmt(fn *Function, s *ast.ReturnStmt) { … } type buildFunc … // iterate causes all created but unbuilt functions to be built. As // this may create new methods, the process is iterated until it // converges. // // Waits for any dependencies to finish building. func (b *builder) iterate() { … } // buildFunction builds SSA code for the body of function fn. Idempotent. func (b *builder) buildFunction(fn *Function) { … } // buildParamsOnly builds fn.Params from fn.Signature, but does not build fn.Body. func (b *builder) buildParamsOnly(fn *Function) { … } // buildFromSyntax builds fn.Body from fn.syntax, which must be non-nil. func (b *builder) buildFromSyntax(fn *Function) { … } // buildYieldFunc builds the body of the yield function created // from a range-over-func *ast.RangeStmt. func (b *builder) buildYieldFunc(fn *Function) { … } // addMakeInterfaceType records non-interface type t as the type of // the operand a MakeInterface operation, for [Program.RuntimeTypes]. // // Acquires prog.makeInterfaceTypesMu. func addMakeInterfaceType(prog *Program, t types.Type) { … } // Build calls Package.Build for each package in prog. // Building occurs in parallel unless the BuildSerially mode flag was set. // // Build is intended for whole-program analysis; a typical compiler // need only build a single package. // // Build is idempotent and thread-safe. func (prog *Program) Build() { … } var cpuLimit … // Build builds SSA code for all functions and vars in package p. // // CreatePackage must have been called for all of p's direct imports // (and hence its direct imports must have been error-free). It is not // necessary to call CreatePackage for indirect dependencies. // Functions will be created for all necessary methods in those // packages on demand. // // Build is idempotent and thread-safe. func (p *Package) Build() { … } func (p *Package) build() { … } // buildPackageInit builds fn.Body for the synthetic package initializer. func (b *builder) buildPackageInit(fn *Function) { … }