1
0
mirror of https://github.com/golang/go synced 2024-09-24 03:20:12 -06: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

@ -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. */)