github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/cmd/compile/internal/abi/abiutils.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package abi 6 7 import ( 8 "github.com/shogo82148/std/cmd/compile/internal/ir" 9 "github.com/shogo82148/std/cmd/compile/internal/types" 10 "github.com/shogo82148/std/cmd/internal/obj" 11 ) 12 13 // ABIParamResultInfo stores the results of processing a given 14 // function type to compute stack layout and register assignments. For 15 // each input and output parameter we capture whether the param was 16 // register-assigned (and to which register(s)) or the stack offset 17 // for the param if is not going to be passed in registers according 18 // to the rules in the Go internal ABI specification (1.17). 19 type ABIParamResultInfo struct { 20 inparams []ABIParamAssignment 21 outparams []ABIParamAssignment 22 offsetToSpillArea int64 23 spillAreaSize int64 24 inRegistersUsed int 25 outRegistersUsed int 26 config *ABIConfig 27 } 28 29 func (a *ABIParamResultInfo) Config() *ABIConfig 30 31 func (a *ABIParamResultInfo) InParams() []ABIParamAssignment 32 33 func (a *ABIParamResultInfo) OutParams() []ABIParamAssignment 34 35 func (a *ABIParamResultInfo) InRegistersUsed() int 36 37 func (a *ABIParamResultInfo) OutRegistersUsed() int 38 39 func (a *ABIParamResultInfo) InParam(i int) *ABIParamAssignment 40 41 func (a *ABIParamResultInfo) OutParam(i int) *ABIParamAssignment 42 43 func (a *ABIParamResultInfo) SpillAreaOffset() int64 44 45 func (a *ABIParamResultInfo) SpillAreaSize() int64 46 47 // ArgWidth returns the amount of stack needed for all the inputs 48 // and outputs of a function or method, including ABI-defined parameter 49 // slots and ABI-defined spill slots for register-resident parameters. 50 // The name is inherited from (*Type).ArgWidth(), which it replaces. 51 func (a *ABIParamResultInfo) ArgWidth() int64 52 53 // RegIndex stores the index into the set of machine registers used by 54 // the ABI on a specific architecture for parameter passing. RegIndex 55 // values 0 through N-1 (where N is the number of integer registers 56 // used for param passing according to the ABI rules) describe integer 57 // registers; values N through M (where M is the number of floating 58 // point registers used). Thus if the ABI says there are 5 integer 59 // registers and 7 floating point registers, then RegIndex value of 4 60 // indicates the 5th integer register, and a RegIndex value of 11 61 // indicates the 7th floating point register. 62 type RegIndex uint8 63 64 // ABIParamAssignment holds information about how a specific param or 65 // result will be passed: in registers (in which case 'Registers' is 66 // populated) or on the stack (in which case 'Offset' is set to a 67 // non-negative stack offset). The values in 'Registers' are indices 68 // (as described above), not architected registers. 69 type ABIParamAssignment struct { 70 Type *types.Type 71 Name *ir.Name 72 Registers []RegIndex 73 offset int32 74 } 75 76 // Offset returns the stack offset for addressing the parameter that "a" describes. 77 // This will panic if "a" describes a register-allocated parameter. 78 func (a *ABIParamAssignment) Offset() int32 79 80 // RegisterTypes returns a slice of the types of the registers 81 // corresponding to a slice of parameters. The returned slice 82 // has capacity for one more, likely a memory type. 83 func RegisterTypes(apa []ABIParamAssignment) []*types.Type 84 85 func (pa *ABIParamAssignment) RegisterTypesAndOffsets() ([]*types.Type, []int64) 86 87 // FrameOffset returns the frame-pointer-relative location that a function 88 // would spill its input or output parameter to, if such a spill slot exists. 89 // If there is none defined (e.g., register-allocated outputs) it panics. 90 // For register-allocated inputs that is their spill offset reserved for morestack; 91 // for stack-allocated inputs and outputs, that is their location on the stack. 92 // (In a future version of the ABI, register-resident inputs may lose their defined 93 // spill area to help reduce stack sizes.) 94 func (a *ABIParamAssignment) FrameOffset(i *ABIParamResultInfo) int64 95 96 // RegAmounts holds a specified number of integer/float registers. 97 type RegAmounts struct { 98 intRegs int 99 floatRegs int 100 } 101 102 // ABIConfig captures the number of registers made available 103 // by the ABI rules for parameter passing and result returning. 104 type ABIConfig struct { 105 // Do we need anything more than this? 106 offsetForLocals int64 107 regAmounts RegAmounts 108 which obj.ABI 109 } 110 111 // NewABIConfig returns a new ABI configuration for an architecture with 112 // iRegsCount integer/pointer registers and fRegsCount floating point registers. 113 func NewABIConfig(iRegsCount, fRegsCount int, offsetForLocals int64, which uint8) *ABIConfig 114 115 // Copy returns config. 116 // 117 // TODO(mdempsky): Remove. 118 func (config *ABIConfig) Copy() *ABIConfig 119 120 // Which returns the ABI number 121 func (config *ABIConfig) Which() obj.ABI 122 123 // LocalsOffset returns the architecture-dependent offset from SP for args and results. 124 // In theory this is only used for debugging; it ought to already be incorporated into 125 // results from the ABI-related methods 126 func (config *ABIConfig) LocalsOffset() int64 127 128 // FloatIndexFor translates r into an index in the floating point parameter 129 // registers. If the result is negative, the input index was actually for the 130 // integer parameter registers. 131 func (config *ABIConfig) FloatIndexFor(r RegIndex) int64 132 133 // NumParamRegs returns the total number of registers used to 134 // represent a parameter of the given type, which must be register 135 // assignable. 136 func (config *ABIConfig) NumParamRegs(typ *types.Type) int 137 138 // ABIAnalyzeTypes takes slices of parameter and result types, and returns an ABIParamResultInfo, 139 // based on the given configuration. This is the same result computed by config.ABIAnalyze applied to the 140 // corresponding method/function type, except that all the embedded parameter names are nil. 141 // This is intended for use by ssagen/ssa.go:(*state).rtcall, for runtime functions that lack a parsed function type. 142 func (config *ABIConfig) ABIAnalyzeTypes(params, results []*types.Type) *ABIParamResultInfo 143 144 // ABIAnalyzeFuncType takes a function type 'ft' and an ABI rules description 145 // 'config' and analyzes the function to determine how its parameters 146 // and results will be passed (in registers or on the stack), returning 147 // an ABIParamResultInfo object that holds the results of the analysis. 148 func (config *ABIConfig) ABIAnalyzeFuncType(ft *types.Type) *ABIParamResultInfo 149 150 // ABIAnalyze returns the same result as ABIAnalyzeFuncType, but also 151 // updates the offsets of all the receiver, input, and output fields. 152 // If setNname is true, it also sets the FrameOffset of the Nname for 153 // the field(s); this is for use when compiling a function and figuring out 154 // spill locations. Doing this for callers can cause races for register 155 // outputs because their frame location transitions from BOGUS_FUNARG_OFFSET 156 // to zero to an as-if-AUTO offset that has no use for callers. 157 func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResultInfo 158 159 // ToString method renders an ABIParamAssignment in human-readable 160 // form, suitable for debugging or unit testing. 161 func (ri *ABIParamAssignment) ToString(config *ABIConfig, extra bool) string 162 163 // String method renders an ABIParamResultInfo in human-readable 164 // form, suitable for debugging or unit testing. 165 func (ri *ABIParamResultInfo) String() string 166 167 // ComputePadding returns a list of "post element" padding values in 168 // the case where we have a structure being passed in registers. Given 169 // a param assignment corresponding to a struct, it returns a list 170 // containing padding values for each field, e.g. the Kth element in 171 // the list is the amount of padding between field K and the following 172 // field. For things that are not structs (or structs without padding) 173 // it returns a list of zeros. Example: 174 // 175 // type small struct { 176 // x uint16 177 // y uint8 178 // z int32 179 // w int32 180 // } 181 // 182 // For this struct we would return a list [0, 1, 0, 0], meaning that 183 // we have one byte of padding after the second field, and no bytes of 184 // padding after any of the other fields. Input parameter "storage" is 185 // a slice with enough capacity to accommodate padding elements for 186 // the architected register set in question. 187 func (pa *ABIParamAssignment) ComputePadding(storage []uint64) []uint64