From: Matthew Dempsky Date: Sun, 20 Aug 2023 22:37:34 +0000 (-0700) Subject: cmd/compile: simplify various signature type handling code X-Git-Tag: go1.22rc1~1137 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c6dd97e533d480d9a972682c9357a07fc87b51ab;p=gostls13.git cmd/compile: simplify various signature type handling code Make more use of RecvParams and RecvParamsResults helper methods. Also, correct misuse of Go spec terminology ("return" is a statement; "result" is the class of parameters that appear in a function type). Change-Id: I94807a747c494c9daa5441da7d9e3aea77aae33b Reviewed-on: https://go-review.googlesource.com/c/go/+/521395 TryBot-Result: Gopher Robot Reviewed-by: Cuong Manh Le Run-TryBot: Matthew Dempsky Auto-Submit: Matthew Dempsky Reviewed-by: Than McIntosh --- diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index 78094d4ae9..0ff8c0961a 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -326,54 +326,42 @@ func (a *ABIConfig) NumParamRegs(t *types.Type) int { return n } -// preAllocateParams gets the slice sizes right for inputs and outputs. -func (a *ABIParamResultInfo) preAllocateParams(hasRcvr bool, nIns, nOuts int) { - if hasRcvr { - nIns++ - } - a.inparams = make([]ABIParamAssignment, 0, nIns) - a.outparams = make([]ABIParamAssignment, 0, nOuts) -} - -// ABIAnalyzeTypes takes an optional receiver type, arrays of ins and outs, and returns an ABIParamResultInfo, +// ABIAnalyzeTypes takes slices of parameter and result types, and returns an ABIParamResultInfo, // based on the given configuration. This is the same result computed by config.ABIAnalyze applied to the // corresponding method/function type, except that all the embedded parameter names are nil. // This is intended for use by ssagen/ssa.go:(*state).rtcall, for runtime functions that lack a parsed function type. -func (config *ABIConfig) ABIAnalyzeTypes(rcvr *types.Type, ins, outs []*types.Type) *ABIParamResultInfo { +func (config *ABIConfig) ABIAnalyzeTypes(params, results []*types.Type) *ABIParamResultInfo { setup() s := assignState{ stackOffset: config.offsetForLocals, rTotal: config.regAmounts, } - result := &ABIParamResultInfo{config: config} - result.preAllocateParams(rcvr != nil, len(ins), len(outs)) - // Receiver - if rcvr != nil { - result.inparams = append(result.inparams, - s.assignParamOrReturn(rcvr, nil, false)) + assignParams := func(params []*types.Type, isResult bool) []ABIParamAssignment { + res := make([]ABIParamAssignment, len(params)) + for i, param := range params { + res[i] = s.assignParam(param, nil, isResult) + } + return res } + info := &ABIParamResultInfo{config: config} + // Inputs - for _, t := range ins { - result.inparams = append(result.inparams, - s.assignParamOrReturn(t, nil, false)) - } + info.inparams = assignParams(params, false) s.stackOffset = types.RoundUp(s.stackOffset, int64(types.RegSize)) - result.inRegistersUsed = s.rUsed.intRegs + s.rUsed.floatRegs + info.inRegistersUsed = s.rUsed.intRegs + s.rUsed.floatRegs // Outputs s.rUsed = RegAmounts{} - for _, t := range outs { - result.outparams = append(result.outparams, s.assignParamOrReturn(t, nil, true)) - } + info.outparams = assignParams(results, true) // The spill area is at a register-aligned offset and its size is rounded up to a register alignment. // TODO in theory could align offset only to minimum required by spilled data types. - result.offsetToSpillArea = alignTo(s.stackOffset, types.RegSize) - result.spillAreaSize = alignTo(s.spillOffset, types.RegSize) - result.outRegistersUsed = s.rUsed.intRegs + s.rUsed.floatRegs + info.offsetToSpillArea = alignTo(s.stackOffset, types.RegSize) + info.spillAreaSize = alignTo(s.spillOffset, types.RegSize) + info.outRegistersUsed = s.rUsed.intRegs + s.rUsed.floatRegs - return result + return info } // ABIAnalyzeFuncType takes a function type 'ft' and an ABI rules description @@ -386,37 +374,31 @@ func (config *ABIConfig) ABIAnalyzeFuncType(ft *types.Type) *ABIParamResultInfo stackOffset: config.offsetForLocals, rTotal: config.regAmounts, } - result := &ABIParamResultInfo{config: config} - result.preAllocateParams(ft.Recv() != nil, ft.NumParams(), ft.NumResults()) - // Receiver - // TODO(register args) ? seems like "struct" and "fields" is not right anymore for describing function parameters - if r := ft.Recv(); r != nil { - result.inparams = append(result.inparams, - s.assignParamOrReturn(r.Type, r.Nname, false)) + assignParams := func(params []*types.Field, isResult bool) []ABIParamAssignment { + res := make([]ABIParamAssignment, len(params)) + for i, param := range params { + res[i] = s.assignParam(param.Type, param.Nname, isResult) + } + return res } + info := &ABIParamResultInfo{config: config} + // Inputs - ifsl := ft.Params() - for _, f := range ifsl { - result.inparams = append(result.inparams, - s.assignParamOrReturn(f.Type, f.Nname, false)) - } + info.inparams = assignParams(ft.RecvParams(), false) s.stackOffset = types.RoundUp(s.stackOffset, int64(types.RegSize)) - result.inRegistersUsed = s.rUsed.intRegs + s.rUsed.floatRegs + info.inRegistersUsed = s.rUsed.intRegs + s.rUsed.floatRegs // Outputs s.rUsed = RegAmounts{} - ofsl := ft.Results() - for _, f := range ofsl { - result.outparams = append(result.outparams, s.assignParamOrReturn(f.Type, f.Nname, true)) - } + info.outparams = assignParams(ft.Results(), true) // The spill area is at a register-aligned offset and its size is rounded up to a register alignment. // TODO in theory could align offset only to minimum required by spilled data types. - result.offsetToSpillArea = alignTo(s.stackOffset, types.RegSize) - result.spillAreaSize = alignTo(s.spillOffset, types.RegSize) - result.outRegistersUsed = s.rUsed.intRegs + s.rUsed.floatRegs - return result + info.offsetToSpillArea = alignTo(s.stackOffset, types.RegSize) + info.spillAreaSize = alignTo(s.spillOffset, types.RegSize) + info.outRegistersUsed = s.rUsed.intRegs + s.rUsed.floatRegs + return info } // ABIAnalyze returns the same result as ABIAnalyzeFuncType, but also @@ -430,13 +412,8 @@ func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResul result := config.ABIAnalyzeFuncType(t) // Fill in the frame offsets for receiver, inputs, results - k := 0 - if t.NumRecvs() != 0 { - config.updateOffset(result, t.Recv(), result.inparams[0], false, setNname) - k++ - } - for i, f := range t.Params() { - config.updateOffset(result, f, result.inparams[k+i], false, setNname) + for i, f := range t.RecvParams() { + config.updateOffset(result, f, result.inparams[i], false, setNname) } for i, f := range t.Results() { config.updateOffset(result, f, result.outparams[i], true, setNname) @@ -444,13 +421,13 @@ func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResul return result } -func (config *ABIConfig) updateOffset(result *ABIParamResultInfo, f *types.Field, a ABIParamAssignment, isReturn, setNname bool) { +func (config *ABIConfig) updateOffset(result *ABIParamResultInfo, f *types.Field, a ABIParamAssignment, isResult, setNname bool) { if f.Offset != types.BADWIDTH { base.Fatalf("field offset for %s at %s has been set to %d", f.Sym.Name, base.FmtPos(f.Pos), f.Offset) } // Everything except return values in registers has either a frame home (if not in a register) or a frame spill location. - if !isReturn || len(a.Registers) == 0 { + if !isResult || len(a.Registers) == 0 { // The type frame offset DOES NOT show effects of minimum frame size. // Getting this wrong breaks stackmaps, see liveness/plive.go:WriteFuncMap and typebits/typebits.go:Set off := a.FrameOffset(result) @@ -601,9 +578,9 @@ func (state *assignState) allocateRegs(regs []RegIndex, t *types.Type) []RegInde // regAllocate creates a register ABIParamAssignment object for a param // or result with the specified type, as a final step (this assumes // that all of the safety/suitability analysis is complete). -func (state *assignState) regAllocate(t *types.Type, name types.Object, isReturn bool) ABIParamAssignment { +func (state *assignState) regAllocate(t *types.Type, name types.Object, isResult bool) ABIParamAssignment { spillLoc := int64(-1) - if !isReturn { + if !isResult { // Spill for register-resident t must be aligned for storage of a t. spillLoc = align(state.spillOffset, t) state.spillOffset = spillLoc + t.Size() @@ -759,11 +736,11 @@ func (state *assignState) regassign(pt *types.Type) bool { } } -// assignParamOrReturn processes a given receiver, param, or result +// assignParam processes a given receiver, param, or result // of field f to determine whether it can be register assigned. // The result of the analysis is recorded in the result // ABIParamResultInfo held in 'state'. -func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, isReturn bool) ABIParamAssignment { +func (state *assignState) assignParam(pt *types.Type, n types.Object, isResult bool) ABIParamAssignment { state.pUsed = RegAmounts{} if pt.Size() == types.BADWIDTH { base.Fatalf("should never happen") @@ -771,7 +748,7 @@ func (state *assignState) assignParamOrReturn(pt *types.Type, n types.Object, is } else if pt.Size() == 0 { return state.stackAllocate(pt, n) } else if state.regassign(pt) { - return state.regAllocate(pt, n, isReturn) + return state.regAllocate(pt, n, isResult) } else { return state.stackAllocate(pt, n) } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 93506a8fdf..1bf7c8dc73 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -1027,22 +1027,14 @@ func writeType(t *types.Type) *obj.LSym { ot = dextratype(lsym, ot, t, 0) case types.TFUNC: - for _, t1 := range t.Recvs() { - writeType(t1.Type) - } - isddd := false - for _, t1 := range t.Params() { - isddd = t1.IsDDD() - writeType(t1.Type) - } - for _, t1 := range t.Results() { + for _, t1 := range t.RecvParamsResults() { writeType(t1.Type) } ot = dcommontype(lsym, t) inCount := t.NumRecvs() + t.NumParams() outCount := t.NumResults() - if isddd { + if t.IsVariadic() { outCount |= 1 << 15 } ot = objw.Uint16(lsym, ot, uint16(inCount)) @@ -1055,13 +1047,7 @@ func writeType(t *types.Type) *obj.LSym { ot = dextratype(lsym, ot, t, dataAdd) // Array of rtype pointers follows funcType. - for _, t1 := range t.Recvs() { - ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) - } - for _, t1 := range t.Params() { - ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) - } - for _, t1 := range t.Results() { + for _, t1 := range t.RecvParamsResults() { ot = objw.SymPtr(lsym, ot, writeType(t1.Type), 0) } diff --git a/src/cmd/compile/internal/ssa/loopreschedchecks.go b/src/cmd/compile/internal/ssa/loopreschedchecks.go index 7c56523ad8..0ac473d229 100644 --- a/src/cmd/compile/internal/ssa/loopreschedchecks.go +++ b/src/cmd/compile/internal/ssa/loopreschedchecks.go @@ -247,7 +247,7 @@ func insertLoopReschedChecks(f *Func) { // mem1 := call resched (mem0) // goto header resched := f.fe.Syslook("goschedguarded") - call := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeResultMem, StaticAuxCall(resched, bb.Func.ABIDefault.ABIAnalyzeTypes(nil, nil, nil)), mem0) + call := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeResultMem, StaticAuxCall(resched, bb.Func.ABIDefault.ABIAnalyzeTypes(nil, nil)), mem0) mem1 := sched.NewValue1I(bb.Pos, OpSelectN, types.TypeMem, 0, call) sched.AddEdgeTo(h) headerMemPhi.AddArg(mem1) diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 64c95662f8..294306d8c2 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -657,7 +657,7 @@ func wbcall(pos src.XPos, b *Block, fn *obj.LSym, sp, mem *Value, args ...*Value for i := 0; i < nargs; i++ { argTypes[i] = typ } - call := b.NewValue0A(pos, OpStaticCall, types.TypeResultMem, StaticAuxCall(fn, b.Func.ABIDefault.ABIAnalyzeTypes(nil, argTypes, nil))) + call := b.NewValue0A(pos, OpStaticCall, types.TypeResultMem, StaticAuxCall(fn, b.Func.ABIDefault.ABIAnalyzeTypes(argTypes, nil))) call.AddArgs(args...) call.AuxInt = int64(nargs) * typ.Size() return b.NewValue1I(pos, OpSelectN, types.TypeMem, 0, call) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 9b93b599f3..cdf6bfd8b9 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -5142,10 +5142,10 @@ func (s *state) openDeferExit() { v := s.load(r.closure.Type.Elem(), r.closure) s.maybeNilCheckClosure(v, callDefer) codeptr := s.rawLoad(types.Types[types.TUINTPTR], v) - aux := ssa.ClosureAuxCall(s.f.ABIDefault.ABIAnalyzeTypes(nil, nil, nil)) + aux := ssa.ClosureAuxCall(s.f.ABIDefault.ABIAnalyzeTypes(nil, nil)) call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, v) } else { - aux := ssa.StaticAuxCall(fn.(*ir.Name).Linksym(), s.f.ABIDefault.ABIAnalyzeTypes(nil, nil, nil)) + aux := ssa.StaticAuxCall(fn.(*ir.Name).Linksym(), s.f.ABIDefault.ABIAnalyzeTypes(nil, nil)) call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux) } callArgs = append(callArgs, s.mem()) @@ -5268,7 +5268,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val // Call runtime.deferprocStack with pointer to _defer record. ACArgs = append(ACArgs, types.Types[types.TUINTPTR]) - aux := ssa.StaticAuxCall(ir.Syms.DeferprocStack, s.f.ABIDefault.ABIAnalyzeTypes(nil, ACArgs, ACResults)) + aux := ssa.StaticAuxCall(ir.Syms.DeferprocStack, s.f.ABIDefault.ABIAnalyzeTypes(ACArgs, ACResults)) callArgs = append(callArgs, addr, s.mem()) call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux) call.AddArgs(callArgs...) @@ -5319,10 +5319,10 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val // call target switch { case k == callDefer: - aux := ssa.StaticAuxCall(ir.Syms.Deferproc, s.f.ABIDefault.ABIAnalyzeTypes(nil, ACArgs, ACResults)) // TODO paramResultInfo for DeferProc + aux := ssa.StaticAuxCall(ir.Syms.Deferproc, s.f.ABIDefault.ABIAnalyzeTypes(ACArgs, ACResults)) // TODO paramResultInfo for DeferProc call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux) case k == callGo: - aux := ssa.StaticAuxCall(ir.Syms.Newproc, s.f.ABIDefault.ABIAnalyzeTypes(nil, ACArgs, ACResults)) + aux := ssa.StaticAuxCall(ir.Syms.Newproc, s.f.ABIDefault.ABIAnalyzeTypes(ACArgs, ACResults)) call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux) // TODO paramResultInfo for NewProc case closure != nil: // rawLoad because loading the code pointer from a @@ -5331,7 +5331,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val // critical that we not clobber any arguments already // stored onto the stack. codeptr = s.rawLoad(types.Types[types.TUINTPTR], closure) - aux := ssa.ClosureAuxCall(callABI.ABIAnalyzeTypes(nil, ACArgs, ACResults)) + aux := ssa.ClosureAuxCall(callABI.ABIAnalyzeTypes(ACArgs, ACResults)) call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, closure) case codeptr != nil: // Note that the "receiver" parameter is nil because the actual receiver is the first input parameter. @@ -5804,7 +5804,7 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args . // Issue call var call *ssa.Value - aux := ssa.StaticAuxCall(fn, s.f.ABIDefault.ABIAnalyzeTypes(nil, callArgTypes, results)) + aux := ssa.StaticAuxCall(fn, s.f.ABIDefault.ABIAnalyzeTypes(callArgTypes, results)) callArgs = append(callArgs, s.mem()) call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux) call.AddArgs(callArgs...)