Source file src/internal/abi/bounds.go

     1  // Copyright 2025 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  // This type and constants are for encoding different
     8  // kinds of bounds check failures.
     9  type BoundsErrorCode uint8
    10  
    11  const (
    12  	BoundsIndex      BoundsErrorCode = iota // s[x], 0 <= x < len(s) failed
    13  	BoundsSliceAlen                         // s[?:x], 0 <= x <= len(s) failed
    14  	BoundsSliceAcap                         // s[?:x], 0 <= x <= cap(s) failed
    15  	BoundsSliceB                            // s[x:y], 0 <= x <= y failed (but boundsSliceA didn't happen)
    16  	BoundsSlice3Alen                        // s[?:?:x], 0 <= x <= len(s) failed
    17  	BoundsSlice3Acap                        // s[?:?:x], 0 <= x <= cap(s) failed
    18  	BoundsSlice3B                           // s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen)
    19  	BoundsSlice3C                           // s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen)
    20  	BoundsConvert                           // (*[x]T)(s), 0 <= x <= len(s) failed
    21  	numBoundsCodes
    22  )
    23  
    24  const (
    25  	BoundsMaxReg   = 15
    26  	BoundsMaxConst = 31
    27  )
    28  
    29  // Here's how we encode PCDATA_PanicBounds entries:
    30  
    31  // We allow 16 registers (0-15) and 32 constants (0-31).
    32  // Encode the following constant c:
    33  //     bits    use
    34  // -----------------------------
    35  //       0     x is in a register
    36  //       1     y is in a register
    37  //
    38  // if x is in a register
    39  //       2     x is signed
    40  //     [3:6]   x's register number
    41  // else
    42  //     [2:6]   x's constant value
    43  //
    44  // if y is in a register
    45  //     [7:10]  y's register number
    46  // else
    47  //     [7:11]  y's constant value
    48  //
    49  // The final integer is c * numBoundsCode + code
    50  
    51  // TODO: 32-bit
    52  
    53  // Encode bounds failure information into an integer for PCDATA_PanicBounds.
    54  // Register numbers must be in 0-15. Constants must be in 0-31.
    55  func BoundsEncode(code BoundsErrorCode, signed, xIsReg, yIsReg bool, xVal, yVal int) int {
    56  	c := int(0)
    57  	if xIsReg {
    58  		c |= 1 << 0
    59  		if signed {
    60  			c |= 1 << 2
    61  		}
    62  		if xVal < 0 || xVal > BoundsMaxReg {
    63  			panic("bad xReg")
    64  		}
    65  		c |= xVal << 3
    66  	} else {
    67  		if xVal < 0 || xVal > BoundsMaxConst {
    68  			panic("bad xConst")
    69  		}
    70  		c |= xVal << 2
    71  	}
    72  	if yIsReg {
    73  		c |= 1 << 1
    74  		if yVal < 0 || yVal > BoundsMaxReg {
    75  			panic("bad yReg")
    76  		}
    77  		c |= yVal << 7
    78  	} else {
    79  		if yVal < 0 || yVal > BoundsMaxConst {
    80  			panic("bad yConst")
    81  		}
    82  		c |= yVal << 7
    83  	}
    84  	return c*int(numBoundsCodes) + int(code)
    85  }
    86  func BoundsDecode(v int) (code BoundsErrorCode, signed, xIsReg, yIsReg bool, xVal, yVal int) {
    87  	code = BoundsErrorCode(v % int(numBoundsCodes))
    88  	c := v / int(numBoundsCodes)
    89  	xIsReg = c&1 != 0
    90  	c >>= 1
    91  	yIsReg = c&1 != 0
    92  	c >>= 1
    93  	if xIsReg {
    94  		signed = c&1 != 0
    95  		c >>= 1
    96  		xVal = c & 0xf
    97  		c >>= 4
    98  	} else {
    99  		xVal = c & 0x1f
   100  		c >>= 5
   101  	}
   102  	if yIsReg {
   103  		yVal = c & 0xf
   104  		c >>= 4
   105  	} else {
   106  		yVal = c & 0x1f
   107  		c >>= 5
   108  	}
   109  	if c != 0 {
   110  		panic("BoundsDecode decoding error")
   111  	}
   112  	return
   113  }
   114  

View as plain text