aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/runtime/core_builtin.odin13
-rw-r--r--base/runtime/core_builtin_soa.odin5
-rw-r--r--base/runtime/internal.odin15
-rw-r--r--core/os/os2/file_windows.odin33
-rw-r--r--core/os/os2/process.odin10
-rw-r--r--core/strings/builder.odin87
-rw-r--r--core/sys/darwin/Foundation/NSApplication.odin19
-rw-r--r--core/sys/darwin/Foundation/NSCursor.odin26
-rw-r--r--core/sys/darwin/Foundation/NSEvent.odin5
-rw-r--r--core/sys/darwin/Foundation/NSObject.odin8
-rw-r--r--core/sys/darwin/Foundation/NSRunLoop.odin27
-rw-r--r--core/sys/darwin/Foundation/NSTimer.odin15
-rw-r--r--core/sys/darwin/Foundation/NSWindow.odin8
-rw-r--r--core/text/edit/text_edit.odin27
-rw-r--r--core/time/timezone/tz_unix.odin26
-rw-r--r--src/build_settings.cpp2
-rw-r--r--src/check_expr.cpp23
-rw-r--r--src/exact_value.cpp19
-rw-r--r--src/llvm_backend.cpp16
-rw-r--r--src/llvm_backend_utility.cpp6
-rw-r--r--vendor/curl/curl.odin4
-rw-r--r--vendor/curl/curl_multi.odin4
-rw-r--r--vendor/darwin/QuartzCore/QuartzCore.odin22
-rw-r--r--vendor/glfw/bindings/bindings.odin4
24 files changed, 351 insertions, 73 deletions
diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin
index 9f3fcbf9a..6fecbaad9 100644
--- a/base/runtime/core_builtin.odin
+++ b/base/runtime/core_builtin.odin
@@ -267,7 +267,10 @@ non_zero_resize :: proc{
// Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
@builtin
-shrink :: proc{shrink_dynamic_array, shrink_map}
+shrink :: proc{
+ shrink_dynamic_array,
+ shrink_map,
+}
// `free` will try to free the passed pointer, with the given `allocator` if the allocator supports this operation.
@builtin
@@ -794,7 +797,11 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, ar
}
// `inject_at` injects something into a dynamic array at a specified index and moves the previous elements after that index "across"
-@builtin inject_at :: proc{inject_at_elem, inject_at_elems, inject_at_elem_string}
+@builtin inject_at :: proc{
+ inject_at_elem,
+ inject_at_elems,
+ inject_at_elem_string,
+}
@@ -861,7 +868,6 @@ assign_at :: proc{
-
// `clear_dynamic_array` will set the length of a passed dynamic array to `0`
//
// Note: Prefer the procedure group `clear`.
@@ -1000,6 +1006,7 @@ non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: i
// If `len(array) < new_cap`, then `len(array)` will be left unchanged.
//
// Note: Prefer the procedure group `shrink`
+@builtin
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc)
}
diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin
index 0ccc8fd9b..5078b85d0 100644
--- a/base/runtime/core_builtin_soa.odin
+++ b/base/runtime/core_builtin_soa.odin
@@ -615,7 +615,7 @@ inject_at_elems_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, #no
// `inject_at_soa` injects something into a dynamic SOA array at a specified index and moves the previous elements after that index "across"
@builtin inject_at_soa :: proc{inject_at_elem_soa, inject_at_elems_soa}
-
+@builtin
delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
when field_count != 0 {
@@ -626,6 +626,7 @@ delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc
return nil
}
+@builtin
delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error {
field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
when field_count != 0 {
@@ -644,7 +645,7 @@ delete_soa :: proc{
delete_soa_dynamic_array,
}
-
+@builtin
clear_soa_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) {
field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
when field_count != 0 {
diff --git a/base/runtime/internal.odin b/base/runtime/internal.odin
index 0e674aca8..cf96098b8 100644
--- a/base/runtime/internal.odin
+++ b/base/runtime/internal.odin
@@ -7,10 +7,11 @@ import "base:intrinsics"
IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
@(private)
-RUNTIME_LINKAGE :: "strong" when (
- ODIN_USE_SEPARATE_MODULES ||
- ODIN_BUILD_MODE == .Dynamic ||
- !ODIN_NO_CRT) else "internal"
+RUNTIME_LINKAGE :: "strong" when ODIN_USE_SEPARATE_MODULES else
+ "internal" when ODIN_NO_ENTRY_POINT && (ODIN_BUILD_MODE == .Static || ODIN_BUILD_MODE == .Dynamic || ODIN_BUILD_MODE == .Object) else
+ "strong" when ODIN_BUILD_MODE == .Dynamic else
+ "strong" when !ODIN_NO_CRT else
+ "internal"
RUNTIME_REQUIRE :: false // !ODIN_TILDE
@(private)
@@ -147,6 +148,7 @@ mem_alloc_non_zeroed :: #force_no_inline proc(size: int, alignment: int = DEFAUL
return allocator.procedure(allocator.data, .Alloc_Non_Zeroed, size, alignment, nil, 0, loc)
}
+@builtin
mem_free :: #force_no_inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
if ptr == nil || allocator.procedure == nil {
return nil
@@ -171,7 +173,7 @@ mem_free_bytes :: #force_no_inline proc(bytes: []byte, allocator := context.allo
return err
}
-
+@builtin
mem_free_all :: #force_no_inline proc(allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) {
if allocator.procedure != nil {
_, err = allocator.procedure(allocator.data, .Free_All, 0, 0, nil, 0, loc)
@@ -340,7 +342,7 @@ memory_compare :: proc "contextless" (x, y: rawptr, n: int) -> int #no_bounds_ch
case y == nil: return +1
}
a, b := cast([^]byte)x, cast([^]byte)y
-
+
n := uint(n)
i := uint(0)
m := uint(0)
@@ -1408,4 +1410,3 @@ when .Address in ODIN_SANITIZER_FLAGS {
__asan_unpoison_memory_region :: proc "system" (address: rawptr, size: uint) ---
}
}
-
diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin
index 0d2f28642..7c075b7b1 100644
--- a/core/os/os2/file_windows.odin
+++ b/core/os/os2/file_windows.odin
@@ -364,33 +364,30 @@ _read_internal :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) {
handle := _handle(&f.file)
- single_read_length: win32.DWORD
total_read: int
sync.shared_guard(&f.rw_mutex) // multiple readers
if sync.guard(&f.p_mutex) {
to_read := min(win32.DWORD(length), MAX_RW)
- ok: win32.BOOL
- if f.kind == .Console {
- n, cerr := read_console(handle, p[total_read:][:to_read])
- total_read += n
- if cerr != nil {
- return i64(total_read), cerr
+ switch f.kind {
+ case .Console:
+ total_read, err = read_console(handle, p[total_read:][:to_read])
+ case .Pipe, .File:
+ single_read_length: win32.DWORD
+ ok := win32.ReadFile(handle, &p[total_read], to_read, &single_read_length, nil)
+ if ok {
+ total_read += int(single_read_length)
+ } else {
+ err = _get_platform_error()
}
- } else {
- ok = win32.ReadFile(handle, &p[total_read], to_read, &single_read_length, nil)
}
+ }
- if single_read_length > 0 && ok {
- total_read += int(single_read_length)
- } else if single_read_length == 0 && ok {
- // ok and 0 bytes means EOF:
- // https://learn.microsoft.com/en-us/windows/win32/fileio/testing-for-the-end-of-a-file
- err = .EOF
- } else {
- err = _get_platform_error()
- }
+ if total_read == 0 && err == nil {
+ // ok and 0 bytes means EOF:
+ // https://learn.microsoft.com/en-us/windows/win32/fileio/testing-for-the-end-of-a-file
+ err = .EOF
}
return i64(total_read), err
diff --git a/core/os/os2/process.odin b/core/os/os2/process.odin
index def561e28..201d4f6e7 100644
--- a/core/os/os2/process.odin
+++ b/core/os/os2/process.odin
@@ -16,19 +16,25 @@ Arguments to the current process.
args := get_args()
@(private="file")
+internal_args_to_free: []string
+
+@(private="file")
get_args :: proc "contextless" () -> []string {
context = runtime.default_context()
result := make([]string, len(runtime.args__), heap_allocator())
for rt_arg, i in runtime.args__ {
result[i] = string(rt_arg)
}
+ internal_args_to_free = result
return result
}
@(fini, private="file")
delete_args :: proc "contextless" () {
- context = runtime.default_context()
- delete(args, heap_allocator())
+ if internal_args_to_free != nil {
+ context = runtime.default_context()
+ delete(internal_args_to_free, heap_allocator())
+ }
}
/*
diff --git a/core/strings/builder.odin b/core/strings/builder.odin
index a6d0b24b3..da9b6df27 100644
--- a/core/strings/builder.odin
+++ b/core/strings/builder.odin
@@ -835,3 +835,90 @@ Returns:
write_int :: proc(b: ^Builder, i: int, base: int = 10) -> (n: int) {
return write_i64(b, i64(i), base)
}
+
+
+/*
+Replaces all instances of `old` in the string in a Builder `b` with the `new` string
+
+*Allocates Using The Allocator On The Builder*
+
+Inputs:
+- b: The input `Builder`
+- old: The substring to be replaced
+- new: The replacement string
+
+Returns:
+- replaced: The number of replacements
+- err: if any allocation errors occurred
+*/
+builder_replace_all :: proc(b: ^Builder, old, new: string) -> (replaced: int, err: mem.Allocator_Error) {
+ return builder_replace(b, old, new, -1)
+}
+
+/*
+Replaces n instances of `old` in the string in a Builder `b` with the `new` string
+
+*Allocates Using The Allocator On The Builder*
+
+Inputs:
+- b: The input `Builder`
+- old: The substring to be replaced
+- new: The replacement string
+- n: The number of instances to replace (if `n < 0`, no limit on the number of replacements)
+
+Returns:
+- replaced: The number of replacements
+- err: if any allocation errors occurred
+*/
+builder_replace :: proc(b: ^Builder, old, new: string, n: int, loc := #caller_location) -> (replaced: int, err: mem.Allocator_Error) {
+ if old == new || n == 0 {
+ return
+ }
+
+ if m := count(to_string(b^), old); m == 0 {
+ return
+ }
+
+ if len(old) == 0 {
+ for i := 0; i <= len(b.buf); i += len(new)+1 {
+ if n > 0 && replaced == n {
+ break
+ }
+
+ resize(&b.buf, len(b.buf)+len(new), loc) or_return
+ copy(b.buf[i+len(new):], b.buf[i:])
+ copy(b.buf[i:], new)
+ replaced += 1
+ }
+ } else {
+ for i := 0; i < len(b.buf); /**/ {
+ if n > 0 && replaced == n {
+ break
+ }
+
+ j := index(string(b.buf[i:]), old)
+ if j < 0 {
+ break
+ }
+
+ if len(new) >= len(old) {
+ resize(&b.buf, len(b.buf) + len(new)-len(old)) or_return
+ }
+
+ cur := b.buf[i+j:]
+ src := cur[len(old):]
+ dst := cur[len(new):]
+ copy(dst, src)
+ copy(cur, new)
+
+ i += j+len(new)
+
+ replaced += 1
+
+ if len(new) < len(old) {
+ resize(&b.buf, len(b.buf) + len(new)-len(old)) or_return
+ }
+ }
+ }
+ return
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSApplication.odin b/core/sys/darwin/Foundation/NSApplication.odin
index 2295e46b8..cdda7b3e4 100644
--- a/core/sys/darwin/Foundation/NSApplication.odin
+++ b/core/sys/darwin/Foundation/NSApplication.odin
@@ -1,21 +1,9 @@
package objc_Foundation
-foreign import "system:Foundation.framework"
-
import "base:intrinsics"
import "base:runtime"
import "core:strings"
-RunLoopMode :: ^String
-
-@(link_prefix="NS")
-foreign Foundation {
- RunLoopCommonModes: RunLoopMode
- DefaultRunLoopMode: RunLoopMode
- EventTrackingRunLoopMode: RunLoopMode
- ModalPanelRunLoopMode: RunLoopMode
-}
-
ActivationPolicy :: enum UInteger {
Regular = 0,
Accessory = 1,
@@ -206,6 +194,13 @@ Application_updateWindows :: proc "c" (self: ^Application) {
msgSend(nil, self, "updateWindows")
}
+@(objc_type=Application, objc_name="sendAction")
+Application_sendAction :: proc "c" (self: ^Application, action: SEL, to: id, from: id) {
+ msgSend(nil, self, "sendAction:to:from:", action, to, from)
+}
+
+
+
@(objc_class="NSRunningApplication")
RunningApplication :: struct {using _: Object}
diff --git a/core/sys/darwin/Foundation/NSCursor.odin b/core/sys/darwin/Foundation/NSCursor.odin
new file mode 100644
index 000000000..ad2decdca
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSCursor.odin
@@ -0,0 +1,26 @@
+package objc_Foundation
+
+@(objc_class="NSCursor")
+Cursor :: struct {using _: Object}
+
+@(objc_type=Cursor, objc_name="set")
+Cursor_set :: proc(self: ^Cursor) {
+ msgSend(EventType, self, "set")
+}
+@(objc_type=Cursor, objc_name="currentCursor", objc_is_class_method=true)
+Cursor_currentCursor :: proc "c" () -> ^Cursor {
+ return msgSend(^Cursor, Cursor, "currentCursor")
+}
+@(objc_type=Cursor, objc_name="IBeamCursor", objc_is_class_method=true)
+Cursor_IBeamCursor :: proc "c" () -> ^Cursor {
+ return msgSend(^Cursor, Cursor, "IBeamCursor")
+}
+@(objc_type=Cursor, objc_name="arrowCursor", objc_is_class_method=true)
+Cursor_arrowCursor :: proc "c" () -> ^Cursor {
+ return msgSend(^Cursor, Cursor, "arrowCursor")
+}
+@(objc_type=Cursor, objc_name="pointingHandCursor", objc_is_class_method=true)
+Cursor_pointingHandCursor :: proc "c" () -> ^Cursor {
+ return msgSend(^Cursor, Cursor, "pointingHandCursor")
+}
+
diff --git a/core/sys/darwin/Foundation/NSEvent.odin b/core/sys/darwin/Foundation/NSEvent.odin
index 3bd0c1879..952a1726c 100644
--- a/core/sys/darwin/Foundation/NSEvent.odin
+++ b/core/sys/darwin/Foundation/NSEvent.odin
@@ -334,6 +334,11 @@ Event_locationInWindow :: proc "c" (self: ^Event) -> Point {
return msgSend(Point, self, "locationInWindow")
}
+@(objc_type=Event, objc_name="mouseLocation", objc_is_class_method=true)
+Event_mouseLocation :: proc "c" () -> Point {
+ return msgSend(Point, Event, "mouseLocation")
+}
+
@(objc_type=Event, objc_name="deltaX")
Event_deltaX :: proc "c" (self: ^Event) -> Float {
diff --git a/core/sys/darwin/Foundation/NSObject.odin b/core/sys/darwin/Foundation/NSObject.odin
index 31ece47a1..7a423e757 100644
--- a/core/sys/darwin/Foundation/NSObject.odin
+++ b/core/sys/darwin/Foundation/NSObject.odin
@@ -81,6 +81,12 @@ debugDescription :: proc "c" (self: ^Object) -> ^String {
return nil
}
+
+@(objc_type=Object, objc_name="performSelectorOnMainThread")
+performSelectorOnMainThread :: proc "c" (self: ^Object, aSelector: SEL, arg: id, wait: BOOL) {
+ msgSend(^String, self, "performSelectorOnMainThread:withObject:waitUntilDone:", aSelector, arg, wait)
+}
+
bridgingCast :: proc "c" ($T: typeid, obj: ^Object) where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
return (T)(obj)
}
@@ -88,4 +94,4 @@ bridgingCast :: proc "c" ($T: typeid, obj: ^Object) where intrinsics.type_is_poi
@(objc_class="NSCoder")
Coder :: struct {using _: Object}
-// TODO(bill): Implement all the methods for this massive type \ No newline at end of file
+// TODO(bill): Implement all the methods for this massive type
diff --git a/core/sys/darwin/Foundation/NSRunLoop.odin b/core/sys/darwin/Foundation/NSRunLoop.odin
new file mode 100644
index 000000000..a9c47bd0e
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSRunLoop.odin
@@ -0,0 +1,27 @@
+package objc_Foundation
+
+foreign import "system:Foundation.framework"
+
+RunLoopMode :: ^String
+
+@(link_prefix="NS")
+foreign Foundation {
+ RunLoopCommonModes: RunLoopMode
+ DefaultRunLoopMode: RunLoopMode
+ EventTrackingRunLoopMode: RunLoopMode
+ ModalPanelRunLoopMode: RunLoopMode
+}
+
+@(objc_class="NSRunLoop")
+RunLoop :: struct { using _: Object }
+
+@(objc_type=RunLoop, objc_name="mainRunLoop", objc_is_class_method=true)
+RunLoop_mainRunLoop :: proc() -> ^RunLoop {
+ return msgSend(^RunLoop, RunLoop, "mainRunLoop")
+}
+
+@(objc_type=RunLoop, objc_name="addTimerForMode")
+RunLoop_addTimerForMode :: proc(self: ^RunLoop, timer: ^Timer, forMode: RunLoopMode) {
+ msgSend(nil, self, "addTimer:forMode:", timer, forMode)
+}
+
diff --git a/core/sys/darwin/Foundation/NSTimer.odin b/core/sys/darwin/Foundation/NSTimer.odin
new file mode 100644
index 000000000..2edcf34c3
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSTimer.odin
@@ -0,0 +1,15 @@
+package objc_Foundation
+
+@(objc_class="NSTimer")
+Timer :: struct { using _: Object }
+
+@(objc_type=Timer, objc_name="scheduledTimerWithTimeIntervalRepeatsBlock", objc_is_class_method=true)
+Timer_scheduledTimerWithTimeIntervalRepeatsBlock :: proc(interval: TimeInterval, repeats: BOOL, block: ^Block) -> ^Timer {
+ return msgSend(^Timer, Timer, "scheduledTimerWithTimeInterval:repeats:block:")
+}
+
+@(objc_type=Timer, objc_name="scheduledTimerWithTimeIntervalTargetSelectorUserInfoRepeat", objc_is_class_method=true)
+Timer_scheduledTimerWithTimeIntervalTargetSelectorUserInfoRepeat :: proc(interval: TimeInterval, aTarget: id, aSelector: SEL, userInfo: id, repeats: BOOL) -> ^Timer {
+ return msgSend(^Timer, Timer, "scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:", interval, aTarget, aSelector, userInfo, repeats)
+}
+
diff --git a/core/sys/darwin/Foundation/NSWindow.odin b/core/sys/darwin/Foundation/NSWindow.odin
index 8317c7bb1..f39faca0a 100644
--- a/core/sys/darwin/Foundation/NSWindow.odin
+++ b/core/sys/darwin/Foundation/NSWindow.odin
@@ -699,6 +699,14 @@ View_convertPointFromView :: proc "c" (self: ^View, point: Point, view: ^View) -
View_addSubview :: proc "c" (self: ^View, view: ^View) {
msgSend(nil, self, "addSubview:", view)
}
+@(objc_type=View, objc_name="isFlipped")
+View_isFlipped :: proc "c" (self: ^View) -> BOOL {
+ return msgSend(BOOL, self, "isFlipped")
+}
+@(objc_type=View, objc_name="setIsFlipped")
+View_setIsFlipped :: proc "c" (self: ^View, flipped: BOOL) {
+ msgSend(nil, self, "setIsFlipped:", flipped)
+}
@(objc_class="NSWindow")
Window :: struct {using _: Responder}
diff --git a/core/text/edit/text_edit.odin b/core/text/edit/text_edit.odin
index 8713f6eff..58e184309 100644
--- a/core/text/edit/text_edit.odin
+++ b/core/text/edit/text_edit.odin
@@ -24,6 +24,7 @@ State :: struct {
up_index, down_index: int, // multi-lines
+ translate_by_grapheme: bool, // translates by codepoint by default
// undo
undo: [dynamic]^Undo_State,
@@ -302,14 +303,32 @@ translate_position :: proc(s: ^State, t: Translation) -> int {
case .End:
pos = len(buf)
case .Left:
- pos -= 1
- for pos >= 0 && is_continuation_byte(buf[pos]) {
+ if s.translate_by_grapheme {
+ // TODO(bill): determine if there is a faster way to determine the last grapheme
+ // rather than iterate across the entire string (which may be very slow)
+ it := utf8.decode_grapheme_iterator_make(string(buf[:pos]))
+ g: utf8.Grapheme
+ for {
+ _, g = utf8.decode_grapheme_iterate(&it) or_break
+ }
+ pos -= max(g.width, 1)
+ } else {
pos -= 1
+ for pos >= 0 && is_continuation_byte(buf[pos]) {
+ pos -= 1
+ }
}
case .Right:
- pos += 1
- for pos < len(buf) && is_continuation_byte(buf[pos]) {
+ if s.translate_by_grapheme {
+ it := utf8.decode_grapheme_iterator_make(string(buf[pos:]))
+
+ _, g, _ := utf8.decode_grapheme_iterate(&it)
+ pos += max(g.width, 1)
+ } else {
pos += 1
+ for pos < len(buf) && is_continuation_byte(buf[pos]) {
+ pos += 1
+ }
}
case .Up:
pos = s.up_index
diff --git a/core/time/timezone/tz_unix.odin b/core/time/timezone/tz_unix.odin
index 990e78d41..542e5c4f2 100644
--- a/core/time/timezone/tz_unix.odin
+++ b/core/time/timezone/tz_unix.odin
@@ -81,9 +81,27 @@ _region_load :: proc(_reg_str: string, allocator := context.allocator) -> (out_r
}
defer if _reg_str == "local" { delete(reg_str, allocator) }
- db_path := "/usr/share/zoneinfo"
- region_path := filepath.join({db_path, reg_str}, allocator)
- defer delete(region_path, allocator)
+ tzdir_str, tzdir_ok := os.lookup_env("TZDIR", allocator)
+ defer if tzdir_ok { delete(tzdir_str, allocator) }
- return load_tzif_file(region_path, reg_str, allocator)
+ if tzdir_ok {
+ region_path := filepath.join({tzdir_str, reg_str}, allocator)
+ defer delete(region_path, allocator)
+
+ if tz_reg, ok := load_tzif_file(region_path, reg_str, allocator); ok {
+ return tz_reg, true
+ }
+ }
+
+ db_paths := []string{"/usr/share/zoneinfo", "/share/zoneinfo", "/etc/zoneinfo"}
+ for db_path in db_paths {
+ region_path := filepath.join({db_path, reg_str}, allocator)
+ defer delete(region_path, allocator)
+
+ if tz_reg, ok := load_tzif_file(region_path, reg_str, allocator); ok {
+ return tz_reg, true
+ }
+ }
+
+ return nil, false
}
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index 757df95f7..7160f3721 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -835,7 +835,7 @@ gb_global TargetMetrics target_freestanding_amd64_win64 = {
TargetOs_freestanding,
TargetArch_amd64,
8, 8, AMD64_MAX_ALIGNMENT, 32,
- str_lit("x86_64-pc-none-msvc"),
+ str_lit("x86_64-pc-windows-msvc"),
TargetABI_Win64,
};
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 83af90280..2fe6c0251 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -4390,10 +4390,6 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ
return;
}
- if (c->proc_name == "main") {
- gb_printf_err("HERE! 1 %s\n", type_to_string(x->type));
- }
-
if (op.kind == Token_Quo && is_type_integer(x->type)) {
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
}
@@ -12107,6 +12103,25 @@ gb_internal bool is_exact_value_zero(ExactValue const &v) {
+gb_internal bool compare_exact_values_compound_lit(TokenKind op, ExactValue x, ExactValue y, bool *do_break_) {
+ ast_node(x_cl, CompoundLit, x.value_compound);
+ ast_node(y_cl, CompoundLit, y.value_compound);
+
+ if (x_cl->elems.count != y_cl->elems.count) {
+ if (do_break_) *do_break_ = true;
+ }
+
+ bool test = op == Token_CmpEq;
+
+ for (isize i = 0; i < x_cl->elems.count; i++) {
+ Ast *lhs = x_cl->elems[i];
+ Ast *rhs = y_cl->elems[i];
+ if (compare_exact_values(op, lhs->tav.value, rhs->tav.value) != test) {
+ return !test;
+ }
+ }
+ return test;
+}
diff --git a/src/exact_value.cpp b/src/exact_value.cpp
index e7077bd5b..f266b8b24 100644
--- a/src/exact_value.cpp
+++ b/src/exact_value.cpp
@@ -947,6 +947,8 @@ gb_internal gb_inline i32 cmp_f64(f64 a, f64 b) {
return (a > b) - (a < b);
}
+gb_internal bool compare_exact_values_compound_lit(TokenKind op, ExactValue x, ExactValue y, bool *do_break_);
+
gb_internal bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
match_exact_values(&x, &y);
@@ -1055,9 +1057,24 @@ gb_internal bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y)
case Token_NotEq: return x.value_typeid != y.value_typeid;
}
break;
+
+ case ExactValue_Compound:
+ if (op != Token_CmpEq && op != Token_NotEq) {
+ break;
+ }
+
+ if (x.kind != y.kind) {
+ break;
+ }
+ bool do_break = false;
+ bool res = compare_exact_values_compound_lit(op, x, y, &do_break);
+ if (do_break) {
+ break;
+ }
+ return res;
}
- GB_PANIC("Invalid comparison");
+ GB_PANIC("Invalid comparison: %d", x.kind);
return false;
}
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 71bca42ab..1cde65640 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -15,6 +15,8 @@
#define LLVM_WEAK_MONOMORPHIZATION (USE_SEPARATE_MODULES && build_context.internal_weak_monomorphization)
#endif
+#define LLVM_SET_INTERNAL_WEAK_LINKAGE(value) LLVMSetLinkage(value, USE_SEPARATE_MODULES ? LLVMWeakAnyLinkage : LLVMInternalLinkage);
+
#include "llvm_backend.hpp"
#include "llvm_abi.cpp"
@@ -170,7 +172,7 @@ gb_internal void lb_correct_entity_linkage(lbGenerator *gen) {
if (ec.e->kind == Entity_Variable) {
other_global = LLVMGetNamedGlobal(ec.other_module->mod, ec.cname);
if (other_global) {
- LLVMSetLinkage(other_global, LLVMWeakAnyLinkage);
+ LLVM_SET_INTERNAL_WEAK_LINKAGE(other_global);
if (!ec.e->Variable.is_export && !ec.e->Variable.is_foreign) {
LLVMSetVisibility(other_global, LLVMHiddenVisibility);
}
@@ -178,7 +180,7 @@ gb_internal void lb_correct_entity_linkage(lbGenerator *gen) {
} else if (ec.e->kind == Entity_Procedure) {
other_global = LLVMGetNamedFunction(ec.other_module->mod, ec.cname);
if (other_global) {
- LLVMSetLinkage(other_global, LLVMWeakAnyLinkage);
+ LLVM_SET_INTERNAL_WEAK_LINKAGE(other_global);
if (!ec.e->Procedure.is_export && !ec.e->Procedure.is_foreign) {
LLVMSetVisibility(other_global, LLVMHiddenVisibility);
}
@@ -2083,7 +2085,7 @@ gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedur
continue;
}
- if (type_size_of(e->type) > 8) {
+ if (false && type_size_of(e->type) > 8) {
String ename = lb_get_entity_name(m, e);
gbString name = gb_string_make(permanent_allocator(), "");
name = gb_string_appendc(name, "__$startup$");
@@ -2092,7 +2094,7 @@ gb_internal void lb_create_startup_runtime_generate_body(lbModule *m, lbProcedur
lbProcedure *dummy = lb_create_dummy_procedure(m, make_string_c(name), dummy_type);
dummy->is_startup = true;
LLVMSetVisibility(dummy->value, LLVMHiddenVisibility);
- LLVMSetLinkage(dummy->value, LLVMWeakAnyLinkage);
+ LLVM_SET_INTERNAL_WEAK_LINKAGE(p->value);
lb_begin_procedure_body(dummy);
lb_init_global_var(m, dummy, e, init_expr, var);
@@ -2127,7 +2129,7 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
// Make sure shared libraries call their own runtime startup on Linux.
LLVMSetVisibility(p->value, LLVMHiddenVisibility);
- LLVMSetLinkage(p->value, LLVMWeakAnyLinkage);
+ LLVM_SET_INTERNAL_WEAK_LINKAGE(p->value);
p->global_variables = &global_variables;
p->objc_names = objc_names;
@@ -2147,7 +2149,7 @@ gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // C
// Make sure shared libraries call their own runtime cleanup on Linux.
LLVMSetVisibility(p->value, LLVMHiddenVisibility);
- LLVMSetLinkage(p->value, LLVMWeakAnyLinkage);
+ LLVM_SET_INTERNAL_WEAK_LINKAGE(p->value);
lb_begin_procedure_body(p);
@@ -3418,7 +3420,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
LLVMSetLinkage(g.value, LLVMDLLExportLinkage);
LLVMSetDLLStorageClass(g.value, LLVMDLLExportStorageClass);
} else if (!is_foreign) {
- LLVMSetLinkage(g.value, USE_SEPARATE_MODULES ? LLVMWeakAnyLinkage : LLVMInternalLinkage);
+ LLVM_SET_INTERNAL_WEAK_LINKAGE(g.value);
}
lb_set_linkage_from_entity_flags(m, g.value, e->flags);
LLVMSetAlignment(g.value, cast(u32)type_align_of(e->type));
diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp
index 33ad2ee8d..9ddbd1f9c 100644
--- a/src/llvm_backend_utility.cpp
+++ b/src/llvm_backend_utility.cpp
@@ -2868,9 +2868,13 @@ gb_internal lbValue lb_handle_objc_auto_send(lbProcedure *p, Ast *expr, Slice<lb
GB_ASSERT(se->expr->tav.mode == Addressing_Type && se->expr->tav.type->kind == Type_Named);
objc_class = entity_from_expr(se->expr);
-
GB_ASSERT(objc_class);
GB_ASSERT(objc_class->kind == Entity_TypeName);
+
+ if (objc_class->TypeName.is_type_alias) {
+ objc_class = objc_class->type->Named.type_name;
+ }
+
GB_ASSERT(objc_class->TypeName.objc_class_name != "");
}
diff --git a/vendor/curl/curl.odin b/vendor/curl/curl.odin
index 073927dc6..ce10c443f 100644
--- a/vendor/curl/curl.odin
+++ b/vendor/curl/curl.odin
@@ -2502,7 +2502,7 @@ foreign lib {
* Appends a string to a linked list. If no list exists, it will be created
* first. Returns the new list, after appending.
*/
- slist_append :: proc(list: ^slist, data: [^]byte) -> ^slist ---
+ slist_append :: proc(list: ^slist, data: cstring) -> ^slist ---
/*
* NAME curl_slist_free_all()
@@ -2932,4 +2932,4 @@ foreign lib {
userptr: rawptr) -> code ---
-} \ No newline at end of file
+}
diff --git a/vendor/curl/curl_multi.odin b/vendor/curl/curl_multi.odin
index 860c8dbc1..624078684 100644
--- a/vendor/curl/curl_multi.odin
+++ b/vendor/curl/curl_multi.odin
@@ -410,7 +410,7 @@ foreign lib {
*
* Returns: NULL on failure, otherwise a CURL **array pointer
*/
- multi_get_handles :: proc(multi_handle: ^CURLM) -> ^^CURL ---
+ multi_get_handles :: proc(multi_handle: ^CURLM) -> [^]^CURL ---
/*
* Name: curl_multi_get_offt()
@@ -482,4 +482,4 @@ foreign lib {
ufds: [^]waitfd,
size: c.uint,
fd_count: ^c.uint) -> Mcode ---
-} \ No newline at end of file
+}
diff --git a/vendor/darwin/QuartzCore/QuartzCore.odin b/vendor/darwin/QuartzCore/QuartzCore.odin
index 0e54b3d30..64e8e66d3 100644
--- a/vendor/darwin/QuartzCore/QuartzCore.odin
+++ b/vendor/darwin/QuartzCore/QuartzCore.odin
@@ -47,6 +47,10 @@ MetalLayer_pixelFormat :: proc "c" (self: ^MetalLayer) -> MTL.PixelFormat {
MetalLayer_setPixelFormat :: proc "c" (self: ^MetalLayer, pixelFormat: MTL.PixelFormat) {
msgSend(nil, self, "setPixelFormat:", pixelFormat)
}
+@(objc_type=MetalLayer, objc_name="setColorSpace")
+MetalLayer_setColorSpace :: proc "c" (self: ^MetalLayer, colorspace: NS.id) {
+ msgSend(nil, self, "setColorspace:", colorspace)
+}
@(objc_type=MetalLayer, objc_name="framebufferOnly")
MetalLayer_framebufferOnly :: proc "c" (self: ^MetalLayer) -> NS.BOOL {
@@ -126,3 +130,21 @@ MetalDrawable_addPresentedHandler :: proc "c" (self: ^MetalDrawable, block: Draw
msgSend(nil, self, "addPresentedHandler:", block)
}
+@(objc_class="CATransaction")
+Transaction :: struct { using _: NS.Object }
+
+@(objc_type=Transaction, objc_name="begin", objc_is_class_method=true)
+transaction_begin :: proc() {
+ msgSend(nil, Transaction, "begin")
+}
+
+@(objc_type=Transaction, objc_name="commit", objc_is_class_method=true)
+transaction_commit :: proc() {
+ msgSend(nil, Transaction, "commit")
+}
+
+@(objc_type=Transaction, objc_name="flush", objc_is_class_method=true)
+transaction_flush :: proc() {
+ msgSend(nil, Transaction, "flush")
+}
+
diff --git a/vendor/glfw/bindings/bindings.odin b/vendor/glfw/bindings/bindings.odin
index abf6c2150..3f2f08237 100644
--- a/vendor/glfw/bindings/bindings.odin
+++ b/vendor/glfw/bindings/bindings.odin
@@ -212,9 +212,9 @@ foreign glfw {
// Functions added in 3.4, Linux links against system glfw so we define these as weak to be able
// to check at runtime if they are available.
- @(linkage="weak")
+ @(linkage="strong" when ODIN_OS == .Windows else "weak")
GetPlatform :: proc() -> c.int ---
- @(linkage="weak")
+ @(linkage="strong" when ODIN_OS == .Windows else "weak")
PlatformSupported :: proc(platform: c.int) -> b32 ---
}