diff options
Diffstat (limited to 'src/cmd/compile/internal/noder/reader.go')
| -rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 1dae4da167..ce4cc1cc4e 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -3971,14 +3971,23 @@ func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) { args[i] = param.Nname.(*ir.Name) } - // TODO(mdempsky): Support creating OTAILCALL, when possible. See reflectdata.methodWrapper. - // Not urgent though, because tail calls are currently incompatible with regabi anyway. - - fn.SetWrapper(true) // TODO(mdempsky): Leave unset for tail calls? - dot := typecheck.XDotMethod(pos, recv, method.Sym, true) call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr) + if recv.Type() != nil && recv.Type().IsPtr() && method.Type.Recv().Type.IsPtr() && + method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && + !unifiedHaveInlineBody(ir.MethodExprName(dot).Func) && + !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) { + if base.Debug.TailCall != 0 { + base.WarnfAt(fn.Nname.Type().Recv().Type.Elem().Pos(), "tail call emitted for the method %v wrapper", method.Nname) + } + // Prefer OTAILCALL to reduce code size (except the case when the called method can be inlined). + fn.Body.Append(ir.NewTailCallStmt(pos, call)) + return + } + + fn.SetWrapper(true) + if method.Type.NumResults() == 0 { fn.Body.Append(call) return |
