error_checks.odin 6.4 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. }