Skip to content

Commit cc90e7a

Browse files
committed
[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 <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Matthew Dempsky <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent cd5b74d commit cc90e7a

File tree

6 files changed

+28
-73
lines changed

6 files changed

+28
-73
lines changed

src/cmd/compile/internal/base/debug.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ type DebugFlags struct {
3232
Append int `help:"print information about append compilation"`
3333
Checkptr int `help:"instrument unsafe pointer conversions"`
3434
Closure int `help:"print information about closure compilation"`
35-
CompileLater int `help:"compile functions as late as possible"`
3635
DclStack int `help:"run internal dclstack check"`
3736
Defer int `help:"print information about defer compilation"`
3837
DisableNil int `help:"disable nil checks"`

src/cmd/compile/internal/gc/compile.go

Lines changed: 22 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -26,57 +26,49 @@ var (
2626
compilequeue []*ir.Func // functions waiting to be compiled
2727
)
2828

29-
func funccompile(fn *ir.Func) {
29+
func enqueueFunc(fn *ir.Func) {
3030
if ir.CurFunc != nil {
31-
base.Fatalf("funccompile %v inside %v", fn.Sym(), ir.CurFunc.Sym())
31+
base.FatalfAt(fn.Pos(), "enqueueFunc %v inside %v", fn, ir.CurFunc)
3232
}
3333

34-
if fn.Type() == nil {
35-
if base.Errors() == 0 {
36-
base.Fatalf("funccompile missing type")
37-
}
34+
if ir.FuncName(fn) == "_" {
35+
// Skip compiling blank functions.
36+
// Frontend already reported any spec-mandated errors (#29870).
3837
return
3938
}
4039

41-
// assign parameter offsets
42-
types.CalcSize(fn.Type())
43-
4440
if len(fn.Body) == 0 {
4541
// Initialize ABI wrappers if necessary.
4642
ssagen.InitLSym(fn, false)
4743
liveness.WriteFuncMap(fn)
4844
return
4945
}
5046

51-
typecheck.DeclContext = ir.PAUTO
52-
ir.CurFunc = fn
53-
compile(fn)
54-
ir.CurFunc = nil
55-
typecheck.DeclContext = ir.PEXTERN
47+
errorsBefore := base.Errors()
48+
prepareFunc(fn)
49+
if base.Errors() > errorsBefore {
50+
return
51+
}
52+
53+
compilequeue = append(compilequeue, fn)
5654
}
5755

58-
func compile(fn *ir.Func) {
56+
// prepareFunc handles any remaining frontend compilation tasks that
57+
// aren't yet safe to perform concurrently.
58+
func prepareFunc(fn *ir.Func) {
5959
// Set up the function's LSym early to avoid data races with the assemblers.
6060
// Do this before walk, as walk needs the LSym to set attributes/relocations
6161
// (e.g. in markTypeUsedInInterface).
6262
ssagen.InitLSym(fn, true)
6363

64-
errorsBefore := base.Errors()
65-
walk.Walk(fn)
66-
if base.Errors() > errorsBefore {
67-
return
68-
}
69-
70-
// From this point, there should be no uses of Curfn. Enforce that.
71-
ir.CurFunc = nil
64+
// Calculate parameter offsets.
65+
types.CalcSize(fn.Type())
7266

73-
if ir.FuncName(fn) == "_" {
74-
// We don't need to generate code for this function, just report errors in its body.
75-
// At this point we've generated any errors needed.
76-
// (Beyond here we generate only non-spec errors, like "stack frame too large".)
77-
// See issue 29870.
78-
return
79-
}
67+
typecheck.DeclContext = ir.PAUTO
68+
ir.CurFunc = fn
69+
walk.Walk(fn)
70+
ir.CurFunc = nil // enforce no further uses of CurFunc
71+
typecheck.DeclContext = ir.PEXTERN
8072

8173
// Make sure type syms are declared for all types that might
8274
// be types of stack objects. We need to do this here
@@ -95,28 +87,6 @@ func compile(fn *ir.Func) {
9587
}
9688
}
9789
}
98-
99-
if compilenow(fn) {
100-
ssagen.Compile(fn, 0)
101-
} else {
102-
compilequeue = append(compilequeue, fn)
103-
}
104-
}
105-
106-
// compilenow reports whether to compile immediately.
107-
// If functions are not compiled immediately,
108-
// they are enqueued in compilequeue,
109-
// which is drained by compileFunctions.
110-
func compilenow(fn *ir.Func) bool {
111-
// Issue 38068: if this function is a method AND an inline
112-
// candidate AND was not inlined (yet), put it onto the compile
113-
// queue instead of compiling it immediately. This is in case we
114-
// wind up inlining it into a method wrapper that is generated by
115-
// compiling a function later on in the Target.Decls list.
116-
if ir.IsMethod(fn) && isInlinableButNotInlined(fn) {
117-
return false
118-
}
119-
return base.Flag.LowerC == 1 && base.Debug.CompileLater == 0
12090
}
12191

12292
// compileFunctions compiles all functions in compilequeue.
@@ -163,16 +133,3 @@ func compileFunctions() {
163133
types.CalcSizeDisabled = false
164134
}
165135
}
166-
167-
// isInlinableButNotInlined returns true if 'fn' was marked as an
168-
// inline candidate but then never inlined (presumably because we
169-
// found no call sites).
170-
func isInlinableButNotInlined(fn *ir.Func) bool {
171-
if fn.Inl == nil {
172-
return false
173-
}
174-
if fn.Sym() == nil {
175-
return true
176-
}
177-
return !fn.Linksym().WasInlined()
178-
}

src/cmd/compile/internal/gc/main.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,8 @@ func Main(archInit func(*ssagen.ArchInfo)) {
300300
base.Timer.Start("be", "compilefuncs")
301301
fcount := int64(0)
302302
for i := 0; i < len(typecheck.Target.Decls); i++ {
303-
n := typecheck.Target.Decls[i]
304-
if n.Op() == ir.ODCLFUNC {
305-
funccompile(n.(*ir.Func))
303+
if fn, ok := typecheck.Target.Decls[i].(*ir.Func); ok {
304+
enqueueFunc(fn)
306305
fcount++
307306
}
308307
}

src/cmd/compile/internal/gc/obj.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,8 @@ func dumpdata() {
131131
// It was not until issue 24761 that we found any code that required a loop at all.
132132
for {
133133
for i := numDecls; i < len(typecheck.Target.Decls); i++ {
134-
n := typecheck.Target.Decls[i]
135-
if n.Op() == ir.ODCLFUNC {
136-
funccompile(n.(*ir.Func))
134+
if n, ok := typecheck.Target.Decls[i].(*ir.Func); ok {
135+
enqueueFunc(n)
137136
}
138137
}
139138
numDecls = len(typecheck.Target.Decls)

src/cmd/compile/internal/liveness/plive.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,7 @@ func WriteFuncMap(fn *ir.Func) {
12231223
if ir.FuncName(fn) == "_" || fn.Sym().Linkname != "" {
12241224
return
12251225
}
1226+
types.CalcSize(fn.Type())
12261227
lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap")
12271228
nptr := int(fn.Type().ArgWidth() / int64(types.PtrSize))
12281229
bv := bitvec.New(int32(nptr) * 2)

test/fixedbugs/issue20250.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// errorcheck -0 -live -l -d=compilelater
1+
// errorcheck -0 -live -l
22

33
// Copyright 2017 The Go Authors. All rights reserved.
44
// Use of this source code is governed by a BSD-style

0 commit comments

Comments
 (0)