error_checks.odin 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. package runtime
  2. @(no_instrumentation)
  3. bounds_trap :: proc "contextless" () -> ! {
  4. when ODIN_OS == .Windows {
  5. windows_trap_array_bounds()
  6. } else when ODIN_OS == .Orca {
  7. abort_ext("", "", 0, "bounds trap")
  8. } else {
  9. trap()
  10. }
  11. }
  12. @(no_instrumentation)
  13. type_assertion_trap :: proc "contextless" () -> ! {
  14. when ODIN_OS == .Windows {
  15. windows_trap_type_assertion()
  16. } else when ODIN_OS == .Orca {
  17. abort_ext("", "", 0, "type assertion trap")
  18. } else {
  19. trap()
  20. }
  21. }
  22. @(disabled=ODIN_NO_BOUNDS_CHECK)
  23. bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) {
  24. if uint(index) < uint(count) {
  25. return
  26. }
  27. @(cold, no_instrumentation)
  28. handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) -> ! {
  29. print_caller_location(Source_Code_Location{file, line, column, ""})
  30. print_string(" Index ")
  31. print_i64(i64(index))
  32. print_string(" is out of range 0..<")
  33. print_i64(i64(count))
  34. print_byte('\n')
  35. bounds_trap()
  36. }
  37. handle_error(file, line, column, index, count)
  38. }
  39. @(no_instrumentation)
  40. slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! {
  41. print_caller_location(Source_Code_Location{file, line, column, ""})
  42. print_string(" Invalid slice indices ")
  43. print_i64(i64(lo))
  44. print_string(":")
  45. print_i64(i64(hi))
  46. print_string(" is out of range 0..<")
  47. print_i64(i64(len))
  48. print_byte('\n')
  49. bounds_trap()
  50. }
  51. @(no_instrumentation)
  52. multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! {
  53. print_caller_location(Source_Code_Location{file, line, column, ""})
  54. print_string(" Invalid slice indices ")
  55. print_i64(i64(lo))
  56. print_string(":")
  57. print_i64(i64(hi))
  58. print_byte('\n')
  59. bounds_trap()
  60. }
  61. @(disabled=ODIN_NO_BOUNDS_CHECK)
  62. multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) {
  63. if lo <= hi {
  64. return
  65. }
  66. multi_pointer_slice_handle_error(file, line, column, lo, hi)
  67. }
  68. @(disabled=ODIN_NO_BOUNDS_CHECK)
  69. slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) {
  70. if 0 <= hi && hi <= len {
  71. return
  72. }
  73. slice_handle_error(file, line, column, 0, hi, len)
  74. }
  75. @(disabled=ODIN_NO_BOUNDS_CHECK)
  76. slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) {
  77. if 0 <= lo && lo <= len && lo <= hi && hi <= len {
  78. return
  79. }
  80. slice_handle_error(file, line, column, lo, hi, len)
  81. }
  82. @(disabled=ODIN_NO_BOUNDS_CHECK)
  83. dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) {
  84. if 0 <= low && low <= high && high <= max {
  85. return
  86. }
  87. @(cold, no_instrumentation)
  88. handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) -> ! {
  89. print_caller_location(Source_Code_Location{file, line, column, ""})
  90. print_string(" Invalid dynamic array indices ")
  91. print_i64(i64(low))
  92. print_string(":")
  93. print_i64(i64(high))
  94. print_string(" is out of range 0..<")
  95. print_i64(i64(max))
  96. print_byte('\n')
  97. bounds_trap()
  98. }
  99. handle_error(file, line, column, low, high, max)
  100. }
  101. @(disabled=ODIN_NO_BOUNDS_CHECK)
  102. matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) {
  103. if uint(row_index) < uint(row_count) &&
  104. uint(column_index) < uint(column_count) {
  105. return
  106. }
  107. @(cold, no_instrumentation)
  108. handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) -> ! {
  109. print_caller_location(Source_Code_Location{file, line, column, ""})
  110. print_string(" Matrix indices [")
  111. print_i64(i64(row_index))
  112. print_string(", ")
  113. print_i64(i64(column_index))
  114. print_string(" is out of range [0..<")
  115. print_i64(i64(row_count))
  116. print_string(", 0..<")
  117. print_i64(i64(column_count))
  118. print_string("]")
  119. print_byte('\n')
  120. bounds_trap()
  121. }
  122. handle_error(file, line, column, row_index, column_index, row_count, column_count)
  123. }
  124. when ODIN_NO_RTTI {
  125. type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32) {
  126. if ok {
  127. return
  128. }
  129. @(cold, no_instrumentation)
  130. handle_error :: proc "contextless" (file: string, line, column: i32) -> ! {
  131. print_caller_location(Source_Code_Location{file, line, column, ""})
  132. print_string(" Invalid type assertion\n")
  133. type_assertion_trap()
  134. }
  135. handle_error(file, line, column)
  136. }
  137. type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32) {
  138. if ok {
  139. return
  140. }
  141. @(cold, no_instrumentation)
  142. handle_error :: proc "contextless" (file: string, line, column: i32) -> ! {
  143. print_caller_location(Source_Code_Location{file, line, column, ""})
  144. print_string(" Invalid type assertion\n")
  145. type_assertion_trap()
  146. }
  147. handle_error(file, line, column)
  148. }
  149. } else {
  150. type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) {
  151. if ok {
  152. return
  153. }
  154. @(cold, no_instrumentation)
  155. handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) -> ! {
  156. print_caller_location(Source_Code_Location{file, line, column, ""})
  157. print_string(" Invalid type assertion from ")
  158. print_typeid(from)
  159. print_string(" to ")
  160. print_typeid(to)
  161. print_byte('\n')
  162. type_assertion_trap()
  163. }
  164. handle_error(file, line, column, from, to)
  165. }
  166. type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
  167. if ok {
  168. return
  169. }
  170. variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid {
  171. if id == nil || data == nil {
  172. return id
  173. }
  174. ti := type_info_base(type_info_of(id))
  175. #partial switch v in ti.variant {
  176. case Type_Info_Any:
  177. return (^any)(data).id
  178. case Type_Info_Union:
  179. tag_ptr := uintptr(data) + v.tag_offset
  180. idx := 0
  181. switch v.tag_type.size {
  182. case 1: idx = int((^u8)(tag_ptr)^) - 1
  183. case 2: idx = int((^u16)(tag_ptr)^) - 1
  184. case 4: idx = int((^u32)(tag_ptr)^) - 1
  185. case 8: idx = int((^u64)(tag_ptr)^) - 1
  186. case 16: idx = int((^u128)(tag_ptr)^) - 1
  187. }
  188. if idx < 0 {
  189. return nil
  190. } else if idx < len(v.variants) {
  191. return v.variants[idx].id
  192. }
  193. }
  194. return id
  195. }
  196. @(cold, no_instrumentation)
  197. handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) -> ! {
  198. actual := variant_type(from, from_data)
  199. print_caller_location(Source_Code_Location{file, line, column, ""})
  200. print_string(" Invalid type assertion from ")
  201. print_typeid(from)
  202. print_string(" to ")
  203. print_typeid(to)
  204. if actual != from {
  205. print_string(", actual type: ")
  206. print_typeid(actual)
  207. }
  208. print_byte('\n')
  209. type_assertion_trap()
  210. }
  211. handle_error(file, line, column, from, to, from_data)
  212. }
  213. }
  214. @(disabled=ODIN_NO_BOUNDS_CHECK)
  215. make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len: int) {
  216. if 0 <= len {
  217. return
  218. }
  219. @(cold, no_instrumentation)
  220. handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) -> ! {
  221. print_caller_location(loc)
  222. print_string(" Invalid slice length for make: ")
  223. print_i64(i64(len))
  224. print_byte('\n')
  225. bounds_trap()
  226. }
  227. handle_error(loc, len)
  228. }
  229. @(disabled=ODIN_NO_BOUNDS_CHECK)
  230. make_dynamic_array_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len, cap: int) {
  231. if 0 <= len && len <= cap {
  232. return
  233. }
  234. @(cold, no_instrumentation)
  235. handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) -> ! {
  236. print_caller_location(loc)
  237. print_string(" Invalid dynamic array parameters for make: ")
  238. print_i64(i64(len))
  239. print_byte(':')
  240. print_i64(i64(cap))
  241. print_byte('\n')
  242. bounds_trap()
  243. }
  244. handle_error(loc, len, cap)
  245. }
  246. @(disabled=ODIN_NO_BOUNDS_CHECK)
  247. make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_location, cap: int) {
  248. if 0 <= cap {
  249. return
  250. }
  251. @(cold, no_instrumentation)
  252. handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) -> ! {
  253. print_caller_location(loc)
  254. print_string(" Invalid map capacity for make: ")
  255. print_i64(i64(cap))
  256. print_byte('\n')
  257. bounds_trap()
  258. }
  259. handle_error(loc, cap)
  260. }
  261. @(disabled=ODIN_NO_BOUNDS_CHECK)
  262. bounds_check_error_loc :: #force_inline proc "contextless" (loc := #caller_location, index, count: int) {
  263. bounds_check_error(loc.file_path, loc.line, loc.column, index, count)
  264. }
  265. @(disabled=ODIN_NO_BOUNDS_CHECK)
  266. slice_expr_error_hi_loc :: #force_inline proc "contextless" (loc := #caller_location, hi: int, len: int) {
  267. slice_expr_error_hi(loc.file_path, loc.line, loc.column, hi, len)
  268. }
  269. @(disabled=ODIN_NO_BOUNDS_CHECK)
  270. slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (loc := #caller_location, lo, hi: int, len: int) {
  271. slice_expr_error_lo_hi(loc.file_path, loc.line, loc.column, lo, hi, len)
  272. }
  273. @(disabled=ODIN_NO_BOUNDS_CHECK)
  274. dynamic_array_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_location, low, high, max: int) {
  275. dynamic_array_expr_error(loc.file_path, loc.line, loc.column, low, high, max)
  276. }