diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-01-12 11:38:32 -0800 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-01-12 23:22:04 +0000 |
commit | cc90e7a51e15659ea1a1eb53ca08361b6a77696a (patch) | |
tree | 2103231742aab67a2be2351ee0f4d8189ada3abe | |
parent | cd5b74d2dfe6009d55c86e90f6c204e58c229c16 (diff) | |
download | go-cc90e7a51e15659ea1a1eb53ca08361b6a77696a.tar.gz go-cc90e7a51e15659ea1a1eb53ca08361b6a77696a.zip |
[dev.regabi] cmd/compile: always use the compile queue
The compiler currently has two modes for compilation: one where it
compiles each function as it sees them, and another where it enqueues
them all into a work queue. A subsequent CL is going to reorder
function compilation to ensure that functions are always compiled
before any non-trivial function literals they enclose, and this will
be easier if we always use the compile work queue.
Also, fewer compilation modes makes things simpler to reason about.
Change-Id: Ie090e81f7476c49486296f2b90911fa0a466a5dd
Reviewed-on: https://go-review.googlesource.com/c/go/+/283313
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
-rw-r--r-- | src/cmd/compile/internal/base/debug.go | 1 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/compile.go | 87 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/main.go | 5 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/obj.go | 5 | ||||
-rw-r--r-- | src/cmd/compile/internal/liveness/plive.go | 1 | ||||
-rw-r--r-- | test/fixedbugs/issue20250.go | 2 |
6 files changed, 28 insertions, 73 deletions
diff --git a/src/cmd/compile/internal/base/debug.go b/src/cmd/compile/internal/base/debug.go index 3acdcea846..164941bb26 100644 --- a/src/cmd/compile/internal/base/debug.go +++ b/src/cmd/compile/internal/base/debug.go @@ -32,7 +32,6 @@ type DebugFlags struct { Append int `help:"print information about append compilation"` Checkptr int `help:"instrument unsafe pointer conversions"` Closure int `help:"print information about closure compilation"` - CompileLater int `help:"compile functions as late as possible"` DclStack int `help:"run internal dclstack check"` Defer int `help:"print information about defer compilation"` DisableNil int `help:"disable nil checks"` diff --git a/src/cmd/compile/internal/gc/compile.go b/src/cmd/compile/internal/gc/compile.go index 25b1c76737..b9c10056b4 100644 --- a/src/cmd/compile/internal/gc/compile.go +++ b/src/cmd/compile/internal/gc/compile.go @@ -26,21 +26,17 @@ var ( compilequeue []*ir.Func // functions waiting to be compiled ) -func funccompile(fn *ir.Func) { +func enqueueFunc(fn *ir.Func) { if ir.CurFunc != nil { - base.Fatalf("funccompile %v inside %v", fn.Sym(), ir.CurFunc.Sym()) + base.FatalfAt(fn.Pos(), "enqueueFunc %v inside %v", fn, ir.CurFunc) } - if fn.Type() == nil { - if base.Errors() == 0 { - base.Fatalf("funccompile missing type") - } + if ir.FuncName(fn) == "_" { + // Skip compiling blank functions. + // Frontend already reported any spec-mandated errors (#29870). return } - // assign parameter offsets - types.CalcSize(fn.Type()) - if len(fn.Body) == 0 { // Initialize ABI wrappers if necessary. ssagen.InitLSym(fn, false) @@ -48,35 +44,31 @@ func funccompile(fn *ir.Func) { return } - typecheck.DeclContext = ir.PAUTO - ir.CurFunc = fn - compile(fn) - ir.CurFunc = nil - typecheck.DeclContext = ir.PEXTERN + errorsBefore := base.Errors() + prepareFunc(fn) + if base.Errors() > errorsBefore { + return + } + + compilequeue = append(compilequeue, fn) } -func compile(fn *ir.Func) { +// prepareFunc handles any remaining frontend compilation tasks that +// aren't yet safe to perform concurrently. +func prepareFunc(fn *ir.Func) { // Set up the function's LSym early to avoid data races with the assemblers. // Do this before walk, as walk needs the LSym to set attributes/relocations // (e.g. in markTypeUsedInInterface). ssagen.InitLSym(fn, true) - errorsBefore := base.Errors() - walk.Walk(fn) - if base.Errors() > errorsBefore { - return - } - - // From this point, there should be no uses of Curfn. Enforce that. - ir.CurFunc = nil + // Calculate parameter offsets. + types.CalcSize(fn.Type()) - if ir.FuncName(fn) == "_" { - // We don't need to generate code for this function, just report errors in its body. - // At this point we've generated any errors needed. - // (Beyond here we generate only non-spec errors, like "stack frame too large".) - // See issue 29870. - return - } + typecheck.DeclContext = ir.PAUTO + ir.CurFunc = fn + walk.Walk(fn) + ir.CurFunc = nil // enforce no further uses of CurFunc + typecheck.DeclContext = ir.PEXTERN // Make sure type syms are declared for all types that might // be types of stack objects. We need to do this here @@ -95,28 +87,6 @@ func compile(fn *ir.Func) { } } } - - if compilenow(fn) { - ssagen.Compile(fn, 0) - } else { - compilequeue = append(compilequeue, fn) - } -} - -// compilenow reports whether to compile immediately. -// If functions are not compiled immediately, -// they are enqueued in compilequeue, -// which is drained by compileFunctions. -func compilenow(fn *ir.Func) bool { - // Issue 38068: if this function is a method AND an inline - // candidate AND was not inlined (yet), put it onto the compile - // queue instead of compiling it immediately. This is in case we - // wind up inlining it into a method wrapper that is generated by - // compiling a function later on in the Target.Decls list. - if ir.IsMethod(fn) && isInlinableButNotInlined(fn) { - return false - } - return base.Flag.LowerC == 1 && base.Debug.CompileLater == 0 } // compileFunctions compiles all functions in compilequeue. @@ -163,16 +133,3 @@ func compileFunctions() { types.CalcSizeDisabled = false } } - -// isInlinableButNotInlined returns true if 'fn' was marked as an -// inline candidate but then never inlined (presumably because we -// found no call sites). -func isInlinableButNotInlined(fn *ir.Func) bool { - if fn.Inl == nil { - return false - } - if fn.Sym() == nil { - return true - } - return !fn.Linksym().WasInlined() -} diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 1541bc4285..2903d64ff8 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -300,9 +300,8 @@ func Main(archInit func(*ssagen.ArchInfo)) { base.Timer.Start("be", "compilefuncs") fcount := int64(0) for i := 0; i < len(typecheck.Target.Decls); i++ { - n := typecheck.Target.Decls[i] - if n.Op() == ir.ODCLFUNC { - funccompile(n.(*ir.Func)) + if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok { + enqueueFunc(fn) fcount++ } } diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index fbb2145e1b..753db80f76 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -131,9 +131,8 @@ func dumpdata() { // 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.Decls); i++ { - n := typecheck.Target.Decls[i] - if n.Op() == ir.ODCLFUNC { - funccompile(n.(*ir.Func)) + if n, ok := typecheck.Target.Decls[i].(*ir.Func); ok { + enqueueFunc(n) } } numDecls = len(typecheck.Target.Decls) diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index 26d90824b2..8d1754c813 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -1223,6 +1223,7 @@ func WriteFuncMap(fn *ir.Func) { if ir.FuncName(fn) == "_" || fn.Sym().Linkname != "" { return } + types.CalcSize(fn.Type()) lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap") nptr := int(fn.Type().ArgWidth() / int64(types.PtrSize)) bv := bitvec.New(int32(nptr) * 2) diff --git a/test/fixedbugs/issue20250.go b/test/fixedbugs/issue20250.go index c190515274..1a513bea56 100644 --- a/test/fixedbugs/issue20250.go +++ b/test/fixedbugs/issue20250.go @@ -1,4 +1,4 @@ -// errorcheck -0 -live -l -d=compilelater +// errorcheck -0 -live -l // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style |