error_checks.odin 6.1 KB

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