mirror of
https://github.com/golang/go
synced 2024-11-23 07:20:06 -07:00
cmd/compile: wrap defer/go call with results
CL 298669 implemented wrapping for defer/go calls so the function being called with defer or go statement has no arguments. This simplifies the compiler and the runtime, especially with the new ABI. Currently, it does not wrap functions that has no arguments but only results. For defer/go calls, the results are not used. But the runtime needs to allocate stack space for the callee to store the results. Wrapping functions with results makes the runtime simpler. TODO: maybe not wrap if all results are in registers. Updates #40724. Change-Id: I74d2f4db1cbf9979afbcd846facb30d11d72ab23 Reviewed-on: https://go-review.googlesource.com/c/go/+/305550 Trust: Cherry Zhang <cherryyz@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
e27f3966bb
commit
06ad41642c
@ -4608,8 +4608,8 @@ func (s *state) openDeferRecord(n *ir.CallExpr) {
|
||||
var args []*ssa.Value
|
||||
var argNodes []*ir.Name
|
||||
|
||||
if objabi.Experiment.RegabiDefer && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER) {
|
||||
s.Fatalf("defer call with arguments: %v", n)
|
||||
if objabi.Experiment.RegabiDefer && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0) {
|
||||
s.Fatalf("defer call with arguments or results: %v", n)
|
||||
}
|
||||
|
||||
opendefer := &openDeferInfo{
|
||||
@ -4860,7 +4860,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||
}
|
||||
}
|
||||
|
||||
if objabi.Experiment.RegabiDefer && k != callNormal && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER) {
|
||||
if objabi.Experiment.RegabiDefer && k != callNormal && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.X.Type().NumResults() != 0) {
|
||||
s.Fatalf("go/defer call with arguments: %v", n)
|
||||
}
|
||||
|
||||
|
@ -1504,7 +1504,7 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) {
|
||||
panic("unhandled op")
|
||||
}
|
||||
|
||||
// No need to wrap if called func has no args and no receiver.
|
||||
// No need to wrap if called func has no args, no receiver, and no results.
|
||||
// However in the case of "defer func() { ... }()" we need to
|
||||
// protect against the possibility of directClosureCall rewriting
|
||||
// things so that the call does have arguments.
|
||||
@ -1514,7 +1514,10 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) {
|
||||
//
|
||||
// Also do wrap builtin functions, because they may be expanded to
|
||||
// calls with arguments (e.g. ORECOVER).
|
||||
if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC {
|
||||
//
|
||||
// TODO: maybe not wrap if the called function has no arguments and
|
||||
// only in-register results?
|
||||
if len(callArgs) == 0 && call.Op() == ir.OCALLFUNC && callX.Type().NumResults() == 0 {
|
||||
if c, ok := call.(*ir.CallExpr); ok && callX != nil && callX.Op() == ir.OCLOSURE {
|
||||
cloFunc := callX.(*ir.ClosureExpr).Func
|
||||
cloFunc.SetClosureCalled(false)
|
||||
|
Loading…
Reference in New Issue
Block a user