Currently, we rely on a "crawling" step during export to identify
function and method bodies that need to be exported or re-exported so
we can trim out unnecessary ones and reduce build artifact sizes. To
catch cases where we expect a function to be inlinable but we failed
to export its body, we made this condition a fatal compiler error.
However, with generics, it's much harder to perfectly identify all
function bodies that need to be exported; and several attempts at
tweaking the algorithm have resulted in still having failure cases.
So for now, this CL changes a missing inline body into a graceful
failure instead.
Change-Id: I04b0872d0dcaae9c3de473e92ce584e4ec6fd782
Reviewed-on: https://go-review.googlesource.com/c/go/+/361403
Trust: Matthew Dempsky <mdempsky@google.com>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Dan Scales <danscales@google.com>
break
}
- if fn := inlCallee(n.X); fn != nil && fn.Inl != nil {
+ if fn := inlCallee(n.X); fn != nil && typecheck.HaveInlineBody(fn) {
v.budget -= fn.Inl.Cost
break
}
if ir.IsIntrinsicCall(call) {
break
}
- if fn := inlCallee(call.X); fn != nil && fn.Inl != nil {
+ if fn := inlCallee(call.X); fn != nil && typecheck.HaveInlineBody(fn) {
n = mkinlcall(call, fn, maxCost, inlMap, edit)
}
}
if fn == nil {
base.Fatalf("markInlBody: missing Func on %v", n)
}
- if fn.Inl == nil {
+ if !HaveInlineBody(fn) {
return
}
inimport = false
}
+// HaveInlineBody reports whether we have fn's inline body available
+// for inlining.
+func HaveInlineBody(fn *ir.Func) bool {
+ if fn.Inl == nil {
+ return false
+ }
+
+ // Unified IR is much more conservative about pruning unreachable
+ // methods (at the cost of increased build artifact size).
+ if base.Debug.Unified != 0 {
+ return true
+ }
+
+ if fn.Inl.Body != nil {
+ return true
+ }
+
+ _, ok := inlineImporter[fn.Nname.Sym()]
+ return ok
+}
+
func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader {
x, ok := importers[sym]
if !ok {