error_checks.odin 8.0 KB

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