aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-01-12 11:38:32 -0800
committerMatthew Dempsky <mdempsky@google.com>2021-01-12 23:22:04 +0000
commitcc90e7a51e15659ea1a1eb53ca08361b6a77696a (patch)
tree2103231742aab67a2be2351ee0f4d8189ada3abe /src
parentcd5b74d2dfe6009d55c86e90f6c204e58c229c16 (diff)
downloadgo-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>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/base/debug.go1
-rw-r--r--src/cmd/compile/internal/gc/compile.go87
-rw-r--r--src/cmd/compile/internal/gc/main.go5
-rw-r--r--src/cmd/compile/internal/gc/obj.go5
-rw-r--r--src/cmd/compile/internal/liveness/plive.go1
5 files changed, 27 insertions, 72 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)