aboutsummaryrefslogtreecommitdiff
path: root/core/runtime
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2022-04-27 14:37:15 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2022-04-27 14:37:15 +0200
commitc4e0d1efa1ec655bae9134b95a0fcd060cc7bbea (patch)
treec29bd0b78138e8d67aebe34ac689d13e32d9d15f /core/runtime
parent6e61abc7d06f22129f93110a9f652c3eec21f0c6 (diff)
parent9349dfba8fec53f52f77a0c8928e115ec93ff447 (diff)
Merge branch 'master' into xml
Diffstat (limited to 'core/runtime')
-rw-r--r--core/runtime/core.odin92
-rw-r--r--core/runtime/core_builtin.odin45
-rw-r--r--core/runtime/core_builtin_matrix.odin24
-rw-r--r--core/runtime/default_allocators_nil.odin2
-rw-r--r--core/runtime/default_temporary_allocator.odin2
-rw-r--r--core/runtime/entry_unix.odin33
-rw-r--r--core/runtime/entry_wasm.odin19
-rw-r--r--core/runtime/entry_windows.odin45
-rw-r--r--core/runtime/error_checks.odin160
-rw-r--r--core/runtime/internal.odin22
-rw-r--r--core/runtime/print.odin39
-rw-r--r--core/runtime/procs.odin4
-rw-r--r--core/runtime/procs_darwin.odin21
-rw-r--r--core/runtime/procs_wasm32.odin41
-rw-r--r--core/runtime/procs_windows_amd64.odin2
-rw-r--r--core/runtime/procs_windows_i386.odin (renamed from core/runtime/procs_windows_386.odin)0
-rw-r--r--core/runtime/udivmod128.odin2
17 files changed, 418 insertions, 135 deletions
diff --git a/core/runtime/core.odin b/core/runtime/core.odin
index be30eef02..4269450de 100644
--- a/core/runtime/core.odin
+++ b/core/runtime/core.odin
@@ -33,6 +33,11 @@ Calling_Convention :: enum u8 {
None = 6,
Naked = 7,
+
+ _ = 8, // reserved
+
+ Win64 = 9,
+ SysV = 10,
}
Type_Info_Enum_Value :: distinct i64
@@ -95,6 +100,7 @@ Type_Info_Enumerated_Array :: struct {
count: int,
min_value: Type_Info_Enum_Value,
max_value: Type_Info_Enum_Value,
+ is_sparse: bool,
}
Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int}
Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int}
@@ -130,6 +136,7 @@ Type_Info_Union :: struct {
custom_align: bool,
no_nil: bool,
maybe: bool,
+ shared_nil: bool,
}
Type_Info_Enum :: struct {
base: ^Type_Info,
@@ -345,7 +352,6 @@ Context :: struct {
assertion_failure_proc: Assertion_Failure_Proc,
logger: Logger,
- user_data: any,
user_ptr: rawptr,
user_index: int,
@@ -386,6 +392,59 @@ Raw_Cstring :: struct {
}
+/*
+ // Defined internally by the compiler
+ Odin_OS_Type :: enum int {
+ Unknown,
+ Windows,
+ Darwin,
+ Linux,
+ Essence,
+ FreeBSD,
+ OpenBSD,
+ WASI,
+ JS,
+ Freestanding,
+ }
+*/
+Odin_OS_Type :: type_of(ODIN_OS)
+
+/*
+ // Defined internally by the compiler
+ Odin_Arch_Type :: enum int {
+ Unknown,
+ amd64,
+ i386,
+ arm64,
+ wasm32,
+ wasm64,
+ }
+*/
+Odin_Arch_Type :: type_of(ODIN_ARCH)
+
+/*
+ // Defined internally by the compiler
+ Odin_Build_Mode_Type :: enum int {
+ Executable,
+ Dynamic,
+ Object,
+ Assembly,
+ LLVM_IR,
+ }
+*/
+Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
+
+/*
+ // Defined internally by the compiler
+ Odin_Endian_Type :: enum int {
+ Unknown,
+ Little,
+ Big,
+ }
+*/
+Odin_Endian_Type :: type_of(ODIN_ENDIAN)
+
+
/////////////////////////////
// Init Startup Procedures //
/////////////////////////////
@@ -394,7 +453,7 @@ Raw_Cstring :: struct {
// This is probably only useful for freestanding targets
foreign {
@(link_name="__$startup_runtime")
- _startup_runtime :: proc() ---
+ _startup_runtime :: proc "odin" () ---
}
@(link_name="__$cleanup_runtime")
@@ -402,6 +461,11 @@ _cleanup_runtime :: proc() {
default_temp_allocator_destroy(&global_default_temp_allocator_data)
}
+_cleanup_runtime_contextless :: proc "contextless" () {
+ context = default_context()
+ _cleanup_runtime()
+}
+
/////////////////////////////
/////////////////////////////
@@ -451,16 +515,18 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check
return &type_table[n]
}
-typeid_base :: proc "contextless" (id: typeid) -> typeid {
- ti := type_info_of(id)
- ti = type_info_base(ti)
- return ti.id
-}
-typeid_core :: proc "contextless" (id: typeid) -> typeid {
- ti := type_info_core(type_info_of(id))
- return ti.id
+when !ODIN_DISALLOW_RTTI {
+ typeid_base :: proc "contextless" (id: typeid) -> typeid {
+ ti := type_info_of(id)
+ ti = type_info_base(ti)
+ return ti.id
+ }
+ typeid_core :: proc "contextless" (id: typeid) -> typeid {
+ ti := type_info_core(type_info_of(id))
+ return ti.id
+ }
+ typeid_base_without_enum :: typeid_core
}
-typeid_base_without_enum :: typeid_core
@@ -500,7 +566,7 @@ __init_context :: proc "contextless" (c: ^Context) {
return
}
- // NOTE(bill): Do not initialize these procedures with a call as they are not defined with the "contexless" calling convention
+ // NOTE(bill): Do not initialize these procedures with a call as they are not defined with the "contextless" calling convention
c.allocator.procedure = default_allocator_proc
c.allocator.data = nil
@@ -516,7 +582,7 @@ __init_context :: proc "contextless" (c: ^Context) {
}
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {
- when ODIN_OS == "freestanding" {
+ when ODIN_OS == .Freestanding {
// Do nothing
} else {
print_caller_location(loc)
diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin
index 44da894c1..13e464a76 100644
--- a/core/runtime/core_builtin.odin
+++ b/core/runtime/core_builtin.odin
@@ -5,6 +5,16 @@ import "core:intrinsics"
@builtin
Maybe :: union($T: typeid) #maybe {T}
+
+@builtin
+container_of :: #force_inline proc "contextless" (ptr: $P/^$Field_Type, $T: typeid, $field_name: string) -> ^T
+ where intrinsics.type_has_field(T, field_name),
+ intrinsics.type_field_type(T, field_name) == Field_Type {
+ offset :: offset_of_by_string(T, field_name)
+ return (^T)(uintptr(ptr) - offset) if ptr != nil else nil
+}
+
+
@thread_local global_default_temp_allocator_data: Default_Temp_Allocator
@builtin
@@ -386,12 +396,13 @@ insert_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
if array == nil {
return
}
- n := len(array)
+ n := max(len(array), index)
m :: 1
- resize(array, n+m, loc)
- if n+m <= len(array) {
+ new_size := n + m
+
+ if resize(array, new_size, loc) {
when size_of(E) != 0 {
- copy(array[index+m:], array[index:])
+ copy(array[index + m:], array[index:])
array[index] = arg
}
ok = true
@@ -409,12 +420,13 @@ insert_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #c
return
}
- n := len(array)
+ n := max(len(array), index)
m := len(args)
- resize(array, n+m, loc)
- if n+m <= len(array) {
+ new_size := n + m
+
+ if resize(array, new_size, loc) {
when size_of(E) != 0 {
- copy(array[index+m:], array[index:])
+ copy(array[index + m:], array[index:])
copy(array[index:], args)
}
ok = true
@@ -427,17 +439,18 @@ insert_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
if array == nil {
return
}
- if len(args) == 0 {
+ if len(arg) == 0 {
ok = true
return
}
- n := len(array)
- m := len(args)
- resize(array, n+m, loc)
- if n+m <= len(array) {
+ n := max(len(array), index)
+ m := len(arg)
+ new_size := n + m
+
+ if resize(array, new_size, loc) {
copy(array[index+m:], array[index:])
- copy(array[index:], args)
+ copy(array[index:], arg)
ok = true
}
return
@@ -614,6 +627,10 @@ raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_str
@(disabled=ODIN_DISABLE_ASSERT)
assert :: proc(condition: bool, message := "", loc := #caller_location) {
if !condition {
+ // NOTE(bill): This is wrapped in a procedure call
+ // to improve performance to make the CPU not
+ // execute speculatively, making it about an order of
+ // magnitude faster
proc(message: string, loc: Source_Code_Location) {
p := context.assertion_failure_proc
if p == nil {
diff --git a/core/runtime/core_builtin_matrix.odin b/core/runtime/core_builtin_matrix.odin
index 08dca288e..53589587c 100644
--- a/core/runtime/core_builtin_matrix.odin
+++ b/core/runtime/core_builtin_matrix.odin
@@ -146,14 +146,14 @@ matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
when intrinsics.type_is_integer(T) {
y[0, 0] = +x[1, 1] / d
- y[1, 0] = -x[1, 0] / d
- y[0, 1] = -x[0, 1] / d
+ y[1, 0] = -x[0, 1] / d
+ y[0, 1] = -x[1, 0] / d
y[1, 1] = +x[0, 0] / d
} else {
id := 1 / d
y[0, 0] = +x[1, 1] * id
- y[1, 0] = -x[1, 0] * id
- y[0, 1] = -x[0, 1] * id
+ y[1, 0] = -x[0, 1] * id
+ y[0, 1] = -x[1, 0] * id
y[1, 1] = +x[0, 0] * id
}
return
@@ -214,16 +214,16 @@ matrix1x1_inverse :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
when intrinsics.type_is_integer(T) {
- y[0, 0] = x[1, 1] / d
- y[0, 1] = x[1, 0] / d
- y[1, 0] = x[0, 1] / d
- y[1, 1] = x[0, 0] / d
+ y[0, 0] = +x[1, 1] / d
+ y[0, 1] = -x[0, 1] / d
+ y[1, 0] = -x[1, 0] / d
+ y[1, 1] = +x[0, 0] / d
} else {
id := 1 / d
- y[0, 0] = x[1, 1] * id
- y[0, 1] = x[1, 0] * id
- y[1, 0] = x[0, 1] * id
- y[1, 1] = x[0, 0] * id
+ y[0, 0] = +x[1, 1] * id
+ y[0, 1] = -x[0, 1] * id
+ y[1, 0] = -x[1, 0] * id
+ y[1, 1] = +x[0, 0] * id
}
return
}
diff --git a/core/runtime/default_allocators_nil.odin b/core/runtime/default_allocators_nil.odin
index ccb4a3381..04dea0e19 100644
--- a/core/runtime/default_allocators_nil.odin
+++ b/core/runtime/default_allocators_nil.odin
@@ -32,7 +32,7 @@ nil_allocator :: proc() -> Allocator {
-when ODIN_OS == "freestanding" {
+when ODIN_OS == .Freestanding {
default_allocator_proc :: nil_allocator_proc
default_allocator :: nil_allocator
} \ No newline at end of file
diff --git a/core/runtime/default_temporary_allocator.odin b/core/runtime/default_temporary_allocator.odin
index 01143e222..4337e555b 100644
--- a/core/runtime/default_temporary_allocator.odin
+++ b/core/runtime/default_temporary_allocator.odin
@@ -3,7 +3,7 @@ package runtime
DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE, 1<<22)
-when ODIN_OS == "freestanding" || ODIN_OS == "js" || ODIN_DEFAULT_TO_NIL_ALLOCATOR {
+when ODIN_OS == .Freestanding || ODIN_OS == .JS || ODIN_DEFAULT_TO_NIL_ALLOCATOR {
Default_Temp_Allocator :: struct {}
default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backup_allocator := context.allocator) {}
diff --git a/core/runtime/entry_unix.odin b/core/runtime/entry_unix.odin
new file mode 100644
index 000000000..9f7d219c3
--- /dev/null
+++ b/core/runtime/entry_unix.odin
@@ -0,0 +1,33 @@
+//+private
+//+build linux, darwin, freebsd, openbsd
+package runtime
+
+import "core:intrinsics"
+
+when ODIN_BUILD_MODE == .Dynamic {
+ @(link_name="_odin_entry_point", linkage="strong", require/*, link_section=".init"*/)
+ _odin_entry_point :: proc "c" () {
+ context = default_context()
+ #force_no_inline _startup_runtime()
+ intrinsics.__entry_point()
+ }
+ @(link_name="_odin_exit_point", linkage="strong", require/*, link_section=".fini"*/)
+ _odin_exit_point :: proc "c" () {
+ context = default_context()
+ #force_no_inline _cleanup_runtime()
+ }
+ @(link_name="main", linkage="strong", require)
+ main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
+ return 0
+ }
+} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
+ @(link_name="main", linkage="strong", require)
+ main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
+ args__ = argv[:argc]
+ context = default_context()
+ #force_no_inline _startup_runtime()
+ intrinsics.__entry_point()
+ #force_no_inline _cleanup_runtime()
+ return 0
+ }
+}
diff --git a/core/runtime/entry_wasm.odin b/core/runtime/entry_wasm.odin
new file mode 100644
index 000000000..125abc756
--- /dev/null
+++ b/core/runtime/entry_wasm.odin
@@ -0,0 +1,19 @@
+//+private
+//+build wasm32, wasm64
+package runtime
+
+import "core:intrinsics"
+
+when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
+ @(link_name="_start", linkage="strong", require, export)
+ _start :: proc "c" () {
+ context = default_context()
+ #force_no_inline _startup_runtime()
+ intrinsics.__entry_point()
+ }
+ @(link_name="_end", linkage="strong", require, export)
+ _end :: proc "c" () {
+ context = default_context()
+ #force_no_inline _cleanup_runtime()
+ }
+} \ No newline at end of file
diff --git a/core/runtime/entry_windows.odin b/core/runtime/entry_windows.odin
new file mode 100644
index 000000000..2f323cb41
--- /dev/null
+++ b/core/runtime/entry_windows.odin
@@ -0,0 +1,45 @@
+//+private
+//+build windows
+package runtime
+
+import "core:intrinsics"
+
+when ODIN_BUILD_MODE == .Dynamic {
+ @(link_name="DllMain", linkage="strong", require)
+ DllMain :: proc "stdcall" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 {
+ context = default_context()
+ switch fdwReason {
+ case 1: // DLL_PROCESS_ATTACH
+ #force_no_inline _startup_runtime()
+ intrinsics.__entry_point()
+ case 0: // DLL_PROCESS_DETACH
+ #force_no_inline _cleanup_runtime()
+ case 2: // DLL_THREAD_ATTACH
+ break
+ case 3: // DLL_THREAD_DETACH
+ break
+ }
+ return true
+ }
+} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
+ when ODIN_ARCH == .i386 || ODIN_NO_CRT {
+ @(link_name="mainCRTStartup", linkage="strong", require)
+ mainCRTStartup :: proc "stdcall" () -> i32 {
+ context = default_context()
+ #force_no_inline _startup_runtime()
+ intrinsics.__entry_point()
+ #force_no_inline _cleanup_runtime()
+ return 0
+ }
+ } else {
+ @(link_name="main", linkage="strong", require)
+ main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
+ args__ = argv[:argc]
+ context = default_context()
+ #force_no_inline _startup_runtime()
+ intrinsics.__entry_point()
+ #force_no_inline _cleanup_runtime()
+ return 0
+ }
+ }
+} \ No newline at end of file
diff --git a/core/runtime/error_checks.odin b/core/runtime/error_checks.odin
index 7f1aeb2d7..0d0b39072 100644
--- a/core/runtime/error_checks.odin
+++ b/core/runtime/error_checks.odin
@@ -1,7 +1,7 @@
package runtime
bounds_trap :: proc "contextless" () -> ! {
- when ODIN_OS == "windows" {
+ when ODIN_OS == .Windows {
windows_trap_array_bounds()
} else {
trap()
@@ -9,7 +9,7 @@ bounds_trap :: proc "contextless" () -> ! {
}
type_assertion_trap :: proc "contextless" () -> ! {
- when ODIN_OS == "windows" {
+ when ODIN_OS == .Windows {
windows_trap_type_assertion()
} else {
trap()
@@ -21,11 +21,12 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index
if 0 <= index && index < count {
return
}
+ @(cold)
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 bounds range 0:")
+ print_string(" is out of range 0..<")
print_i64(i64(count))
print_byte('\n')
bounds_trap()
@@ -35,11 +36,11 @@ bounds_check_error :: proc "contextless" (file: string, line, column: i32, index
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_string(" Invalid slice indices ")
print_i64(i64(lo))
print_string(":")
print_i64(i64(hi))
- print_string(":")
+ print_string(" is out of range 0..<")
print_i64(i64(len))
print_byte('\n')
bounds_trap()
@@ -47,7 +48,7 @@ slice_handle_error :: proc "contextless" (file: string, line, column: i32, lo, h
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_string(" Invalid slice indices ")
print_i64(i64(lo))
print_string(":")
print_i64(i64(hi))
@@ -81,13 +82,14 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32,
if 0 <= low && low <= high && high <= max {
return
}
+ @(cold)
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 values: ")
+ print_string(" Invalid dynamic array indices ")
print_i64(i64(low))
print_string(":")
print_i64(i64(high))
- print_string(":")
+ print_string(" is out of range 0..<")
print_i64(i64(max))
print_byte('\n')
bounds_trap()
@@ -97,17 +99,18 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32,
matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) {
- if 0 <= row_index && row_index < row_count &&
+ if 0 <= row_index && row_index < row_count &&
0 <= column_index && column_index < column_count {
return
}
+ @(cold)
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 bounds range [0..<")
+ print_string(" is out of range [0..<")
print_i64(i64(row_count))
print_string(", 0..<")
print_i64(i64(column_count))
@@ -119,71 +122,101 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32
}
-type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid) {
- if ok {
- return
- }
- 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()
+when ODIN_DISALLOW_RTTI {
+ type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: i32) {
+ if ok {
+ return
+ }
+ @(cold)
+ 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)
}
- 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
+ type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32) {
+ if ok {
+ return
+ }
+ @(cold)
+ 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)
+ 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)
}
- variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid {
- if id == nil || data == nil {
- return id
+ type_assertion_check2 :: proc "contextless" (ok: bool, file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
+ if ok {
+ return
}
- 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
+
+ variant_type :: proc "contextless" (id: typeid, data: rawptr) -> typeid {
+ if id == nil || data == nil {
+ return id
}
- if idx < 0 {
- return nil
- } else if idx < len(v.variants) {
- return v.variants[idx].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
}
- return id
- }
- handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
+ @(cold)
+ handle_error :: proc "contextless" (file: string, line, column: i32, from, to: typeid, from_data: rawptr) {
- actual := variant_type(from, from_data)
+ 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_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()
}
- print_byte('\n')
- type_assertion_trap()
+ handle_error(file, line, column, from, to, from_data)
}
- handle_error(file, line, column, from, to, from_data)
}
@@ -191,6 +224,7 @@ make_slice_error_loc :: #force_inline proc "contextless" (loc := #caller_locatio
if 0 <= len {
return
}
+ @(cold)
handle_error :: proc "contextless" (loc: Source_Code_Location, len: int) {
print_caller_location(loc)
print_string(" Invalid slice length for make: ")
@@ -205,6 +239,7 @@ make_dynamic_array_error_loc :: #force_inline proc "contextless" (using loc := #
if 0 <= len && len <= cap {
return
}
+ @(cold)
handle_error :: proc "contextless" (loc: Source_Code_Location, len, cap: int) {
print_caller_location(loc)
print_string(" Invalid dynamic array parameters for make: ")
@@ -221,6 +256,7 @@ make_map_expr_error_loc :: #force_inline proc "contextless" (loc := #caller_loca
if 0 <= cap {
return
}
+ @(cold)
handle_error :: proc "contextless" (loc: Source_Code_Location, cap: int) {
print_caller_location(loc)
print_string(" Invalid map capacity for make: ")
diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin
index ed58f4318..30798f623 100644
--- a/core/runtime/internal.odin
+++ b/core/runtime/internal.odin
@@ -2,13 +2,15 @@ package runtime
import "core:intrinsics"
+@(private="file")
+IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64
+
@(private)
RUNTIME_LINKAGE :: "strong" when (
(ODIN_USE_SEPARATE_MODULES ||
- ODIN_BUILD_MODE == "dynamic" ||
+ ODIN_BUILD_MODE == .Dynamic ||
!ODIN_NO_CRT) &&
- !(ODIN_ARCH == "wasm32" ||
- ODIN_ARCH == "wasm64")) else "internal"
+ !IS_WASM) else "internal"
RUNTIME_REQUIRE :: true
@@ -35,10 +37,8 @@ bswap_64 :: proc "contextless" (x: u64) -> u64 {
bswap_128 :: proc "contextless" (x: u128) -> u128 {
z := transmute([4]u32)x
- z[0] = bswap_32(z[3])
- z[1] = bswap_32(z[2])
- z[2] = bswap_32(z[1])
- z[3] = bswap_32(z[0])
+ z[0], z[3] = bswap_32(z[3]), bswap_32(z[0])
+ z[1], z[2] = bswap_32(z[2]), bswap_32(z[1])
return transmute(u128)z
}
@@ -752,6 +752,9 @@ extendhfsf2 :: proc "c" (value: u16) -> f32 {
@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
floattidf :: proc "c" (a: i128) -> f64 {
+when IS_WASM {
+ return 0
+} else {
DBL_MANT_DIG :: 53
if a == 0 {
return 0.0
@@ -791,10 +794,14 @@ floattidf :: proc "c" (a: i128) -> f64 {
fb[0] = u32(a) // mantissa-low
return transmute(f64)fb
}
+}
@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
floattidf_unsigned :: proc "c" (a: u128) -> f64 {
+when IS_WASM {
+ return 0
+} else {
DBL_MANT_DIG :: 53
if a == 0 {
return 0.0
@@ -832,6 +839,7 @@ floattidf_unsigned :: proc "c" (a: u128) -> f64 {
fb[0] = u32(a) // mantissa-low
return transmute(f64)fb
}
+}
diff --git a/core/runtime/print.odin b/core/runtime/print.odin
index 8a14eba08..89c196fc2 100644
--- a/core/runtime/print.odin
+++ b/core/runtime/print.odin
@@ -143,18 +143,36 @@ print_int :: proc "contextless" (x: int) { print_i64(i64(x)) }
print_caller_location :: proc "contextless" (using loc: Source_Code_Location) {
print_string(file_path)
- print_byte('(')
- print_u64(u64(line))
- print_byte(':')
- print_u64(u64(column))
- print_byte(')')
+ when ODIN_ERROR_POS_STYLE == .Default {
+ print_byte('(')
+ print_u64(u64(line))
+ print_byte(':')
+ print_u64(u64(column))
+ print_byte(')')
+ } else when ODIN_ERROR_POS_STYLE == .Unix {
+ print_byte(':')
+ print_u64(u64(line))
+ print_byte(':')
+ print_u64(u64(column))
+ print_byte(':')
+ } else {
+ #panic("unhandled ODIN_ERROR_POS_STYLE")
+ }
}
print_typeid :: proc "contextless" (id: typeid) {
- if id == nil {
- print_string("nil")
+ when ODIN_DISALLOW_RTTI {
+ if id == nil {
+ print_string("nil")
+ } else {
+ print_string("<unknown type>")
+ }
} else {
- ti := type_info_of(id)
- print_type(ti)
+ if id == nil {
+ print_string("nil")
+ } else {
+ ti := type_info_of(id)
+ print_type(ti)
+ }
}
}
print_type :: proc "contextless" (ti: ^Type_Info) {
@@ -250,6 +268,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) {
print_type(info.elem)
case Type_Info_Enumerated_Array:
+ if info.is_sparse {
+ print_string("#sparse")
+ }
print_byte('[')
print_type(info.index)
print_byte(']')
diff --git a/core/runtime/procs.odin b/core/runtime/procs.odin
index 961f6376f..5a1d11fe0 100644
--- a/core/runtime/procs.odin
+++ b/core/runtime/procs.odin
@@ -1,6 +1,6 @@
package runtime
-when ODIN_NO_CRT && ODIN_OS == "windows" {
+when ODIN_NO_CRT && ODIN_OS == .Windows {
foreign import lib "system:NtDll.lib"
@(private="file")
@@ -25,7 +25,7 @@ when ODIN_NO_CRT && ODIN_OS == "windows" {
RtlMoveMemory(dst, src, len)
return dst
}
-} else when ODIN_NO_CRT || (ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64") {
+} else when ODIN_NO_CRT || (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64) {
@(link_name="memset", linkage="strong", require)
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
if ptr != nil && len != 0 {
diff --git a/core/runtime/procs_darwin.odin b/core/runtime/procs_darwin.odin
new file mode 100644
index 000000000..b54a28dcc
--- /dev/null
+++ b/core/runtime/procs_darwin.odin
@@ -0,0 +1,21 @@
+//+private
+package runtime
+
+foreign import "system:Foundation.framework"
+
+import "core:intrinsics"
+
+objc_id :: ^intrinsics.objc_object
+objc_Class :: ^intrinsics.objc_class
+objc_SEL :: ^intrinsics.objc_selector
+
+foreign Foundation {
+ objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class ---
+ sel_registerName :: proc "c" (name: cstring) -> objc_SEL ---
+ objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) ---
+
+ objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
+ objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 ---
+ objc_msgSend_fp2ret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> complex128 ---
+ objc_msgSend_stret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
+}
diff --git a/core/runtime/procs_wasm32.odin b/core/runtime/procs_wasm32.odin
index 5caf6d2f8..2a4210c1e 100644
--- a/core/runtime/procs_wasm32.odin
+++ b/core/runtime/procs_wasm32.odin
@@ -1,23 +1,40 @@
//+build wasm32
package runtime
+@(private="file")
+ti_int :: struct #raw_union {
+ using s: struct { lo, hi: u64 },
+ all: i128,
+}
+
@(link_name="__ashlti3", linkage="strong")
-__ashlti3 :: proc "c" (a: i64, b_: i32) -> i64 {
- /*
+__ashlti3 :: proc "c" (a: i128, b_: u32) -> i128 {
+ bits_in_dword :: size_of(u32)*8
b := u32(b_)
- input := transmute([2]i32)a
- result: [2]i32
- if b & 32 != 0 {
- result[0] = 0
- result[1] = input[0] << (b - 32)
+
+ input, result: ti_int
+ input.all = a
+ if b & bits_in_dword != 0 {
+ result.lo = 0
+ result.hi = input.lo << (b-bits_in_dword)
} else {
if b == 0 {
return a
}
- result[0] = input[0]<<b
- result[1] = (input[1]<<b) | (input[0]>>(32-b))
+ result.lo = input.lo<<b
+ result.hi = (input.hi<<b) | (input.lo>>(bits_in_dword-b))
}
- return transmute(i64)result
- */
- return 0
+ return result.all
+}
+
+
+@(link_name="__multi3", linkage="strong")
+__multi3 :: proc "c" (a, b: i128) -> i128 {
+ x, y, r: ti_int
+
+ x.all = a
+ y.all = b
+ r.all = i128(x.lo * y.lo) // TODO this is incorrect
+ r.hi += x.hi*y.lo + x.lo*y.hi
+ return r.all
} \ No newline at end of file
diff --git a/core/runtime/procs_windows_amd64.odin b/core/runtime/procs_windows_amd64.odin
index 273bb57b2..e430357be 100644
--- a/core/runtime/procs_windows_amd64.odin
+++ b/core/runtime/procs_windows_amd64.odin
@@ -22,4 +22,4 @@ windows_trap_type_assertion :: proc "contextless" () -> ! {
when ODIN_NO_CRT {
@(require)
foreign import crt_lib "procs_windows_amd64.asm"
-} \ No newline at end of file
+}
diff --git a/core/runtime/procs_windows_386.odin b/core/runtime/procs_windows_i386.odin
index f810197f1..f810197f1 100644
--- a/core/runtime/procs_windows_386.odin
+++ b/core/runtime/procs_windows_i386.odin
diff --git a/core/runtime/udivmod128.odin b/core/runtime/udivmod128.odin
index 1fd1b5f84..87ef73c2c 100644
--- a/core/runtime/udivmod128.odin
+++ b/core/runtime/udivmod128.odin
@@ -11,7 +11,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
q, r: [2]u64
sr: u32 = 0
- low :: 1 when ODIN_ENDIAN == "big" else 0
+ low :: 1 when ODIN_ENDIAN == .Big else 0
high :: 1 - low
U64_BITS :: 8*size_of(u64)
U128_BITS :: 8*size_of(u128)