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)