type callSiteAnalyzer … type callSiteTableBuilder … func makeCallSiteAnalyzer(fn *ir.Func) *callSiteAnalyzer { … } func makeCallSiteTableBuilder(fn *ir.Func, cstab CallSiteTab, ptab map[ir.Node]pstate, loopNestingLevel int, nf *nameFinder) *callSiteTableBuilder { … } // computeCallSiteTable builds and returns a table of call sites for // the specified region in function fn. A region here corresponds to a // specific subtree within the AST for a function. The main intended // use cases are for 'region' to be either A) an entire function body, // or B) an inlined call expression. func computeCallSiteTable(fn *ir.Func, region ir.Nodes, cstab CallSiteTab, ptab map[ir.Node]pstate, loopNestingLevel int, nf *nameFinder) CallSiteTab { … } func (cstb *callSiteTableBuilder) flagsForNode(call *ir.CallExpr) CSPropBits { … } // determinePanicPathBits updates the CallSiteOnPanicPath bit within // "r" if we think this call is on an unconditional path to // panic/exit. Do this by walking back up the node stack to see if we // can find either A) an enclosing panic, or B) a statement node that // we've determined leads to a panic/exit. func (cstb *callSiteTableBuilder) determinePanicPathBits(call ir.Node, r CSPropBits) CSPropBits { … } // propsForArg returns property bits for a given call argument expression arg. func (cstb *callSiteTableBuilder) propsForArg(arg ir.Node) ActualExprPropBits { … } // argPropsForCall returns a slice of argument properties for the // expressions being passed to the callee in the specific call // expression; these will be stored in the CallSite object for a given // call and then consulted when scoring. If no arg has any interesting // properties we try to save some space and return a nil slice. func (cstb *callSiteTableBuilder) argPropsForCall(ce *ir.CallExpr) []ActualExprPropBits { … } func (cstb *callSiteTableBuilder) addCallSite(callee *ir.Func, call *ir.CallExpr) { … } func (cstb *callSiteTableBuilder) nodeVisitPre(n ir.Node) { … } func (cstb *callSiteTableBuilder) nodeVisitPost(n ir.Node) { … } func loopBody(n ir.Node) ir.Nodes { … } // hasTopLevelLoopBodyReturnOrBreak examines the body of a "for" or // "range" loop to try to verify that it is a real loop, as opposed to // a construct that is syntactically loopy but doesn't actually iterate // multiple times, like: // // for { // blah() // return 1 // } // // [Remark: the pattern above crops up quite a bit in the source code // for the compiler itself, e.g. the auto-generated rewrite code] // // Note that we don't look for GOTO statements here, so it's possible // we'll get the wrong result for a loop with complicated control // jumps via gotos. func hasTopLevelLoopBodyReturnOrBreak(loopBody ir.Nodes) bool { … } // containingAssignment returns the top-level assignment statement // for a statement level function call "n". Examples: // // x := foo() // x, y := bar(z, baz()) // if blah() { ... // // Here the top-level assignment statement for the foo() call is the // statement assigning to "x"; the top-level assignment for "bar()" // call is the assignment to x,y. For the baz() and blah() calls, // there is no top level assignment statement. // // The unstated goal here is that we want to use the containing // assignment to establish a connection between a given call and the // variables to which its results/returns are being assigned. // // Note that for the "bar" command above, the front end sometimes // decomposes this into two assignments, the first one assigning the // call to a pair of auto-temps, then the second one assigning the // auto-temps to the user-visible vars. This helper will return the // second (outer) of these two. func (cstb *callSiteTableBuilder) containingAssignment(n ir.Node) ir.Node { … } // UpdateCallsiteTable handles updating of callerfn's call site table // after an inlined has been carried out, e.g. the call at 'n' as been // turned into the inlined call expression 'ic' within function // callerfn. The chief thing of interest here is to make sure that any // call nodes within 'ic' are added to the call site table for // 'callerfn' and scored appropriately. func UpdateCallsiteTable(callerfn *ir.Func, n *ir.CallExpr, ic *ir.InlinedCallExpr) { … }