// Like ObjectOf, but panics instead of returning nil. // Only valid during f's create and build phases. func (f *Function) objectOf(id *ast.Ident) types.Object { … } // Like TypeOf, but panics instead of returning nil. // Only valid during f's create and build phases. func (f *Function) typeOf(e ast.Expr) types.Type { … } // typ is the locally instantiated type of T. // If f is not an instantiation, then f.typ(T)==T. func (f *Function) typ(T types.Type) types.Type { … } // If id is an Instance, returns info.Instances[id].Type. // Otherwise returns f.typeOf(id). func (f *Function) instanceType(id *ast.Ident) types.Type { … } // selection returns a *selection corresponding to f.info.Selections[selector] // with potential updates for type substitution. func (f *Function) selection(selector *ast.SelectorExpr) *selection { … } type targets … type lblock … // label returns the symbol denoted by a label identifier. // // label should be a non-blank identifier (label.Name != "_"). func (f *Function) label(label *ast.Ident) *types.Label { … } // lblockOf returns the branch target associated with the // specified label, creating it if needed. func (f *Function) lblockOf(label *types.Label) *lblock { … } // labelledBlock searches f for the block of the specified label. // // If f is a yield function, it additionally searches ancestor Functions // corresponding to enclosing range-over-func statements within the // same source function, so the returned block may belong to a different Function. func labelledBlock(f *Function, label *types.Label, tok token.Token) *BasicBlock { … } // targetedBlock looks for the nearest block in f.targets // (and f's ancestors) that matches tok's type, and returns // the block and function it was found in. func targetedBlock(f *Function, tok token.Token) *BasicBlock { … } // instrs returns an iterator that returns each reachable instruction of the SSA function. // TODO: return an iter.Seq once x/tools is on 1.23 func (f *Function) instrs() func(yield func(i Instruction) bool) { … } // addResultVar adds a result for a variable v to f.results and v to f.returnVars. func (f *Function) addResultVar(v *types.Var) { … } // addParamVar adds a parameter to f.Params. func (f *Function) addParamVar(v *types.Var) *Parameter { … } // addSpilledParam declares a parameter that is pre-spilled to the // stack; the function body will load/store the spilled location. // Subsequent lifting will eliminate spills where possible. func (f *Function) addSpilledParam(obj *types.Var) { … } // startBody initializes the function prior to generating SSA code for its body. // Precondition: f.Type() already set. func (f *Function) startBody() { … } // createSyntacticParams populates f.Params and generates code (spills // and named result locals) for all the parameters declared in the // syntax. In addition it populates the f.objects mapping. // // Preconditions: // f.startBody() was called. f.info != nil. // Postcondition: // len(f.Params) == len(f.Signature.Params) + (f.Signature.Recv() ? 1 : 0) func (f *Function) createSyntacticParams(recv *ast.FieldList, functype *ast.FuncType) { … } // createDeferStack initializes fn.deferstack to local variable // initialized to a ssa:deferstack() call. func (fn *Function) createDeferStack() { … } type setNumable … // numberRegisters assigns numbers to all SSA registers // (value-defining Instructions) in f, to aid debugging. // (Non-Instruction Values are named at construction.) func numberRegisters(f *Function) { … } // buildReferrers populates the def/use information in all non-nil // Value.Referrers slice. // Precondition: all such slices are initially empty. func buildReferrers(f *Function) { … } // finishBody() finalizes the contents of the function after SSA code generation of its body. // // The function is not done being built until done() is called. func (f *Function) finishBody() { … } // done marks the building of f's SSA body complete, // along with any nested functions, and optionally prints them. func (f *Function) done() { … } // removeNilBlocks eliminates nils from f.Blocks and updates each // BasicBlock.Index. Use this after any pass that may delete blocks. func (f *Function) removeNilBlocks() { … } // SetDebugMode sets the debug mode for package pkg. If true, all its // functions will include full debug info. This greatly increases the // size of the instruction stream, and causes Functions to depend upon // the ASTs, potentially keeping them live in memory for longer. func (pkg *Package) SetDebugMode(debug bool) { … } // debugInfo reports whether debug info is wanted for this function. func (f *Function) debugInfo() bool { … } // lookup returns the address of the named variable identified by obj // that is local to function f or one of its enclosing functions. // If escaping, the reference comes from a potentially escaping pointer // expression and the referent must be heap-allocated. // We assume the referent is a *Alloc or *Phi. // (The only Phis at this stage are those created directly by go1.22 "for" loops.) func (f *Function) lookup(obj *types.Var, escaping bool) Value { … } // emit emits the specified instruction to function f. func (f *Function) emit(instr Instruction) Value { … } // RelString returns the full name of this function, qualified by // package name, receiver type, etc. // // The specific formatting rules are not guaranteed and may change. // // Examples: // // "math.IsNaN" // a package-level function // "(*bytes.Buffer).Bytes" // a declared method or a wrapper // "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0) // "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure) // "main.main$1" // an anonymous function in main // "main.init#1" // a declared init function // "main.init" // the synthesized package initializer // // When these functions are referred to from within the same package // (i.e. from == f.Pkg.Object), they are rendered without the package path. // For example: "IsNaN", "(*Buffer).Bytes", etc. // // All non-synthetic functions have distinct package-qualified names. // (But two methods may have the same name "(T).f" if one is a synthetic // wrapper promoting a non-exported method "f" from another package; in // that case, the strings are equal but the identifiers "f" are distinct.) func (f *Function) RelString(from *types.Package) string { … } func (f *Function) relMethod(from *types.Package, recv types.Type) string { … } // writeSignature writes to buf the signature sig in declaration syntax. func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature) { … } // declaredPackage returns the package fn is declared in or nil if the // function is not declared in a package. func (fn *Function) declaredPackage() *Package { … } // relPkg returns types.Package fn is printed in relationship to. func (fn *Function) relPkg() *types.Package { … } var _ … func (f *Function) WriteTo(w io.Writer) (int64, error) { … } // WriteFunction writes to buf a human-readable "disassembly" of f. func WriteFunction(buf *bytes.Buffer, f *Function) { … } // newBasicBlock adds to f a new basic block and returns it. It does // not automatically become the current block for subsequent calls to emit. // comment is an optional string for more readable debugging output. func (f *Function) newBasicBlock(comment string) *BasicBlock { … } // NewFunction returns a new synthetic Function instance belonging to // prog, with its name and signature fields set as specified. // // The caller is responsible for initializing the remaining fields of // the function object, e.g. Pkg, Params, Blocks. // // It is practically impossible for clients to construct well-formed // SSA functions/packages/programs directly, so we assume this is the // job of the Builder alone. NewFunction exists to provide clients a // little flexibility. For example, analysis tools may wish to // construct fake Functions for the root of the callgraph, a fake // "reflect" package, etc. // // TODO(adonovan): think harder about the API here. func (prog *Program) NewFunction(name string, sig *types.Signature, provenance string) *Function { … } // Syntax returns the function's syntax (*ast.Func{Decl,Lit}) // if it was produced from syntax or an *ast.RangeStmt if // it is a range-over-func yield function. func (f *Function) Syntax() ast.Node { … } // identVar returns the variable defined by id. func identVar(fn *Function, id *ast.Ident) *types.Var { … } // unique returns a unique positive int within the source tree of f. // The source tree of f includes all of f's ancestors by parent and all // of the AnonFuncs contained within these. func unique(f *Function) int64 { … } type exit … // storeVar emits to function f code to store a value v to a *types.Var x. func storeVar(f *Function, x *types.Var, v Value, pos token.Pos) { … } // labelExit creates a new exit to a yield fn to exit the function using a label. func labelExit(fn *Function, label *types.Label, pos token.Pos) *exit { … } // blockExit creates a new exit to a yield fn that jumps to a basic block. func blockExit(fn *Function, block *BasicBlock, pos token.Pos) *exit { … } // blockExit creates a new exit to a yield fn that returns the source function. func returnExit(fn *Function, pos token.Pos) *exit { … }