error_checks.odin 5.9 KB

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