github.com/primecitizens/pcz/std@v0.2.1/runtime/panic.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright 2023 The Prime Citizens
     3  
     4  //go:build pcz
     5  
     6  package runtime
     7  
     8  import (
     9  	"github.com/primecitizens/pcz/std/core/abi"
    10  	"github.com/primecitizens/pcz/std/core/assert"
    11  	"github.com/primecitizens/pcz/std/core/debug"
    12  )
    13  
    14  // see $GOROOT/src/runtime/panic.go
    15  
    16  func throwinit() {
    17  	// TODO
    18  }
    19  
    20  func panicdivide() { assert.Throw("integer", "divide", "by", "zero") }
    21  func panicshift()  { assert.Throw("negative", "shift", "amount") }
    22  
    23  // panicwrap generates a panic for a call to a wrapped value method
    24  // with a nil pointer receiver.
    25  //
    26  // It is called from the generated wrapper code.
    27  func panicwrap() {
    28  	pc := getcallerpc()
    29  	println("value", "method", abi.FindFunc(pc).Name(), "called", "using", "nil", "pointer")
    30  	debug.Abort()
    31  }
    32  
    33  // failures in the comparisons for s[x], 0 <= x < y (y == len(s))
    34  func goPanicIndex(x int, y int) {
    35  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsIndex})
    36  }
    37  
    38  func goPanicIndexU(x uint, y int) {
    39  	panicBoundsError(boundsError{x: int64(x), signed: false, y: y, code: boundsIndex})
    40  }
    41  
    42  // failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))
    43  func goPanicSliceAlen(x int, y int) {
    44  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAlen})
    45  }
    46  
    47  func goPanicSliceAlenU(x uint, y int) {
    48  	panicBoundsError(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAlen})
    49  }
    50  
    51  func goPanicSliceAcap(x int, y int) {
    52  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAcap})
    53  }
    54  
    55  func goPanicSliceAcapU(x uint, y int) {
    56  	panicBoundsError(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAcap})
    57  }
    58  
    59  // failures in the comparisons for s[x:y], 0 <= x <= y
    60  func goPanicSliceB(x int, y int) {
    61  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceB})
    62  }
    63  
    64  func goPanicSliceBU(x uint, y int) {
    65  	panicBoundsError(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceB})
    66  }
    67  
    68  // failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))
    69  func goPanicSlice3Alen(x int, y int) {
    70  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Alen})
    71  }
    72  
    73  func goPanicSlice3AlenU(x uint, y int) {
    74  	panicBoundsError(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Alen})
    75  }
    76  
    77  func goPanicSlice3Acap(x int, y int) {
    78  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Acap})
    79  }
    80  
    81  func goPanicSlice3AcapU(x uint, y int) {
    82  	panicBoundsError(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Acap})
    83  }
    84  
    85  func goPanicSlice3B(x int, y int) {
    86  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3B})
    87  }
    88  
    89  func goPanicSlice3BU(x uint, y int) {
    90  	panicBoundsError(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3B})
    91  }
    92  
    93  func goPanicSlice3C(x int, y int) {
    94  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3C})
    95  }
    96  
    97  func goPanicSlice3CU(x uint, y int) {
    98  	panicBoundsError(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C})
    99  }
   100  
   101  // failures in the conversion ([x]T)(s) or (*[x]T)(s), 0 <= x <= y, y == len(s)
   102  func goPanicSliceConvert(x int, y int) {
   103  	panicBoundsError(boundsError{x: int64(x), signed: true, y: y, code: boundsConvert})
   104  }
   105  
   106  func panicBoundsError(e boundsError) {
   107  	if e.code == boundsConvert {
   108  		println(
   109  			"runtime", "error:", "cannot", "convert", "slice", "with", "length", e.y,
   110  			"to", "array", "or", "pointer", "to", "array", "with", "length", e.x,
   111  		)
   112  		debug.Abort()
   113  		return
   114  	}
   115  
   116  	if e.signed && e.x < 0 {
   117  		before, after := negBoundsErrorCode(e.code).fmt()
   118  		println("runtime", "error:", before, e.x, after)
   119  		debug.Abort()
   120  		return
   121  	}
   122  
   123  	before, between, after := e.code.fmt()
   124  	println("runtime", "error:", before, e.x, between, e.y, after)
   125  	debug.Abort()
   126  	return
   127  }
   128  
   129  // A boundsError represents an indexing or slicing operation gone wrong.
   130  type boundsError struct {
   131  	x int64
   132  	y int
   133  	// Values in an index or slice expression can be signed or unsigned.
   134  	// That means we'd need 65 bits to encode all possible indexes, from -2^63 to 2^64-1.
   135  	// Instead, we keep track of whether x should be interpreted as signed or unsigned.
   136  	// y is known to be nonnegative and to fit in an int.
   137  	signed bool
   138  	code   boundsErrorCode
   139  }
   140  
   141  const (
   142  	boundsIndex = iota // s[x], 0 <= x < len(s) failed
   143  
   144  	boundsSliceAlen // s[?:x], 0 <= x <= len(s) failed
   145  	boundsSliceAcap // s[?:x], 0 <= x <= cap(s) failed
   146  	boundsSliceB    // s[x:y], 0 <= x <= y failed (but boundsSliceA didn't happen)
   147  
   148  	boundsSlice3Alen // s[?:?:x], 0 <= x <= len(s) failed
   149  	boundsSlice3Acap // s[?:?:x], 0 <= x <= cap(s) failed
   150  	boundsSlice3B    // s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen)
   151  	boundsSlice3C    // s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen)
   152  
   153  	boundsConvert // (*[x]T)(s), 0 <= x <= len(s) failed
   154  	// Note: in the above, len(s) and cap(s) are stored in y
   155  )
   156  
   157  type boundsErrorCode uint8
   158  
   159  func (c boundsErrorCode) fmt() (before, between, after string) {
   160  	switch c {
   161  	case boundsIndex:
   162  		return "index out of range [", "] with length", ""
   163  	case boundsSliceAlen:
   164  		return "slice bounds out of range [:", "] with length", ""
   165  	case boundsSliceAcap:
   166  		return "slice bounds out of range [:", "] with capacity", ""
   167  	case boundsSliceB:
   168  		return "slice bounds out of range [", ":", "]"
   169  	case boundsSlice3Alen:
   170  		return "slice bounds out of range [::", "] with length", ""
   171  	case boundsSlice3Acap:
   172  		return "slice bounds out of range [::", "] with capacity", ""
   173  	case boundsSlice3B:
   174  		return "slice bounds out of range [:", ":", "]"
   175  	case boundsSlice3C:
   176  		return "slice bounds out of range [", ":", ":]"
   177  	default:
   178  		assert.Unreachable()
   179  		return
   180  	}
   181  }
   182  
   183  type negBoundsErrorCode boundsErrorCode
   184  
   185  func (c negBoundsErrorCode) fmt() (before, after string) {
   186  	switch c {
   187  	case boundsIndex:
   188  		return "index out of range [", "]"
   189  	case boundsSliceAlen:
   190  		return "slice bounds out of range [:", "]"
   191  	case boundsSliceAcap:
   192  		return "slice bounds out of range [:", "]"
   193  	case boundsSliceB:
   194  		return "slice bounds out of range [", ":]"
   195  	case boundsSlice3Alen:
   196  		return "slice bounds out of range [::", "]"
   197  	case boundsSlice3Acap:
   198  		return "slice bounds out of range [::", "]"
   199  	case boundsSlice3B:
   200  		return "slice bounds out of range [:", ":]"
   201  	case boundsSlice3C:
   202  		return "slice bounds out of range [", "::]"
   203  	default:
   204  		assert.Unreachable()
   205  		return
   206  	}
   207  }
   208  
   209  // Implemented in assembly, as they take arguments in registers.
   210  // Declared here to mark them as ABIInternal.
   211  
   212  func panicIndex(x int, y int)
   213  func panicIndexU(x uint, y int)
   214  func panicSliceAlen(x int, y int)
   215  func panicSliceAlenU(x uint, y int)
   216  func panicSliceAcap(x int, y int)
   217  func panicSliceAcapU(x uint, y int)
   218  func panicSliceB(x int, y int)
   219  func panicSliceBU(x uint, y int)
   220  func panicSlice3Alen(x int, y int)
   221  func panicSlice3AlenU(x uint, y int)
   222  func panicSlice3Acap(x int, y int)
   223  func panicSlice3AcapU(x uint, y int)
   224  func panicSlice3B(x int, y int)
   225  func panicSlice3BU(x uint, y int)
   226  func panicSlice3C(x int, y int)
   227  func panicSlice3CU(x uint, y int)
   228  func panicSliceConvert(x int, y int)