runtime: move bounds check constants to internal/abi

For future use by the compiler.

Change-Id: Id3da62006b283ac38008261c0ef88aaf71ef5896
Reviewed-on: https://go-review.googlesource.com/c/go/+/682456
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Keith Randall 2025-06-17 14:44:56 -07:00
parent ce05ad448f
commit 741a19ab41
4 changed files with 73 additions and 69 deletions

View file

@ -0,0 +1,21 @@
// 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
)

View file

@ -132,52 +132,34 @@ type boundsError struct {
// Instead, we keep track of whether x should be interpreted as signed or unsigned. // Instead, we keep track of whether x should be interpreted as signed or unsigned.
// y is known to be nonnegative and to fit in an int. // y is known to be nonnegative and to fit in an int.
signed bool signed bool
code boundsErrorCode code abi.BoundsErrorCode
} }
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
// Note: in the above, len(s) and cap(s) are stored in y
)
// boundsErrorFmts provide error text for various out-of-bounds panics. // boundsErrorFmts provide error text for various out-of-bounds panics.
// Note: if you change these strings, you should adjust the size of the buffer // Note: if you change these strings, you should adjust the size of the buffer
// in boundsError.Error below as well. // in boundsError.Error below as well.
var boundsErrorFmts = [...]string{ var boundsErrorFmts = [...]string{
boundsIndex: "index out of range [%x] with length %y", abi.BoundsIndex: "index out of range [%x] with length %y",
boundsSliceAlen: "slice bounds out of range [:%x] with length %y", abi.BoundsSliceAlen: "slice bounds out of range [:%x] with length %y",
boundsSliceAcap: "slice bounds out of range [:%x] with capacity %y", abi.BoundsSliceAcap: "slice bounds out of range [:%x] with capacity %y",
boundsSliceB: "slice bounds out of range [%x:%y]", abi.BoundsSliceB: "slice bounds out of range [%x:%y]",
boundsSlice3Alen: "slice bounds out of range [::%x] with length %y", abi.BoundsSlice3Alen: "slice bounds out of range [::%x] with length %y",
boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y", abi.BoundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y",
boundsSlice3B: "slice bounds out of range [:%x:%y]", abi.BoundsSlice3B: "slice bounds out of range [:%x:%y]",
boundsSlice3C: "slice bounds out of range [%x:%y:]", abi.BoundsSlice3C: "slice bounds out of range [%x:%y:]",
boundsConvert: "cannot convert slice with length %y to array or pointer to array with length %x", abi.BoundsConvert: "cannot convert slice with length %y to array or pointer to array with length %x",
} }
// boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y. // boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y.
var boundsNegErrorFmts = [...]string{ var boundsNegErrorFmts = [...]string{
boundsIndex: "index out of range [%x]", abi.BoundsIndex: "index out of range [%x]",
boundsSliceAlen: "slice bounds out of range [:%x]", abi.BoundsSliceAlen: "slice bounds out of range [:%x]",
boundsSliceAcap: "slice bounds out of range [:%x]", abi.BoundsSliceAcap: "slice bounds out of range [:%x]",
boundsSliceB: "slice bounds out of range [%x:]", abi.BoundsSliceB: "slice bounds out of range [%x:]",
boundsSlice3Alen: "slice bounds out of range [::%x]", abi.BoundsSlice3Alen: "slice bounds out of range [::%x]",
boundsSlice3Acap: "slice bounds out of range [::%x]", abi.BoundsSlice3Acap: "slice bounds out of range [::%x]",
boundsSlice3B: "slice bounds out of range [:%x:]", abi.BoundsSlice3B: "slice bounds out of range [:%x:]",
boundsSlice3C: "slice bounds out of range [%x::]", abi.BoundsSlice3C: "slice bounds out of range [%x::]",
} }
func (e boundsError) RuntimeError() {} func (e boundsError) RuntimeError() {}

View file

@ -112,13 +112,13 @@ func panicCheck2(err string) {
//go:yeswritebarrierrec //go:yeswritebarrierrec
func goPanicIndex(x int, y int) { func goPanicIndex(x int, y int) {
panicCheck1(sys.GetCallerPC(), "index out of range") panicCheck1(sys.GetCallerPC(), "index out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsIndex}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsIndex})
} }
//go:yeswritebarrierrec //go:yeswritebarrierrec
func goPanicIndexU(x uint, y int) { func goPanicIndexU(x uint, y int) {
panicCheck1(sys.GetCallerPC(), "index out of range") panicCheck1(sys.GetCallerPC(), "index out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsIndex}) panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsIndex})
} }
// failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s)) // failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))
@ -126,25 +126,25 @@ func goPanicIndexU(x uint, y int) {
//go:yeswritebarrierrec //go:yeswritebarrierrec
func goPanicSliceAlen(x int, y int) { func goPanicSliceAlen(x int, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAlen}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSliceAlen})
} }
//go:yeswritebarrierrec //go:yeswritebarrierrec
func goPanicSliceAlenU(x uint, y int) { func goPanicSliceAlenU(x uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAlen}) panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSliceAlen})
} }
//go:yeswritebarrierrec //go:yeswritebarrierrec
func goPanicSliceAcap(x int, y int) { func goPanicSliceAcap(x int, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAcap}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSliceAcap})
} }
//go:yeswritebarrierrec //go:yeswritebarrierrec
func goPanicSliceAcapU(x uint, y int) { func goPanicSliceAcapU(x uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAcap}) panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSliceAcap})
} }
// failures in the comparisons for s[x:y], 0 <= x <= y // failures in the comparisons for s[x:y], 0 <= x <= y
@ -152,57 +152,57 @@ func goPanicSliceAcapU(x uint, y int) {
//go:yeswritebarrierrec //go:yeswritebarrierrec
func goPanicSliceB(x int, y int) { func goPanicSliceB(x int, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceB}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSliceB})
} }
//go:yeswritebarrierrec //go:yeswritebarrierrec
func goPanicSliceBU(x uint, y int) { func goPanicSliceBU(x uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceB}) panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSliceB})
} }
// failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s)) // failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))
func goPanicSlice3Alen(x int, y int) { func goPanicSlice3Alen(x int, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Alen}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSlice3Alen})
} }
func goPanicSlice3AlenU(x uint, y int) { func goPanicSlice3AlenU(x uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Alen}) panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSlice3Alen})
} }
func goPanicSlice3Acap(x int, y int) { func goPanicSlice3Acap(x int, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Acap}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSlice3Acap})
} }
func goPanicSlice3AcapU(x uint, y int) { func goPanicSlice3AcapU(x uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Acap}) panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSlice3Acap})
} }
// failures in the comparisons for s[:x:y], 0 <= x <= y // failures in the comparisons for s[:x:y], 0 <= x <= y
func goPanicSlice3B(x int, y int) { func goPanicSlice3B(x int, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3B}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSlice3B})
} }
func goPanicSlice3BU(x uint, y int) { func goPanicSlice3BU(x uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3B}) panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSlice3B})
} }
// failures in the comparisons for s[x:y:], 0 <= x <= y // failures in the comparisons for s[x:y:], 0 <= x <= y
func goPanicSlice3C(x int, y int) { func goPanicSlice3C(x int, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3C}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSlice3C})
} }
func goPanicSlice3CU(x uint, y int) { func goPanicSlice3CU(x uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C}) panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSlice3C})
} }
// failures in the conversion ([x]T)(s) or (*[x]T)(s), 0 <= x <= y, y == len(s) // failures in the conversion ([x]T)(s) or (*[x]T)(s), 0 <= x <= y, y == len(s)
func goPanicSliceConvert(x int, y int) { func goPanicSliceConvert(x int, y int) {
panicCheck1(sys.GetCallerPC(), "slice length too short to convert to array or pointer to array") panicCheck1(sys.GetCallerPC(), "slice length too short to convert to array or pointer to array")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsConvert}) panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsConvert})
} }
// Implemented in assembly, as they take arguments in registers. // Implemented in assembly, as they take arguments in registers.

View file

@ -7,6 +7,7 @@
package runtime package runtime
import ( import (
"internal/abi"
"internal/runtime/sys" "internal/runtime/sys"
) )
@ -16,77 +17,77 @@ import (
// failures in the comparisons for s[x], 0 <= x < y (y == len(s)) // failures in the comparisons for s[x], 0 <= x < y (y == len(s))
func goPanicExtendIndex(hi int, lo uint, y int) { func goPanicExtendIndex(hi int, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "index out of range") panicCheck1(sys.GetCallerPC(), "index out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: boundsIndex}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: abi.BoundsIndex})
} }
func goPanicExtendIndexU(hi uint, lo uint, y int) { func goPanicExtendIndexU(hi uint, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "index out of range") panicCheck1(sys.GetCallerPC(), "index out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: boundsIndex}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: abi.BoundsIndex})
} }
// failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s)) // failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))
func goPanicExtendSliceAlen(hi int, lo uint, y int) { func goPanicExtendSliceAlen(hi int, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: boundsSliceAlen}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: abi.BoundsSliceAlen})
} }
func goPanicExtendSliceAlenU(hi uint, lo uint, y int) { func goPanicExtendSliceAlenU(hi uint, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: boundsSliceAlen}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: abi.BoundsSliceAlen})
} }
func goPanicExtendSliceAcap(hi int, lo uint, y int) { func goPanicExtendSliceAcap(hi int, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: boundsSliceAcap}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: abi.BoundsSliceAcap})
} }
func goPanicExtendSliceAcapU(hi uint, lo uint, y int) { func goPanicExtendSliceAcapU(hi uint, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: boundsSliceAcap}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: abi.BoundsSliceAcap})
} }
// failures in the comparisons for s[x:y], 0 <= x <= y // failures in the comparisons for s[x:y], 0 <= x <= y
func goPanicExtendSliceB(hi int, lo uint, y int) { func goPanicExtendSliceB(hi int, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: boundsSliceB}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: abi.BoundsSliceB})
} }
func goPanicExtendSliceBU(hi uint, lo uint, y int) { func goPanicExtendSliceBU(hi uint, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: boundsSliceB}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: abi.BoundsSliceB})
} }
// failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s)) // failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))
func goPanicExtendSlice3Alen(hi int, lo uint, y int) { func goPanicExtendSlice3Alen(hi int, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: boundsSlice3Alen}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: abi.BoundsSlice3Alen})
} }
func goPanicExtendSlice3AlenU(hi uint, lo uint, y int) { func goPanicExtendSlice3AlenU(hi uint, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: boundsSlice3Alen}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: abi.BoundsSlice3Alen})
} }
func goPanicExtendSlice3Acap(hi int, lo uint, y int) { func goPanicExtendSlice3Acap(hi int, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: boundsSlice3Acap}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: abi.BoundsSlice3Acap})
} }
func goPanicExtendSlice3AcapU(hi uint, lo uint, y int) { func goPanicExtendSlice3AcapU(hi uint, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: boundsSlice3Acap}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: abi.BoundsSlice3Acap})
} }
// failures in the comparisons for s[:x:y], 0 <= x <= y // failures in the comparisons for s[:x:y], 0 <= x <= y
func goPanicExtendSlice3B(hi int, lo uint, y int) { func goPanicExtendSlice3B(hi int, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: boundsSlice3B}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: abi.BoundsSlice3B})
} }
func goPanicExtendSlice3BU(hi uint, lo uint, y int) { func goPanicExtendSlice3BU(hi uint, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: boundsSlice3B}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: abi.BoundsSlice3B})
} }
// failures in the comparisons for s[x:y:], 0 <= x <= y // failures in the comparisons for s[x:y:], 0 <= x <= y
func goPanicExtendSlice3C(hi int, lo uint, y int) { func goPanicExtendSlice3C(hi int, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: boundsSlice3C}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: true, y: y, code: abi.BoundsSlice3C})
} }
func goPanicExtendSlice3CU(hi uint, lo uint, y int) { func goPanicExtendSlice3CU(hi uint, lo uint, y int) {
panicCheck1(sys.GetCallerPC(), "slice bounds out of range") panicCheck1(sys.GetCallerPC(), "slice bounds out of range")
panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: boundsSlice3C}) panic(boundsError{x: int64(hi)<<32 + int64(lo), signed: false, y: y, code: abi.BoundsSlice3C})
} }
// Implemented in assembly, as they take arguments in registers. // Implemented in assembly, as they take arguments in registers.