1
0
mirror of https://github.com/golang/go synced 2024-11-18 01:24:49 -07:00

cmd/compile: fix outgoing calls with GOEXPERIMENT=regabiargs

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>
This commit is contained in:
Austin Clements 2021-03-31 17:41:07 -04:00
parent 3304b2235a
commit 1f29e69bad

View File

@ -4854,21 +4854,24 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
var ACArgs []*types.Type // AuxCall args var ACArgs []*types.Type // AuxCall args
var ACResults []*types.Type // AuxCall results var ACResults []*types.Type // AuxCall results
var callArgs []*ssa.Value // For late-expansion, the args themselves (not stored, args to the call instead). 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
callABI := s.f.ABIDefault
if !objabi.Experiment.RegabiArgs {
var magicFnNameSym *types.Sym var magicFnNameSym *types.Sym
if fn.Name() != nil { if fn.Name() != nil {
magicFnNameSym = fn.Name().Sym() magicFnNameSym = fn.Name().Sym()
ss := magicFnNameSym.Name ss := magicFnNameSym.Name
if strings.HasSuffix(ss, magicNameDotSuffix) { if strings.HasSuffix(ss, magicNameDotSuffix) {
inRegistersForTesting = true callABI = s.f.ABI1
} }
} }
if magicFnNameSym == nil && n.Op() == ir.OCALLINTER { if magicFnNameSym == nil && n.Op() == ir.OCALLINTER {
magicFnNameSym = fn.(*ir.SelectorExpr).Sym() magicFnNameSym = fn.(*ir.SelectorExpr).Sym()
ss := magicFnNameSym.Name ss := magicFnNameSym.Name
if strings.HasSuffix(ss, magicNameDotSuffix[1:]) { if strings.HasSuffix(ss, magicNameDotSuffix[1:]) {
inRegistersForTesting = true 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 { if k == callNormal && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC {
fn := fn.(*ir.Name) fn := fn.(*ir.Name)
callee = fn callee = fn
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 // TODO(register args) remove after register abi is working
inRegistersImported := fn.Pragma()&ir.RegisterParams != 0 inRegistersImported := fn.Pragma()&ir.RegisterParams != 0
inRegistersSamePackage := fn.Func != nil && fn.Func.Pragma&ir.RegisterParams != 0 inRegistersSamePackage := fn.Func != nil && fn.Func.Pragma&ir.RegisterParams != 0
inRegistersForTesting = inRegistersForTesting || inRegistersImported || inRegistersSamePackage if inRegistersImported || inRegistersSamePackage {
callABI = s.f.ABI1
}
}
break break
} }
closure = s.expr(fn) closure = s.expr(fn)
@ -4909,15 +4925,12 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
} }
} }
if !objabi.Experiment.RegabiArgs {
if regAbiForFuncType(n.X.Type().FuncType()) { if regAbiForFuncType(n.X.Type().FuncType()) {
// Magic last type in input args to call // Magic last type in input args to call
inRegistersForTesting = true
}
callABI := s.f.ABIDefault
if inRegistersForTesting {
callABI = s.f.ABI1 callABI = s.f.ABI1
} }
}
params := callABI.ABIAnalyze(n.X.Type(), false /* Do not set (register) nNames from caller side -- can cause races. */) params := callABI.ABIAnalyze(n.X.Type(), false /* Do not set (register) nNames from caller side -- can cause races. */)
types.CalcSize(fn.Type()) types.CalcSize(fn.Type())