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