]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix outgoing calls with GOEXPERIMENT=regabiargs
authorAustin Clements <austin@google.com>
Wed, 31 Mar 2021 21:41:07 +0000 (17:41 -0400)
committerAustin Clements <austin@google.com>
Thu, 1 Apr 2021 00:51:24 +0000 (00:51 +0000)
The logic for constructing calls in (*state).call is based around
targeted experiments with register-based calls. However, when the
register ABI is turned on everywhere, it currently doesn't account for
direct calls to non-ABIInternal functions. This CL adds a much simpler
path to (*state).call when regabiargs is turned on that looks at the
ABI of the target function.

For #40724.

Change-Id: I7f4f5fed8a5ec131bcf1ce5b9d94d45672a304cb
Reviewed-on: https://go-review.googlesource.com/c/go/+/306410
Trust: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/ssagen/ssa.go

index aaea732057a106ff63b33b56b9b102dd91aab673..9c1c493233fc6011a2754eb402bd1a47d5a5a015 100644 (file)
@@ -4851,24 +4851,27 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
        var codeptr *ssa.Value // ptr to target code (if dynamic)
        var rcvr *ssa.Value    // receiver to set
        fn := n.X
-       var ACArgs []*types.Type       // AuxCall args
-       var ACResults []*types.Type    // AuxCall results
-       var callArgs []*ssa.Value      // For late-expansion, the args themselves (not stored, args to the call instead).
-       inRegistersForTesting := false // If a call uses register ABI for one of the testing reasons, pragma, magic types, magic names
+       var ACArgs []*types.Type    // AuxCall args
+       var ACResults []*types.Type // AuxCall results
+       var callArgs []*ssa.Value   // For late-expansion, the args themselves (not stored, args to the call instead).
 
-       var magicFnNameSym *types.Sym
-       if fn.Name() != nil {
-               magicFnNameSym = fn.Name().Sym()
-               ss := magicFnNameSym.Name
-               if strings.HasSuffix(ss, magicNameDotSuffix) {
-                       inRegistersForTesting = true
+       callABI := s.f.ABIDefault
+
+       if !objabi.Experiment.RegabiArgs {
+               var magicFnNameSym *types.Sym
+               if fn.Name() != nil {
+                       magicFnNameSym = fn.Name().Sym()
+                       ss := magicFnNameSym.Name
+                       if strings.HasSuffix(ss, magicNameDotSuffix) {
+                               callABI = s.f.ABI1
+                       }
                }
-       }
-       if magicFnNameSym == nil && n.Op() == ir.OCALLINTER {
-               magicFnNameSym = fn.(*ir.SelectorExpr).Sym()
-               ss := magicFnNameSym.Name
-               if strings.HasSuffix(ss, magicNameDotSuffix[1:]) {
-                       inRegistersForTesting = true
+               if magicFnNameSym == nil && n.Op() == ir.OCALLINTER {
+                       magicFnNameSym = fn.(*ir.SelectorExpr).Sym()
+                       ss := magicFnNameSym.Name
+                       if strings.HasSuffix(ss, magicNameDotSuffix[1:]) {
+                               callABI = s.f.ABI1
+                       }
                }
        }
 
@@ -4881,10 +4884,23 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
                if k == callNormal && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC {
                        fn := fn.(*ir.Name)
                        callee = fn
-                       // TODO(register args) remove after register abi is working
-                       inRegistersImported := fn.Pragma()&ir.RegisterParams != 0
-                       inRegistersSamePackage := fn.Func != nil && fn.Func.Pragma&ir.RegisterParams != 0
-                       inRegistersForTesting = inRegistersForTesting || inRegistersImported || inRegistersSamePackage
+                       if objabi.Experiment.RegabiArgs {
+                               // This is a static call, so it may be
+                               // a direct call to a non-ABIInternal
+                               // function. fn.Func may be nil for
+                               // some compiler-generated functions,
+                               // but those are all ABIInternal.
+                               if fn.Func != nil {
+                                       callABI = abiForFunc(fn.Func, s.f.ABI0, s.f.ABI1)
+                               }
+                       } else {
+                               // TODO(register args) remove after register abi is working
+                               inRegistersImported := fn.Pragma()&ir.RegisterParams != 0
+                               inRegistersSamePackage := fn.Func != nil && fn.Func.Pragma&ir.RegisterParams != 0
+                               if inRegistersImported || inRegistersSamePackage {
+                                       callABI = s.f.ABI1
+                               }
+                       }
                        break
                }
                closure = s.expr(fn)
@@ -4909,14 +4925,11 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
                }
        }
 
-       if regAbiForFuncType(n.X.Type().FuncType()) {
-               // Magic last type in input args to call
-               inRegistersForTesting = true
-       }
-
-       callABI := s.f.ABIDefault
-       if inRegistersForTesting {
-               callABI = s.f.ABI1
+       if !objabi.Experiment.RegabiArgs {
+               if regAbiForFuncType(n.X.Type().FuncType()) {
+                       // Magic last type in input args to call
+                       callABI = s.f.ABI1
+               }
        }
 
        params := callABI.ABIAnalyze(n.X.Type(), false /* Do not set (register) nNames from caller side -- can cause races. */)