cmd/compile: call fninit earlier

This allows the global initializers function to go through normal
mid-end optimizations (e.g., inlining, escape analysis) like any other
function.

Updates #33485.

Change-Id: I9bcfe98b8628d1aca09b4c238d8d3b74c69010a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/254839
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2020-09-14 12:56:37 -07:00
parent 237410547b
commit f4936d09fd
3 changed files with 6 additions and 10 deletions

View file

@ -59,7 +59,7 @@ func fninit(n []*Node) {
Curfn = fn Curfn = fn
typecheckslice(nf, ctxStmt) typecheckslice(nf, ctxStmt)
Curfn = nil Curfn = nil
funccompile(fn) xtop = append(xtop, fn)
fns = append(fns, initializers.Linksym()) fns = append(fns, initializers.Linksym())
} }
if dummyInitFn.Func.Dcl != nil { if dummyInitFn.Func.Dcl != nil {
@ -68,16 +68,14 @@ func fninit(n []*Node) {
// something's weird if we get here. // something's weird if we get here.
Fatalf("dummyInitFn still has declarations") Fatalf("dummyInitFn still has declarations")
} }
dummyInitFn = nil
// Record user init functions. // Record user init functions.
for i := 0; i < renameinitgen; i++ { for i := 0; i < renameinitgen; i++ {
s := lookupN("init.", i) s := lookupN("init.", i)
fn := asNode(s.Def).Name.Defn fn := asNode(s.Def).Name.Defn
// Skip init functions with empty bodies. // Skip init functions with empty bodies.
// noder.go doesn't allow external init functions, and if fn.Nbody.Len() == 1 && fn.Nbody.First().Op == OEMPTY {
// order.go has already removed any OEMPTY nodes, so
// checking Len() == 0 is sufficient here.
if fn.Nbody.Len() == 0 {
continue continue
} }
fns = append(fns, s.Linksym()) fns = append(fns, s.Linksym())

View file

@ -642,6 +642,8 @@ func Main(archInit func(*Arch)) {
errorexit() errorexit()
} }
fninit(xtop)
// Phase 4: Decide how to capture closed variables. // Phase 4: Decide how to capture closed variables.
// This needs to run before escape analysis, // This needs to run before escape analysis,
// because variables captured by value do not escape. // because variables captured by value do not escape.
@ -751,10 +753,6 @@ func Main(archInit func(*Arch)) {
} }
timings.AddEvent(fcount, "funcs") timings.AddEvent(fcount, "funcs")
if nsavederrors+nerrors == 0 {
fninit(xtop)
}
compileFunctions() compileFunctions()
if nowritebarrierrecCheck != nil { if nowritebarrierrecCheck != nil {

View file

@ -50,7 +50,7 @@ func j(x int) int { // ERROR "can inline j"
} }
} }
var somethingWrong error = errors.New("something went wrong") var somethingWrong error = errors.New("something went wrong") // ERROR "can inline init" "inlining call to errors.New" "errors.errorString.* escapes to heap"
// local closures can be inlined // local closures can be inlined
func l(x, y int) (int, int, error) { func l(x, y int) (int, int, error) {