error_checks.odin 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 0 <= index && index < count {
  18. return
  19. }
  20. handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) {
  21. print_caller_location(Source_Code_Location{file, line, column, ""})
  22. print_string(" Index ")
  23. print_i64(i64(index))
  24. print_string(" is out of bounds range 0:")
  25. print_i64(i64(count))
  26. print_byte('\n')
  27. bounds_trap()
  28. }
  29. handle_error(file, line, column, index, count)
  30. }
  31. slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! {
  32. print_caller_location(Source_Code_Location{file, line, column, ""})
  33. print_string(" Invalid slice indices: ")
  34. print_i64(i64(lo))
  35. print_string(":")
  36. print_i64(i64(hi))
  37. print_string(":")
  38. print_i64(i64(len))
  39. print_byte('\n')
  40. bounds_trap()
  41. }
  42. multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! {
  43. print_caller_location(Source_Code_Location{file, line, column, ""})
  44. print_string(" Invalid slice indices: ")
  45. print_i64(i64(lo))
  46. print_string(":")
  47. print_i64(i64(hi))
  48. print_byte('\n')
  49. bounds_trap()
  50. }
  51. multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) {
  52. if lo <= hi {
  53. return
  54. }
  55. multi_pointer_slice_handle_error(file, line, column, lo, hi)
  56. }
  57. slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) {
  58. if 0 <= hi && hi <= len {
  59. return
  60. }
  61. slice_handle_error(file, line, column, 0, hi, len)
  62. }
  63. slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) {
  64. if 0 <= lo && lo <= len && lo <= hi && hi <= len {
  65. return
  66. }
  67. slice_handle_error(file, line, column, lo, hi, len)
  68. }
  69. dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) {
  70. if 0 <= low && low <= high && high <= max {
  71. return
  72. }
  73. handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) {
  74. print_caller_location(Source_Code_Location{file, line, column, ""})
  75. print_string(" Invalid dynamic array values: ")
  76. print_i64(i64(low))
  77. print_string(":")
  78. print_i64(i64(high))
  79. print_string(":")
  80. print_i64(i64(max))
  81. print_byte('\n')
  82. bounds_trap()
  83. }
  84. handle_error(file, line, column, low, high, max)
  85. }
  86. type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) {
  87. if ok {
  88. return
  89. }
  90. handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) {
  91. print_caller_location(Source_Code_Location{file, line, column, ""})
  92. print_string(" Invalid type assertion from ")
  93. print_typeid(from)
  94. print_string(" to ")
  95. print_typeid(to)
  96. print_byte('\n')
  97. type_assertion_trap()
  98. }
  99. handle_error(file, line, column, from, to)
  100. }
  101. type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
  102. if ok {
  103. return
  104. }
  105. variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid {
  106. if id == nil || data == nil {
  107. return id
  108. }
  109. ti := type_info_base(type_info_of(id))
  110. #partial switch v in ti.variant {
  111. case Type_Info_Any:
  112. return (^any)(data).id
  113. case Type_Info_Union:
  114. tag_ptr := uintptr(data) + v.tag_offset
  115. idx := 0
  116. switch v.tag_type.size {
  117. case 1: idx = int((^u8)(tag_ptr)^) - 1
  118. case 2: idx = int((^u16)(tag_ptr)^) - 1
  119. case 4: idx = int((^u32)(tag_ptr)^) - 1
  120. case 8: idx = int((^u64)(tag_ptr)^) - 1
  121. case 16: idx = int((^u128)(tag_ptr)^) - 1
  122. }
  123. if idx < 0 {
  124. return nil
  125. } else if idx < len(v.variants) {
  126. return v.variants[idx].id
  127. }
  128. }
  129. return id
  130. }
  131. handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
  132. actual := variant_type(from, from_data)
  133. print_caller_location(Source_Code_Location{file, line, column, ""})
  134. print_string(" Invalid type assertion from ")
  135. print_typeid(from)
  136. print_string(" to ")
  137. print_typeid(to)
  138. if actual != from {
  139. print_string(", actual type: ")
  140. print_typeid(actual)
  141. }
  142. print_byte('\n')
  143. type_assertion_trap()
  144. }
  145. handle_error(file, line, column, from, to, from_data)
  146. }
  147. make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len: int) {
  148. if 0 <= len {
  149. return
  150. }
  151. handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) {
  152. print_caller_location(loc)
  153. print_string(" Invalid slice length for make: ")
  154. print_i64(i64(len))
  155. print_byte('\n')
  156. bounds_trap()
  157. }
  158. handle_error(loc, len)
  159. }
  160. make_dynamic_array_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, len, cap: int) {
  161. if 0 <= len && len <= cap {
  162. return
  163. }
  164. handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) {
  165. print_caller_location(loc)
  166. print_string(" Invalid dynamic array parameters for make: ")
  167. print_i64(i64(len))
  168. print_byte(':')
  169. print_i64(i64(cap))
  170. print_byte('\n')
  171. bounds_trap()
  172. }
  173. handle_error(loc, len, cap)
  174. }
  175. make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_location, cap: int) {
  176. if 0 <= cap {
  177. return
  178. }
  179. handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) {
  180. print_caller_location(loc)
  181. print_string(" Invalid map capacity for make: ")
  182. print_i64(i64(cap))
  183. print_byte('\n')
  184. bounds_trap()
  185. }
  186. handle_error(loc, cap)
  187. }
  188. bounds_check_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, index, count: int) {
  189. bounds_check_error(file_path, line, column, index, count)
  190. }
  191. slice_expr_error_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, hi: int, len: int) {
  192. slice_expr_error_hi(file_path, line, column, hi, len)
  193. }
  194. slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (using loc := #caller_location, lo, hi: int, len: int) {
  195. slice_expr_error_lo_hi(file_path, line, column, lo, hi, len)
  196. }
  197. dynamic_array_expr_error_loc :: #force_inline proc "contextless" (using loc := #caller_location, low, high, max: int) {
  198. dynamic_array_expr_error(file_path, line, column, low, high, max)
  199. }