aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2023-08-18 00:32:11 -0700
committerGopher Robot <gobot@golang.org>2023-08-24 23:18:16 +0000
commitcf6838467453be54d1c6b45f431db35cf95b1eee (patch)
tree983abd5af5a5e1d9789f27346a062fb7f460429f /src
parent96b6e78ea906001a31d03d0acbfc4a4f20eb7db9 (diff)
downloadgo-cf6838467453be54d1c6b45f431db35cf95b1eee.tar.xz
cmd/compile/internal/gc: steps towards work-queue
[This is a reattempt of go.dev/cl/520611.] This CL reorganizes the top-level functions for handling package-level declarations, runtime type descriptors, and SSA compilation to work in a loop. This generalizes the loop that previously existed in dumpdata. Change-Id: I7502798a8662b3cec92d3001169f3af4f804df2a Reviewed-on: https://go-review.googlesource.com/c/go/+/522339 Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/gc/compile.go4
-rw-r--r--src/cmd/compile/internal/gc/main.go72
-rw-r--r--src/cmd/compile/internal/gc/obj.go51
-rw-r--r--src/cmd/compile/internal/reflectdata/reflect.go2
-rw-r--r--src/cmd/go/testdata/script/build_issue62156.txt27
5 files changed, 84 insertions, 72 deletions
diff --git a/src/cmd/compile/internal/gc/compile.go b/src/cmd/compile/internal/gc/compile.go
index 27d9c55fdb..0f57f8ca82 100644
--- a/src/cmd/compile/internal/gc/compile.go
+++ b/src/cmd/compile/internal/gc/compile.go
@@ -113,10 +113,6 @@ func prepareFunc(fn *ir.Func) {
// It fans out nBackendWorkers to do the work
// and waits for them to complete.
func compileFunctions() {
- if len(compilequeue) == 0 {
- return
- }
-
if race.Enabled {
// Randomize compilation order to try to shake out races.
tmp := make([]*ir.Func, len(compilequeue))
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 05f0340d39..1314a207de 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -19,6 +19,7 @@ import (
"cmd/compile/internal/noder"
"cmd/compile/internal/pgo"
"cmd/compile/internal/pkginit"
+ "cmd/compile/internal/reflectdata"
"cmd/compile/internal/ssa"
"cmd/compile/internal/ssagen"
"cmd/compile/internal/staticinit"
@@ -295,18 +296,62 @@ func Main(archInit func(*ssagen.ArchInfo)) {
ir.CurFunc = nil
- // Compile top level functions.
- // Don't use range--walk can add functions to Target.Decls.
+ reflectdata.WriteBasicTypes()
+
+ // Compile top-level declarations.
+ //
+ // There are cyclic dependencies between all of these phases, so we
+ // need to iterate all of them until we reach a fixed point.
base.Timer.Start("be", "compilefuncs")
- fcount := int64(0)
- for i := 0; i < len(typecheck.Target.Funcs); i++ {
- fn := typecheck.Target.Funcs[i]
- enqueueFunc(fn)
- fcount++
+ for nextFunc, nextExtern := 0, 0; ; {
+ reflectdata.WriteRuntimeTypes()
+
+ if nextExtern < len(typecheck.Target.Externs) {
+ switch n := typecheck.Target.Externs[nextExtern]; n.Op() {
+ case ir.ONAME:
+ dumpGlobal(n)
+ case ir.OLITERAL:
+ dumpGlobalConst(n)
+ case ir.OTYPE:
+ reflectdata.NeedRuntimeType(n.Type())
+ }
+ nextExtern++
+ continue
+ }
+
+ if nextFunc < len(typecheck.Target.Funcs) {
+ enqueueFunc(typecheck.Target.Funcs[nextFunc])
+ nextFunc++
+ continue
+ }
+
+ // The SSA backend supports using multiple goroutines, so keep it
+ // as late as possible to maximize how much work we can batch and
+ // process concurrently.
+ if len(compilequeue) != 0 {
+ compileFunctions()
+ continue
+ }
+
+ // Finalize DWARF inline routine DIEs, then explicitly turn off
+ // further DWARF inlining generation to avoid problems with
+ // generated method wrappers.
+ //
+ // Note: The DWARF fixup code for inlined calls currently doesn't
+ // allow multiple invocations, so we intentionally run it just
+ // once after everything else. Worst case, some generated
+ // functions have slightly larger DWARF DIEs.
+ if base.Ctxt.DwFixups != nil {
+ base.Ctxt.DwFixups.Finalize(base.Ctxt.Pkgpath, base.Debug.DwarfInl != 0)
+ base.Ctxt.DwFixups = nil
+ base.Flag.GenDwarfInl = 0
+ continue // may have called reflectdata.TypeLinksym (#62156)
+ }
+
+ break
}
- base.Timer.AddEvent(fcount, "funcs")
- compileFunctions()
+ base.Timer.AddEvent(int64(len(typecheck.Target.Funcs)), "funcs")
if base.Flag.CompilingRuntime {
// Write barriers are now known. Check the call graph.
@@ -318,15 +363,6 @@ func Main(archInit func(*ssagen.ArchInfo)) {
staticinit.AddKeepRelocations()
}
- // Finalize DWARF inline routine DIEs, then explicitly turn off
- // DWARF inlining gen so as to avoid problems with generated
- // method wrappers.
- if base.Ctxt.DwFixups != nil {
- base.Ctxt.DwFixups.Finalize(base.Ctxt.Pkgpath, base.Debug.DwarfInl != 0)
- base.Ctxt.DwFixups = nil
- base.Flag.GenDwarfInl = 0
- }
-
// Write object data to disk.
base.Timer.Start("be", "dumpobj")
dumpdata()
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index 4ff249ca2e..249eeb221d 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -110,39 +110,11 @@ func dumpCompilerObj(bout *bio.Writer) {
}
func dumpdata() {
- numExterns := len(typecheck.Target.Externs)
- numDecls := len(typecheck.Target.Funcs)
- dumpglobls(typecheck.Target.Externs)
- addsignats(typecheck.Target.Externs)
- reflectdata.WriteRuntimeTypes()
+ reflectdata.WriteGCSymbols()
reflectdata.WritePluginTable()
reflectdata.WriteImportStrings()
- reflectdata.WriteBasicTypes()
dumpembeds()
- // Calls to WriteRuntimeTypes can generate functions,
- // like method wrappers and hash and equality routines.
- // Compile any generated functions, process any new resulting types, repeat.
- // This can't loop forever, because there is no way to generate an infinite
- // number of types in a finite amount of code.
- // In the typical case, we loop 0 or 1 times.
- // It was not until issue 24761 that we found any code that required a loop at all.
- for {
- for i := numDecls; i < len(typecheck.Target.Funcs); i++ {
- fn := typecheck.Target.Funcs[i]
- enqueueFunc(fn)
- }
- numDecls = len(typecheck.Target.Funcs)
- compileFunctions()
- reflectdata.WriteRuntimeTypes()
- if numDecls == len(typecheck.Target.Funcs) {
- break
- }
- }
-
- // Dump extra globals.
- dumpglobls(typecheck.Target.Externs[numExterns:])
-
if reflectdata.ZeroSize > 0 {
zero := base.PkgLinksym("go:map", "zero", obj.ABI0)
objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA)
@@ -217,18 +189,6 @@ func dumpGlobalConst(n *ir.Name) {
base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, types.TypeSymName(t), ir.IntVal(t, v))
}
-func dumpglobls(externs []*ir.Name) {
- // add globals
- for _, n := range externs {
- switch n.Op() {
- case ir.ONAME:
- dumpGlobal(n)
- case ir.OLITERAL:
- dumpGlobalConst(n)
- }
- }
-}
-
// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.
//
// This is done during the sequential phase after compilation, since
@@ -323,12 +283,3 @@ func dumpembeds() {
staticdata.WriteEmbed(v)
}
}
-
-func addsignats(dcls []*ir.Name) {
- // copy types from dcl list to signatset
- for _, n := range dcls {
- if n.Op() == ir.OTYPE {
- reflectdata.NeedRuntimeType(n.Type())
- }
- }
-}
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index 1bf7c8dc73..223ba1b7ba 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -1266,7 +1266,9 @@ func WriteRuntimeTypes() {
}
signatslice = signatslice[len(signats):]
}
+}
+func WriteGCSymbols() {
// Emit GC data symbols.
gcsyms := make([]typeAndStr, 0, len(gcsymset))
for t := range gcsymset {
diff --git a/src/cmd/go/testdata/script/build_issue62156.txt b/src/cmd/go/testdata/script/build_issue62156.txt
new file mode 100644
index 0000000000..d241570cf6
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_issue62156.txt
@@ -0,0 +1,27 @@
+# Regression test for https://go.dev/issue/62156:
+# DWARF generation for inlined functions may require more runtime type
+# descriptors to be written.
+
+go build
+
+-- go.mod --
+module m
+
+go 1.20
+-- main.go --
+package main
+
+import "m/sub"
+
+func main() { sub.F() }
+-- sub/sub.go --
+package sub
+
+type iface interface{ m() }
+
+func F() {
+ f := func(rt []iface) []iface {
+ return append([]iface{}, rt...)
+ }
+ f(nil)
+}