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 The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -1059,10 +1059,11 @@ class Expression ...@@ -1059,10 +1059,11 @@ class Expression
static Expression* static Expression*
import_expression(Import_expression*, Location); import_expression(Import_expression*, Location);
// Return an expression which checks that VAL, of arbitrary integer type, // Insert bounds checks for an index expression.
// is non-negative and is not more than the maximum integer value. static void
static Expression* check_bounds(Expression* val, Operator, Expression* bound, Runtime::Function,
check_bounds(Expression* val, Location); Runtime::Function, Runtime::Function, Runtime::Function,
Statement_inserter*, Location);
// Return an expression for constructing a direct interface type from a // Return an expression for constructing a direct interface type from a
// pointer. // pointer.
...@@ -2998,7 +2999,7 @@ class Array_index_expression : public Expression ...@@ -2998,7 +2999,7 @@ class Array_index_expression : public Expression
Expression* end, Expression* cap, Location location) Expression* end, Expression* cap, Location location)
: Expression(EXPRESSION_ARRAY_INDEX, location), : Expression(EXPRESSION_ARRAY_INDEX, location),
array_(array), start_(start), end_(end), cap_(cap), type_(NULL), 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. // Return the array.
...@@ -3121,6 +3122,8 @@ class Array_index_expression : public Expression ...@@ -3121,6 +3122,8 @@ class Array_index_expression : public Expression
bool is_lvalue_; bool is_lvalue_;
// Whether bounds check is needed. // Whether bounds check is needed.
bool needs_bounds_check_; bool needs_bounds_check_;
// Whether this has already been flattened.
bool is_flattened_;
}; };
// A string index. This is used for both indexing and slicing. // A string index. This is used for both indexing and slicing.
...@@ -3131,7 +3134,7 @@ class String_index_expression : public Expression ...@@ -3131,7 +3134,7 @@ class String_index_expression : public Expression
String_index_expression(Expression* string, Expression* start, String_index_expression(Expression* string, Expression* start,
Expression* end, Location location) Expression* end, Location location)
: Expression(EXPRESSION_STRING_INDEX, 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. // Return the string being indexed.
...@@ -3203,6 +3206,8 @@ class String_index_expression : public Expression ...@@ -3203,6 +3206,8 @@ class String_index_expression : public Expression
// The end index of a slice. This may be NULL for a single index, // 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. // or it may be a nil expression for the length of the string.
Expression* end_; Expression* end_;
// Whether this has already been flattened.
bool is_flattened_;
}; };
// An index into a map. // An index into a map.
......
...@@ -6300,6 +6300,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no) ...@@ -6300,6 +6300,7 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
} }
if (this->asm_name_ == "runtime.gopanic" if (this->asm_name_ == "runtime.gopanic"
|| this->asm_name_.compare(0, 15, "runtime.goPanic") == 0
|| this->asm_name_ == "__go_runtime_error" || this->asm_name_ == "__go_runtime_error"
|| this->asm_name_ == "runtime.panicdottype" || this->asm_name_ == "runtime.panicdottype"
|| this->asm_name_ == "runtime.block") || this->asm_name_ == "runtime.block")
......
...@@ -30,6 +30,8 @@ enum Runtime_function_type ...@@ -30,6 +30,8 @@ enum Runtime_function_type
RFT_BOOLPTR, RFT_BOOLPTR,
// Go type int, C type intgo. // Go type int, C type intgo.
RFT_INT, RFT_INT,
// Go type uint, C type uintgo.
RFT_UINT,
// Go type uint8, C type uint8_t. // Go type uint8, C type uint8_t.
RFT_UINT8, RFT_UINT8,
// Go type uint16, C type uint16_t. // Go type uint16, C type uint16_t.
...@@ -113,6 +115,10 @@ runtime_function_type(Runtime_function_type bft) ...@@ -113,6 +115,10 @@ runtime_function_type(Runtime_function_type bft)
t = Type::lookup_integer_type("int"); t = Type::lookup_integer_type("int");
break; break;
case RFT_UINT:
t = Type::lookup_integer_type("uint");
break;
case RFT_UINT8: case RFT_UINT8:
t = Type::lookup_integer_type("uint8"); t = Type::lookup_integer_type("uint8");
break; break;
...@@ -262,6 +268,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e, ...@@ -262,6 +268,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_BOOL: case RFT_BOOL:
case RFT_BOOLPTR: case RFT_BOOLPTR:
case RFT_INT: case RFT_INT:
case RFT_UINT:
case RFT_UINT8: case RFT_UINT8:
case RFT_UINT16: case RFT_UINT16:
case RFT_INT32: case RFT_INT32:
......
...@@ -499,6 +499,75 @@ DEF_GO_RUNTIME(ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", ...@@ -499,6 +499,75 @@ DEF_GO_RUNTIME(ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1",
P3(POINTER, UINT8, INT32), P3(POINTER, UINT8, INT32),
R1(UINT8)) 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. // Remove helper macros.
#undef ABFT6 #undef ABFT6
#undef ABFT2 #undef ABFT2
......
...@@ -79,6 +79,21 @@ func unquote(s string) string { ...@@ -79,6 +79,21 @@ func unquote(s string) string {
return string(r[:j]) 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. // An errorString represents a runtime error described by a single string.
type errorString string type errorString string
...@@ -114,6 +129,99 @@ func (e plainError) Error() string { ...@@ -114,6 +129,99 @@ func (e plainError) Error() string {
return string(e) 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 { type stringer interface {
String() string String() string
} }
......
...@@ -23,81 +23,189 @@ import ( ...@@ -23,81 +23,189 @@ import (
//go:linkname makefuncreturning runtime.makefuncreturning //go:linkname makefuncreturning runtime.makefuncreturning
//go:linkname gorecover runtime.gorecover //go:linkname gorecover runtime.gorecover
//go:linkname deferredrecover runtime.deferredrecover //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 //go:linkname panicmem runtime.panicmem
// Temporary for C code to call: // Temporary for C code to call:
//go:linkname throw runtime.throw //go:linkname throw runtime.throw
// Calling panic with one of the errors below will call errorString.Error // Check to make sure we can really generate a panic. If the panic
// which will call mallocgc to concatenate strings. That will fail if // was generated from the runtime, or from inside malloc, then convert
// malloc is locked, causing a confusing error message. Throw a better // to a throw of msg.
// error message instead. // pc should be the program counter of the compiler-generated code that
func panicCheckMalloc(err error) { // 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() gp := getg()
if gp != nil && gp.m != nil && gp.m.mallocing != 0 { 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, // code generated by the compiler for out of bounds index expressions,
// out of bounds slice expressions, and division by zero. The // out of bounds slice expressions, division by zero, and shift by negative.
// panicdivide (again), panicoverflow, panicfloat, and panicmem // The panicdivide (again), panicoverflow, panicfloat, and panicmem
// functions are called by the signal handler when a signal occurs // functions are called by the signal handler when a signal occurs
// indicating the respective problem. // 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 // 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 // runtime package we turn the panic into a throw. That will dump the
// entire runtime stack for easier debugging. // 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() { // failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))
name, _, _, _ := funcfileline(getcallerpc()-1, -1) func goPanicSliceAlen(x int, y int) {
if hasPrefix(name, "runtime.") { panicCheck1(getcallerpc(), "slice bounds out of range")
throw(string(indexError.(errorString))) panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAlen})
} }
panicCheckMalloc(indexError) func goPanicSliceAlenU(x uint, y int) {
panic(indexError) 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() { // failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))
name, _, _, _ := funcfileline(getcallerpc()-1, -1) func goPanicSlice3Alen(x int, y int) {
if hasPrefix(name, "runtime.") { panicCheck1(getcallerpc(), "slice bounds out of range")
throw(string(sliceError.(errorString))) panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Alen})
} }
panicCheckMalloc(sliceError) func goPanicSlice3AlenU(x uint, y int) {
panic(sliceError) 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")) var divideError = error(errorString("integer divide by zero"))
func panicdivide() { func panicdivide() {
panicCheckMalloc(divideError) panicCheck2("integer divide by zero")
panic(divideError) panic(divideError)
} }
var overflowError = error(errorString("integer overflow")) var overflowError = error(errorString("integer overflow"))
func panicoverflow() { func panicoverflow() {
panicCheckMalloc(overflowError) panicCheck2("integer overflow")
panic(overflowError) panic(overflowError)
} }
var floatError = error(errorString("floating point error")) var floatError = error(errorString("floating point error"))
func panicfloat() { func panicfloat() {
panicCheckMalloc(floatError) panicCheck2("floating point error")
panic(floatError) panic(floatError)
} }
var memoryError = error(errorString("invalid memory address or nil pointer dereference")) var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
func panicmem() { func panicmem() {
panicCheckMalloc(memoryError) panicCheck2("invalid memory address or nil pointer dereference")
panic(memoryError) 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 ...@@ -15,14 +15,15 @@ rm -f runtime.inc.tmp2 runtime.inc.tmp3
# types and should not be exported back to C # 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 # 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. # 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 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 for pattern in '_[GP][a-z]' _Max _Lock _Sig _Trace _MHeap _Num
do do
grep "#define $pattern" ${IN} >> runtime.inc.tmp2 grep "#define $pattern" ${IN} >> runtime.inc.tmp2
done done
TYPES="_Complex_lock _Reader_lock semt" TYPES="_Complex_lock _Reader_lock semt boundsError"
for TYPE in $TYPES for TYPE in $TYPES
do do
sed -e '/struct '${TYPE}' {/,/^}/s/^.*$//' runtime.inc.tmp2 > runtime.inc.tmp3; 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