From 26f9688c69caa1ea8211da7ef072ea6ec292d8f7 Mon Sep 17 00:00:00 2001 From: misomosi Date: Sat, 21 Dec 2024 16:53:31 -0500 Subject: [PATCH 01/22] Fix early overwrite of dst w/ exp_u64 --- src/big_int.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/big_int.cpp b/src/big_int.cpp index 8e476f090..0b0a9a400 100644 --- a/src/big_int.cpp +++ b/src/big_int.cpp @@ -251,7 +251,10 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success exp *= 10; exp += v; } - big_int_exp_u64(dst, &b, exp, success); + BigInt tmp = {}; + mp_init(&tmp); + big_int_exp_u64(&tmp, &b, exp, success); + big_int_mul_eq(dst, &tmp); } if (is_negative) { From bf581074028dae7f5d15b5d1e6d58619fdb6f77f Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 20 Jan 2025 20:15:03 +0100 Subject: [PATCH 02/22] os/os2: bring Linux to other impls standards by looping writes and maxing one shot RW sizes --- core/os/os2/file_linux.odin | 61 +++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index f8e4026da..9f6625091 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -7,6 +7,13 @@ import "core:time" import "core:sync" import "core:sys/linux" +// Most implementations will EINVAL at some point when doing big writes. +// In practice a read/write call would probably never read/write these big buffers all at once, +// which is why the number of bytes is returned and why there are procs that will call this in a +// loop for you. +// We set a max of 1GB to keep alignment and to be safe. +MAX_RW :: 1 << 30 + File_Impl :: struct { file: File, name: string, @@ -179,10 +186,11 @@ _seek :: proc(f: ^File_Impl, offset: i64, whence: io.Seek_From) -> (ret: i64, er } _read :: proc(f: ^File_Impl, p: []byte) -> (i64, Error) { - if len(p) == 0 { + if len(p) <= 0 { return 0, nil } - n, errno := linux.read(f.fd, p[:]) + + n, errno := linux.read(f.fd, p[:min(len(p), MAX_RW)]) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -190,13 +198,13 @@ _read :: proc(f: ^File_Impl, p: []byte) -> (i64, Error) { } _read_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (i64, Error) { - if len(p) == 0 { + if len(p) <= 0 { return 0, nil } if offset < 0 { return 0, .Invalid_Offset } - n, errno := linux.pread(f.fd, p[:], offset) + n, errno := linux.pread(f.fd, p[:min(len(p), MAX_RW)], offset) if errno != .NONE { return -1, _get_platform_error(errno) } @@ -206,29 +214,42 @@ _read_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (i64, Error) { return i64(n), nil } -_write :: proc(f: ^File_Impl, p: []byte) -> (i64, Error) { - if len(p) == 0 { - return 0, nil +_write :: proc(f: ^File_Impl, p: []byte) -> (nt: i64, err: Error) { + p := p + for len(p) > 0 { + n, errno := linux.write(f.fd, p[:min(len(p), MAX_RW)]) + if errno != .NONE { + err = _get_platform_error(errno) + return + } + + p = p[n:] + nt += i64(n) } - n, errno := linux.write(f.fd, p[:]) - if errno != .NONE { - return -1, _get_platform_error(errno) - } - return i64(n), nil + + return } -_write_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (i64, Error) { - if len(p) == 0 { - return 0, nil - } +_write_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (nt: i64, err: Error) { if offset < 0 { return 0, .Invalid_Offset } - n, errno := linux.pwrite(f.fd, p[:], offset) - if errno != .NONE { - return -1, _get_platform_error(errno) + + p := p + offset := offset + for len(p) > 0 { + n, errno := linux.pwrite(f.fd, p[:min(len(p), MAX_RW)], offset) + if errno != .NONE { + err = _get_platform_error(errno) + return + } + + p = p[n:] + nt += i64(n) + offset += i64(n) } - return i64(n), nil + + return } _file_size :: proc(f: ^File_Impl) -> (n: i64, err: Error) { From b6736424125f0ad7dd633369a875050788c7df65 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 20 Jan 2025 22:35:35 +0100 Subject: [PATCH 03/22] os/os2: add get_executable_path and get_executable_directory --- core/os/os2/errors_posix.odin | 13 ++++++-- core/os/os2/path.odin | 12 ++++++++ core/os/os2/path_darwin.odin | 31 +++++++++++++++++++ core/os/os2/path_freebsd.odin | 29 ++++++++++++++++++ core/os/os2/path_linux.odin | 22 +++++++++++++- core/os/os2/path_netbsd.odin | 24 +++++++++++++++ core/os/os2/path_openbsd.odin | 57 +++++++++++++++++++++++++++++++++++ core/os/os2/path_windows.odin | 20 ++++++++++++ core/sys/darwin/dyld.odin | 7 +++++ tests/core/os/os2/path.odin | 22 ++++++++++++++ 10 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 core/os/os2/path_darwin.odin create mode 100644 core/os/os2/path_freebsd.odin create mode 100644 core/os/os2/path_netbsd.odin create mode 100644 core/os/os2/path_openbsd.odin create mode 100644 core/sys/darwin/dyld.odin create mode 100644 tests/core/os/os2/path.odin diff --git a/core/os/os2/errors_posix.odin b/core/os/os2/errors_posix.odin index 0b5876c0b..8a9ca07df 100644 --- a/core/os/os2/errors_posix.odin +++ b/core/os/os2/errors_posix.odin @@ -10,8 +10,12 @@ _error_string :: proc(errno: i32) -> string { return string(posix.strerror(posix.Errno(errno))) } -_get_platform_error :: proc() -> Error { - #partial switch errno := posix.errno(); errno { +_get_platform_error_from_errno :: proc() -> Error { + return _get_platform_error_existing(posix.errno()) +} + +_get_platform_error_existing :: proc(errno: posix.Errno) -> Error { + #partial switch errno { case .EPERM: return .Permission_Denied case .EEXIST: @@ -32,3 +36,8 @@ _get_platform_error :: proc() -> Error { return Platform_Error(errno) } } + +_get_platform_error :: proc{ + _get_platform_error_existing, + _get_platform_error_from_errno, +} diff --git a/core/os/os2/path.odin b/core/os/os2/path.odin index 254950d68..9231307f5 100644 --- a/core/os/os2/path.odin +++ b/core/os/os2/path.odin @@ -2,6 +2,8 @@ package os2 import "base:runtime" +import "core:path/filepath" + Path_Separator :: _Path_Separator // OS-Specific Path_Separator_String :: _Path_Separator_String // OS-Specific Path_List_Separator :: _Path_List_Separator // OS-Specific @@ -39,3 +41,13 @@ setwd :: set_working_directory set_working_directory :: proc(dir: string) -> (err: Error) { return _set_working_directory(dir) } + +get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + return _get_executable_path(allocator) +} + +get_executable_directory :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + path = _get_executable_path(allocator) or_return + path, _ = filepath.split(path) + return +} diff --git a/core/os/os2/path_darwin.odin b/core/os/os2/path_darwin.odin new file mode 100644 index 000000000..2e7bbc7b9 --- /dev/null +++ b/core/os/os2/path_darwin.odin @@ -0,0 +1,31 @@ +package os2 + +import "base:runtime" + +import "core:sys/darwin" +import "core:sys/posix" + +_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + size: u32 + + ret := darwin._NSGetExecutablePath(nil, &size) + assert(ret == -1) + assert(size > 0) + + TEMP_ALLOCATOR_GUARD() + + buf := make([]byte, size, temp_allocator()) or_return + assert(u32(len(buf)) == size) + + ret = darwin._NSGetExecutablePath(raw_data(buf), &size) + assert(ret == 0) + + real := posix.realpath(cstring(raw_data(buf))) + if real == nil { + err = _get_platform_error() + return + } + defer posix.free(real) + + return clone_string(string(real), allocator) +} diff --git a/core/os/os2/path_freebsd.odin b/core/os/os2/path_freebsd.odin new file mode 100644 index 000000000..577108eca --- /dev/null +++ b/core/os/os2/path_freebsd.odin @@ -0,0 +1,29 @@ +package os2 + +import "base:runtime" + +import "core:sys/freebsd" +import "core:sys/posix" + +_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + req := []freebsd.MIB_Identifier{.CTL_KERN, .KERN_PROC, .KERN_PROC_PATHNAME, freebsd.MIB_Identifier(-1)} + + size: uint + if ret := freebsd.sysctl(req, nil, &size, nil, 0); ret != .NONE { + err = _get_platform_error(posix.Errno(ret)) + return + } + assert(size > 0) + + buf := make([]byte, size, allocator) or_return + defer if err != nil { delete(buf, allocator) } + + assert(uint(len(buf)) == size) + + if ret := freebsd.sysctl(req, raw_data(buf), &size, nil, 0); ret != .NONE { + err = _get_platform_error(posix.Errno(ret)) + return + } + + return string(buf[:size]), nil +} diff --git a/core/os/os2/path_linux.odin b/core/os/os2/path_linux.odin index bfdb645ef..e3e7f8a7c 100644 --- a/core/os/os2/path_linux.odin +++ b/core/os/os2/path_linux.odin @@ -1,9 +1,10 @@ #+private package os2 +import "base:runtime" + import "core:strings" import "core:strconv" -import "base:runtime" import "core:sys/linux" _Path_Separator :: '/' @@ -171,6 +172,25 @@ _set_working_directory :: proc(dir: string) -> Error { return _get_platform_error(linux.chdir(dir_cstr)) } +_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + TEMP_ALLOCATOR_GUARD() + + buf := make([dynamic]byte, 1024, temp_allocator()) or_return + for { + n, errno := linux.readlink("/proc/self/exe", buf[:]) + if errno != .NONE { + err = _get_platform_error(errno) + return + } + + if n < len(buf) { + return clone_string(string(buf[:n]), allocator) + } + + resize(&buf, len(buf)*2) or_return + } +} + _get_full_path :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fullpath: string, err: Error) { PROC_FD_PATH :: "/proc/self/fd/" diff --git a/core/os/os2/path_netbsd.odin b/core/os/os2/path_netbsd.odin new file mode 100644 index 000000000..f56a91fd6 --- /dev/null +++ b/core/os/os2/path_netbsd.odin @@ -0,0 +1,24 @@ +package os2 + +import "base:runtime" + +import "core:sys/posix" + +_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + TEMP_ALLOCATOR_GUARD() + + buf := make([dynamic]byte, 1024, temp_allocator()) or_return + for { + n := posix.readlink("/proc/curproc/exe", raw_data(buf), len(buf)) + if n < 0 { + err = _get_platform_error() + return + } + + if n < len(buf) { + return clone_string(string(buf[:n]), allocator) + } + + resize(&buf, len(buf)*2) or_return + } +} diff --git a/core/os/os2/path_openbsd.odin b/core/os/os2/path_openbsd.odin new file mode 100644 index 000000000..f56c1a61b --- /dev/null +++ b/core/os/os2/path_openbsd.odin @@ -0,0 +1,57 @@ +package os2 + +import "base:runtime" + +import "core:strings" +import "core:sys/posix" + +_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + // OpenBSD does not have an API for this, we do our best below. + + if len(runtime.args__) <= 0 { + err = .Invalid_Path + return + } + + real :: proc(path: cstring, allocator: runtime.Allocator) -> (out: string, err: Error) { + real := posix.realpath(path) + if real == nil { + err = _get_platform_error() + return + } + defer posix.free(real) + return clone_string(string(real), allocator) + } + + arg := runtime.args__[0] + sarg := string(arg) + + if len(sarg) == 0 { + err = .Invalid_Path + return + } + + if sarg[0] == '.' || sarg[0] == '/' { + return real(arg, allocator) + } + + TEMP_ALLOCATOR_GUARD() + + buf := strings.builder_make(temp_allocator()) + + paths := get_env("PATH", temp_allocator()) + for dir in strings.split_iterator(&paths, ":") { + strings.builder_reset(&buf) + strings.write_string(&buf, dir) + strings.write_string(&buf, "/") + strings.write_string(&buf, sarg) + + cpath := strings.to_cstring(&buf) + if posix.access(cpath, {.X_OK}) == .OK { + return real(cpath, allocator) + } + } + + err = .Invalid_Path + return +} diff --git a/core/os/os2/path_windows.odin b/core/os/os2/path_windows.odin index 3e92cb6f3..041a4d1e3 100644 --- a/core/os/os2/path_windows.odin +++ b/core/os/os2/path_windows.odin @@ -136,6 +136,26 @@ _set_working_directory :: proc(dir: string) -> (err: Error) { return } +_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + TEMP_ALLOCATOR_GUARD() + + buf := make([dynamic]u16, 512, temp_allocator()) or_return + for { + ret := win32.GetModuleFileNameW(nil, raw_data(buf), win32.DWORD(len(buf))) + if ret == 0 { + err = _get_platform_error() + return + } + + if ret == win32.DWORD(len(buf)) && win32.GetLastError() == win32.ERROR_INSUFFICIENT_BUFFER { + resize(&buf, len(buf)*2) or_return + continue + } + + return win32_utf16_to_utf8(buf[:ret], allocator) + } +} + can_use_long_paths: bool @(init) diff --git a/core/sys/darwin/dyld.odin b/core/sys/darwin/dyld.odin new file mode 100644 index 000000000..0a6a2cfa6 --- /dev/null +++ b/core/sys/darwin/dyld.odin @@ -0,0 +1,7 @@ +package darwin + +foreign import system "system:System.framework" + +foreign system { + _NSGetExecutablePath :: proc(buf: [^]byte, bufsize: ^u32) -> i32 --- +} diff --git a/tests/core/os/os2/path.odin b/tests/core/os/os2/path.odin new file mode 100644 index 000000000..b91f43368 --- /dev/null +++ b/tests/core/os/os2/path.odin @@ -0,0 +1,22 @@ +package tests_core_os_os2 + +import os "core:os/os2" +import "core:log" +import "core:path/filepath" +import "core:testing" +import "core:strings" + +@(test) +test_executable :: proc(t: ^testing.T) { + path, err := os.get_executable_path(context.allocator) + defer delete(path) + + log.infof("executable path: %q", path) + + // NOTE: some sanity checks that should always be the case, at least in the CI. + + testing.expect_value(t, err, nil) + testing.expect(t, len(path) > 0) + testing.expect(t, filepath.is_abs(path)) + testing.expectf(t, strings.contains(path, filepath.base(os.args[0])), "expected the executable path to contain the base of os.args[0] which is %q", filepath.base(os.args[0])) +} From f1b0b197109a2ffea9435a2ff8eb7bd037298292 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 21 Jan 2025 19:14:15 +0100 Subject: [PATCH 04/22] os/os2: get_executable_path and working directory on wasi --- core/os/os2/path_wasi.odin | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/core/os/os2/path_wasi.odin b/core/os/os2/path_wasi.odin index 17efbff62..2f8a3c8c6 100644 --- a/core/os/os2/path_wasi.odin +++ b/core/os/os2/path_wasi.odin @@ -4,6 +4,7 @@ package os2 import "base:runtime" import "core:path/filepath" +import "core:sync" import "core:sys/wasm/wasi" _Path_Separator :: '/' @@ -74,11 +75,39 @@ _remove_all :: proc(path: string) -> (err: Error) { return remove(path) } +g_wd: string +g_wd_mutex: sync.Mutex + _get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) { - return ".", .Unsupported + sync.guard(&g_wd_mutex) + + return clone_string(g_wd if g_wd != "" else "/", allocator) } _set_working_directory :: proc(dir: string) -> (err: Error) { - err = .Unsupported + sync.guard(&g_wd_mutex) + + if dir == g_wd { + return + } + + if g_wd != "" { + delete(g_wd, file_allocator()) + } + + g_wd = clone_string(dir, file_allocator()) or_return return } + +_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { + if len(args) <= 0 { + return clone_string("/", allocator) + } + + arg := args[0] + if len(arg) > 0 && (arg[0] == '.' || arg[0] == '/') { + return clone_string(arg, allocator) + } + + return concatenate({"/", arg}, allocator) +} From d54de6704a0acb95e8123480121f0ddba62f1516 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 22 Jan 2025 18:39:33 +0100 Subject: [PATCH 05/22] os/os2: use proc_pidpath for executable path on darwin --- core/os/os2/path_darwin.odin | 26 ++++++-------------------- core/sys/darwin/dyld.odin | 7 ------- 2 files changed, 6 insertions(+), 27 deletions(-) delete mode 100644 core/sys/darwin/dyld.odin diff --git a/core/os/os2/path_darwin.odin b/core/os/os2/path_darwin.odin index 2e7bbc7b9..65aaf1e95 100644 --- a/core/os/os2/path_darwin.odin +++ b/core/os/os2/path_darwin.odin @@ -6,26 +6,12 @@ import "core:sys/darwin" import "core:sys/posix" _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) { - size: u32 - - ret := darwin._NSGetExecutablePath(nil, &size) - assert(ret == -1) - assert(size > 0) - - TEMP_ALLOCATOR_GUARD() - - buf := make([]byte, size, temp_allocator()) or_return - assert(u32(len(buf)) == size) - - ret = darwin._NSGetExecutablePath(raw_data(buf), &size) - assert(ret == 0) - - real := posix.realpath(cstring(raw_data(buf))) - if real == nil { - err = _get_platform_error() - return + buffer: [darwin.PIDPATHINFO_MAXSIZE]byte = --- + ret := darwin.proc_pidpath(posix.getpid(), raw_data(buffer[:]), len(buffer)) + if ret > 0 { + return clone_string(string(buffer[:ret]), allocator) } - defer posix.free(real) - return clone_string(string(real), allocator) + err = _get_platform_error() + return } diff --git a/core/sys/darwin/dyld.odin b/core/sys/darwin/dyld.odin deleted file mode 100644 index 0a6a2cfa6..000000000 --- a/core/sys/darwin/dyld.odin +++ /dev/null @@ -1,7 +0,0 @@ -package darwin - -foreign import system "system:System.framework" - -foreign system { - _NSGetExecutablePath :: proc(buf: [^]byte, bufsize: ^u32) -> i32 --- -} From 5a29e80bc35e040a9193dccca6a4d495bd1df37b Mon Sep 17 00:00:00 2001 From: prescientmoon Date: Thu, 23 Jan 2025 05:56:27 +0100 Subject: [PATCH 06/22] Fix 2x2 matrix inverses in specific.odin --- core/math/linalg/specific.odin | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/math/linalg/specific.odin b/core/math/linalg/specific.odin index b841f0610..c23feddce 100644 --- a/core/math/linalg/specific.odin +++ b/core/math/linalg/specific.odin @@ -1207,8 +1207,8 @@ matrix2_inverse_f16 :: proc "contextless" (m: Matrix2f16) -> (c: Matrix2f16) #no d := m[0, 0]*m[1, 1] - m[0, 1]*m[1, 0] id := 1.0/d c[0, 0] = +m[1, 1] * id - c[0, 1] = -m[1, 0] * id - c[1, 0] = -m[0, 1] * id + c[0, 1] = -m[0, 1] * id + c[1, 0] = -m[1, 0] * id c[1, 1] = +m[0, 0] * id return c } @@ -1217,8 +1217,8 @@ matrix2_inverse_f32 :: proc "contextless" (m: Matrix2f32) -> (c: Matrix2f32) #no d := m[0, 0]*m[1, 1] - m[0, 1]*m[1, 0] id := 1.0/d c[0, 0] = +m[1, 1] * id - c[0, 1] = -m[1, 0] * id - c[1, 0] = -m[0, 1] * id + c[0, 1] = -m[0, 1] * id + c[1, 0] = -m[1, 0] * id c[1, 1] = +m[0, 0] * id return c } @@ -1227,8 +1227,8 @@ matrix2_inverse_f64 :: proc "contextless" (m: Matrix2f64) -> (c: Matrix2f64) #no d := m[0, 0]*m[1, 1] - m[0, 1]*m[1, 0] id := 1.0/d c[0, 0] = +m[1, 1] * id - c[0, 1] = -m[1, 0] * id - c[1, 0] = -m[0, 1] * id + c[0, 1] = -m[0, 1] * id + c[1, 0] = -m[1, 0] * id c[1, 1] = +m[0, 0] * id return c } From 7127992625d8d1df4db6140f564526004aa3eaa3 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Fri, 24 Jan 2025 08:36:01 +1100 Subject: [PATCH 07/22] Fix the '+' sign placement in the presence of '0'-padding --- core/fmt/fmt.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index da3b419d5..51e70f6b7 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1379,9 +1379,9 @@ _pad :: proc(fi: ^Info, s: string) { if fi.minus { // right pad io.write_string(fi.writer, s, &fi.n) fmt_write_padding(fi, width) - } else if !fi.space && s != "" && s[0] == '-' { + } else if !fi.space && s != "" && (s[0] == '-' || s[0] == '+') { // left pad accounting for zero pad of negative number - io.write_byte(fi.writer, '-', &fi.n) + io.write_byte(fi.writer, s[0], &fi.n) fmt_write_padding(fi, width) io.write_string(fi.writer, s[1:], &fi.n) } else { // left pad From f57048f8627b5928df2bdbdffd85e3ec98e1481a Mon Sep 17 00:00:00 2001 From: Dan Korostelev Date: Fri, 24 Jan 2025 01:12:49 +0100 Subject: [PATCH 08/22] fix raylib.CameraMoveRight signature --- vendor/raylib/raylib.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/raylib/raylib.odin b/vendor/raylib/raylib.odin index 755f3bedd..02bb6deea 100644 --- a/vendor/raylib/raylib.odin +++ b/vendor/raylib/raylib.odin @@ -1205,7 +1205,7 @@ foreign lib { CameraMoveForward :: proc(camera: ^Camera, distance: f32, moveInWorldPlane: bool) --- // move the camera in its forward direction CameraMoveUp :: proc(camera: ^Camera, distance: f32) --- // move camera in its up direction - CameraMoveRight :: proc(camera: ^Camera, distance: f32, delta: f32) --- // move camera in it's current right direction + CameraMoveRight :: proc(camera: ^Camera, distance: f32, moveInWorldPlane: bool) --- // move camera in it's current right direction CameraMoveToTarget :: proc(camera: ^Camera, delta: f32) --- // moves the camera position closer/farther to/from the camera target CameraYaw :: proc(camera: ^Camera, angle: f32, rotateAroundTarget: bool) --- // rotates the camera around its up vector (left and right) CameraPitch :: proc(camera: ^Camera, angle: f32, lockView: bool, rotateAroundTarget: bool, rotateUp: bool) --- // rotates the camera around its right vector (up and down) From 98b3a9eacd9b95a5db75fb001da0bfb0c7a18645 Mon Sep 17 00:00:00 2001 From: Barinzaya Date: Fri, 24 Jan 2025 09:42:10 -0500 Subject: [PATCH 09/22] Added support for growing in place to some arenas. This affects `runtime.Arena` and `virtual.Arena`, but not currently `mem.Arena`. These changes allow the last allocation that has been made to be resized to a larger size by just extending their allocation in-place, when there's sufficient room in the memory block to do so. Shrinking in place and re-using the rest of the allocation can be supported using almost the same logic, but would require the memory to be zeroed. Since this would add a additional cost that isn't currently present, shrinking has not been changed. --- .../runtime/default_temp_allocator_arena.odin | 22 +++++++++++++++---- core/mem/virtual/arena.odin | 22 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/base/runtime/default_temp_allocator_arena.odin b/base/runtime/default_temp_allocator_arena.odin index 878a2d070..6e2900411 100644 --- a/base/runtime/default_temp_allocator_arena.odin +++ b/base/runtime/default_temp_allocator_arena.odin @@ -210,10 +210,24 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, case size == 0: err = .Mode_Not_Implemented return - case (uintptr(old_data) & uintptr(alignment-1) == 0) && size < old_size: - // shrink data in-place - data = old_data[:size] - return + case uintptr(old_data) & uintptr(alignment-1) == 0: + if size < old_size { + // shrink data in-place + data = old_data[:size] + return + } + + if block := arena.curr_block; block != nil { + start := uint(uintptr(old_memory)) - uint(uintptr(block.base)) + old_end := start + old_size + new_end := start + size + if start < old_end && old_end == block.used && new_end <= block.capacity { + // grow data in-place, adjusting next allocation + block.used = uint(new_end) + data = block.base[start:new_end] + return + } + } } new_memory := arena_alloc(arena, size, alignment, location) or_return diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 675558ec8..5191505cf 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -328,10 +328,24 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, case size == 0: err = .Mode_Not_Implemented return - case (uintptr(old_data) & uintptr(alignment-1) == 0) && size < old_size: - // shrink data in-place - data = old_data[:size] - return + case uintptr(old_data) & uintptr(alignment-1) == 0: + if size < old_size { + // shrink data in-place + data = old_data[:size] + return + } + + if block := arena.curr_block; block != nil { + start := uint(uintptr(old_memory)) - uint(uintptr(block.base)) + old_end := start + old_size + new_end := start + size + if start < old_end && old_end == block.used && new_end <= block.reserved { + // grow data in-place, adjusting next allocation + _ = alloc_from_memory_block(block, new_end - old_end, 1, default_commit_size=arena.default_commit_size) or_return + data = block.base[start:new_end] + return + } + } } new_memory := arena_alloc(arena, size, alignment, location) or_return From b2aaf90f88aa85e8893325f78260b3723dc4fe99 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 24 Jan 2025 19:23:49 +0100 Subject: [PATCH 10/22] fix separate modules with objc code --- src/llvm_backend.cpp | 12 +++- src/llvm_backend.hpp | 4 +- src/llvm_backend_utility.cpp | 104 +++++++++++++++++++---------------- 3 files changed, 69 insertions(+), 51 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 696ced0df..277d0433e 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1147,14 +1147,22 @@ gb_internal void lb_finalize_objc_names(lbProcedure *p) { String name = entry.key; args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); lbValue ptr = lb_emit_runtime_call(p, "objc_lookUpClass", args); - lb_addr_store(p, entry.value, ptr); + + lbValue ptr_ = lb_find_value_from_entity(m, entry.value); + lbAddr local_addr = lb_addr(ptr_); + + lb_addr_store(p, local_addr, ptr); } for (auto const &entry : m->objc_selectors) { String name = entry.key; args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); lbValue ptr = lb_emit_runtime_call(p, "sel_registerName", args); - lb_addr_store(p, entry.value, ptr); + + lbValue ptr_ = lb_find_value_from_entity(m, entry.value); + lbAddr local_addr = lb_addr(ptr_); + + lb_addr_store(p, local_addr, ptr); } lb_end_procedure_body(p); diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 42d283a1e..dd56d56a3 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -196,8 +196,8 @@ struct lbModule { RecursiveMutex debug_values_mutex; PtrMap debug_values; - StringMap objc_classes; - StringMap objc_selectors; + StringMap objc_classes; + StringMap objc_selectors; PtrMap map_cell_info_map; // address of runtime.Map_Info PtrMap map_info_map; // address of runtime.Map_Cell_Info diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 7b7c9d6e9..61dafa1c0 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2093,23 +2093,36 @@ gb_internal void lb_set_wasm_export_attributes(LLVMValueRef value, String export gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { - lbAddr *found = string_map_get(&p->module->objc_selectors, name); + lbModule *default_module = &p->module->gen->default_module; + Entity *entity = {}; + + Entity **found = string_map_get(&p->module->objc_selectors, name); if (found) { - return *found; - } else { - lbModule *default_module = &p->module->gen->default_module; - Entity *e = nullptr; - lbAddr default_addr = lb_add_global_generated(default_module, t_objc_SEL, {}, &e); - - lbValue ptr = lb_find_value_from_entity(p->module, e); - lbAddr local_addr = lb_addr(ptr); - - string_map_set(&default_module->objc_selectors, name, default_addr); - if (default_module != p->module) { - string_map_set(&p->module->objc_selectors, name, local_addr); - } - return local_addr; + entity = *found; } + + if (!entity) { + if (default_module != p->module) { + found = string_map_get(&default_module->objc_selectors, name); + if (found) { + entity = *found; + } + } + + if (!entity) { + lbAddr default_addr = lb_add_global_generated(default_module, t_objc_SEL, {}, &entity); + string_map_set(&default_module->objc_selectors, name, entity); + } + } + + lbValue ptr = lb_find_value_from_entity(p->module, entity); + lbAddr local_addr = lb_addr(ptr); + + if (default_module != p->module) { + string_map_set(&p->module->objc_selectors, name, entity); + } + + return local_addr; } gb_internal lbValue lb_handle_objc_find_selector(lbProcedure *p, Ast *expr) { @@ -2139,23 +2152,36 @@ gb_internal lbValue lb_handle_objc_register_selector(lbProcedure *p, Ast *expr) } gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String const &name) { - lbAddr *found = string_map_get(&p->module->objc_classes, name); + lbModule *default_module = &p->module->gen->default_module; + Entity *entity = {}; + + Entity **found = string_map_get(&p->module->objc_classes, name); if (found) { - return *found; - } else { - lbModule *default_module = &p->module->gen->default_module; - Entity *e = nullptr; - lbAddr default_addr = lb_add_global_generated(default_module, t_objc_SEL, {}, &e); - - lbValue ptr = lb_find_value_from_entity(p->module, e); - lbAddr local_addr = lb_addr(ptr); - - string_map_set(&default_module->objc_classes, name, default_addr); - if (default_module != p->module) { - string_map_set(&p->module->objc_classes, name, local_addr); - } - return local_addr; + entity = *found; } + + if (!entity) { + if (default_module != p->module) { + found = string_map_get(&default_module->objc_classes, name); + if (found) { + entity = *found; + } + } + + if (!entity) { + lbAddr default_addr = lb_add_global_generated(default_module, t_objc_Class, {}, &entity); + string_map_set(&default_module->objc_classes, name, entity); + } + } + + lbValue ptr = lb_find_value_from_entity(p->module, entity); + lbAddr local_addr = lb_addr(ptr); + + if (default_module != p->module) { + string_map_set(&p->module->objc_classes, name, entity); + } + + return local_addr; } gb_internal lbValue lb_handle_objc_find_class(lbProcedure *p, Ast *expr) { @@ -2196,23 +2222,7 @@ gb_internal lbValue lb_handle_objc_id(lbProcedure *p, Ast *expr) { GB_ASSERT(e->kind == Entity_TypeName); String name = e->TypeName.objc_class_name; - lbAddr *found = string_map_get(&p->module->objc_classes, name); - if (found) { - return lb_addr_load(p, *found); - } else { - lbModule *default_module = &p->module->gen->default_module; - Entity *e = nullptr; - lbAddr default_addr = lb_add_global_generated(default_module, t_objc_Class, {}, &e); - - lbValue ptr = lb_find_value_from_entity(p->module, e); - lbAddr local_addr = lb_addr(ptr); - - string_map_set(&default_module->objc_classes, name, default_addr); - if (default_module != p->module) { - string_map_set(&p->module->objc_classes, name, local_addr); - } - return lb_addr_load(p, local_addr); - } + return lb_addr_load(p, lb_handle_objc_find_or_register_class(p, name)); } return lb_build_expr(p, expr); From 9dc17f4c47471829b8360c9114ac382582e2b9b6 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 24 Jan 2025 19:33:57 +0100 Subject: [PATCH 11/22] optimize fix --- src/llvm_backend.cpp | 12 ++------ src/llvm_backend.hpp | 9 ++++-- src/llvm_backend_utility.cpp | 56 +++++++++++++++++------------------- 3 files changed, 35 insertions(+), 42 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 277d0433e..29fa67f3f 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1147,22 +1147,14 @@ gb_internal void lb_finalize_objc_names(lbProcedure *p) { String name = entry.key; args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); lbValue ptr = lb_emit_runtime_call(p, "objc_lookUpClass", args); - - lbValue ptr_ = lb_find_value_from_entity(m, entry.value); - lbAddr local_addr = lb_addr(ptr_); - - lb_addr_store(p, local_addr, ptr); + lb_addr_store(p, entry.value.local_module_addr, ptr); } for (auto const &entry : m->objc_selectors) { String name = entry.key; args[0] = lb_const_value(m, t_cstring, exact_value_string(name)); lbValue ptr = lb_emit_runtime_call(p, "sel_registerName", args); - - lbValue ptr_ = lb_find_value_from_entity(m, entry.value); - lbAddr local_addr = lb_addr(ptr_); - - lb_addr_store(p, local_addr, ptr); + lb_addr_store(p, entry.value.local_module_addr, ptr); } lb_end_procedure_body(p); diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index dd56d56a3..a0775ac3b 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -143,6 +143,11 @@ struct lbPadType { LLVMTypeRef type; }; +struct lbObjcRef { + Entity * entity; + lbAddr local_module_addr; +}; + struct lbModule { LLVMModuleRef mod; LLVMContextRef ctx; @@ -196,8 +201,8 @@ struct lbModule { RecursiveMutex debug_values_mutex; PtrMap debug_values; - StringMap objc_classes; - StringMap objc_selectors; + StringMap objc_classes; + StringMap objc_selectors; PtrMap map_cell_info_map; // address of runtime.Map_Info PtrMap map_info_map; // address of runtime.Map_Cell_Info diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 61dafa1c0..8910bd67a 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2093,33 +2093,31 @@ gb_internal void lb_set_wasm_export_attributes(LLVMValueRef value, String export gb_internal lbAddr lb_handle_objc_find_or_register_selector(lbProcedure *p, String const &name) { + lbObjcRef *found = string_map_get(&p->module->objc_selectors, name); + if (found) { + return found->local_module_addr; + } + lbModule *default_module = &p->module->gen->default_module; Entity *entity = {}; - Entity **found = string_map_get(&p->module->objc_selectors, name); - if (found) { - entity = *found; + if (default_module != p->module) { + found = string_map_get(&default_module->objc_selectors, name); + if (found) { + entity = found->entity; + } } if (!entity) { - if (default_module != p->module) { - found = string_map_get(&default_module->objc_selectors, name); - if (found) { - entity = *found; - } - } - - if (!entity) { - lbAddr default_addr = lb_add_global_generated(default_module, t_objc_SEL, {}, &entity); - string_map_set(&default_module->objc_selectors, name, entity); - } + lbAddr default_addr = lb_add_global_generated(default_module, t_objc_SEL, {}, &entity); + string_map_set(&default_module->objc_selectors, name, lbObjcRef{entity, default_addr}); } lbValue ptr = lb_find_value_from_entity(p->module, entity); lbAddr local_addr = lb_addr(ptr); if (default_module != p->module) { - string_map_set(&p->module->objc_selectors, name, entity); + string_map_set(&p->module->objc_selectors, name, lbObjcRef{entity, local_addr}); } return local_addr; @@ -2152,33 +2150,31 @@ gb_internal lbValue lb_handle_objc_register_selector(lbProcedure *p, Ast *expr) } gb_internal lbAddr lb_handle_objc_find_or_register_class(lbProcedure *p, String const &name) { + lbObjcRef *found = string_map_get(&p->module->objc_classes, name); + if (found) { + return found->local_module_addr; + } + lbModule *default_module = &p->module->gen->default_module; Entity *entity = {}; - Entity **found = string_map_get(&p->module->objc_classes, name); - if (found) { - entity = *found; + if (default_module != p->module) { + found = string_map_get(&default_module->objc_classes, name); + if (found) { + entity = found->entity; + } } if (!entity) { - if (default_module != p->module) { - found = string_map_get(&default_module->objc_classes, name); - if (found) { - entity = *found; - } - } - - if (!entity) { - lbAddr default_addr = lb_add_global_generated(default_module, t_objc_Class, {}, &entity); - string_map_set(&default_module->objc_classes, name, entity); - } + lbAddr default_addr = lb_add_global_generated(default_module, t_objc_Class, {}, &entity); + string_map_set(&default_module->objc_classes, name, lbObjcRef{entity, default_addr}); } lbValue ptr = lb_find_value_from_entity(p->module, entity); lbAddr local_addr = lb_addr(ptr); if (default_module != p->module) { - string_map_set(&p->module->objc_classes, name, entity); + string_map_set(&p->module->objc_classes, name, lbObjcRef{entity, local_addr}); } return local_addr; From f957542cd3a35fa544052632b1e9e7e3e00c4253 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sat, 25 Jan 2025 00:50:57 +0100 Subject: [PATCH 12/22] fix duplicate linker warning on macos Fixes #4747 --- build_odin.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build_odin.sh b/build_odin.sh index f4452e291..c7d5c9288 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -9,7 +9,7 @@ set -eu CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\"" CXXFLAGS="$CXXFLAGS -std=c++14" DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value" -LDFLAGS="$LDFLAGS -pthread -lm -lstdc++" +LDFLAGS="$LDFLAGS -pthread -lm" OS_ARCH="$(uname -m)" OS_NAME="$(uname -s)" @@ -95,15 +95,15 @@ Darwin) ;; FreeBSD) CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" + LDFLAGS="$LDFLAGS -lstdc++ $($LLVM_CONFIG --libs core native --system-libs)" ;; NetBSD) CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" + LDFLAGS="$LDFLAGS -lstdc++ $($LLVM_CONFIG --libs core native --system-libs)" ;; Linux) CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS -ldl $($LLVM_CONFIG --libs core native --system-libs --libfiles)" + LDFLAGS="$LDFLAGS -lstdc++ -ldl $($LLVM_CONFIG --libs core native --system-libs --libfiles)" # Copy libLLVM*.so into current directory for linking # NOTE: This is needed by the Linux release pipeline! # cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./ @@ -111,12 +111,12 @@ Linux) ;; OpenBSD) CXXFLAGS="$CXXFLAGS -I/usr/local/include $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS -L/usr/local/lib -liconv" + LDFLAGS="$LDFLAGS -lstdc++ -L/usr/local/lib -liconv" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" ;; Haiku) CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel" - LDFLAGS="$LDFLAGS -liconv" + LDFLAGS="$LDFLAGS -lstdc++ -liconv" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" ;; *) From 61f02d9f49e4bd6b8aac7a689e0c2c1fe612fdd6 Mon Sep 17 00:00:00 2001 From: Samuel Elgozi Date: Sun, 26 Jan 2025 14:03:45 +0200 Subject: [PATCH 13/22] pass flags down from `os.send` in darwin and linux --- core/os/os_darwin.odin | 2 +- core/os/os_linux.odin | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index d4435ec63..bbffc46d7 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -1287,7 +1287,7 @@ sendto :: proc(sd: Socket, data: []u8, flags: int, addr: ^SOCKADDR, addrlen: soc } send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Error) { - result := _unix_send(c.int(sd), raw_data(data), len(data), 0) + result := _unix_send(c.int(sd), raw_data(data), len(data), i32(flags)) if result < 0 { return 0, get_last_error() } diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index e023ce7cb..2281e6a82 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -1155,7 +1155,7 @@ sendto :: proc(sd: Socket, data: []u8, flags: int, addr: ^SOCKADDR, addrlen: soc } send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Error) { - result := unix.sys_sendto(int(sd), raw_data(data), len(data), 0, nil, 0) + result := unix.sys_sendto(int(sd), raw_data(data), len(data), flags, nil, 0) if result < 0 { return 0, _get_errno(int(result)) } From 72bbbc94a989bf5a8ec21398cdb71cbdd606b662 Mon Sep 17 00:00:00 2001 From: p1xelHer0 Date: Sun, 26 Jan 2025 23:36:35 +0100 Subject: [PATCH 14/22] Vendor - miniaudio - engine: fix sound_config_init2 The new way to init `sound_group` and `sound_group_config` is currently using a binding that doesn't match the miniaudio API. The functions in miniaudio have an underscore between the `init` and `2`. This fixes this. --- vendor/miniaudio/engine.odin | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/miniaudio/engine.odin b/vendor/miniaudio/engine.odin index 467bde583..a06e6c62c 100644 --- a/vendor/miniaudio/engine.odin +++ b/vendor/miniaudio/engine.odin @@ -150,9 +150,9 @@ sound_inlined :: struct { @(default_calling_convention="c", link_prefix="ma_") foreign lib { - @(deprecated="Will be removed in 0.12. Use sound_config_init2() instead.") + @(deprecated="Will be removed in 0.12. Use sound_config_init_2() instead.") sound_config_init :: proc() -> sound_config --- - sound_config_init2 :: proc(pEngine: ^engine) -> sound_config --- /* Will be renamed to sound_config_init() in version 0.12. */ + sound_config_init_2 :: proc(pEngine: ^engine) -> sound_config --- /* Will be renamed to sound_config_init() in version 0.12. */ sound_init_from_file :: proc(pEngine: ^engine, pFilePath: cstring, flags: sound_flags, pGroup: ^sound_group, pDoneFence: ^fence, pSound: ^sound) -> result --- sound_init_from_file_w :: proc(pEngine: ^engine, pFilePath: [^]c.wchar_t, flags: sound_flags, pGroup: ^sound_group, pDoneFence: ^fence, pSound: ^sound) -> result --- @@ -241,9 +241,9 @@ sound_group :: distinct sound @(default_calling_convention="c", link_prefix="ma_") foreign lib { - @(deprecated="Will be removed in 0.12. Use sound_config_init2() instead.") + @(deprecated="Will be removed in 0.12. Use sound_config_init_2() instead.") sound_group_config_init :: proc() -> sound_group_config --- - sound_group_config_init2 :: proc(pEngine: ^engine) -> sound_group_config --- + sound_group_config_init_2 :: proc(pEngine: ^engine) -> sound_group_config --- sound_group_init :: proc(pEngine: ^engine, flags: sound_flags, pParentGroup, pGroup: ^sound_group) -> result --- sound_group_init_ex :: proc(pEngine: ^engine, pConfig: ^sound_group_config, pGroup: ^sound_group) -> result --- From 34aa326d9995b1372429bbc712f0a6b5ad8170a6 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 27 Jan 2025 18:59:41 +0100 Subject: [PATCH 15/22] put FILE in core:c and use that in bindings to fix wasm --- core/c/c.odin | 2 ++ core/c/libc/stdio.odin | 3 ++- vendor/commonmark/cmark.odin | 3 +-- vendor/stb/image/stb_image.odin | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/c/c.odin b/core/c/c.odin index 3dfc19ffc..73727d8d5 100644 --- a/core/c/c.odin +++ b/core/c/c.odin @@ -114,3 +114,5 @@ CHAR_BIT :: 8 va_list :: struct #align(16) { _: [4096]u8, } + +FILE :: struct {} diff --git a/core/c/libc/stdio.odin b/core/c/libc/stdio.odin index a94a53696..56e4e8f66 100644 --- a/core/c/libc/stdio.odin +++ b/core/c/libc/stdio.odin @@ -1,5 +1,6 @@ package libc +import "core:c" import "core:io" when ODIN_OS == .Windows { @@ -15,7 +16,7 @@ when ODIN_OS == .Windows { // 7.21 Input/output -FILE :: struct {} +FILE :: c.FILE Whence :: enum int { SET = SEEK_SET, diff --git a/vendor/commonmark/cmark.odin b/vendor/commonmark/cmark.odin index 2fdf1387c..6b07f157f 100644 --- a/vendor/commonmark/cmark.odin +++ b/vendor/commonmark/cmark.odin @@ -7,7 +7,6 @@ package vendor_commonmark import "core:c" -import "core:c/libc" import "base:runtime" COMMONMARK_SHARED :: #config(COMMONMARK_SHARED, false) @@ -450,7 +449,7 @@ foreign lib { // Called `parse_from_libc_file` so as not to confuse with Odin's file handling. @(link_name = "parse_from_file") - parse_from_libc_file :: proc(file: ^libc.FILE, options: Options) -> (root: ^Node) --- + parse_from_libc_file :: proc(file: ^c.FILE, options: Options) -> (root: ^Node) --- } parser_feed_from_string :: proc "c" (parser: ^Parser, s: string) { diff --git a/vendor/stb/image/stb_image.odin b/vendor/stb/image/stb_image.odin index e74c825b8..1ba63dc47 100644 --- a/vendor/stb/image/stb_image.odin +++ b/vendor/stb/image/stb_image.odin @@ -1,6 +1,6 @@ package stb_image -import c "core:c/libc" +import "core:c" @(private) LIB :: ( From d85c2c1ca7d73c5f0513c731a13c80116124b9e4 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 27 Jan 2025 22:16:24 +0100 Subject: [PATCH 16/22] Add mDNS/Bonjour/Avahi (.local) support for Windows --- core/net/common.odin | 3 +++ core/net/dns_windows.odin | 7 ++++++- core/net/socket_linux.odin | 4 +++- core/sys/windows/dnsapi.odin | 2 +- core/sys/windows/types.odin | 25 +++++++++++++++++++++++++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/core/net/common.odin b/core/net/common.odin index 263fc770f..64155313d 100644 --- a/core/net/common.odin +++ b/core/net/common.odin @@ -95,6 +95,7 @@ Resolve_Error :: enum u32 { } DNS_Error :: enum u32 { + None = 0, Invalid_Hostname_Error = 1, Invalid_Hosts_Config_Error, Invalid_Resolv_Config_Error, @@ -147,6 +148,8 @@ IP6_Loopback :: IP6_Address{0, 0, 0, 0, 0, 0, 0, 1} IP4_Any := IP4_Address{} IP6_Any := IP6_Address{} +IP4_mDNS_Broadcast := Endpoint{address=IP4_Address{224, 0, 0, 251}, port=5353} + Endpoint :: struct { address: Address, port: int, diff --git a/core/net/dns_windows.odin b/core/net/dns_windows.odin index 2f3831767..7736851b8 100644 --- a/core/net/dns_windows.odin +++ b/core/net/dns_windows.odin @@ -29,9 +29,14 @@ import win "core:sys/windows" _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) { context.allocator = allocator + options := win.DNS_QUERY_OPTIONS{} + if strings.has_suffix(hostname, ".local") { + options = {.MULTICAST_ONLY, .MULTICAST_WAIT} // 0x00020500 + } + host_cstr := strings.clone_to_cstring(hostname, context.temp_allocator) rec: ^win.DNS_RECORD - res := win.DnsQuery_UTF8(host_cstr, u16(type), 0, nil, &rec, nil) + res := win.DnsQuery_UTF8(host_cstr, u16(type), options, nil, &rec, nil) switch u32(res) { case 0: diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index b7816b0b6..cafec747d 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -35,6 +35,7 @@ Socket_Option :: enum c.int { Send_Buffer_Size = c.int(linux.Socket_Option.SNDBUF), Receive_Timeout = c.int(linux.Socket_Option.RCVTIMEO), Send_Timeout = c.int(linux.Socket_Option.SNDTIMEO), + Broadcast = c.int(linux.Socket_Option.BROADCAST), } // Wrappers and unwrappers for system-native types @@ -337,7 +338,8 @@ _set_option :: proc(sock: Any_Socket, option: Socket_Option, value: any, loc := .Reuse_Address, .Keep_Alive, .Out_Of_Bounds_Data_Inline, - .TCP_Nodelay: + .TCP_Nodelay, + .Broadcast: // TODO: verify whether these are options or not on Linux // .Broadcast, <-- yes // .Conditional_Accept, diff --git a/core/sys/windows/dnsapi.odin b/core/sys/windows/dnsapi.odin index 4fd9f7a19..728813696 100644 --- a/core/sys/windows/dnsapi.odin +++ b/core/sys/windows/dnsapi.odin @@ -5,6 +5,6 @@ foreign import "system:Dnsapi.lib" @(default_calling_convention="system") foreign Dnsapi { - DnsQuery_UTF8 :: proc(name: cstring, type: u16, options: DWORD, extra: PVOID, results: ^^DNS_RECORD, reserved: PVOID) -> DNS_STATUS --- + DnsQuery_UTF8 :: proc(name: cstring, type: u16, options: DNS_QUERY_OPTIONS, extra: PVOID, results: ^^DNS_RECORD, reserved: PVOID) -> DNS_STATUS --- DnsRecordListFree :: proc(list: ^DNS_RECORD, options: DWORD) --- } diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index ab79c682a..8069659c9 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -4576,6 +4576,31 @@ DNS_SRV_DATAA :: struct { _: WORD, // padding } +// See https://learn.microsoft.com/en-us/windows/win32/dns/dns-constants +DNS_QUERY_OPTION :: enum DWORD { + ACCEPT_TRUNCATED_RESPONSE = 0, + DNS_QUERY_USE_TCP_ONLY = 1, + NO_RECURSION = 2, + BYPASS_CACHE = 3, + NO_WIRE_QUERY = 4, + NO_LOCAL_NAME = 5, + NO_HOSTS_FILE = 6, + NO_NETBT = 7, + WIRE_ONLY = 8, + RETURN_MESSAGE = 9, + MULTICAST_ONLY = 10, + NO_MULTICAST = 11, + TREAT_AS_FQDN = 12, + ADDRCONFIG = 13, + DUAL_ADDR = 14, + MULTICAST_WAIT = 17, + MULTICAST_VERIFY = 18, + DONT_RESET_TTL_VALUES = 20, + DISABLE_IDN_ENCODING = 21, + APPEND_MULTILABEL = 23, +} +DNS_QUERY_OPTIONS :: bit_set[DNS_QUERY_OPTION; DWORD] + SOCKADDR :: struct { sa_family: ADDRESS_FAMILY, sa_data: [14]CHAR, From 8998d74a926f52ef02a8f77936922dae3da6085f Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 27 Jan 2025 22:55:48 +0100 Subject: [PATCH 17/22] Add mDNS for *nix. --- core/net/common.odin | 1 + core/net/dns.odin | 89 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/core/net/common.odin b/core/net/common.odin index 64155313d..12add8225 100644 --- a/core/net/common.odin +++ b/core/net/common.odin @@ -149,6 +149,7 @@ IP4_Any := IP4_Address{} IP6_Any := IP6_Address{} IP4_mDNS_Broadcast := Endpoint{address=IP4_Address{224, 0, 0, 251}, port=5353} +IP6_mDNS_Broadcast := Endpoint{address=IP6_Address{65282, 0, 0, 0, 0, 0, 0, 251}, port = 5353} Endpoint :: struct { address: Address, diff --git a/core/net/dns.odin b/core/net/dns.odin index ffb97fc5b..b3649c686 100644 --- a/core/net/dns.odin +++ b/core/net/dns.odin @@ -132,7 +132,14 @@ resolve_ip4 :: proc(hostname_and_maybe_port: string) -> (ep4: Endpoint, err: Net return } case Host: - recs, _ := get_dns_records_from_os(t.hostname, .IP4, context.temp_allocator) + recs: []DNS_Record + + if ODIN_OS != .Windows && strings.has_suffix(t.hostname, ".local") { + recs, _ = get_dns_records_from_mdns(t.hostname, .IP4, context.temp_allocator) + } else { + recs, _ = get_dns_records_from_os(t.hostname, .IP4, context.temp_allocator) + } + if len(recs) == 0 { err = .Unable_To_Resolve return @@ -159,7 +166,14 @@ resolve_ip6 :: proc(hostname_and_maybe_port: string) -> (ep6: Endpoint, err: Net return t, nil } case Host: - recs, _ := get_dns_records_from_os(t.hostname, .IP6, context.temp_allocator) + recs: []DNS_Record + + if ODIN_OS != .Windows && strings.has_suffix(t.hostname, ".local") { + recs, _ = get_dns_records_from_mdns(t.hostname, .IP6, context.temp_allocator) + } else { + recs, _ = get_dns_records_from_os(t.hostname, .IP6, context.temp_allocator) + } + if len(recs) == 0 { err = .Unable_To_Resolve return @@ -283,6 +297,77 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type return } +get_dns_records_from_mdns :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) { + assert(type == .IP4 || type == .IP6) + + context.allocator = allocator + + if !validate_hostname(hostname) { + return nil, .Invalid_Hostname_Error + } + + hdr := DNS_Header{ + id = 0, + is_response = false, + opcode = 0, + is_authoritative = false, + is_truncated = false, + is_recursion_desired = true, + is_recursion_available = false, + response_code = DNS_Response_Code.No_Error, + } + + id, bits := pack_dns_header(hdr) + dns_hdr := [6]u16be{} + dns_hdr[0] = id + dns_hdr[1] = bits + dns_hdr[2] = 1 + + dns_query := [2]u16be{ u16be(type), 1 } + + output := [(size_of(u16be) * 6) + NAME_MAX + (size_of(u16be) * 2)]u8{} + b := strings.builder_from_slice(output[:]) + + strings.write_bytes(&b, mem.slice_data_cast([]u8, dns_hdr[:])) + ok := encode_hostname(&b, hostname) + if !ok { + return nil, .Invalid_Hostname_Error + } + strings.write_bytes(&b, mem.slice_data_cast([]u8, dns_query[:])) + + dns_packet := output[:strings.builder_len(b)] + + dns_response_buf := [4096]u8{} + dns_response: []u8 + + name_server := IP4_mDNS_Broadcast if type == .IP4 else IP6_mDNS_Broadcast + + conn, sock_err := make_unbound_udp_socket(family_from_endpoint(name_server)) + if sock_err != nil { + return nil, .Connection_Error + } + defer close(conn) + + send(conn, dns_packet[:], name_server) + + if set_option(conn, .Receive_Timeout, time.Second * 1) != nil { + return nil, .Connection_Error + } + + recv_sz, _, _ := recv_udp(conn, dns_response_buf[:]) + if recv_sz == 0 { + return nil, .Server_Error + } + + dns_response = dns_response_buf[:recv_sz] + + rsp, _ok := parse_response(dns_response, type) + if !_ok { + return nil, .Server_Error + } + return rsp[:], nil +} + // `records` slice is also destroyed. destroy_dns_records :: proc(records: []DNS_Record, allocator := context.allocator) { context.allocator = allocator From cc29bdaefc8cc34f3a18e7304224252f446a421d Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 27 Jan 2025 23:04:15 +0100 Subject: [PATCH 18/22] Simplify *nix mDNS --- core/net/dns.odin | 81 ++--------------------------------------------- 1 file changed, 2 insertions(+), 79 deletions(-) diff --git a/core/net/dns.odin b/core/net/dns.odin index b3649c686..6d5dfea23 100644 --- a/core/net/dns.odin +++ b/core/net/dns.odin @@ -135,7 +135,7 @@ resolve_ip4 :: proc(hostname_and_maybe_port: string) -> (ep4: Endpoint, err: Net recs: []DNS_Record if ODIN_OS != .Windows && strings.has_suffix(t.hostname, ".local") { - recs, _ = get_dns_records_from_mdns(t.hostname, .IP4, context.temp_allocator) + recs, _ = get_dns_records_from_nameservers(t.hostname, .IP4, {IP4_mDNS_Broadcast}, nil, context.temp_allocator) } else { recs, _ = get_dns_records_from_os(t.hostname, .IP4, context.temp_allocator) } @@ -169,7 +169,7 @@ resolve_ip6 :: proc(hostname_and_maybe_port: string) -> (ep6: Endpoint, err: Net recs: []DNS_Record if ODIN_OS != .Windows && strings.has_suffix(t.hostname, ".local") { - recs, _ = get_dns_records_from_mdns(t.hostname, .IP6, context.temp_allocator) + recs, _ = get_dns_records_from_nameservers(t.hostname, .IP6, {IP6_mDNS_Broadcast}, nil, context.temp_allocator) } else { recs, _ = get_dns_records_from_os(t.hostname, .IP6, context.temp_allocator) } @@ -269,12 +269,6 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type return nil, .Connection_Error } - // recv_sz, _, recv_err := recv_udp(conn, dns_response_buf[:]) - // if recv_err == UDP_Recv_Error.Timeout { - // continue - // } else if recv_err != nil { - // continue - // } recv_sz, _ := recv_udp(conn, dns_response_buf[:]) or_continue if recv_sz == 0 { continue @@ -297,77 +291,6 @@ get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type return } -get_dns_records_from_mdns :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) { - assert(type == .IP4 || type == .IP6) - - context.allocator = allocator - - if !validate_hostname(hostname) { - return nil, .Invalid_Hostname_Error - } - - hdr := DNS_Header{ - id = 0, - is_response = false, - opcode = 0, - is_authoritative = false, - is_truncated = false, - is_recursion_desired = true, - is_recursion_available = false, - response_code = DNS_Response_Code.No_Error, - } - - id, bits := pack_dns_header(hdr) - dns_hdr := [6]u16be{} - dns_hdr[0] = id - dns_hdr[1] = bits - dns_hdr[2] = 1 - - dns_query := [2]u16be{ u16be(type), 1 } - - output := [(size_of(u16be) * 6) + NAME_MAX + (size_of(u16be) * 2)]u8{} - b := strings.builder_from_slice(output[:]) - - strings.write_bytes(&b, mem.slice_data_cast([]u8, dns_hdr[:])) - ok := encode_hostname(&b, hostname) - if !ok { - return nil, .Invalid_Hostname_Error - } - strings.write_bytes(&b, mem.slice_data_cast([]u8, dns_query[:])) - - dns_packet := output[:strings.builder_len(b)] - - dns_response_buf := [4096]u8{} - dns_response: []u8 - - name_server := IP4_mDNS_Broadcast if type == .IP4 else IP6_mDNS_Broadcast - - conn, sock_err := make_unbound_udp_socket(family_from_endpoint(name_server)) - if sock_err != nil { - return nil, .Connection_Error - } - defer close(conn) - - send(conn, dns_packet[:], name_server) - - if set_option(conn, .Receive_Timeout, time.Second * 1) != nil { - return nil, .Connection_Error - } - - recv_sz, _, _ := recv_udp(conn, dns_response_buf[:]) - if recv_sz == 0 { - return nil, .Server_Error - } - - dns_response = dns_response_buf[:recv_sz] - - rsp, _ok := parse_response(dns_response, type) - if !_ok { - return nil, .Server_Error - } - return rsp[:], nil -} - // `records` slice is also destroyed. destroy_dns_records :: proc(records: []DNS_Record, allocator := context.allocator) { context.allocator = allocator From 868ab277209908a3857c874014bced9e0fae6949 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 28 Jan 2025 10:31:46 +0000 Subject: [PATCH 19/22] Add `@(ignore_duplicates)` for `foreign import` declarations --- src/checker.cpp | 9 +++++++++ src/checker.hpp | 1 + src/entity.cpp | 1 + vendor/sdl2/sdl2.odin | 2 ++ vendor/sdl2/sdl_audio.odin | 2 ++ vendor/sdl2/sdl_blendmode.odin | 2 ++ vendor/sdl2/sdl_cpuinfo.odin | 2 ++ vendor/sdl2/sdl_events.odin | 2 ++ vendor/sdl2/sdl_gamecontroller.odin | 2 ++ vendor/sdl2/sdl_gesture_haptic.odin | 2 ++ vendor/sdl2/sdl_hints.odin | 2 ++ vendor/sdl2/sdl_joystick.odin | 2 ++ vendor/sdl2/sdl_keyboard.odin | 2 ++ vendor/sdl2/sdl_log.odin | 2 ++ vendor/sdl2/sdl_messagebox.odin | 2 ++ vendor/sdl2/sdl_metal.odin | 2 ++ vendor/sdl2/sdl_mouse.odin | 2 ++ vendor/sdl2/sdl_mutex.odin | 2 ++ vendor/sdl2/sdl_pixels.odin | 2 ++ vendor/sdl2/sdl_rect.odin | 2 ++ vendor/sdl2/sdl_render.odin | 2 ++ vendor/sdl2/sdl_rwops.odin | 2 ++ vendor/sdl2/sdl_stdinc.odin | 2 ++ vendor/sdl2/sdl_surface.odin | 2 ++ vendor/sdl2/sdl_system.odin | 2 ++ vendor/sdl2/sdl_syswm.odin | 2 ++ vendor/sdl2/sdl_thread.odin | 2 ++ vendor/sdl2/sdl_timer.odin | 2 ++ vendor/sdl2/sdl_touch.odin | 2 ++ vendor/sdl2/sdl_video.odin | 2 ++ vendor/sdl2/sdl_vulkan.odin | 2 ++ 31 files changed, 67 insertions(+) diff --git a/src/checker.cpp b/src/checker.cpp index 85077a5c5..baa1e0d2b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5040,6 +5040,12 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_import_decl_attribute) { ac->extra_linker_flags = ev.value_string; } return true; + } else if (name == "ignore_duplicates") { + if (value != nullptr) { + error(elem, "Expected no parameter for '%.*s'", LIT(name)); + } + ac->ignore_duplicates = true; + return true; } return false; } @@ -5190,6 +5196,9 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { if (ac.foreign_import_priority_index != 0) { e->LibraryName.priority_index = ac.foreign_import_priority_index; } + if (ac.ignore_duplicates) { + e->LibraryName.ignore_duplicates = true; + } String extra_linker_flags = string_trim_whitespace(ac.extra_linker_flags); if (extra_linker_flags.len != 0) { e->LibraryName.extra_linker_flags = extra_linker_flags; diff --git a/src/checker.hpp b/src/checker.hpp index 3951fcefe..4634047c0 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -140,6 +140,7 @@ struct AttributeContext { bool instrumentation_enter : 1; bool instrumentation_exit : 1; bool rodata : 1; + bool ignore_duplicates : 1; u32 optimization_mode; // ProcedureOptimizationMode i64 foreign_import_priority_index; String extra_linker_flags; diff --git a/src/entity.cpp b/src/entity.cpp index 802b381f9..d137a8674 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -274,6 +274,7 @@ struct Entity { Slice paths; String name; i64 priority_index; + bool ignore_duplicates; String extra_linker_flags; } LibraryName; i32 Nil; diff --git a/vendor/sdl2/sdl2.odin b/vendor/sdl2/sdl2.odin index b23389a64..5bc52b70e 100644 --- a/vendor/sdl2/sdl2.odin +++ b/vendor/sdl2/sdl2.odin @@ -26,8 +26,10 @@ import "core:c" import "base:intrinsics" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_audio.odin b/vendor/sdl2/sdl_audio.odin index 28a59d947..6ff9e93f4 100644 --- a/vendor/sdl2/sdl_audio.odin +++ b/vendor/sdl2/sdl_audio.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_blendmode.odin b/vendor/sdl2/sdl_blendmode.odin index 4fde5111b..3105ad72b 100644 --- a/vendor/sdl2/sdl_blendmode.odin +++ b/vendor/sdl2/sdl_blendmode.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_cpuinfo.odin b/vendor/sdl2/sdl_cpuinfo.odin index c5175e4d5..a98b6f8d3 100644 --- a/vendor/sdl2/sdl_cpuinfo.odin +++ b/vendor/sdl2/sdl_cpuinfo.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_events.odin b/vendor/sdl2/sdl_events.odin index b4c92683c..061eb964d 100644 --- a/vendor/sdl2/sdl_events.odin +++ b/vendor/sdl2/sdl_events.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_gamecontroller.odin b/vendor/sdl2/sdl_gamecontroller.odin index beb7d5ce7..be45d6520 100644 --- a/vendor/sdl2/sdl_gamecontroller.odin +++ b/vendor/sdl2/sdl_gamecontroller.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_gesture_haptic.odin b/vendor/sdl2/sdl_gesture_haptic.odin index a21e0df06..01d7a6da3 100644 --- a/vendor/sdl2/sdl_gesture_haptic.odin +++ b/vendor/sdl2/sdl_gesture_haptic.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_hints.odin b/vendor/sdl2/sdl_hints.odin index 913d4ea12..080dc6036 100644 --- a/vendor/sdl2/sdl_hints.odin +++ b/vendor/sdl2/sdl_hints.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_joystick.odin b/vendor/sdl2/sdl_joystick.odin index 35ca5cdcc..0725a3554 100644 --- a/vendor/sdl2/sdl_joystick.odin +++ b/vendor/sdl2/sdl_joystick.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_keyboard.odin b/vendor/sdl2/sdl_keyboard.odin index f880286aa..0d0557de9 100644 --- a/vendor/sdl2/sdl_keyboard.odin +++ b/vendor/sdl2/sdl_keyboard.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_log.odin b/vendor/sdl2/sdl_log.odin index 09b7eaef0..b7668ee1d 100644 --- a/vendor/sdl2/sdl_log.odin +++ b/vendor/sdl2/sdl_log.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_messagebox.odin b/vendor/sdl2/sdl_messagebox.odin index 6228704ac..edd8422e0 100644 --- a/vendor/sdl2/sdl_messagebox.odin +++ b/vendor/sdl2/sdl_messagebox.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_metal.odin b/vendor/sdl2/sdl_metal.odin index 1eccf7f5a..e8e650212 100644 --- a/vendor/sdl2/sdl_metal.odin +++ b/vendor/sdl2/sdl_metal.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_mouse.odin b/vendor/sdl2/sdl_mouse.odin index 0243b6623..8e782a5e3 100644 --- a/vendor/sdl2/sdl_mouse.odin +++ b/vendor/sdl2/sdl_mouse.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_mutex.odin b/vendor/sdl2/sdl_mutex.odin index 6ff7e5d2b..6eb096c81 100644 --- a/vendor/sdl2/sdl_mutex.odin +++ b/vendor/sdl2/sdl_mutex.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_pixels.odin b/vendor/sdl2/sdl_pixels.odin index 195f2920f..6a3d89f4e 100644 --- a/vendor/sdl2/sdl_pixels.odin +++ b/vendor/sdl2/sdl_pixels.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_rect.odin b/vendor/sdl2/sdl_rect.odin index 852309cd2..96cf7180e 100644 --- a/vendor/sdl2/sdl_rect.odin +++ b/vendor/sdl2/sdl_rect.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_render.odin b/vendor/sdl2/sdl_render.odin index cceebf3ac..5e913e5a3 100644 --- a/vendor/sdl2/sdl_render.odin +++ b/vendor/sdl2/sdl_render.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_rwops.odin b/vendor/sdl2/sdl_rwops.odin index 28d09511b..ca7fa0bea 100644 --- a/vendor/sdl2/sdl_rwops.odin +++ b/vendor/sdl2/sdl_rwops.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_stdinc.odin b/vendor/sdl2/sdl_stdinc.odin index 9136ae026..bf04a3f1f 100644 --- a/vendor/sdl2/sdl_stdinc.odin +++ b/vendor/sdl2/sdl_stdinc.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_surface.odin b/vendor/sdl2/sdl_surface.odin index f50de35f7..1502efbc7 100644 --- a/vendor/sdl2/sdl_surface.odin +++ b/vendor/sdl2/sdl_surface.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_system.odin b/vendor/sdl2/sdl_system.odin index d9b6b98df..1c34e557e 100644 --- a/vendor/sdl2/sdl_system.odin +++ b/vendor/sdl2/sdl_system.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_syswm.odin b/vendor/sdl2/sdl_syswm.odin index 62ca9d628..15501c222 100644 --- a/vendor/sdl2/sdl_syswm.odin +++ b/vendor/sdl2/sdl_syswm.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_thread.odin b/vendor/sdl2/sdl_thread.odin index 5d1c0bd37..84516e26b 100644 --- a/vendor/sdl2/sdl_thread.odin +++ b/vendor/sdl2/sdl_thread.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_timer.odin b/vendor/sdl2/sdl_timer.odin index d71ed2da5..50b5eb981 100644 --- a/vendor/sdl2/sdl_timer.odin +++ b/vendor/sdl2/sdl_timer.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_touch.odin b/vendor/sdl2/sdl_touch.odin index f0ca69333..44633aeb6 100644 --- a/vendor/sdl2/sdl_touch.odin +++ b/vendor/sdl2/sdl_touch.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_video.odin b/vendor/sdl2/sdl_video.odin index 86b564541..809735414 100644 --- a/vendor/sdl2/sdl_video.odin +++ b/vendor/sdl2/sdl_video.odin @@ -3,8 +3,10 @@ package sdl2 import "core:c" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } diff --git a/vendor/sdl2/sdl_vulkan.odin b/vendor/sdl2/sdl_vulkan.odin index 33bb8e51c..4e0db0ffe 100644 --- a/vendor/sdl2/sdl_vulkan.odin +++ b/vendor/sdl2/sdl_vulkan.odin @@ -4,8 +4,10 @@ import "core:c" import vk "vendor:vulkan" when ODIN_OS == .Windows { + @(ignore_duplicates) foreign import lib "SDL2.lib" } else { + @(ignore_duplicates) foreign import lib "system:SDL2" } From 15ece42e74acd7d62fc65bbc611e6766ec34187a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 28 Jan 2025 10:34:41 +0000 Subject: [PATCH 20/22] Print frameworks first on Darwin targets --- src/linker.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/linker.cpp b/src/linker.cpp index 59e6d8dc1..cf2ef638d 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -449,6 +449,26 @@ gb_internal i32 linker_stage(LinkerData *gen) { if (extra_linker_flags.len != 0) { lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(extra_linker_flags)); } + + if (build_context.metrics.os == TargetOs_darwin) { + // Print frameworks first + for (String lib : e->LibraryName.paths) { + lib = string_trim_whitespace(lib); + if (lib.len == 0) { + continue; + } + if (string_ends_with(lib, str_lit(".framework"))) { + if (string_set_update(&min_libs_set, lib)) { + continue; + } + + String lib_name = lib; + lib_name = remove_extension_from_path(lib_name); + lib_str = gb_string_append_fmt(lib_str, " -framework %.*s ", LIT(lib_name)); + } + } + } + for (String lib : e->LibraryName.paths) { lib = string_trim_whitespace(lib); if (lib.len == 0) { @@ -541,7 +561,9 @@ gb_internal i32 linker_stage(LinkerData *gen) { short_circuit = true; } else if (string_ends_with(lib, str_lit(".dylib"))) { short_circuit = true; - } else if (string_ends_with(lib, str_lit(".so"))) { + } else if (string_ends_with(lib, str_lit(".so"))) { + short_circuit = true; + } else if (e->LibraryName.ignore_duplicates) { short_circuit = true; } From 0e27acd7551fe49f48fbdea55c2645097af3b0b4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 28 Jan 2025 11:38:06 +0000 Subject: [PATCH 21/22] Update `NSSavelPanel` --- core/sys/darwin/Foundation/NSSavePanel.odin | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/sys/darwin/Foundation/NSSavePanel.odin b/core/sys/darwin/Foundation/NSSavePanel.odin index 8e4d7a07b..2f89696ee 100644 --- a/core/sys/darwin/Foundation/NSSavePanel.odin +++ b/core/sys/darwin/Foundation/NSSavePanel.odin @@ -7,3 +7,13 @@ SavePanel :: struct{ using _: Panel } SavePanel_runModal :: proc "c" (self: ^SavePanel) -> ModalResponse { return msgSend(ModalResponse, self, "runModal") } + +@(objc_type=SavePanel, objc_name="savePanel", objc_is_class_method=true) +SavePanel_savePanel :: proc "c" () -> ^SavePanel { + return msgSend(^SavePanel, SavePanel, "savePanel") +} + +@(objc_type=SavePanel, objc_name="URL") +SavePanel_URL :: proc "c" (self: ^SavePanel) -> ^Array { + return msgSend(^Array, self, "URL") +} \ No newline at end of file From 2656ecd4e17d448f1d972270bde87f75bc096d0d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 29 Jan 2025 15:53:34 +0000 Subject: [PATCH 22/22] Fix #4773 - Change order of evaluation for slicing indices --- src/llvm_backend_expr.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index df9dca801..871536927 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4294,6 +4294,17 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { ast_node(se, SliceExpr, expr); + lbAddr addr = lb_build_addr(p, se->expr); + lbValue base = lb_addr_load(p, addr); + Type *type = base_type(base.type); + + if (is_type_pointer(type)) { + type = base_type(type_deref(type)); + addr = lb_addr(base); + base = lb_addr_load(p, addr); + } + + lbValue low = lb_const_int(p->module, t_int, 0); lbValue high = {}; @@ -4306,16 +4317,6 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { bool no_indices = se->low == nullptr && se->high == nullptr; - lbAddr addr = lb_build_addr(p, se->expr); - lbValue base = lb_addr_load(p, addr); - Type *type = base_type(base.type); - - if (is_type_pointer(type)) { - type = base_type(type_deref(type)); - addr = lb_addr(base); - base = lb_addr_load(p, addr); - } - switch (type->kind) { case Type_Slice: { Type *slice_type = type;