// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package abi

// This type and constants are for encoding different
// kinds of bounds check failures.
type BoundsErrorCode uint8

const (
	BoundsIndex      BoundsErrorCode = iota // s[x], 0 <= x < len(s) failed
	BoundsSliceAlen                         // s[?:x], 0 <= x <= len(s) failed
	BoundsSliceAcap                         // s[?:x], 0 <= x <= cap(s) failed
	BoundsSliceB                            // s[x:y], 0 <= x <= y failed (but boundsSliceA didn't happen)
	BoundsSlice3Alen                        // s[?:?:x], 0 <= x <= len(s) failed
	BoundsSlice3Acap                        // s[?:?:x], 0 <= x <= cap(s) failed
	BoundsSlice3B                           // s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen)
	BoundsSlice3C                           // s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen)
	BoundsConvert                           // (*[x]T)(s), 0 <= x <= len(s) failed
	numBoundsCodes
)

const (
	BoundsMaxReg   = 15
	BoundsMaxConst = 31
)

// Here's how we encode PCDATA_PanicBounds entries:

// We allow 16 registers (0-15) and 32 constants (0-31).
// Encode the following constant c:
//     bits    use
// -----------------------------
//       0     x is in a register
//       1     y is in a register
//
// if x is in a register
//       2     x is signed
//     [3:6]   x's register number
// else
//     [2:6]   x's constant value
//
// if y is in a register
//     [7:10]  y's register number
// else
//     [7:11]  y's constant value
//
// The final integer is c * numBoundsCode + code

// TODO: 32-bit

// Encode bounds failure information into an integer for PCDATA_PanicBounds.
// Register numbers must be in 0-15. Constants must be in 0-31.
func ( BoundsErrorCode, , ,  bool, ,  int) int {
	 := int(0)
	if  {
		 |= 1 << 0
		if  {
			 |= 1 << 2
		}
		if  < 0 ||  > BoundsMaxReg {
			panic("bad xReg")
		}
		 |=  << 3
	} else {
		if  < 0 ||  > BoundsMaxConst {
			panic("bad xConst")
		}
		 |=  << 2
	}
	if  {
		 |= 1 << 1
		if  < 0 ||  > BoundsMaxReg {
			panic("bad yReg")
		}
		 |=  << 7
	} else {
		if  < 0 ||  > BoundsMaxConst {
			panic("bad yConst")
		}
		 |=  << 7
	}
	return *int(numBoundsCodes) + int()
}
func ( int) ( BoundsErrorCode, , ,  bool, ,  int) {
	 = BoundsErrorCode( % int(numBoundsCodes))
	 :=  / int(numBoundsCodes)
	 = &1 != 0
	 >>= 1
	 = &1 != 0
	 >>= 1
	if  {
		 = &1 != 0
		 >>= 1
		 =  & 0xf
		 >>= 4
	} else {
		 =  & 0x1f
		 >>= 5
	}
	if  {
		 =  & 0xf
		 >>= 4
	} else {
		 =  & 0x1f
		 >>= 5
	}
	if  != 0 {
		panic("BoundsDecode decoding error")
	}
	return
}