mirror of
https://github.com/golang/go
synced 2024-11-23 13:00:07 -07:00
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>
This commit is contained in:
parent
96b6e78ea9
commit
cf68384674
@ -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))
|
||||
|
@ -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.
|
||||
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++
|
||||
}
|
||||
base.Timer.AddEvent(fcount, "funcs")
|
||||
reflectdata.WriteBasicTypes()
|
||||
|
||||
compileFunctions()
|
||||
// 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")
|
||||
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(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()
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
27
src/cmd/go/testdata/script/build_issue62156.txt
vendored
Normal file
27
src/cmd/go/testdata/script/build_issue62156.txt
vendored
Normal file
@ -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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user