From 88cb17e1069bef854ead49c703262abdf93c9458 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 24 Aug 2023 03:04:01 -0700 Subject: cmd/compile: create "init" function during noding This CL arranges for package-scope initialization statements to be constructed directly into their eventual "init" function, so we can eliminate the roundabout solution of using InitTodoFunc. While here, somewhat simplify and generalize the logic for outlining map initialization statements. Change-Id: I8aff042e6b266f7024de436424ec6711b8b69129 Reviewed-on: https://go-review.googlesource.com/c/go/+/522318 Run-TryBot: Matthew Dempsky Reviewed-by: Than McIntosh Reviewed-by: Cuong Manh Le Auto-Submit: Matthew Dempsky TryBot-Result: Gopher Robot --- src/cmd/compile/internal/noder/reader.go | 77 ++++++++++++++------------------ src/cmd/compile/internal/noder/writer.go | 9 +++- 2 files changed, 41 insertions(+), 45 deletions(-) (limited to 'src/cmd/compile/internal/noder') diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 0efe2ea2d5..01f001f199 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -2988,52 +2988,12 @@ func (r *reader) multiExpr() []ir.Node { // temp returns a new autotemp of the specified type. func (r *reader) temp(pos src.XPos, typ *types.Type) *ir.Name { - // See typecheck.typecheckargs. - curfn := r.curfn - if curfn == nil { - curfn = typecheck.InitTodoFunc - } - - return typecheck.TempAt(pos, curfn, typ) + return typecheck.TempAt(pos, r.curfn, typ) } // tempCopy declares and returns a new autotemp initialized to the // value of expr. func (r *reader) tempCopy(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name { - if r.curfn == nil { - // Escape analysis doesn't know how to handle package-scope - // function literals with free variables (i.e., that capture - // temporary variables added to typecheck.InitTodoFunc). - // - // stencil.go works around this limitation by spilling values to - // global variables instead, but that causes the value to stay - // alive indefinitely; see go.dev/issue/54343. - // - // This code path (which implements the same workaround) isn't - // actually needed by unified IR, because it creates uses normal - // OMETHEXPR/OMETHVALUE nodes when statically-known instantiated - // types are used. But it's kept around for now because it's handy - // for testing that the generic fallback paths work correctly. - base.Fatalf("tempCopy called at package scope") - - tmp := staticinit.StaticName(expr.Type()) - - assign := ir.NewAssignStmt(pos, tmp, expr) - assign.Def = true - tmp.Defn = assign - - // TODO(mdempsky): This code doesn't work anymore, because we now - // rely on types2 to compute InitOrder. If it's going to be used - // for testing again, the assignment here probably needs to be - // added to typecheck.Target.InitOrder somewhere. - // - // Probably just easier to address the escape analysis limitation. - // - // typecheck.Target.Decls = append(typecheck.Target.Decls, typecheck.Stmt(assign)) - - return tmp - } - tmp := r.temp(pos, expr.Type()) init.Append(typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp))) @@ -3328,9 +3288,32 @@ func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) { } target.CgoPragmas = cgoPragmas + r.pkgInitOrder(target) + r.pkgDecls(target) + r.Sync(pkgbits.SyncEOF) +} + +// pkgInitOrder creates a synthetic init function to handle any +// package-scope initialization statements. +func (r *reader) pkgInitOrder(target *ir.Package) { initOrder := make([]ir.Node, r.Len()) + if len(initOrder) == 0 { + return + } + + // Make a function that contains all the initialization statements. + pos := base.AutogeneratedPos + base.Pos = pos + + fn := ir.NewFunc(pos, pos, typecheck.Lookup("init"), types.NewSignature(nil, nil, nil)) + fn.SetIsPackageInit(true) + fn.SetInlinabilityChecked(true) // suppress useless "can inline" diagnostics + + typecheck.DeclFunc(fn) + r.curfn = fn + for i := range initOrder { lhs := make([]ir.Node, r.Len()) for j := range lhs { @@ -3352,9 +3335,17 @@ func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) { initOrder[i] = as } - target.InitOrder = initOrder - r.Sync(pkgbits.SyncEOF) + fn.Body = initOrder + + typecheck.FinishFuncBody() + r.curfn = nil + r.locals = nil + + // Outline (if legal/profitable) global map inits. + staticinit.OutlineMapInits(fn) + + target.Inits = append(target.Inits, fn) } func (r *reader) pkgDecls(target *ir.Package) { diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 10cf46f3f2..5982e714a3 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -2597,6 +2597,8 @@ func (w *writer) pkgInit(noders []*noder) { w.Strings(cgoPragma) } + w.pkgInitOrder() + w.Sync(pkgbits.SyncDecls) for _, p := range noders { for _, decl := range p.file.DeclList { @@ -2605,6 +2607,11 @@ func (w *writer) pkgInit(noders []*noder) { } w.Code(declEnd) + w.Sync(pkgbits.SyncEOF) +} + +func (w *writer) pkgInitOrder() { + // TODO(mdempsky): Write as a function body instead? w.Len(len(w.p.info.InitOrder)) for _, init := range w.p.info.InitOrder { w.Len(len(init.Lhs)) @@ -2613,8 +2620,6 @@ func (w *writer) pkgInit(noders []*noder) { } w.expr(init.Rhs) } - - w.Sync(pkgbits.SyncEOF) } func (w *writer) pkgDecl(decl syntax.Decl) { -- cgit v1.3