aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2025-01-30 10:37:21 +0000
committergingerBill <bill@gingerbill.org>2025-01-30 10:37:21 +0000
commit5efa3510cfeebf498f78b35a213bab0c1014a85e (patch)
tree8d0040882adf0bf2a6c5a5a8a91d99906b5664da
parent998d6525b7e1cc046f9cf58577fa71ee88b7c9a0 (diff)
parent2656ecd4e17d448f1d972270bde87f75bc096d0d (diff)
Merge branch 'master' into bill/sdl3
-rw-r--r--base/runtime/default_temp_allocator_arena.odin22
-rwxr-xr-xbuild_odin.sh12
-rw-r--r--core/c/c.odin2
-rw-r--r--core/c/libc/stdio.odin3
-rw-r--r--core/fmt/fmt.odin4
-rw-r--r--core/math/linalg/specific.odin12
-rw-r--r--core/mem/virtual/arena.odin22
-rw-r--r--core/net/common.odin4
-rw-r--r--core/net/dns.odin24
-rw-r--r--core/net/dns_windows.odin7
-rw-r--r--core/net/socket_linux.odin4
-rw-r--r--core/os/os2/errors_posix.odin13
-rw-r--r--core/os/os2/file_linux.odin61
-rw-r--r--core/os/os2/path.odin12
-rw-r--r--core/os/os2/path_darwin.odin17
-rw-r--r--core/os/os2/path_freebsd.odin29
-rw-r--r--core/os/os2/path_linux.odin22
-rw-r--r--core/os/os2/path_netbsd.odin24
-rw-r--r--core/os/os2/path_openbsd.odin57
-rw-r--r--core/os/os2/path_wasi.odin33
-rw-r--r--core/os/os2/path_windows.odin20
-rw-r--r--core/os/os_darwin.odin2
-rw-r--r--core/os/os_linux.odin2
-rw-r--r--core/sys/darwin/Foundation/NSSavePanel.odin10
-rw-r--r--core/sys/windows/dnsapi.odin2
-rw-r--r--core/sys/windows/types.odin25
-rw-r--r--src/big_int.cpp5
-rw-r--r--src/checker.cpp9
-rw-r--r--src/checker.hpp1
-rw-r--r--src/entity.cpp1
-rw-r--r--src/linker.cpp24
-rw-r--r--src/llvm_backend.cpp4
-rw-r--r--src/llvm_backend.hpp9
-rw-r--r--src/llvm_backend_expr.cpp21
-rw-r--r--src/llvm_backend_utility.cpp88
-rw-r--r--tests/core/os/os2/path.odin22
-rw-r--r--vendor/commonmark/cmark.odin3
-rw-r--r--vendor/miniaudio/engine.odin8
-rw-r--r--vendor/raylib/raylib.odin2
-rw-r--r--vendor/sdl2/sdl2.odin2
-rw-r--r--vendor/sdl2/sdl_audio.odin2
-rw-r--r--vendor/sdl2/sdl_blendmode.odin2
-rw-r--r--vendor/sdl2/sdl_cpuinfo.odin2
-rw-r--r--vendor/sdl2/sdl_events.odin2
-rw-r--r--vendor/sdl2/sdl_gamecontroller.odin2
-rw-r--r--vendor/sdl2/sdl_gesture_haptic.odin2
-rw-r--r--vendor/sdl2/sdl_hints.odin2
-rw-r--r--vendor/sdl2/sdl_joystick.odin2
-rw-r--r--vendor/sdl2/sdl_keyboard.odin2
-rw-r--r--vendor/sdl2/sdl_log.odin2
-rw-r--r--vendor/sdl2/sdl_messagebox.odin2
-rw-r--r--vendor/sdl2/sdl_metal.odin2
-rw-r--r--vendor/sdl2/sdl_mouse.odin2
-rw-r--r--vendor/sdl2/sdl_mutex.odin2
-rw-r--r--vendor/sdl2/sdl_pixels.odin2
-rw-r--r--vendor/sdl2/sdl_rect.odin2
-rw-r--r--vendor/sdl2/sdl_render.odin2
-rw-r--r--vendor/sdl2/sdl_rwops.odin2
-rw-r--r--vendor/sdl2/sdl_stdinc.odin2
-rw-r--r--vendor/sdl2/sdl_surface.odin2
-rw-r--r--vendor/sdl2/sdl_system.odin2
-rw-r--r--vendor/sdl2/sdl_syswm.odin2
-rw-r--r--vendor/sdl2/sdl_thread.odin2
-rw-r--r--vendor/sdl2/sdl_timer.odin2
-rw-r--r--vendor/sdl2/sdl_touch.odin2
-rw-r--r--vendor/sdl2/sdl_video.odin2
-rw-r--r--vendor/sdl2/sdl_vulkan.odin2
-rw-r--r--vendor/stb/image/stb_image.odin2
68 files changed, 574 insertions, 126 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/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)"
;;
*)
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/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
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
}
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
diff --git a/core/net/common.odin b/core/net/common.odin
index 263fc770f..12add8225 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,9 @@ 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}
+IP6_mDNS_Broadcast := Endpoint{address=IP6_Address{65282, 0, 0, 0, 0, 0, 0, 251}, port = 5353}
+
Endpoint :: struct {
address: Address,
port: int,
diff --git a/core/net/dns.odin b/core/net/dns.odin
index ffb97fc5b..6d5dfea23 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_nameservers(t.hostname, .IP4, {IP4_mDNS_Broadcast}, nil, 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_nameservers(t.hostname, .IP6, {IP6_mDNS_Broadcast}, nil, 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
@@ -255,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
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/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/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
- }
- n, errno := linux.write(f.fd, p[:])
- if errno != .NONE {
- return -1, _get_platform_error(errno)
+_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)
}
- 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) {
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..65aaf1e95
--- /dev/null
+++ b/core/os/os2/path_darwin.odin
@@ -0,0 +1,17 @@
+package os2
+
+import "base:runtime"
+
+import "core:sys/darwin"
+import "core:sys/posix"
+
+_get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err: Error) {
+ 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)
+ }
+
+ err = _get_platform_error()
+ return
+}
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_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)
+}
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/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))
}
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
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,
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) {
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<String> paths;
String name;
i64 priority_index;
+ bool ignore_duplicates;
String extra_linker_flags;
} LibraryName;
i32 Nil;
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;
}
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 696ced0df..29fa67f3f 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -1147,14 +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);
- lb_addr_store(p, entry.value, 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);
- lb_addr_store(p, entry.value, 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 42d283a1e..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<void *, LLVMMetadataRef> debug_values;
- StringMap<lbAddr> objc_classes;
- StringMap<lbAddr> objc_selectors;
+ StringMap<lbObjcRef> objc_classes;
+ StringMap<lbObjcRef> objc_selectors;
PtrMap<Type *, lbAddr> map_cell_info_map; // address of runtime.Map_Info
PtrMap<Type *, lbAddr> map_info_map; // address of runtime.Map_Cell_Info
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;
diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp
index 7b7c9d6e9..8910bd67a 100644
--- a/src/llvm_backend_utility.cpp
+++ b/src/llvm_backend_utility.cpp
@@ -2093,23 +2093,34 @@ 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);
+ lbObjcRef *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);
+ return found->local_module_addr;
+ }
- lbValue ptr = lb_find_value_from_entity(p->module, e);
- lbAddr local_addr = lb_addr(ptr);
+ lbModule *default_module = &p->module->gen->default_module;
+ Entity *entity = {};
- 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);
+ if (default_module != p->module) {
+ found = string_map_get(&default_module->objc_selectors, name);
+ if (found) {
+ entity = found->entity;
}
- return local_addr;
}
+
+ if (!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, lbObjcRef{entity, local_addr});
+ }
+
+ return local_addr;
}
gb_internal lbValue lb_handle_objc_find_selector(lbProcedure *p, Ast *expr) {
@@ -2139,23 +2150,34 @@ 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);
+ lbObjcRef *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);
+ return found->local_module_addr;
+ }
- lbValue ptr = lb_find_value_from_entity(p->module, e);
- lbAddr local_addr = lb_addr(ptr);
+ lbModule *default_module = &p->module->gen->default_module;
+ Entity *entity = {};
- 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);
+ if (default_module != p->module) {
+ found = string_map_get(&default_module->objc_classes, name);
+ if (found) {
+ entity = found->entity;
}
- return local_addr;
}
+
+ if (!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, lbObjcRef{entity, local_addr});
+ }
+
+ return local_addr;
}
gb_internal lbValue lb_handle_objc_find_class(lbProcedure *p, Ast *expr) {
@@ -2196,23 +2218,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);
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]))
+}
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/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 ---
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)
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"
}
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 :: (