aboutsummaryrefslogtreecommitdiff
path: root/base/runtime/error_checks.odin
diff options
context:
space:
mode:
Diffstat (limited to 'base/runtime/error_checks.odin')
-rw-r--r--base/runtime/error_checks.odin292
1 files changed, 292 insertions, 0 deletions
diff --git a/base/runtime/error_checks.odin b/base/runtime/error_checks.odin
new file mode 100644
index 000000000..ea6333c29
--- /dev/null
+++ b/base/runtime/error_checks.odin
@@ -0,0 +1,292 @@
+package runtime
+
+@(no_instrumentation)
+bounds_trap :: proc "contextless" () -> ! {
+ when ODIN_OS == .Windows {
+ windows_trap_array_bounds()
+ } else {
+ trap()
+ }
+}
+
+@(no_instrumentation)
+type_assertion_trap :: proc "contextless" () -> ! {
+ when ODIN_OS == .Windows {
+ windows_trap_type_assertion()
+ } else {
+ trap()
+ }
+}
+
+
+bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) {
+ if uint(index) < uint(count) {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (file: string, line, column: i32, index, count: int) -> ! {
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Index ")
+ print_i64(i64(index))
+ print_string(" is out of range 0..<")
+ print_i64(i64(count))
+ print_byte('\n')
+ bounds_trap()
+ }
+ handle_error(file, line, column, index, count)
+}
+
+@(no_instrumentation)
+slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) -> ! {
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Invalid slice indices ")
+ print_i64(i64(lo))
+ print_string(":")
+ print_i64(i64(hi))
+ print_string(" is out of range 0..<")
+ print_i64(i64(len))
+ print_byte('\n')
+ bounds_trap()
+}
+
+@(no_instrumentation)
+multi_pointer_slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) -> ! {
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Invalid slice indices ")
+ print_i64(i64(lo))
+ print_string(":")
+ print_i64(i64(hi))
+ print_byte('\n')
+ bounds_trap()
+}
+
+
+multi_pointer_slice_expr_error :: proc "contextless" (file: string, line, column: i32, lo, hi: int) {
+ if lo <= hi {
+ return
+ }
+ multi_pointer_slice_handle_error(file, line, column, lo, hi)
+}
+
+slice_expr_error_hi :: proc "contextless" (file: string, line, column: i32, hi: int, len: int) {
+ if 0 <= hi && hi <= len {
+ return
+ }
+ slice_handle_error(file, line, column, 0, hi, len)
+}
+
+slice_expr_error_lo_hi :: proc "contextless" (file: string, line, column: i32, lo, hi: int, len: int) {
+ if 0 <= lo && lo <= len && lo <= hi && hi <= len {
+ return
+ }
+ slice_handle_error(file, line, column, lo, hi, len)
+}
+
+dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) {
+ if 0 <= low && low <= high && high <= max {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (file: string, line, column: i32, low, high, max: int) -> ! {
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Invalid dynamic array indices ")
+ print_i64(i64(low))
+ print_string(":")
+ print_i64(i64(high))
+ print_string(" is out of range 0..<")
+ print_i64(i64(max))
+ print_byte('\n')
+ bounds_trap()
+ }
+ handle_error(file, line, column, low, high, max)
+}
+
+
+matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) {
+ if uint(row_index) < uint(row_count) &&
+ uint(column_index) < uint(column_count) {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) -> ! {
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Matrix indices [")
+ print_i64(i64(row_index))
+ print_string(", ")
+ print_i64(i64(column_index))
+ print_string(" is out of range [0..<")
+ print_i64(i64(row_count))
+ print_string(", 0..<")
+ print_i64(i64(column_count))
+ print_string("]")
+ print_byte('\n')
+ bounds_trap()
+ }
+ handle_error(file, line, column, row_index, column_index, row_count, column_count)
+}
+
+
+when ODIN_NO_RTTI {
+ type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32) {
+ if ok {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (file: string, line, column: i32) -> ! {
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Invalid type assertion\n")
+ type_assertion_trap()
+ }
+ handle_error(file, line, column)
+ }
+
+ type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32) {
+ if ok {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (file: string, line, column: i32) -> ! {
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Invalid type assertion\n")
+ type_assertion_trap()
+ }
+ handle_error(file, line, column)
+ }
+} else {
+ type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) {
+ if ok {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid) -> ! {
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Invalid type assertion from ")
+ print_typeid(from)
+ print_string(" to ")
+ print_typeid(to)
+ print_byte('\n')
+ type_assertion_trap()
+ }
+ handle_error(file, line, column, from, to)
+ }
+
+ type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
+ if ok {
+ return
+ }
+
+ variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid {
+ if id == nil || data == nil {
+ return id
+ }
+ ti := type_info_base(type_info_of(id))
+ #partial switch v in ti.variant {
+ case Type_Info_Any:
+ return (^any)(data).id
+ case Type_Info_Union:
+ tag_ptr := uintptr(data) + v.tag_offset
+ idx := 0
+ switch v.tag_type.size {
+ case 1: idx = int((^u8)(tag_ptr)^) - 1
+ case 2: idx = int((^u16)(tag_ptr)^) - 1
+ case 4: idx = int((^u32)(tag_ptr)^) - 1
+ case 8: idx = int((^u64)(tag_ptr)^) - 1
+ case 16: idx = int((^u128)(tag_ptr)^) - 1
+ }
+ if idx < 0 {
+ return nil
+ } else if idx < len(v.variants) {
+ return v.variants[idx].id
+ }
+ }
+ return id
+ }
+
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) -> ! {
+
+ actual := variant_type(from, from_data)
+
+ print_caller_location(Source_Code_Location{file, line, column, ""})
+ print_string(" Invalid type assertion from ")
+ print_typeid(from)
+ print_string(" to ")
+ print_typeid(to)
+ if actual != from {
+ print_string(", actual type: ")
+ print_typeid(actual)
+ }
+ print_byte('\n')
+ type_assertion_trap()
+ }
+ handle_error(file, line, column, from, to, from_data)
+ }
+}
+
+
+make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len: int) {
+ if 0 <= len {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) -> ! {
+ print_caller_location(loc)
+ print_string(" Invalid slice length for make: ")
+ print_i64(i64(len))
+ print_byte('\n')
+ bounds_trap()
+ }
+ handle_error(loc, len)
+}
+
+make_dynamic_array_error_loc :: #force_inline proc "contextless" (loc := #caller_location, len, cap: int) {
+ if 0 <= len && len <= cap {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) -> ! {
+ print_caller_location(loc)
+ print_string(" Invalid dynamic array parameters for make: ")
+ print_i64(i64(len))
+ print_byte(':')
+ print_i64(i64(cap))
+ print_byte('\n')
+ bounds_trap()
+ }
+ handle_error(loc, len, cap)
+}
+
+make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_location, cap: int) {
+ if 0 <= cap {
+ return
+ }
+ @(cold, no_instrumentation)
+ handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) -> ! {
+ print_caller_location(loc)
+ print_string(" Invalid map capacity for make: ")
+ print_i64(i64(cap))
+ print_byte('\n')
+ bounds_trap()
+ }
+ handle_error(loc, cap)
+}
+
+
+
+
+
+bounds_check_error_loc :: #force_inline proc "contextless" (loc := #caller_location, index, count: int) {
+ bounds_check_error(loc.file_path, loc.line, loc.column, index, count)
+}
+
+slice_expr_error_hi_loc :: #force_inline proc "contextless" (loc := #caller_location, hi: int, len: int) {
+ slice_expr_error_hi(loc.file_path, loc.line, loc.column, hi, len)
+}
+
+slice_expr_error_lo_hi_loc :: #force_inline proc "contextless" (loc := #caller_location, lo, hi: int, len: int) {
+ slice_expr_error_lo_hi(loc.file_path, loc.line, loc.column, lo, hi, len)
+}
+
+dynamic_array_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_location, low, high, max: int) {
+ dynamic_array_expr_error(loc.file_path, loc.line, loc.column, low, high, max)
+}