Source file src/cmd/compile/internal/ssa/op.go

     1  // Copyright 2015 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 ssa
     6  
     7  import (
     8  	"cmd/compile/internal/abi"
     9  	"cmd/compile/internal/base"
    10  	"cmd/compile/internal/ir"
    11  	"cmd/compile/internal/types"
    12  	"cmd/internal/obj"
    13  	"fmt"
    14  	rtabi "internal/abi"
    15  	"strings"
    16  )
    17  
    18  // An Op encodes the specific operation that a Value performs.
    19  // Opcodes' semantics can be modified by the type and aux fields of the Value.
    20  // For instance, OpAdd can be 32 or 64 bit, signed or unsigned, float or complex, depending on Value.Type.
    21  // Semantics of each op are described in the opcode files in _gen/*Ops.go.
    22  // There is one file for generic (architecture-independent) ops and one file
    23  // for each architecture.
    24  type Op int32
    25  
    26  type opInfo struct {
    27  	name              string
    28  	reg               regInfo
    29  	auxType           auxType
    30  	argLen            int32 // the number of arguments, -1 if variable length
    31  	asm               obj.As
    32  	generic           bool      // this is a generic (arch-independent) opcode
    33  	rematerializeable bool      // this op is rematerializeable
    34  	commutative       bool      // this operation is commutative (e.g. addition)
    35  	resultInArg0      bool      // (first, if a tuple) output of v and v.Args[0] must be allocated to the same register
    36  	resultNotInArgs   bool      // outputs must not be allocated to the same registers as inputs
    37  	clobberFlags      bool      // this op clobbers flags register
    38  	needIntTemp       bool      // need a temporary free integer register
    39  	call              bool      // is a function call
    40  	tailCall          bool      // is a tail call
    41  	nilCheck          bool      // this op is a nil check on arg0
    42  	faultOnNilArg0    bool      // this op will fault if arg0 is nil (and aux encodes a small offset)
    43  	faultOnNilArg1    bool      // this op will fault if arg1 is nil (and aux encodes a small offset)
    44  	usesScratch       bool      // this op requires scratch memory space
    45  	hasSideEffects    bool      // for "reasons", not to be eliminated.  E.g., atomic store, #19182.
    46  	zeroWidth         bool      // op never translates into any machine code. example: copy, which may sometimes translate to machine code, is not zero-width.
    47  	unsafePoint       bool      // this op is an unsafe point, i.e. not safe for async preemption
    48  	fixedReg          bool      // this op will be assigned a fixed register
    49  	earlyOk           bool      // executing this op in an earlier block is ok
    50  	addrSinkArg0      bool      // the address in arg0 does not propagate to the result
    51  	addrSinkArg1      bool      // the address in arg1 does not propagate to the result
    52  	symEffect         SymEffect // effect this op has on symbol in aux
    53  	scale             uint8     // amd64/386 indexed load scale
    54  }
    55  
    56  type inputInfo struct {
    57  	idx  int     // index in Args array
    58  	regs regMask // allowed input registers
    59  }
    60  
    61  type outputInfo struct {
    62  	idx  int     // index in output tuple
    63  	regs regMask // allowed output registers
    64  }
    65  
    66  type regInfo struct {
    67  	// inputs encodes the register restrictions for an instruction's inputs.
    68  	// Each entry specifies an allowed register set for a particular input.
    69  	// They are listed in the order in which regalloc should pick a register
    70  	// from the register set (most constrained first).
    71  	// Inputs which do not need registers are not listed.
    72  	inputs []inputInfo
    73  	// clobbers encodes the set of registers that are overwritten by
    74  	// the instruction (other than the output registers).
    75  	clobbers regMask
    76  	// Instruction clobbers the register containing input 0.
    77  	clobbersArg0 bool
    78  	// Instruction clobbers the register containing input 1.
    79  	clobbersArg1 bool
    80  	// outputs is the same as inputs, but for the outputs of the instruction.
    81  	outputs []outputInfo
    82  }
    83  
    84  func (r *regInfo) String() string {
    85  	s := ""
    86  	s += "INS:\n"
    87  	for _, i := range r.inputs {
    88  		mask := fmt.Sprintf("%64b", i.regs)
    89  		mask = strings.ReplaceAll(mask, "0", ".")
    90  		s += fmt.Sprintf("%2d |%s|\n", i.idx, mask)
    91  	}
    92  	s += "OUTS:\n"
    93  	for _, i := range r.outputs {
    94  		mask := fmt.Sprintf("%64b", i.regs)
    95  		mask = strings.ReplaceAll(mask, "0", ".")
    96  		s += fmt.Sprintf("%2d |%s|\n", i.idx, mask)
    97  	}
    98  	s += "CLOBBERS:\n"
    99  	mask := fmt.Sprintf("%64b", r.clobbers)
   100  	mask = strings.ReplaceAll(mask, "0", ".")
   101  	s += fmt.Sprintf("   |%s|\n", mask)
   102  	return s
   103  }
   104  
   105  type auxType int8
   106  
   107  type AuxNameOffset struct {
   108  	Name   *ir.Name
   109  	Offset int64
   110  }
   111  
   112  func (a *AuxNameOffset) CanBeAnSSAAux() {}
   113  func (a *AuxNameOffset) String() string {
   114  	return fmt.Sprintf("%s+%d", a.Name.Sym().Name, a.Offset)
   115  }
   116  
   117  func (a *AuxNameOffset) FrameOffset() int64 {
   118  	return a.Name.FrameOffset() + a.Offset
   119  }
   120  
   121  type AuxCall struct {
   122  	Fn      *obj.LSym
   123  	reg     *regInfo // regInfo for this call
   124  	abiInfo *abi.ABIParamResultInfo
   125  }
   126  
   127  // Reg returns the regInfo for a given call, combining the derived in/out register masks
   128  // with the machine-specific register information in the input i.  (The machine-specific
   129  // regInfo is much handier at the call site than it is when the AuxCall is being constructed,
   130  // therefore do this lazily).
   131  //
   132  // TODO: there is a Clever Hack that allows pre-generation of a small-ish number of the slices
   133  // of inputInfo and outputInfo used here, provided that we are willing to reorder the inputs
   134  // and outputs from calls, so that all integer registers come first, then all floating registers.
   135  // At this point (active development of register ABI) that is very premature,
   136  // but if this turns out to be a cost, we could do it.
   137  func (a *AuxCall) Reg(i *regInfo, c *Config) *regInfo {
   138  	if !a.reg.clobbers.empty() {
   139  		// Already updated
   140  		return a.reg
   141  	}
   142  	if a.abiInfo.InRegistersUsed()+a.abiInfo.OutRegistersUsed() == 0 {
   143  		// Shortcut for zero case, also handles old ABI.
   144  		a.reg = i
   145  		return a.reg
   146  	}
   147  
   148  	k := len(i.inputs)
   149  	for _, p := range a.abiInfo.InParams() {
   150  		for _, r := range p.Registers {
   151  			m := archRegForAbiReg(r, c)
   152  			a.reg.inputs = append(a.reg.inputs, inputInfo{idx: k, regs: regMaskAt(register(m))})
   153  			k++
   154  		}
   155  	}
   156  	a.reg.inputs = append(a.reg.inputs, i.inputs...) // These are less constrained, thus should come last
   157  	k = len(i.outputs)
   158  	for _, p := range a.abiInfo.OutParams() {
   159  		for _, r := range p.Registers {
   160  			m := archRegForAbiReg(r, c)
   161  			a.reg.outputs = append(a.reg.outputs, outputInfo{idx: k, regs: regMaskAt(register(m))})
   162  			k++
   163  		}
   164  	}
   165  	a.reg.outputs = append(a.reg.outputs, i.outputs...)
   166  	a.reg.clobbers = i.clobbers
   167  	return a.reg
   168  }
   169  func (a *AuxCall) ABI() *abi.ABIConfig {
   170  	return a.abiInfo.Config()
   171  }
   172  func (a *AuxCall) ABIInfo() *abi.ABIParamResultInfo {
   173  	return a.abiInfo
   174  }
   175  func (a *AuxCall) ResultReg(c *Config) *regInfo {
   176  	if a.abiInfo.OutRegistersUsed() == 0 {
   177  		return a.reg
   178  	}
   179  	if len(a.reg.inputs) > 0 {
   180  		return a.reg
   181  	}
   182  	k := 0
   183  	for _, p := range a.abiInfo.OutParams() {
   184  		for _, r := range p.Registers {
   185  			m := archRegForAbiReg(r, c)
   186  			a.reg.inputs = append(a.reg.inputs, inputInfo{idx: k, regs: regMaskAt(register(m))})
   187  			k++
   188  		}
   189  	}
   190  	return a.reg
   191  }
   192  
   193  // For ABI register index r, returns the (dense) register number used in
   194  // SSA backend.
   195  func archRegForAbiReg(r abi.RegIndex, c *Config) uint8 {
   196  	var m int8
   197  	if int(r) < len(c.intParamRegs) {
   198  		m = c.intParamRegs[r]
   199  	} else {
   200  		m = c.floatParamRegs[int(r)-len(c.intParamRegs)]
   201  	}
   202  	return uint8(m)
   203  }
   204  
   205  // For ABI register index r, returns the register number used in the obj
   206  // package (assembler).
   207  func ObjRegForAbiReg(r abi.RegIndex, c *Config) int16 {
   208  	m := archRegForAbiReg(r, c)
   209  	return c.registers[m].objNum
   210  }
   211  
   212  // ArgWidth returns the amount of stack needed for all the inputs
   213  // and outputs of a function or method, including ABI-defined parameter
   214  // slots and ABI-defined spill slots for register-resident parameters.
   215  //
   216  // The name is taken from the types package's ArgWidth(<function type>),
   217  // which predated changes to the ABI; this version handles those changes.
   218  func (a *AuxCall) ArgWidth() int64 {
   219  	return a.abiInfo.ArgWidth()
   220  }
   221  
   222  // ParamAssignmentForResult returns the ABI Parameter assignment for result which (indexed 0, 1, etc).
   223  func (a *AuxCall) ParamAssignmentForResult(which int64) *abi.ABIParamAssignment {
   224  	return a.abiInfo.OutParam(int(which))
   225  }
   226  
   227  // OffsetOfResult returns the SP offset of result which (indexed 0, 1, etc).
   228  func (a *AuxCall) OffsetOfResult(which int64) int64 {
   229  	n := int64(a.abiInfo.OutParam(int(which)).Offset())
   230  	return n
   231  }
   232  
   233  // OffsetOfArg returns the SP offset of argument which (indexed 0, 1, etc).
   234  // If the call is to a method, the receiver is the first argument (i.e., index 0)
   235  func (a *AuxCall) OffsetOfArg(which int64) int64 {
   236  	n := int64(a.abiInfo.InParam(int(which)).Offset())
   237  	return n
   238  }
   239  
   240  // RegsOfResult returns the register(s) used for result which (indexed 0, 1, etc).
   241  func (a *AuxCall) RegsOfResult(which int64) []abi.RegIndex {
   242  	return a.abiInfo.OutParam(int(which)).Registers
   243  }
   244  
   245  // RegsOfArg returns the register(s) used for argument which (indexed 0, 1, etc).
   246  // If the call is to a method, the receiver is the first argument (i.e., index 0)
   247  func (a *AuxCall) RegsOfArg(which int64) []abi.RegIndex {
   248  	return a.abiInfo.InParam(int(which)).Registers
   249  }
   250  
   251  // NameOfResult returns the ir.Name of result which (indexed 0, 1, etc).
   252  func (a *AuxCall) NameOfResult(which int64) *ir.Name {
   253  	return a.abiInfo.OutParam(int(which)).Name
   254  }
   255  
   256  // TypeOfResult returns the type of result which (indexed 0, 1, etc).
   257  func (a *AuxCall) TypeOfResult(which int64) *types.Type {
   258  	return a.abiInfo.OutParam(int(which)).Type
   259  }
   260  
   261  // TypeOfArg returns the type of argument which (indexed 0, 1, etc).
   262  // If the call is to a method, the receiver is the first argument (i.e., index 0)
   263  func (a *AuxCall) TypeOfArg(which int64) *types.Type {
   264  	return a.abiInfo.InParam(int(which)).Type
   265  }
   266  
   267  // SizeOfResult returns the size of result which (indexed 0, 1, etc).
   268  func (a *AuxCall) SizeOfResult(which int64) int64 {
   269  	return a.TypeOfResult(which).Size()
   270  }
   271  
   272  // SizeOfArg returns the size of argument which (indexed 0, 1, etc).
   273  // If the call is to a method, the receiver is the first argument (i.e., index 0)
   274  func (a *AuxCall) SizeOfArg(which int64) int64 {
   275  	return a.TypeOfArg(which).Size()
   276  }
   277  
   278  // NResults returns the number of results.
   279  func (a *AuxCall) NResults() int64 {
   280  	return int64(len(a.abiInfo.OutParams()))
   281  }
   282  
   283  // LateExpansionResultType returns the result type (including trailing mem)
   284  // for a call that will be expanded later in the SSA phase.
   285  func (a *AuxCall) LateExpansionResultType() *types.Type {
   286  	var tys []*types.Type
   287  	for i := int64(0); i < a.NResults(); i++ {
   288  		tys = append(tys, a.TypeOfResult(i))
   289  	}
   290  	tys = append(tys, types.TypeMem)
   291  	return types.NewResults(tys)
   292  }
   293  
   294  // NArgs returns the number of arguments (including receiver, if there is one).
   295  func (a *AuxCall) NArgs() int64 {
   296  	return int64(len(a.abiInfo.InParams()))
   297  }
   298  
   299  // String returns "AuxCall{<fn>}"
   300  func (a *AuxCall) String() string {
   301  	var fn string
   302  	if a.Fn == nil {
   303  		fn = "AuxCall{nil" // could be interface/closure etc.
   304  	} else {
   305  		fn = fmt.Sprintf("AuxCall{%v", a.Fn)
   306  	}
   307  	// TODO how much of the ABI should be printed?
   308  
   309  	return fn + "}"
   310  }
   311  
   312  // StaticAuxCall returns an AuxCall for a static call.
   313  func StaticAuxCall(sym *obj.LSym, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
   314  	if paramResultInfo == nil {
   315  		panic(fmt.Errorf("Nil paramResultInfo, sym=%v", sym))
   316  	}
   317  	var reg *regInfo
   318  	if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
   319  		reg = &regInfo{}
   320  	}
   321  	return &AuxCall{Fn: sym, abiInfo: paramResultInfo, reg: reg}
   322  }
   323  
   324  // InterfaceAuxCall returns an AuxCall for an interface call.
   325  func InterfaceAuxCall(paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
   326  	var reg *regInfo
   327  	if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
   328  		reg = &regInfo{}
   329  	}
   330  	return &AuxCall{Fn: nil, abiInfo: paramResultInfo, reg: reg}
   331  }
   332  
   333  // ClosureAuxCall returns an AuxCall for a closure call.
   334  func ClosureAuxCall(paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
   335  	var reg *regInfo
   336  	if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
   337  		reg = &regInfo{}
   338  	}
   339  	return &AuxCall{Fn: nil, abiInfo: paramResultInfo, reg: reg}
   340  }
   341  
   342  func (*AuxCall) CanBeAnSSAAux() {}
   343  
   344  // OwnAuxCall returns a function's own AuxCall.
   345  func OwnAuxCall(fn *obj.LSym, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
   346  	// TODO if this remains identical to ClosureAuxCall above after new ABI is done, should deduplicate.
   347  	var reg *regInfo
   348  	if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
   349  		reg = &regInfo{}
   350  	}
   351  	return &AuxCall{Fn: fn, abiInfo: paramResultInfo, reg: reg}
   352  }
   353  
   354  const (
   355  	auxNone           auxType = iota
   356  	auxBool                   // auxInt is 0/1 for false/true
   357  	auxInt8                   // auxInt is an 8-bit integer
   358  	auxInt16                  // auxInt is a 16-bit integer
   359  	auxInt32                  // auxInt is a 32-bit integer
   360  	auxInt64                  // auxInt is a 64-bit integer
   361  	auxInt128                 // auxInt represents a 128-bit integer.  Always 0.
   362  	auxUInt8                  // auxInt is an 8-bit unsigned integer
   363  	auxFloat32                // auxInt is a float32 (encoded with math.Float64bits)
   364  	auxFloat64                // auxInt is a float64 (encoded with math.Float64bits)
   365  	auxFlagConstant           // auxInt is a flagConstant
   366  	auxCCop                   // auxInt is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan)
   367  	auxNameOffsetInt8         // aux is a &struct{Name ir.Name, Offset int64}; auxInt is index in parameter registers array
   368  	auxString                 // aux is a string
   369  	auxSym                    // aux is a symbol (a *ir.Name for locals, an *obj.LSym for globals, or nil for none)
   370  	auxSymOff                 // aux is a symbol, auxInt is an offset
   371  	auxSymValAndOff           // aux is a symbol, auxInt is a ValAndOff
   372  	auxTyp                    // aux is a type
   373  	auxTypSize                // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt
   374  	auxCall                   // aux is a *ssa.AuxCall
   375  	auxCallOff                // aux is a *ssa.AuxCall, AuxInt is int64 param (in+out) size
   376  
   377  	auxPanicBoundsC  // constant for a bounds failure
   378  	auxPanicBoundsCC // two constants for a bounds failure
   379  
   380  	// architecture specific aux types
   381  	auxARM64BitField          // aux is an arm64 bitfield lsb and width packed into auxInt
   382  	auxARM64ConditionalParams // aux is a structure, which contains condition, NZCV flags and constant with indicator of using it
   383  	auxS390XRotateParams      // aux is a s390x rotate parameters object encoding start bit, end bit and rotate amount
   384  	auxS390XCCMask            // aux is a s390x 4-bit condition code mask
   385  	auxS390XCCMaskInt8        // aux is a s390x 4-bit condition code mask, auxInt is an int8 immediate
   386  	auxS390XCCMaskUint8       // aux is a s390x 4-bit condition code mask, auxInt is a uint8 immediate
   387  )
   388  
   389  // A SymEffect describes the effect that an SSA Value has on the variable
   390  // identified by the symbol in its Aux field.
   391  type SymEffect int8
   392  
   393  const (
   394  	SymRead SymEffect = 1 << iota
   395  	SymWrite
   396  	SymAddr
   397  
   398  	SymRdWr = SymRead | SymWrite
   399  
   400  	SymNone SymEffect = 0
   401  )
   402  
   403  // A Sym represents a symbolic offset from a base register.
   404  // Currently a Sym can be one of 3 things:
   405  //   - a *ir.Name, for an offset from SP (the stack pointer)
   406  //   - a *obj.LSym, for an offset from SB (the global pointer)
   407  //   - nil, for no offset
   408  type Sym interface {
   409  	Aux
   410  	CanBeAnSSASym()
   411  }
   412  
   413  // A ValAndOff is used by the several opcodes. It holds
   414  // both a value and a pointer offset.
   415  // A ValAndOff is intended to be encoded into an AuxInt field.
   416  // The zero ValAndOff encodes a value of 0 and an offset of 0.
   417  // The high 32 bits hold a value.
   418  // The low 32 bits hold a pointer offset.
   419  type ValAndOff int64
   420  
   421  func (x ValAndOff) Val() int32   { return int32(int64(x) >> 32) }
   422  func (x ValAndOff) Val64() int64 { return int64(x) >> 32 }
   423  func (x ValAndOff) Val16() int16 { return int16(int64(x) >> 32) }
   424  func (x ValAndOff) Val8() int8   { return int8(int64(x) >> 32) }
   425  
   426  func (x ValAndOff) Off64() int64 { return int64(int32(x)) }
   427  func (x ValAndOff) Off() int32   { return int32(x) }
   428  
   429  func (x ValAndOff) String() string {
   430  	return fmt.Sprintf("val=%d,off=%d", x.Val(), x.Off())
   431  }
   432  
   433  // validVal reports whether the value can be used
   434  // as an argument to makeValAndOff.
   435  func validVal(val int64) bool {
   436  	return val == int64(int32(val))
   437  }
   438  
   439  func makeValAndOff(val, off int32) ValAndOff {
   440  	return ValAndOff(int64(val)<<32 + int64(uint32(off)))
   441  }
   442  
   443  func (x ValAndOff) canAdd32(off int32) bool {
   444  	newoff := x.Off64() + int64(off)
   445  	return newoff == int64(int32(newoff))
   446  }
   447  func (x ValAndOff) canAdd64(off int64) bool {
   448  	newoff := x.Off64() + off
   449  	return newoff == int64(int32(newoff))
   450  }
   451  
   452  func (x ValAndOff) addOffset32(off int32) ValAndOff {
   453  	if !x.canAdd32(off) {
   454  		panic("invalid ValAndOff.addOffset32")
   455  	}
   456  	return makeValAndOff(x.Val(), x.Off()+off)
   457  }
   458  func (x ValAndOff) addOffset64(off int64) ValAndOff {
   459  	if !x.canAdd64(off) {
   460  		panic("invalid ValAndOff.addOffset64")
   461  	}
   462  	return makeValAndOff(x.Val(), x.Off()+int32(off))
   463  }
   464  
   465  // int128 is a type that stores a 128-bit constant.
   466  // The only allowed constant right now is 0, so we can cheat quite a bit.
   467  type int128 int64
   468  
   469  type BoundsKind uint8
   470  
   471  const (
   472  	BoundsIndex       BoundsKind = iota // indexing operation, 0 <= idx < len failed
   473  	BoundsIndexU                        // ... with unsigned idx
   474  	BoundsSliceAlen                     // 2-arg slicing operation, 0 <= high <= len failed
   475  	BoundsSliceAlenU                    // ... with unsigned high
   476  	BoundsSliceAcap                     // 2-arg slicing operation, 0 <= high <= cap failed
   477  	BoundsSliceAcapU                    // ... with unsigned high
   478  	BoundsSliceB                        // 2-arg slicing operation, 0 <= low <= high failed
   479  	BoundsSliceBU                       // ... with unsigned low
   480  	BoundsSlice3Alen                    // 3-arg slicing operation, 0 <= max <= len failed
   481  	BoundsSlice3AlenU                   // ... with unsigned max
   482  	BoundsSlice3Acap                    // 3-arg slicing operation, 0 <= max <= cap failed
   483  	BoundsSlice3AcapU                   // ... with unsigned max
   484  	BoundsSlice3B                       // 3-arg slicing operation, 0 <= high <= max failed
   485  	BoundsSlice3BU                      // ... with unsigned high
   486  	BoundsSlice3C                       // 3-arg slicing operation, 0 <= low <= high failed
   487  	BoundsSlice3CU                      // ... with unsigned low
   488  	BoundsConvert                       // conversion to array pointer failed
   489  	BoundsKindCount
   490  )
   491  
   492  // Returns the bounds error code needed by the runtime, and
   493  // whether the x field is signed.
   494  func (b BoundsKind) Code() (rtabi.BoundsErrorCode, bool) {
   495  	switch b {
   496  	case BoundsIndex:
   497  		return rtabi.BoundsIndex, true
   498  	case BoundsIndexU:
   499  		return rtabi.BoundsIndex, false
   500  	case BoundsSliceAlen:
   501  		return rtabi.BoundsSliceAlen, true
   502  	case BoundsSliceAlenU:
   503  		return rtabi.BoundsSliceAlen, false
   504  	case BoundsSliceAcap:
   505  		return rtabi.BoundsSliceAcap, true
   506  	case BoundsSliceAcapU:
   507  		return rtabi.BoundsSliceAcap, false
   508  	case BoundsSliceB:
   509  		return rtabi.BoundsSliceB, true
   510  	case BoundsSliceBU:
   511  		return rtabi.BoundsSliceB, false
   512  	case BoundsSlice3Alen:
   513  		return rtabi.BoundsSlice3Alen, true
   514  	case BoundsSlice3AlenU:
   515  		return rtabi.BoundsSlice3Alen, false
   516  	case BoundsSlice3Acap:
   517  		return rtabi.BoundsSlice3Acap, true
   518  	case BoundsSlice3AcapU:
   519  		return rtabi.BoundsSlice3Acap, false
   520  	case BoundsSlice3B:
   521  		return rtabi.BoundsSlice3B, true
   522  	case BoundsSlice3BU:
   523  		return rtabi.BoundsSlice3B, false
   524  	case BoundsSlice3C:
   525  		return rtabi.BoundsSlice3C, true
   526  	case BoundsSlice3CU:
   527  		return rtabi.BoundsSlice3C, false
   528  	case BoundsConvert:
   529  		return rtabi.BoundsConvert, false
   530  	default:
   531  		base.Fatalf("bad bounds kind %d", b)
   532  		return 0, false
   533  	}
   534  }
   535  
   536  // arm64BitField is the GO type of ARM64BitField auxInt.
   537  // if x is an ARM64BitField, then width=x&0xff, lsb=(x>>8)&0xff, and
   538  // width+lsb<64 for 64-bit variant, width+lsb<32 for 32-bit variant.
   539  // the meaning of width and lsb are instruction-dependent.
   540  type arm64BitField int16
   541  
   542  // arm64ConditionalParams is the GO type of ARM64ConditionalParams auxInt.
   543  type arm64ConditionalParams struct {
   544  	cond       Op    // Condition code to evaluate
   545  	nzcv       uint8 // Fallback NZCV flags value when condition is false
   546  	constValue uint8 // Immediate value for constant comparisons
   547  	ind        bool  // Constant comparison indicator
   548  }
   549  

View as plain text