diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 36884950c..dd27cf2e0 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -522,6 +522,21 @@ init_global_temporary_allocator :: proc(data: []byte, backup_allocator := contex } +default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) { + fd := os_stderr(); + print_caller_location(fd, loc); + print_string(fd, " "); + print_string(fd, prefix); + if len(message) > 0 { + print_string(fd, ": "); + print_string(fd, message); + } + print_byte(fd, '\n'); + debug_trap(); +} + + + @builtin copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int { diff --git a/core/runtime/defaults.odin b/core/runtime/defaults.odin deleted file mode 100644 index c2536d61a..000000000 --- a/core/runtime/defaults.odin +++ /dev/null @@ -1,21 +0,0 @@ -package runtime - -import "core:os" - -current_thread_id :: proc "contextless" () -> int { - return os.current_thread_id(); -} - -default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) { - fd := os.stderr; - print_caller_location(fd, loc); - os.write_string(fd, " "); - os.write_string(fd, prefix); - if len(message) > 0 { - os.write_string(fd, ": "); - os.write_string(fd, message); - } - os.write_byte(fd, '\n'); - debug_trap(); -} - diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin index 1e1251c38..aed2bfbac 100644 --- a/core/runtime/error_checks.odin +++ b/core/runtime/error_checks.odin @@ -1,8 +1,5 @@ package runtime -import "core:os" - - bounds_trap :: proc "contextless" () -> ! { when ODIN_OS == "windows" { windows_trap_array_bounds(); @@ -24,13 +21,13 @@ bounds_check_error :: proc "contextless" (file: string, line, column: int, index if 0 <= index && index < count do return; handle_error :: proc "contextless" (file: string, line, column: int, index, count: int) { context = default_context(); - fd := os.stderr; + fd := os_stderr(); print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); - os.write_string(fd, " Index "); + print_string(fd, " Index "); print_i64(fd, i64(index)); - os.write_string(fd, " is out of bounds range 0:"); + print_string(fd, " is out of bounds range 0:"); print_i64(fd, i64(count)); - os.write_byte(fd, '\n'); + print_byte(fd, '\n'); bounds_trap(); } handle_error(file, line, column, index, count); @@ -38,15 +35,15 @@ bounds_check_error :: proc "contextless" (file: string, line, column: int, index slice_handle_error :: proc "contextless" (file: string, line, column: int, lo, hi: int, len: int) { context = default_context(); - fd := os.stderr; + fd := os_stderr(); print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); - os.write_string(fd, " Invalid slice indices: "); + print_string(fd, " Invalid slice indices: "); print_i64(fd, i64(lo)); - os.write_string(fd, ":"); + print_string(fd, ":"); print_i64(fd, i64(hi)); - os.write_string(fd, ":"); + print_string(fd, ":"); print_i64(fd, i64(len)); - os.write_byte(fd, '\n'); + print_byte(fd, '\n'); bounds_trap(); } @@ -64,15 +61,15 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: int, if 0 <= low && low <= high && high <= max do return; handle_error :: proc "contextless" (file: string, line, column: int, low, high, max: int) { context = default_context(); - fd := os.stderr; + fd := os_stderr(); print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); - os.write_string(fd, " Invalid dynamic array values: "); + print_string(fd, " Invalid dynamic array values: "); print_i64(fd, i64(low)); - os.write_string(fd, ":"); + print_string(fd, ":"); print_i64(fd, i64(high)); - os.write_string(fd, ":"); + print_string(fd, ":"); print_i64(fd, i64(max)); - os.write_byte(fd, '\n'); + print_byte(fd, '\n'); bounds_trap(); } handle_error(file, line, column, low, high, max); @@ -83,13 +80,13 @@ type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column if ok do return; handle_error :: proc "contextless" (file: string, line, column: int, from, to: typeid) { context = default_context(); - fd := os.stderr; + fd := os_stderr(); print_caller_location(fd, Source_Code_Location{file, line, column, "", 0}); - os.write_string(fd, " Invalid type assertion from "); + print_string(fd, " Invalid type assertion from "); print_typeid(fd, from); - os.write_string(fd, " to "); + print_string(fd, " to "); print_typeid(fd, to); - os.write_byte(fd, '\n'); + print_byte(fd, '\n'); type_assertion_trap(); } handle_error(file, line, column, from, to); @@ -99,11 +96,11 @@ make_slice_error_loc :: inline proc "contextless" (loc := #caller_location, len: if 0 <= len do return; handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) { context = default_context(); - fd := os.stderr; + fd := os_stderr(); print_caller_location(fd, loc); - os.write_string(fd, " Invalid slice length for make: "); + print_string(fd, " Invalid slice length for make: "); print_i64(fd, i64(len)); - os.write_byte(fd, '\n'); + print_byte(fd, '\n'); bounds_trap(); } handle_error(loc, len); @@ -113,13 +110,13 @@ make_dynamic_array_error_loc :: inline proc "contextless" (using loc := #caller_ if 0 <= len && len <= cap do return; handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) { context = default_context(); - fd := os.stderr; + fd := os_stderr(); print_caller_location(fd, loc); - os.write_string(fd, " Invalid dynamic array parameters for make: "); + print_string(fd, " Invalid dynamic array parameters for make: "); print_i64(fd, i64(len)); - os.write_byte(fd, ':'); + print_byte(fd, ':'); print_i64(fd, i64(cap)); - os.write_byte(fd, '\n'); + print_byte(fd, '\n'); bounds_trap(); } handle_error(loc, len, cap); @@ -129,11 +126,11 @@ make_map_expr_error_loc :: inline proc "contextless" (loc := #caller_location, c if 0 <= cap do return; handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) { context = default_context(); - fd := os.stderr; + fd := os_stderr(); print_caller_location(fd, loc); - os.write_string(fd, " Invalid map capacity for make: "); + print_string(fd, " Invalid map capacity for make: "); print_i64(fd, i64(cap)); - os.write_byte(fd, '\n'); + print_byte(fd, '\n'); bounds_trap(); } handle_error(loc, cap); diff --git a/core/runtime/os_specific.odin b/core/runtime/os_specific.odin new file mode 100644 index 000000000..e09acb51c --- /dev/null +++ b/core/runtime/os_specific.odin @@ -0,0 +1,45 @@ +package runtime + +when ODIN_OS == "freestanding" { + _OS_Errno :: distinct int; + _OS_Handle :: distinct uintptr; + + os_stdout :: proc "contextless" () -> _OS_Handle { + return 1; + } + os_stderr :: proc "contextless" () -> _OS_Handle { + return 2; + } + + // TODO(bill): reimplement `os.write` + os_write :: proc(fd: _OS_Handle, data: []byte) -> (int, _OS_Errno) { + return 0, -1; + } + + current_thread_id :: proc "contextless" () -> int { + return 0; + } + +} else { + import "core:os" + + _OS_Errno :: distinct int; + _OS_Handle :: os.Handle; + + os_stdout :: proc "contextless" () -> _OS_Handle { + return os.stdout; + } + os_stderr :: proc "contextless" () -> _OS_Handle { + return os.stderr; + } + + // TODO(bill): reimplement `os.write` + os_write :: proc(fd: _OS_Handle, data: []byte) -> (int, _OS_Errno) { + n, err := os.write(fd, data); + return int(n), _OS_Errno(err); + } + + current_thread_id :: proc "contextless" () -> int { + return os.current_thread_id(); + } +} diff --git a/core/runtime/print.odin b/core/runtime/print.odin index b1d16c1fd..7112bf9b4 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -1,9 +1,93 @@ package runtime -import "core:os" +_INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz"; -print_u64 :: proc(fd: os.Handle, x: u64) { - digits := "0123456789"; +encode_rune :: proc(c: rune) -> ([4]u8, int) { + r := c; + + buf: [4]u8; + i := u32(r); + mask :: u8(0x3f); + if i <= 1<<7-1 { + buf[0] = u8(r); + return buf, 1; + } + if i <= 1<<11-1 { + buf[0] = 0xc0 | u8(r>>6); + buf[1] = 0x80 | u8(r) & mask; + return buf, 2; + } + + // Invalid or Surrogate range + if i > 0x0010ffff || + (0xd800 <= i && i <= 0xdfff) { + r = 0xfffd; + } + + if i <= 1<<16-1 { + buf[0] = 0xe0 | u8(r>>12); + buf[1] = 0x80 | u8(r>>6) & mask; + buf[2] = 0x80 | u8(r) & mask; + return buf, 3; + } + + buf[0] = 0xf0 | u8(r>>18); + buf[1] = 0x80 | u8(r>>12) & mask; + buf[2] = 0x80 | u8(r>>6) & mask; + buf[3] = 0x80 | u8(r) & mask; + return buf, 4; +} + +print_string :: proc(fd: _OS_Handle, str: string) -> (int, _OS_Errno) { + return os_write(fd, transmute([]byte)str); +} + +print_byte :: proc(fd: _OS_Handle, b: byte) -> (int, _OS_Errno) { + return os_write(fd, []byte{b}); +} + +print_encoded_rune :: proc(fd: _OS_Handle, r: rune) { + print_byte(fd, '\''); + + switch r { + case '\a': print_string(fd, "\\a"); + case '\b': print_string(fd, "\\b"); + case '\e': print_string(fd, "\\e"); + case '\f': print_string(fd, "\\f"); + case '\n': print_string(fd, "\\n"); + case '\r': print_string(fd, "\\r"); + case '\t': print_string(fd, "\\t"); + case '\v': print_string(fd, "\\v"); + case: + if r <= 0 { + print_string(fd, "\\x00"); + } else if r < 32 { + digits := _INTEGER_DIGITS; + n0, n1 := u8(r) >> 4, u8(r) & 0xf; + print_string(fd, "\\x"); + print_byte(fd, digits[n0]); + print_byte(fd, digits[n1]); + } else { + print_rune(fd, r); + } + } + print_byte(fd, '\''); +} + +print_rune :: proc(fd: _OS_Handle, r: rune) -> (int, _OS_Errno) { + RUNE_SELF :: 0x80; + + if r < RUNE_SELF { + return print_byte(fd, byte(r)); + } + + b, n := encode_rune(r); + return os_write(fd, b[:n]); +} + + +print_u64 :: proc(fd: _OS_Handle, x: u64) { + digits := _INTEGER_DIGITS; a: [129]byte; i := len(a); @@ -15,11 +99,12 @@ print_u64 :: proc(fd: os.Handle, x: u64) { } i -= 1; a[i] = digits[u % b]; - os.write(fd, a[i:]); + os_write(fd, a[i:]); } -print_i64 :: proc(fd: os.Handle, x: i64) { - digits := "0123456789"; + +print_i64 :: proc(fd: _OS_Handle, x: i64) { + digits := _INTEGER_DIGITS; b :: i64(10); u := x; @@ -37,257 +122,257 @@ print_i64 :: proc(fd: os.Handle, x: i64) { i -= 1; a[i] = '-'; } - os.write(fd, a[i:]); + os_write(fd, a[i:]); } -print_caller_location :: proc(fd: os.Handle, using loc: Source_Code_Location) { - os.write_string(fd, file_path); - os.write_byte(fd, '('); +print_caller_location :: proc(fd: _OS_Handle, using loc: Source_Code_Location) { + print_string(fd, file_path); + print_byte(fd, '('); print_u64(fd, u64(line)); - os.write_byte(fd, ':'); + print_byte(fd, ':'); print_u64(fd, u64(column)); - os.write_byte(fd, ')'); + print_byte(fd, ')'); } -print_typeid :: proc(fd: os.Handle, id: typeid) { +print_typeid :: proc(fd: _OS_Handle, id: typeid) { if id == nil { - os.write_string(fd, "nil"); + print_string(fd, "nil"); } else { ti := type_info_of(id); print_type(fd, ti); } } -print_type :: proc(fd: os.Handle, ti: ^Type_Info) { +print_type :: proc(fd: _OS_Handle, ti: ^Type_Info) { if ti == nil { - os.write_string(fd, "nil"); + print_string(fd, "nil"); return; } switch info in ti.variant { case Type_Info_Named: - os.write_string(fd, info.name); + print_string(fd, info.name); case Type_Info_Integer: switch ti.id { - case int: os.write_string(fd, "int"); - case uint: os.write_string(fd, "uint"); - case uintptr: os.write_string(fd, "uintptr"); + case int: print_string(fd, "int"); + case uint: print_string(fd, "uint"); + case uintptr: print_string(fd, "uintptr"); case: - os.write_byte(fd, 'i' if info.signed else 'u'); + print_byte(fd, 'i' if info.signed else 'u'); print_u64(fd, u64(8*ti.size)); } case Type_Info_Rune: - os.write_string(fd, "rune"); + print_string(fd, "rune"); case Type_Info_Float: - os.write_byte(fd, 'f'); + print_byte(fd, 'f'); print_u64(fd, u64(8*ti.size)); case Type_Info_Complex: - os.write_string(fd, "complex"); + print_string(fd, "complex"); print_u64(fd, u64(8*ti.size)); case Type_Info_Quaternion: - os.write_string(fd, "quaternion"); + print_string(fd, "quaternion"); print_u64(fd, u64(8*ti.size)); case Type_Info_String: - os.write_string(fd, "string"); + print_string(fd, "string"); case Type_Info_Boolean: switch ti.id { - case bool: os.write_string(fd, "bool"); + case bool: print_string(fd, "bool"); case: - os.write_byte(fd, 'b'); + print_byte(fd, 'b'); print_u64(fd, u64(8*ti.size)); } case Type_Info_Any: - os.write_string(fd, "any"); + print_string(fd, "any"); case Type_Info_Type_Id: - os.write_string(fd, "typeid"); + print_string(fd, "typeid"); case Type_Info_Pointer: if info.elem == nil { - os.write_string(fd, "rawptr"); + print_string(fd, "rawptr"); } else { - os.write_string(fd, "^"); + print_string(fd, "^"); print_type(fd, info.elem); } case Type_Info_Procedure: - os.write_string(fd, "proc"); + print_string(fd, "proc"); if info.params == nil { - os.write_string(fd, "()"); + print_string(fd, "()"); } else { t := info.params.variant.(Type_Info_Tuple); - os.write_byte(fd, '('); + print_byte(fd, '('); for t, i in t.types { - if i > 0 do os.write_string(fd, ", "); + if i > 0 do print_string(fd, ", "); print_type(fd, t); } - os.write_string(fd, ")"); + print_string(fd, ")"); } if info.results != nil { - os.write_string(fd, " -> "); + print_string(fd, " -> "); print_type(fd, info.results); } case Type_Info_Tuple: count := len(info.names); - if count != 1 do os.write_byte(fd, '('); + if count != 1 do print_byte(fd, '('); for name, i in info.names { - if i > 0 do os.write_string(fd, ", "); + if i > 0 do print_string(fd, ", "); t := info.types[i]; if len(name) > 0 { - os.write_string(fd, name); - os.write_string(fd, ": "); + print_string(fd, name); + print_string(fd, ": "); } print_type(fd, t); } - if count != 1 do os.write_string(fd, ")"); + if count != 1 do print_string(fd, ")"); case Type_Info_Array: - os.write_byte(fd, '['); + print_byte(fd, '['); print_u64(fd, u64(info.count)); - os.write_byte(fd, ']'); + print_byte(fd, ']'); print_type(fd, info.elem); case Type_Info_Enumerated_Array: - os.write_byte(fd, '['); + print_byte(fd, '['); print_type(fd, info.index); - os.write_byte(fd, ']'); + print_byte(fd, ']'); print_type(fd, info.elem); case Type_Info_Dynamic_Array: - os.write_string(fd, "[dynamic]"); + print_string(fd, "[dynamic]"); print_type(fd, info.elem); case Type_Info_Slice: - os.write_string(fd, "[]"); + print_string(fd, "[]"); print_type(fd, info.elem); case Type_Info_Map: - os.write_string(fd, "map["); + print_string(fd, "map["); print_type(fd, info.key); - os.write_byte(fd, ']'); + print_byte(fd, ']'); print_type(fd, info.value); case Type_Info_Struct: switch info.soa_kind { case .None: // Ignore case .Fixed: - os.write_string(fd, "#soa["); + print_string(fd, "#soa["); print_u64(fd, u64(info.soa_len)); - os.write_byte(fd, ']'); + print_byte(fd, ']'); print_type(fd, info.soa_base_type); return; case .Slice: - os.write_string(fd, "#soa[]"); + print_string(fd, "#soa[]"); print_type(fd, info.soa_base_type); return; case .Dynamic: - os.write_string(fd, "#soa[dynamic]"); + print_string(fd, "#soa[dynamic]"); print_type(fd, info.soa_base_type); return; } - os.write_string(fd, "struct "); - if info.is_packed do os.write_string(fd, "#packed "); - if info.is_raw_union do os.write_string(fd, "#raw_union "); + print_string(fd, "struct "); + if info.is_packed do print_string(fd, "#packed "); + if info.is_raw_union do print_string(fd, "#raw_union "); if info.custom_align { - os.write_string(fd, "#align "); + print_string(fd, "#align "); print_u64(fd, u64(ti.align)); - os.write_byte(fd, ' '); + print_byte(fd, ' '); } - os.write_byte(fd, '{'); + print_byte(fd, '{'); for name, i in info.names { - if i > 0 do os.write_string(fd, ", "); - os.write_string(fd, name); - os.write_string(fd, ": "); + if i > 0 do print_string(fd, ", "); + print_string(fd, name); + print_string(fd, ": "); print_type(fd, info.types[i]); } - os.write_byte(fd, '}'); + print_byte(fd, '}'); case Type_Info_Union: - os.write_string(fd, "union "); + print_string(fd, "union "); if info.custom_align { - os.write_string(fd, "#align "); + print_string(fd, "#align "); print_u64(fd, u64(ti.align)); } if info.no_nil { - os.write_string(fd, "#no_nil "); + print_string(fd, "#no_nil "); } - os.write_byte(fd, '{'); + print_byte(fd, '{'); for variant, i in info.variants { - if i > 0 do os.write_string(fd, ", "); + if i > 0 do print_string(fd, ", "); print_type(fd, variant); } - os.write_string(fd, "}"); + print_string(fd, "}"); case Type_Info_Enum: - os.write_string(fd, "enum "); + print_string(fd, "enum "); print_type(fd, info.base); - os.write_string(fd, " {"); + print_string(fd, " {"); for name, i in info.names { - if i > 0 do os.write_string(fd, ", "); - os.write_string(fd, name); + if i > 0 do print_string(fd, ", "); + print_string(fd, name); } - os.write_string(fd, "}"); + print_string(fd, "}"); case Type_Info_Bit_Field: - os.write_string(fd, "bit_field "); + print_string(fd, "bit_field "); if ti.align != 1 { - os.write_string(fd, "#align "); + print_string(fd, "#align "); print_u64(fd, u64(ti.align)); - os.write_byte(fd, ' '); + print_byte(fd, ' '); } - os.write_string(fd, " {"); + print_string(fd, " {"); for name, i in info.names { - if i > 0 do os.write_string(fd, ", "); - os.write_string(fd, name); - os.write_string(fd, ": "); + if i > 0 do print_string(fd, ", "); + print_string(fd, name); + print_string(fd, ": "); print_u64(fd, u64(info.bits[i])); } - os.write_string(fd, "}"); + print_string(fd, "}"); case Type_Info_Bit_Set: - os.write_string(fd, "bit_set["); + print_string(fd, "bit_set["); #partial switch elem in type_info_base(info.elem).variant { case Type_Info_Enum: print_type(fd, info.elem); case Type_Info_Rune: - os.write_encoded_rune(fd, rune(info.lower)); - os.write_string(fd, ".."); - os.write_encoded_rune(fd, rune(info.upper)); + print_encoded_rune(fd, rune(info.lower)); + print_string(fd, ".."); + print_encoded_rune(fd, rune(info.upper)); case: print_i64(fd, info.lower); - os.write_string(fd, ".."); + print_string(fd, ".."); print_i64(fd, info.upper); } if info.underlying != nil { - os.write_string(fd, "; "); + print_string(fd, "; "); print_type(fd, info.underlying); } - os.write_byte(fd, ']'); + print_byte(fd, ']'); case Type_Info_Opaque: - os.write_string(fd, "opaque "); + print_string(fd, "opaque "); print_type(fd, info.elem); case Type_Info_Simd_Vector: if info.is_x86_mmx { - os.write_string(fd, "intrinsics.x86_mmx"); + print_string(fd, "intrinsics.x86_mmx"); } else { - os.write_string(fd, "#simd["); + print_string(fd, "#simd["); print_u64(fd, u64(info.count)); - os.write_byte(fd, ']'); + print_byte(fd, ']'); print_type(fd, info.elem); } case Type_Info_Relative_Pointer: - os.write_string(fd, "#relative("); + print_string(fd, "#relative("); print_type(fd, info.base_integer); - os.write_string(fd, ") "); + print_string(fd, ") "); print_type(fd, info.pointer); case Type_Info_Relative_Slice: - os.write_string(fd, "#relative("); + print_string(fd, "#relative("); print_type(fd, info.base_integer); - os.write_string(fd, ") "); + print_string(fd, ") "); print_type(fd, info.slice); } }