ir.CurFunc = nil
- 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.
+ // Compile top level functions.
+ // Don't use range--walk can add functions to Target.Decls.
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 the last step to maximize how much work we can batch and
- // process concurrently.
- if len(compilequeue) != 0 {
- compileFunctions()
- continue
- }
-
- break
+ 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")
- base.Timer.AddEvent(int64(len(typecheck.Target.Funcs)), "funcs")
+ compileFunctions()
if base.Flag.CompilingRuntime {
// Write barriers are now known. Check the call graph.
}
func dumpdata() {
- reflectdata.WriteGCSymbols()
+ numExterns := len(typecheck.Target.Externs)
+ numDecls := len(typecheck.Target.Funcs)
+ dumpglobls(typecheck.Target.Externs)
+ addsignats(typecheck.Target.Externs)
+ reflectdata.WriteRuntimeTypes()
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)
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
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())
+ }
+ }
+}