error_checks.odin 8.4 KB

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