Commit fc4f90f0 by Ian Lance Taylor

compiler, runtime: provide index information on bounds check failure

    
    This implements https://golang.org/cl/161477 in the gofrontend.
    
    Updates golang/go#30116
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/191881

From-SVN: r274998
parent 464969eb
a6ddd0e1208a7d229c10be630c1110b3914038f5
189ff44b2c26f29f41f0eb159e0d8f3fa508ecae
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
......@@ -1059,10 +1059,11 @@ class Expression
static Expression*
import_expression(Import_expression*, Location);
// Return an expression which checks that VAL, of arbitrary integer type,
// is non-negative and is not more than the maximum integer value.
static Expression*
check_bounds(Expression* val, Location);
// Insert bounds checks for an index expression.
static void
check_bounds(Expression* val, Operator, Expression* bound, Runtime::Function,
Runtime::Function, Runtime::Function, Runtime::Function,
Statement_inserter*, Location);
// Return an expression for constructing a direct interface type from a
// pointer.
......@@ -2998,7 +2999,7 @@ class Array_index_expression : public Expression
Expression* end, Expression* cap, Location location)
: Expression(EXPRESSION_ARRAY_INDEX, location),
array_(array), start_(start), end_(end), cap_(cap), type_(NULL),
is_lvalue_(false), needs_bounds_check_(true)
is_lvalue_(false), needs_bounds_check_(true), is_flattened_(false)
{ }
// Return the array.
......@@ -3121,6 +3122,8 @@ class Array_index_expression : public Expression
bool is_lvalue_;
// Whether bounds check is needed.
bool needs_bounds_check_;
// Whether this has already been flattened.
bool is_flattened_;
};
// A string index. This is used for both indexing and slicing.
......@@ -3131,7 +3134,7 @@ class String_index_expression : public Expression
String_index_expression(Expression* string, Expression* start,
Expression* end, Location location)
: Expression(EXPRESSION_STRING_INDEX, location),
string_(string), start_(start), end_(end)
string_(string), start_(start), end_(end), is_flattened_(false)
{ }
// Return the string being indexed.
......@@ -3203,6 +3206,8 @@ class String_index_expression : public Expression
// The end index of a slice. This may be NULL for a single index,
// or it may be a nil expression for the length of the string.
Expression* end_;
// Whether this has already been flattened.
bool is_flattened_;
};
// An index into a map.
......
......@@ -6300,6 +6300,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
}
if (this->asm_name_ == "runtime.gopanic"
|| this->asm_name_.compare(0, 15, "runtime.goPanic") == 0
|| this->asm_name_ == "__go_runtime_error"
|| this->asm_name_ == "runtime.panicdottype"
|| this->asm_name_ == "runtime.block")
......
......@@ -30,6 +30,8 @@ enum Runtime_function_type
RFT_BOOLPTR,
// Go type int, C type intgo.
RFT_INT,
// Go type uint, C type uintgo.
RFT_UINT,
// Go type uint8, C type uint8_t.
RFT_UINT8,
// Go type uint16, C type uint16_t.
......@@ -113,6 +115,10 @@ runtime_function_type(Runtime_function_type bft)
t = Type::lookup_integer_type("int");
break;
case RFT_UINT:
t = Type::lookup_integer_type("uint");
break;
case RFT_UINT8:
t = Type::lookup_integer_type("uint8");
break;
......@@ -262,6 +268,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_BOOL:
case RFT_BOOLPTR:
case RFT_INT:
case RFT_UINT:
case RFT_UINT8:
case RFT_UINT16:
case RFT_INT32:
......
......@@ -499,6 +499,75 @@ DEF_GO_RUNTIME(ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1",
P3(POINTER, UINT8, INT32),
R1(UINT8))
// Panics reporting an index or slice out of bounds error.
DEF_GO_RUNTIME(PANIC_INDEX, "runtime.goPanicIndex",
P2(INT, INT), R0())
DEF_GO_RUNTIME(PANIC_INDEX_U, "runtime.goPanicIndexU",
P2(UINT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE_ALEN, "runtime.goPanicSliceAlen",
P2(INT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE_ALEN_U, "runtime.goPanicSliceAlenU",
P2(UINT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE_ACAP, "runtime.goPanicSliceAcap",
P2(INT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE_ACAP_U, "runtime.goPanicSliceAcapU",
P2(UINT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE_B, "runtime.goPanicSliceB",
P2(INT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE_B_U, "runtime.goPanicSliceBU",
P2(UINT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE3_ALEN, "runtime.goPanicSlice3Alen",
P2(INT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE3_ALEN_U, "runtime.goPanicSlice3AlenU",
P2(UINT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE3_ACAP, "runtime.goPanicSlice3Acap",
P2(INT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE3_ACAP_U, "runtime.goPanicSlice3AcapU",
P2(UINT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE3_B, "runtime.goPanicSlice3B",
P2(INT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE3_B_U, "runtime.goPanicSlice3BU",
P2(UINT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE3_C, "runtime.goPanicSlice3C",
P2(INT, INT), R0())
DEF_GO_RUNTIME(PANIC_SLICE3_C_U, "runtime.goPanicSlice3CU",
P2(UINT, INT), R0())
// Panics reporting an index or slice out of bounds error with a
// 64-bit index type. These are only used by 32-bit targets.
DEF_GO_RUNTIME(PANIC_EXTEND_INDEX, "runtime.goPanicExtendIndex",
P2(INT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_INDEX_U, "runtime.goPanicExtendIndexU",
P2(UINT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE_ALEN, "runtime.goPanicExtendSliceAlen",
P2(INT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE_ALEN_U, "runtime.goPanicExtendSliceAlenU",
P2(UINT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE_ACAP, "runtime.goPanicExtendSliceAcap",
P2(INT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE_ACAP_U, "runtime.goPanicExtendSliceAcapU",
P2(UINT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE_B, "runtime.goPanicExtendSliceB",
P2(INT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE_B_U, "runtime.goPanicExtendSliceBU",
P2(UINT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE3_ALEN, "runtime.goPanicExtendSlice3Alen",
P2(INT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE3_ALEN_U, "runtime.goPanicExtendSlice3AlenU",
P2(UINT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE3_ACAP, "runtime.goPanicExtendSlice3Acap",
P2(INT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE3_ACAP_U, "runtime.goPanicExtendSlice3AcapU",
P2(UINT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE3_B, "runtime.goPanicExtendSlice3B",
P2(INT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE3_B_U, "runtime.goPanicExtendSlice3BU",
P2(UINT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE3_C, "runtime.goPanicExtendSlice3C",
P2(INT64, INT), R0())
DEF_GO_RUNTIME(PANIC_EXTEND_SLICE3_C_U, "runtime.goPanicExtendSlice3CU",
P2(UINT64, INT), R0())
// Remove helper macros.
#undef ABFT6
#undef ABFT2
......
......@@ -79,6 +79,21 @@ func unquote(s string) string {
return string(r[:j])
}
//go:nosplit
// itoa converts val to a decimal representation. The result is
// written somewhere within buf and the location of the result is returned.
// buf must be at least 20 bytes.
func itoa(buf []byte, val uint64) []byte {
i := len(buf) - 1
for val >= 10 {
buf[i] = byte(val%10 + '0')
i--
val /= 10
}
buf[i] = byte(val + '0')
return buf[i:]
}
// An errorString represents a runtime error described by a single string.
type errorString string
......@@ -114,6 +129,99 @@ func (e plainError) Error() string {
return string(e)
}
// An boundsError represents a an indexing or slicing operation gone wrong.
type boundsError struct {
x int64
y int
// Values in an index or slice expression can be signed or unsigned.
// That means we'd need 65 bits to encode all possible indexes, from -2^63 to 2^64-1.
// 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.
signed bool
code 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)
// Note: in the above, len(s) and cap(s) are stored in y
)
// boundsErrorFmts provide error text for various out-of-bounds panics.
// Note: if you change these strings, you should adjust the size of the buffer
// in boundsError.Error below as well.
var boundsErrorFmts = [...]string{
boundsIndex: "index out of range [%x] with length %y",
boundsSliceAlen: "slice bounds out of range [:%x] with length %y",
boundsSliceAcap: "slice bounds out of range [:%x] with capacity %y",
boundsSliceB: "slice bounds out of range [%x:%y]",
boundsSlice3Alen: "slice bounds out of range [::%x] with length %y",
boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y",
boundsSlice3B: "slice bounds out of range [:%x:%y]",
boundsSlice3C: "slice bounds out of range [%x:%y:]",
}
// boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y.
var boundsNegErrorFmts = [...]string{
boundsIndex: "index out of range [%x]",
boundsSliceAlen: "slice bounds out of range [:%x]",
boundsSliceAcap: "slice bounds out of range [:%x]",
boundsSliceB: "slice bounds out of range [%x:]",
boundsSlice3Alen: "slice bounds out of range [::%x]",
boundsSlice3Acap: "slice bounds out of range [::%x]",
boundsSlice3B: "slice bounds out of range [:%x:]",
boundsSlice3C: "slice bounds out of range [%x::]",
}
func (e boundsError) RuntimeError() {}
func appendIntStr(b []byte, v int64, signed bool) []byte {
if signed && v < 0 {
b = append(b, '-')
v = -v
}
var buf [20]byte
b = append(b, itoa(buf[:], uint64(v))...)
return b
}
func (e boundsError) Error() string {
fmt := boundsErrorFmts[e.code]
if e.signed && e.x < 0 {
fmt = boundsNegErrorFmts[e.code]
}
// max message length is 99: "runtime error: slice bounds out of range [::%x] with capacity %y"
// x can be at most 20 characters. y can be at most 19.
b := make([]byte, 0, 100)
b = append(b, "runtime error: "...)
for i := 0; i < len(fmt); i++ {
c := fmt[i]
if c != '%' {
b = append(b, c)
continue
}
i++
switch fmt[i] {
case 'x':
b = appendIntStr(b, e.x, e.signed)
case 'y':
b = appendIntStr(b, int64(e.y), true)
}
}
return string(b)
}
type stringer interface {
String() string
}
......
......@@ -23,81 +23,189 @@ import (
//go:linkname makefuncreturning runtime.makefuncreturning
//go:linkname gorecover runtime.gorecover
//go:linkname deferredrecover runtime.deferredrecover
//go:linkname goPanicIndex runtime.goPanicIndex
//go:linkname goPanicIndexU runtime.goPanicIndexU
//go:linkname goPanicSliceAlen runtime.goPanicSliceAlen
//go:linkname goPanicSliceAlenU runtime.goPanicSliceAlenU
//go:linkname goPanicSliceAcap runtime.goPanicSliceAcap
//go:linkname goPanicSliceAcapU runtime.goPanicSliceAcapU
//go:linkname goPanicSliceB runtime.goPanicSliceB
//go:linkname goPanicSliceBU runtime.goPanicSliceBU
//go:linkname goPanicSlice3Alen runtime.goPanicSlice3Alen
//go:linkname goPanicSlice3AlenU runtime.goPanicSlice3AlenU
//go:linkname goPanicSlice3Acap runtime.goPanicSlice3Acap
//go:linkname goPanicSlice3AcapU runtime.goPanicSlice3AcapU
//go:linkname goPanicSlice3B runtime.goPanicSlice3B
//go:linkname goPanicSlice3BU runtime.goPanicSlice3BU
//go:linkname goPanicSlice3C runtime.goPanicSlice3C
//go:linkname goPanicSlice3CU runtime.goPanicSlice3CU
//go:linkname panicmem runtime.panicmem
// Temporary for C code to call:
//go:linkname throw runtime.throw
// Calling panic with one of the errors below will call errorString.Error
// which will call mallocgc to concatenate strings. That will fail if
// malloc is locked, causing a confusing error message. Throw a better
// error message instead.
func panicCheckMalloc(err error) {
// Check to make sure we can really generate a panic. If the panic
// was generated from the runtime, or from inside malloc, then convert
// to a throw of msg.
// pc should be the program counter of the compiler-generated code that
// triggered this panic.
func panicCheck1(pc uintptr, msg string) {
name, _, _, _ := funcfileline(pc-1, -1)
if hasPrefix(name, "runtime.") {
throw(msg)
}
// TODO: is this redundant? How could we be in malloc
// but not in the runtime? runtime/internal/*, maybe?
gp := getg()
if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
throw(string(err.(errorString)))
throw(msg)
}
}
var indexError = error(errorString("index out of range"))
// Same as above, but calling from the runtime is allowed.
//
// Using this function is necessary for any panic that may be
// generated by runtime.sigpanic, since those are always called by the
// runtime.
func panicCheck2(err string) {
// panic allocates, so to avoid recursive malloc, turn panics
// during malloc into throws.
gp := getg()
if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
throw(err)
}
}
// The panicindex, panicslice, and panicdivide functions are called by
// Many of the following panic entry-points turn into throws when they
// happen in various runtime contexts. These should never happen in
// the runtime, and if they do, they indicate a serious issue and
// should not be caught by user code.
//
// The panic{Index,Slice,divide,shift} functions are called by
// code generated by the compiler for out of bounds index expressions,
// out of bounds slice expressions, and division by zero. The
// panicdivide (again), panicoverflow, panicfloat, and panicmem
// out of bounds slice expressions, division by zero, and shift by negative.
// The panicdivide (again), panicoverflow, panicfloat, and panicmem
// functions are called by the signal handler when a signal occurs
// indicating the respective problem.
//
// Since panicindex and panicslice are never called directly, and
// Since panic{Index,Slice,shift} are never called directly, and
// since the runtime package should never have an out of bounds slice
// or array reference, if we see those functions called from the
// or array reference or negative shift, if we see those functions called from the
// runtime package we turn the panic into a throw. That will dump the
// entire runtime stack for easier debugging.
//
// The entry points called by the signal handler will be called from
// runtime.sigpanic, so we can't disallow calls from the runtime to
// these (they always look like they're called from the runtime).
// Hence, for these, we just check for clearly bad runtime conditions.
// failures in the comparisons for s[x], 0 <= x < y (y == len(s))
func goPanicIndex(x int, y int) {
panicCheck1(getcallerpc(), "index out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsIndex})
}
func goPanicIndexU(x uint, y int) {
panicCheck1(getcallerpc(), "index out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsIndex})
}
func panicindex() {
name, _, _, _ := funcfileline(getcallerpc()-1, -1)
if hasPrefix(name, "runtime.") {
throw(string(indexError.(errorString)))
}
panicCheckMalloc(indexError)
panic(indexError)
// failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))
func goPanicSliceAlen(x int, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAlen})
}
func goPanicSliceAlenU(x uint, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAlen})
}
func goPanicSliceAcap(x int, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAcap})
}
func goPanicSliceAcapU(x uint, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAcap})
}
var sliceError = error(errorString("slice bounds out of range"))
// failures in the comparisons for s[x:y], 0 <= x <= y
func goPanicSliceB(x int, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceB})
}
func goPanicSliceBU(x uint, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceB})
}
func panicslice() {
name, _, _, _ := funcfileline(getcallerpc()-1, -1)
if hasPrefix(name, "runtime.") {
throw(string(sliceError.(errorString)))
}
panicCheckMalloc(sliceError)
panic(sliceError)
// failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))
func goPanicSlice3Alen(x int, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Alen})
}
func goPanicSlice3AlenU(x uint, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Alen})
}
func goPanicSlice3Acap(x int, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Acap})
}
func goPanicSlice3AcapU(x uint, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Acap})
}
// failures in the comparisons for s[:x:y], 0 <= x <= y
func goPanicSlice3B(x int, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3B})
}
func goPanicSlice3BU(x uint, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3B})
}
// failures in the comparisons for s[x:y:], 0 <= x <= y
func goPanicSlice3C(x int, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3C})
}
func goPanicSlice3CU(x uint, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C})
}
var shiftError = error(errorString("negative shift amount"))
func panicshift() {
panicCheck1(getcallerpc(), "negative shift amount")
panic(shiftError)
}
var divideError = error(errorString("integer divide by zero"))
func panicdivide() {
panicCheckMalloc(divideError)
panicCheck2("integer divide by zero")
panic(divideError)
}
var overflowError = error(errorString("integer overflow"))
func panicoverflow() {
panicCheckMalloc(overflowError)
panicCheck2("integer overflow")
panic(overflowError)
}
var floatError = error(errorString("floating point error"))
func panicfloat() {
panicCheckMalloc(floatError)
panicCheck2("floating point error")
panic(floatError)
}
var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
func panicmem() {
panicCheckMalloc(memoryError)
panicCheck2("invalid memory address or nil pointer dereference")
panic(memoryError)
}
......
// Copyright 2019 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.
// +build 386 amd64p32 arm mips mipsle m68k nios2 sh shbe
package runtime
import _ "unsafe" // for go:linkname
// For gccgo, use go:linkname to rename compiler-called functions to
// themselves, so that the compiler will export them.
//
//go:linkname goPanicExtendIndex runtime.goPanicExtendIndex
//go:linkname goPanicExtendIndexU runtime.goPanicExtendIndexU
//go:linkname goPanicExtendSliceAlen runtime.goPanicExtendSliceAlen
//go:linkname goPanicExtendSliceAlenU runtime.goPanicExtendSliceAlenU
//go:linkname goPanicExtendSliceAcap runtime.goPanicExtendSliceAcap
//go:linkname goPanicExtendSliceAcapU runtime.goPanicExtendSliceAcapU
//go:linkname goPanicExtendSliceB runtime.goPanicExtendSliceB
//go:linkname goPanicExtendSliceBU runtime.goPanicExtendSliceBU
//go:linkname goPanicExtendSlice3Alen runtime.goPanicExtendSlice3Alen
//go:linkname goPanicExtendSlice3AlenU runtime.goPanicExtendSlice3AlenU
//go:linkname goPanicExtendSlice3Acap runtime.goPanicExtendSlice3Acap
//go:linkname goPanicExtendSlice3AcapU runtime.goPanicExtendSlice3AcapU
//go:linkname goPanicExtendSlice3B runtime.goPanicExtendSlice3B
//go:linkname goPanicExtendSlice3BU runtime.goPanicExtendSlice3BU
//go:linkname goPanicExtendSlice3C runtime.goPanicExtendSlice3C
//go:linkname goPanicExtendSlice3CU runtime.goPanicExtendSlice3CU
// Additional index/slice error paths for 32-bit platforms.
// Used when the high word of a 64-bit index is not zero.
// failures in the comparisons for s[x], 0 <= x < y (y == len(s))
func goPanicExtendIndex(x int64, y int) {
panicCheck1(getcallerpc(), "index out of range")
panic(boundsError{x: x, signed: true, y: y, code: boundsIndex})
}
func goPanicExtendIndexU(x uint64, y int) {
panicCheck1(getcallerpc(), "index out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsIndex})
}
// failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))
func goPanicExtendSliceAlen(x int64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: x, signed: true, y: y, code: boundsSliceAlen})
}
func goPanicExtendSliceAlenU(x uint64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAlen})
}
func goPanicExtendSliceAcap(x int64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: x, signed: true, y: y, code: boundsSliceAcap})
}
func goPanicExtendSliceAcapU(x uint64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAcap})
}
// failures in the comparisons for s[x:y], 0 <= x <= y
func goPanicExtendSliceB(x int64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: x, signed: true, y: y, code: boundsSliceB})
}
func goPanicExtendSliceBU(x uint64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceB})
}
// failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))
func goPanicExtendSlice3Alen(x int64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: x, signed: true, y: y, code: boundsSlice3Alen})
}
func goPanicExtendSlice3AlenU(x uint64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Alen})
}
func goPanicExtendSlice3Acap(x int64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: x, signed: true, y: y, code: boundsSlice3Acap})
}
func goPanicExtendSlice3AcapU(x uint64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Acap})
}
// failures in the comparisons for s[:x:y], 0 <= x <= y
func goPanicExtendSlice3B(x int64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: x, signed: true, y: y, code: boundsSlice3B})
}
func goPanicExtendSlice3BU(x uint64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3B})
}
// failures in the comparisons for s[x:y:], 0 <= x <= y
func goPanicExtendSlice3C(x int64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: x, signed: true, y: y, code: boundsSlice3C})
}
func goPanicExtendSlice3CU(x uint64, y int) {
panicCheck1(getcallerpc(), "slice bounds out of range")
panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C})
}
......@@ -15,14 +15,15 @@ rm -f runtime.inc.tmp2 runtime.inc.tmp3
# types and should not be exported back to C
# semt is a Go translation of the C type sem_t; it fails to convert on
# some systems and need not be exported back to C.
# sigset conflicts with system type sigset on AIX, so we need to rename it
# sigset conflicts with system type sigset on AIX, so we need to rename it.
# boundsError has a field name that is a C keyword, and we don't need it.
grep -v "#define _" ${IN} | grep -v "#define [cm][01234] " | grep -v "#define empty " | grep -v "#define \\$" > runtime.inc.tmp2
for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num
do
grep "#define $pattern" ${IN} >> runtime.inc.tmp2
done
TYPES="_Complex_lock _Reader_lock semt"
TYPES="_Complex_lock _Reader_lock semt boundsError"
for TYPE in $TYPES
do
sed -e '/struct '${TYPE}' {/,/^}/s/^.*$//' runtime.inc.tmp2 > runtime.inc.tmp3;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment