aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/builtin/builtin.odin2
-rw-r--r--base/intrinsics/intrinsics.odin6
-rw-r--r--base/runtime/core_builtin.odin63
-rw-r--r--base/runtime/dynamic_map_internal.odin45
-rwxr-xr-xbuild_odin.sh4
-rw-r--r--core/encoding/base32/base32.odin378
-rw-r--r--core/encoding/base32/base32_test.odin227
-rw-r--r--core/encoding/json/unmarshal.odin4
-rw-r--r--core/image/general.odin2
-rw-r--r--core/image/png/helpers.odin130
-rw-r--r--core/io/util.odin10
-rw-r--r--core/math/linalg/general.odin84
-rw-r--r--core/math/linalg/glsl/linalg_glsl.odin84
-rw-r--r--core/math/linalg/hlsl/linalg_hlsl.odin84
-rw-r--r--core/math/rand/rand.odin24
-rw-r--r--core/mem/allocators.odin23
-rw-r--r--core/mem/mem.odin9
-rw-r--r--core/mem/virtual/arena.odin3
-rw-r--r--core/os/os2/file.odin2
-rw-r--r--core/os/os2/file_linux.odin81
-rw-r--r--core/os/os2/file_posix.odin49
-rw-r--r--core/os/os2/file_windows.odin53
-rw-r--r--core/os/os2/heap_linux.odin2
-rw-r--r--core/os/os2/path_linux.odin2
-rw-r--r--core/os/os2/pipe_linux.odin4
-rw-r--r--core/os/os2/pipe_posix.odin4
-rw-r--r--core/os/os2/process.odin11
-rw-r--r--core/os/os2/process_linux.odin47
-rw-r--r--core/prof/spall/doc.odin2
-rw-r--r--core/sys/linux/bits.odin96
-rw-r--r--core/sys/linux/helpers.odin4
-rw-r--r--core/sys/linux/sys.odin40
-rw-r--r--core/sys/linux/types.odin232
-rw-r--r--core/sys/windows/kernel32.odin22
-rw-r--r--core/sys/windows/types.odin28
-rw-r--r--core/sys/windows/user32.odin1
-rw-r--r--core/time/timezone/tz_windows.odin294
-rw-r--r--examples/demo/demo.odin1
-rw-r--r--src/build_settings.cpp18
-rw-r--r--src/check_decl.cpp98
-rw-r--r--src/check_expr.cpp63
-rw-r--r--src/check_type.cpp9
-rw-r--r--src/checker.cpp52
-rw-r--r--src/checker.hpp2
-rw-r--r--src/entity.cpp1
-rw-r--r--src/llvm_backend.cpp2
-rw-r--r--src/llvm_backend.hpp9
-rw-r--r--src/llvm_backend_expr.cpp16
-rw-r--r--src/llvm_backend_general.cpp18
-rw-r--r--src/llvm_backend_proc.cpp6
-rw-r--r--src/llvm_backend_stmt.cpp81
-rw-r--r--src/llvm_backend_utility.cpp27
-rw-r--r--src/main.cpp6
-rw-r--r--src/parser.cpp70
-rw-r--r--src/parser.hpp2
-rw-r--r--tests/core/encoding/cbor/test_core_cbor.odin1
-rw-r--r--tests/core/fmt/test_core_fmt.odin1
-rw-r--r--tests/core/hash/test_core_hash.odin1
-rw-r--r--tests/core/hash/test_vectors_xxhash.odin1
-rw-r--r--tests/core/image/test_core_image.odin1
-rw-r--r--tests/core/net/test_core_net.odin1
-rw-r--r--tests/core/runtime/test_core_runtime.odin100
-rw-r--r--tests/core/slice/test_core_slice.odin1
-rw-r--r--tests/issues/run.bat1
-rwxr-xr-xtests/issues/run.sh1
-rw-r--r--tests/issues/test_issue_4584.odin198
-rw-r--r--tests/issues/test_issue_829.odin1
-rw-r--r--vendor/box2d/box2d.odin14
-rwxr-xr-xvendor/box2d/build_box2d.sh5
-rw-r--r--vendor/box2d/wasm.Makefile4
-rw-r--r--vendor/cgltf/cgltf.odin71
-rw-r--r--vendor/cgltf/lib/cgltf.libbin347066 -> 376686 bytes
-rw-r--r--vendor/cgltf/lib/cgltf_wasm.obin112327 -> 118286 bytes
-rw-r--r--vendor/cgltf/src/cgltf.h653
-rw-r--r--vendor/cgltf/src/cgltf_write.h67
-rw-r--r--vendor/libc/include/math.h4
-rw-r--r--vendor/libc/math.odin4
-rw-r--r--vendor/libc/stdio.odin1
-rw-r--r--vendor/raylib/raygui.odin5
-rw-r--r--vendor/raylib/raylib.odin5
-rw-r--r--vendor/raylib/raymath.odin2
-rw-r--r--vendor/raylib/rlgl/rlgl.odin7
-rw-r--r--vendor/raylib/wasm/libraygui.abin0 -> 188456 bytes
-rw-r--r--vendor/raylib/wasm/libraylib.abin0 -> 1388436 bytes
-rw-r--r--vendor/vulkan/_gen/create_vulkan_odin_wrapper.py46
-rw-r--r--vendor/vulkan/_gen/vulkan_xcb.h56
-rw-r--r--vendor/vulkan/_gen/vulkan_xlib.h56
-rw-r--r--vendor/vulkan/core.odin6
-rw-r--r--vendor/vulkan/enums.odin4
-rw-r--r--vendor/vulkan/procedures.odin16
-rw-r--r--vendor/vulkan/structs.odin41
-rw-r--r--vendor/x11/xlib/xlib.odin4
92 files changed, 2809 insertions, 1207 deletions
diff --git a/base/builtin/builtin.odin b/base/builtin/builtin.odin
index c4a9b141f..227ceeb49 100644
--- a/base/builtin/builtin.odin
+++ b/base/builtin/builtin.odin
@@ -1,6 +1,8 @@
// This is purely for documentation
package builtin
+import "base:runtime"
+
nil :: nil
false :: 0!=0
true :: 0==0
diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin
index 744a899c0..ee0d357e4 100644
--- a/base/intrinsics/intrinsics.odin
+++ b/base/intrinsics/intrinsics.odin
@@ -2,6 +2,8 @@
#+build ignore
package intrinsics
+import "base:runtime"
+
// Package-Related
is_package_imported :: proc(package_name: string) -> bool ---
@@ -72,7 +74,7 @@ prefetch_write_instruction :: proc(address: rawptr, #const locality: i32 /* 0..=
prefetch_write_data :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
// Compiler Hints
-expect :: proc(val, expected_val: T) -> T ---
+expect :: proc(val, expected_val: $T) -> T ---
// Linux and Darwin Only
syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
@@ -219,7 +221,7 @@ type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
-type_has_shared_fields :: proc($U, $V: typeid) -> bool typeid where type_is_struct(U), type_is_struct(V) ---
+type_has_shared_fields :: proc($U, $V: typeid) -> bool where type_is_struct(U), type_is_struct(V) ---
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin
index d28dadd02..cf379aacb 100644
--- a/base/runtime/core_builtin.odin
+++ b/base/runtime/core_builtin.odin
@@ -826,10 +826,12 @@ _resize_dynamic_array :: #force_inline proc(a: ^Raw_Dynamic_Array, size_of_elem,
return nil
}
+ if should_zero && a.len < length {
+ num_reused := min(a.cap, length) - a.len
+ intrinsics.mem_zero(([^]byte)(a.data)[a.len*size_of_elem:], num_reused*size_of_elem)
+ }
+
if length <= a.cap {
- if should_zero && a.len < length {
- intrinsics.mem_zero(([^]byte)(a.data)[a.len*size_of_elem:], (length-a.len)*size_of_elem)
- }
a.len = max(length, 0)
return nil
}
@@ -936,6 +938,32 @@ map_upsert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location)
return
}
+/*
+Retrieves a pointer to the key and value for a possibly just inserted entry into the map.
+
+If the `key` was not in the map `m`, an entry is inserted with the zero value and `just_inserted` will be `true`.
+Otherwise the existing entry is left untouched and pointers to its key and value are returned.
+
+If the map has to grow in order to insert the entry and the allocation fails, `err` is set and returned.
+
+If `err` is `nil`, `key_ptr` and `value_ptr` are valid pointers and will not be `nil`.
+
+WARN: User modification of the key pointed at by `key_ptr` should only be done if the new key is equal to (in hash) the old key.
+If that is not the case you will corrupt the map.
+*/
+@(builtin, require_results)
+map_entry :: proc(m: ^$T/map[$K]$V, key: K, loc := #caller_location) -> (key_ptr: ^K, value_ptr: ^V, just_inserted: bool, err: Allocator_Error) {
+ key := key
+ zero: V
+
+ _key_ptr, _value_ptr: rawptr
+ _key_ptr, _value_ptr, just_inserted, err = __dynamic_map_entry((^Raw_Map)(m), map_info(T), &key, &zero, loc)
+
+ key_ptr = (^K)(_key_ptr)
+ value_ptr = (^V)(_value_ptr)
+ return
+}
+
@builtin
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
@@ -964,6 +992,24 @@ assert :: proc(condition: bool, message := #caller_expression(condition), loc :=
}
}
+// Evaluates the condition and aborts the program iff the condition is
+// false. This routine ignores `ODIN_DISABLE_ASSERT`, and will always
+// execute.
+@builtin
+ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
+ if !condition {
+ @(cold)
+ internal :: proc(message: string, loc: Source_Code_Location) {
+ p := context.assertion_failure_proc
+ if p == nil {
+ p = default_assertion_failure_proc
+ }
+ p("unsatisfied ensure", message, loc)
+ }
+ internal(message, loc)
+ }
+}
+
@builtin
panic :: proc(message: string, loc := #caller_location) -> ! {
p := context.assertion_failure_proc
@@ -1000,6 +1046,17 @@ assert_contextless :: proc "contextless" (condition: bool, message := #caller_ex
}
@builtin
+ensure_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
+ if !condition {
+ @(cold)
+ internal :: proc "contextless" (message: string, loc: Source_Code_Location) {
+ default_assertion_contextless_failure_proc("unsatisfied ensure", message, loc)
+ }
+ internal(message, loc)
+ }
+}
+
+@builtin
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {
default_assertion_contextless_failure_proc("panic", message, loc)
}
diff --git a/base/runtime/dynamic_map_internal.odin b/base/runtime/dynamic_map_internal.odin
index 3dded7716..b95e3cd14 100644
--- a/base/runtime/dynamic_map_internal.odin
+++ b/base/runtime/dynamic_map_internal.odin
@@ -158,21 +158,21 @@ map_cell_index_static :: #force_inline proc "contextless" (cells: [^]Map_Cell($T
} else when (N & (N - 1)) == 0 && N <= 8*size_of(uintptr) {
// Likely case, N is a power of two because T is a power of two.
+ // Unique case, no need to index data here since only one element.
+ when N == 1 {
+ return &cells[index].data[0]
+ }
+
// Compute the integer log 2 of N, this is the shift amount to index the
// correct cell. Odin's intrinsics.count_leading_zeros does not produce a
// constant, hence this approach. We only need to check up to N = 64.
- SHIFT :: 1 when N < 2 else
- 2 when N < 4 else
- 3 when N < 8 else
- 4 when N < 16 else
- 5 when N < 32 else 6
+ SHIFT :: 1 when N == 2 else
+ 2 when N == 4 else
+ 3 when N == 8 else
+ 4 when N == 16 else
+ 5 when N == 32 else 6
#assert(SHIFT <= MAP_CACHE_LINE_LOG2)
- // Unique case, no need to index data here since only one element.
- when N == 1 {
- return &cells[index >> SHIFT].data[0]
- } else {
- return &cells[index >> SHIFT].data[index & (N - 1)]
- }
+ return &cells[index >> SHIFT].data[index & (N - 1)]
} else {
// Least likely (and worst case), we pay for a division operation but we
// assume the compiler does not actually generate a division. N will be in the
@@ -941,6 +941,29 @@ __dynamic_map_set_extra :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
return nil, rawptr(result)
}
+__dynamic_map_entry :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key: rawptr, zero: rawptr, loc := #caller_location) -> (key_ptr: rawptr, value_ptr: rawptr, just_inserted: bool, err: Allocator_Error) {
+ hash := info.key_hasher(key, map_seed(m^))
+
+ if key_ptr, value_ptr = __dynamic_map_get_key_and_value(m, info, hash, key); value_ptr != nil {
+ return
+ }
+
+ has_grown: bool
+ if err, has_grown = __dynamic_map_check_grow(m, info, loc); err != nil {
+ return
+ } else if has_grown {
+ hash = info.key_hasher(key, map_seed(m^))
+ }
+
+ value_ptr = rawptr(map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(zero)))
+ assert(value_ptr != nil)
+ key_ptr = rawptr(map_cell_index_dynamic(map_data(m^), info.ks, map_desired_position(m^, hash)))
+
+ m.len += 1
+ just_inserted = true
+ return
+}
+
// IMPORTANT: USED WITHIN THE COMPILER
@(private)
diff --git a/build_odin.sh b/build_odin.sh
index 09094c151..f4452e291 100755
--- a/build_odin.sh
+++ b/build_odin.sh
@@ -110,8 +110,8 @@ Linux)
LDFLAGS="$LDFLAGS -Wl,-rpath=\$ORIGIN"
;;
OpenBSD)
- CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
- LDFLAGS="$LDFLAGS -liconv"
+ CXXFLAGS="$CXXFLAGS -I/usr/local/include $($LLVM_CONFIG --cxxflags --ldflags)"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib -liconv"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
;;
Haiku)
diff --git a/core/encoding/base32/base32.odin b/core/encoding/base32/base32.odin
index f3320428d..8629491b1 100644
--- a/core/encoding/base32/base32.odin
+++ b/core/encoding/base32/base32.odin
@@ -1,148 +1,230 @@
-package encoding_base32
-
-// @note(zh): Encoding utility for Base32
-// A secondary param can be used to supply a custom alphabet to
-// @link(encode) and a matching decoding table to @link(decode).
-// If none is supplied it just uses the standard Base32 alphabet.
-// Incase your specific version does not use padding, you may
-// truncate it from the encoded output.
-
-ENC_TABLE := [32]byte {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
- 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
- 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
- 'Y', 'Z', '2', '3', '4', '5', '6', '7',
-}
-
-PADDING :: '='
-
-DEC_TABLE := [?]u8 {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
- 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-}
-
-encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
- out_length := (len(data) + 4) / 5 * 8
- out := make([]byte, out_length)
- _encode(out, data)
- return string(out)
-}
-
-@private
-_encode :: proc(out, data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) {
- out := out
- data := data
-
- for len(data) > 0 {
- carry: byte
- switch len(data) {
- case:
- out[7] = ENC_TABLE[data[4] & 0x1f]
- carry = data[4] >> 5
- fallthrough
- case 4:
- out[6] = ENC_TABLE[carry | (data[3] << 3) & 0x1f]
- out[5] = ENC_TABLE[(data[3] >> 2) & 0x1f]
- carry = data[3] >> 7
- fallthrough
- case 3:
- out[4] = ENC_TABLE[carry | (data[2] << 1) & 0x1f]
- carry = (data[2] >> 4) & 0x1f
- fallthrough
- case 2:
- out[3] = ENC_TABLE[carry | (data[1] << 4) & 0x1f]
- out[2] = ENC_TABLE[(data[1] >> 1) & 0x1f]
- carry = (data[1] >> 6) & 0x1f
- fallthrough
- case 1:
- out[1] = ENC_TABLE[carry | (data[0] << 2) & 0x1f]
- out[0] = ENC_TABLE[data[0] >> 3]
- }
-
- if len(data) < 5 {
- out[7] = byte(PADDING)
- if len(data) < 4 {
- out[6] = byte(PADDING)
- out[5] = byte(PADDING)
- if len(data) < 3 {
- out[4] = byte(PADDING)
- if len(data) < 2 {
- out[3] = byte(PADDING)
- out[2] = byte(PADDING)
- }
- }
- }
- break
- }
- data = data[5:]
- out = out[8:]
- }
-}
-
-decode :: proc(data: string, DEC_TBL := DEC_TABLE, allocator := context.allocator) -> []byte #no_bounds_check{
- if len(data) == 0 {
- return nil
- }
-
- outi := 0
- data := data
-
- out := make([]byte, len(data) / 8 * 5, allocator)
- end := false
- for len(data) > 0 && !end {
- dbuf : [8]byte
- dlen := 8
-
- for j := 0; j < 8; {
- if len(data) == 0 {
- dlen, end = j, true
- break
- }
- input := data[0]
- data = data[1:]
- if input == byte(PADDING) && j >= 2 && len(data) < 8 {
- assert(!(len(data) + j < 8 - 1), "Corrupted input")
- for k := 0; k < 8-1-j; k +=1 {
- assert(len(data) < k || data[k] == byte(PADDING), "Corrupted input")
- }
- dlen, end = j, true
- assert(dlen != 1 && dlen != 3 && dlen != 6, "Corrupted input")
- break
- }
- dbuf[j] = DEC_TABLE[input]
- assert(dbuf[j] != 0xff, "Corrupted input")
- j += 1
- }
-
- switch dlen {
- case 8:
- out[outi + 4] = dbuf[6] << 5 | dbuf[7]
- fallthrough
- case 7:
- out[outi + 3] = dbuf[4] << 7 | dbuf[5] << 2 | dbuf[6] >> 3
- fallthrough
- case 5:
- out[outi + 2] = dbuf[3] << 4 | dbuf[4] >> 1
- fallthrough
- case 4:
- out[outi + 1] = dbuf[1] << 6 | dbuf[2] << 1 | dbuf[3] >> 4
- fallthrough
- case 2:
- out[outi + 0] = dbuf[0] << 3 | dbuf[1] >> 2
- }
- outi += 5
- }
- return out
-}
+// Base32 encoding/decoding implementation as specified in RFC 4648.
+// [[ More; https://www.rfc-editor.org/rfc/rfc4648.html ]]
+package encoding_base32
+
+// @note(zh): Encoding utility for Base32
+// A secondary param can be used to supply a custom alphabet to
+// @link(encode) and a matching decoding table to @link(decode).
+// If none is supplied it just uses the standard Base32 alphabet.
+// In case your specific version does not use padding, you may
+// truncate it from the encoded output.
+
+// Error represents errors that can occur during base32 decoding operations.
+// As per RFC 4648:
+// - Section 3.3: Invalid character handling
+// - Section 3.2: Padding requirements
+// - Section 6: Base32 encoding specifics (including block size requirements)
+Error :: enum {
+ None,
+ Invalid_Character, // Input contains characters outside the specified alphabet
+ Invalid_Length, // Input length is not valid for base32 (must be a multiple of 8 with proper padding)
+ Malformed_Input, // Input has improper structure (wrong padding position or incomplete groups)
+}
+
+Validate_Proc :: #type proc(c: byte) -> bool
+
+@private
+_validate_default :: proc(c: byte) -> bool {
+ return (c >= 'A' && c <= 'Z') || (c >= '2' && c <= '7')
+}
+
+@(rodata)
+ENC_TABLE := [32]byte {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', '2', '3', '4', '5', '6', '7',
+}
+
+PADDING :: '='
+
+@(rodata)
+DEC_TABLE := [256]u8 {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+}
+
+encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> string {
+ out_length := (len(data) + 4) / 5 * 8
+ out := make([]byte, out_length, allocator)
+ _encode(out, data, ENC_TBL)
+ return string(out[:])
+}
+
+@private
+_encode :: proc(out, data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) {
+ out := out
+ data := data
+
+ for len(data) > 0 {
+ carry: byte
+ switch len(data) {
+ case:
+ out[7] = ENC_TBL[data[4] & 0x1f]
+ carry = data[4] >> 5
+ fallthrough
+ case 4:
+ out[6] = ENC_TBL[carry | (data[3] << 3) & 0x1f]
+ out[5] = ENC_TBL[(data[3] >> 2) & 0x1f]
+ carry = data[3] >> 7
+ fallthrough
+ case 3:
+ out[4] = ENC_TBL[carry | (data[2] << 1) & 0x1f]
+ carry = (data[2] >> 4) & 0x1f
+ fallthrough
+ case 2:
+ out[3] = ENC_TBL[carry | (data[1] << 4) & 0x1f]
+ out[2] = ENC_TBL[(data[1] >> 1) & 0x1f]
+ carry = (data[1] >> 6) & 0x1f
+ fallthrough
+ case 1:
+ out[1] = ENC_TBL[carry | (data[0] << 2) & 0x1f]
+ out[0] = ENC_TBL[data[0] >> 3]
+ }
+
+ if len(data) < 5 {
+ out[7] = byte(PADDING)
+ if len(data) < 4 {
+ out[6] = byte(PADDING)
+ out[5] = byte(PADDING)
+ if len(data) < 3 {
+ out[4] = byte(PADDING)
+ if len(data) < 2 {
+ out[3] = byte(PADDING)
+ out[2] = byte(PADDING)
+ }
+ }
+ }
+ break
+ }
+ data = data[5:]
+ out = out[8:]
+ }
+}
+
+@(optimization_mode="favor_size")
+decode :: proc(
+ data: string,
+ DEC_TBL := DEC_TABLE,
+ validate: Validate_Proc = _validate_default,
+ allocator := context.allocator) -> (out: []byte, err: Error) {
+ if len(data) == 0 {
+ return nil, .None
+ }
+
+ // Check minimum length requirement first
+ if len(data) < 2 {
+ return nil, .Invalid_Length
+ }
+
+ // Validate characters using provided validation function
+ for i := 0; i < len(data); i += 1 {
+ c := data[i]
+ if c == byte(PADDING) {
+ break
+ }
+ if !validate(c) {
+ return nil, .Invalid_Character
+ }
+ }
+
+ // Validate padding and length
+ data_len := len(data)
+ padding_count := 0
+ for i := data_len - 1; i >= 0; i -= 1 {
+ if data[i] != byte(PADDING) {
+ break
+ }
+ padding_count += 1
+ }
+
+ // Check for proper padding and length combinations
+ if padding_count > 0 {
+ // Verify no padding in the middle
+ for i := 0; i < data_len - padding_count; i += 1 {
+ if data[i] == byte(PADDING) {
+ return nil, .Malformed_Input
+ }
+ }
+
+ content_len := data_len - padding_count
+ mod8 := content_len % 8
+ required_padding: int
+ switch mod8 {
+ case 2: required_padding = 6 // 2 chars need 6 padding chars
+ case 4: required_padding = 4 // 4 chars need 4 padding chars
+ case 5: required_padding = 3 // 5 chars need 3 padding chars
+ case 7: required_padding = 1 // 7 chars need 1 padding char
+ case: required_padding = 0
+ }
+
+ if required_padding > 0 {
+ if padding_count != required_padding {
+ return nil, .Malformed_Input
+ }
+ } else if mod8 != 0 {
+ return nil, .Malformed_Input
+ }
+ } else {
+ // No padding - must be multiple of 8
+ if data_len % 8 != 0 {
+ return nil, .Malformed_Input
+ }
+ }
+
+ // Calculate decoded length: 5 bytes for every 8 input chars
+ input_chars := data_len - padding_count
+ out_len := input_chars * 5 / 8
+ out = make([]byte, out_len, allocator)
+ defer if err != .None {
+ delete(out)
+ }
+
+ // Process input in 8-byte blocks
+ outi := 0
+ for i := 0; i < input_chars; i += 8 {
+ buf: [8]byte
+ block_size := min(8, input_chars - i)
+
+ // Decode block
+ for j := 0; j < block_size; j += 1 {
+ buf[j] = DEC_TBL[data[i + j]]
+ }
+
+ // Convert to output bytes based on block size
+ bytes_to_write := block_size * 5 / 8
+ switch block_size {
+ case 8:
+ out[outi + 4] = (buf[6] << 5) | buf[7]
+ fallthrough
+ case 7:
+ out[outi + 3] = (buf[4] << 7) | (buf[5] << 2) | (buf[6] >> 3)
+ fallthrough
+ case 5:
+ out[outi + 2] = (buf[3] << 4) | (buf[4] >> 1)
+ fallthrough
+ case 4:
+ out[outi + 1] = (buf[1] << 6) | (buf[2] << 1) | (buf[3] >> 4)
+ fallthrough
+ case 2:
+ out[outi] = (buf[0] << 3) | (buf[1] >> 2)
+ }
+ outi += bytes_to_write
+ }
+
+ return
+}
diff --git a/core/encoding/base32/base32_test.odin b/core/encoding/base32/base32_test.odin
new file mode 100644
index 000000000..ea41ae36f
--- /dev/null
+++ b/core/encoding/base32/base32_test.odin
@@ -0,0 +1,227 @@
+package encoding_base32
+
+import "core:testing"
+import "core:bytes"
+
+@(test)
+test_base32_decode_valid :: proc(t: ^testing.T) {
+ // RFC 4648 Section 10 - Test vectors
+ cases := [?]struct {
+ input, expected: string,
+ }{
+ {"", ""},
+ {"MY======", "f"},
+ {"MZXQ====", "fo"},
+ {"MZXW6===", "foo"},
+ {"MZXW6YQ=", "foob"},
+ {"MZXW6YTB", "fooba"},
+ {"MZXW6YTBOI======", "foobar"},
+ }
+
+ for c in cases {
+ output, err := decode(c.input)
+ if output != nil {
+ defer delete(output)
+ }
+ testing.expect_value(t, err, Error.None)
+ expected := transmute([]u8)c.expected
+ if output != nil {
+ testing.expect(t, bytes.equal(output, expected))
+ } else {
+ testing.expect(t, len(c.expected) == 0)
+ }
+ }
+}
+
+@(test)
+test_base32_encode :: proc(t: ^testing.T) {
+ // RFC 4648 Section 10 - Test vectors
+ cases := [?]struct {
+ input, expected: string,
+ }{
+ {"", ""},
+ {"f", "MY======"},
+ {"fo", "MZXQ===="},
+ {"foo", "MZXW6==="},
+ {"foob", "MZXW6YQ="},
+ {"fooba", "MZXW6YTB"},
+ {"foobar", "MZXW6YTBOI======"},
+ }
+
+ for c in cases {
+ output := encode(transmute([]byte)c.input)
+ defer delete(output)
+ testing.expect(t, output == c.expected)
+ }
+}
+
+@(test)
+test_base32_decode_invalid :: proc(t: ^testing.T) {
+ // Section 3.3 - Non-alphabet characters
+ {
+ // Characters outside alphabet
+ input := "MZ1W6YTB" // '1' not in alphabet (A-Z, 2-7)
+ output, err := decode(input)
+ if output != nil {
+ defer delete(output)
+ }
+ testing.expect_value(t, err, Error.Invalid_Character)
+ }
+ {
+ // Lowercase not allowed
+ input := "mzxq===="
+ output, err := decode(input)
+ if output != nil {
+ defer delete(output)
+ }
+ testing.expect_value(t, err, Error.Invalid_Character)
+ }
+
+ // Section 3.2 - Padding requirements
+ {
+ // Padding must only be at end
+ input := "MZ=Q===="
+ output, err := decode(input)
+ if output != nil {
+ defer delete(output)
+ }
+ testing.expect_value(t, err, Error.Malformed_Input)
+ }
+ {
+ // Missing padding
+ input := "MZXQ" // Should be MZXQ====
+ output, err := decode(input)
+ if output != nil {
+ defer delete(output)
+ }
+ testing.expect_value(t, err, Error.Malformed_Input)
+ }
+ {
+ // Incorrect padding length
+ input := "MZXQ=" // Needs 4 padding chars
+ output, err := decode(input)
+ if output != nil {
+ defer delete(output)
+ }
+ testing.expect_value(t, err, Error.Malformed_Input)
+ }
+ {
+ // Too much padding
+ input := "MY=========" // Extra padding chars
+ output, err := decode(input)
+ if output != nil {
+ defer delete(output)
+ }
+ testing.expect_value(t, err, Error.Malformed_Input)
+ }
+
+ // Section 6 - Base32 block size requirements
+ {
+ // Single character (invalid block)
+ input := "M"
+ output, err := decode(input)
+ if output != nil {
+ defer delete(output)
+ }
+ testing.expect_value(t, err, Error.Invalid_Length)
+ }
+}
+
+@(test)
+test_base32_roundtrip :: proc(t: ^testing.T) {
+ cases := [?]string{
+ "",
+ "f",
+ "fo",
+ "foo",
+ "foob",
+ "fooba",
+ "foobar",
+ }
+
+ for input in cases {
+ encoded := encode(transmute([]byte)input)
+ defer delete(encoded)
+ decoded, err := decode(encoded)
+ if decoded != nil {
+ defer delete(decoded)
+ }
+ testing.expect_value(t, err, Error.None)
+ testing.expect(t, bytes.equal(decoded, transmute([]byte)input))
+ }
+}
+
+@(test)
+test_base32_custom_alphabet :: proc(t: ^testing.T) {
+ custom_enc_table := [32]byte{
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+ }
+
+ custom_dec_table: [256]u8
+ for i := 0; i < len(custom_enc_table); i += 1 {
+ custom_dec_table[custom_enc_table[i]] = u8(i)
+ }
+
+ /*
+ custom_dec_table := [256]u8{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00-0x0f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10-0x1f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20-0x2f
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // 0x30-0x3f ('0'-'9')
+ 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f ('A'-'O')
+ 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50-0x5f ('P'-'V')
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60-0x6f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70-0x7f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80-0x8f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90-0x9f
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0-0xaf
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0-0xbf
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xc0-0xcf
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xd0-0xdf
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0-0xef
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0-0xff
+ }
+ */
+
+ custom_validate :: proc(c: byte) -> bool {
+ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'V') || c == byte(PADDING)
+ }
+
+ cases := [?]struct {
+ input: string,
+ enc_expected: string,
+ }{
+ {"f", "CO======"},
+ {"fo", "CPNG===="},
+ {"foo", "CPNMU==="},
+ }
+
+ for c in cases {
+ // Test encoding
+ encoded := encode(transmute([]byte)c.input, custom_enc_table)
+ defer delete(encoded)
+ testing.expect(t, encoded == c.enc_expected)
+
+ // Test decoding
+ decoded, err := decode(encoded, custom_dec_table, custom_validate)
+ defer if decoded != nil {
+ delete(decoded)
+ }
+
+ testing.expect_value(t, err, Error.None)
+ testing.expect(t, bytes.equal(decoded, transmute([]byte)c.input))
+ }
+
+ // Test invalid character detection
+ {
+ input := "WXY=====" // Contains chars not in our alphabet
+ output, err := decode(input, custom_dec_table, custom_validate)
+ if output != nil {
+ delete(output)
+ }
+ testing.expect_value(t, err, Error.Invalid_Character)
+ }
+}
diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin
index c70b8d39a..57371e360 100644
--- a/core/encoding/json/unmarshal.odin
+++ b/core/encoding/json/unmarshal.odin
@@ -439,7 +439,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
use_field_idx := -1
for field, field_idx in fields {
- tag_value := string(reflect.struct_tag_get(field.tag, "json"))
+ tag_value := reflect.struct_tag_get(field.tag, "json")
json_name, _ := json_name_from_tag_value(tag_value)
if key == json_name {
use_field_idx = field_idx
@@ -470,7 +470,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
}
}
- if field.name == key {
+ if field.name == key || (field.tag != "" && reflect.struct_tag_get(field.tag, "json") == key) {
offset = field.offset
type = field.type
found = true
diff --git a/core/image/general.odin b/core/image/general.odin
index c4a884071..e92b54f18 100644
--- a/core/image/general.odin
+++ b/core/image/general.odin
@@ -146,7 +146,7 @@ which_bytes :: proc(data: []byte) -> Which_File_Type {
case s[6:10] == "JFIF", s[6:10] == "Exif":
return .JPEG
case s[:3] == "\xff\xd8\xff":
- switch s[4] {
+ switch s[3] {
case 0xdb, 0xee, 0xe1, 0xe0:
return .JPEG
}
diff --git a/core/image/png/helpers.odin b/core/image/png/helpers.odin
index f094b54a9..a9495ed4d 100644
--- a/core/image/png/helpers.odin
+++ b/core/image/png/helpers.odin
@@ -396,132 +396,4 @@ exif :: proc(c: image.PNG_Chunk) -> (res: Exif, ok: bool) {
General helper functions
*/
-compute_buffer_size :: image.compute_buffer_size
-
-/*
- PNG save helpers
-*/
-
-when false {
-
- make_chunk :: proc(c: any, t: Chunk_Type) -> (res: Chunk) {
-
- data: []u8
- if v, ok := c.([]u8); ok {
- data = v
- } else {
- data = mem.any_to_bytes(c)
- }
-
- res.header.length = u32be(len(data))
- res.header.type = t
- res.data = data
-
- // CRC the type
- crc := hash.crc32(mem.any_to_bytes(res.header.type))
- // Extend the CRC with the data
- res.crc = u32be(hash.crc32(data, crc))
- return
- }
-
- write_chunk :: proc(fd: os.Handle, chunk: Chunk) {
- c := chunk
- // Write length + type
- os.write_ptr(fd, &c.header, 8)
- // Write data
- os.write_ptr(fd, mem.raw_data(c.data), int(c.header.length))
- // Write CRC32
- os.write_ptr(fd, &c.crc, 4)
- }
-
- write_image_as_png :: proc(filename: string, image: Image) -> (err: Error) {
- profiler.timed_proc()
- using image
- using os
- flags: int = O_WRONLY|O_CREATE|O_TRUNC
-
- if len(image.pixels) == 0 || len(image.pixels) < image.width * image.height * int(image.channels) {
- return .Invalid_Image_Dimensions
- }
-
- mode: int = 0
- when ODIN_OS == .Linux || ODIN_OS == .Darwin {
- // NOTE(justasd): 644 (owner read, write; group read; others read)
- mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
- }
-
- fd, fderr := open(filename, flags, mode)
- if fderr != nil {
- return .Cannot_Open_File
- }
- defer close(fd)
-
- magic := Signature
-
- write_ptr(fd, &magic, 8)
-
- ihdr := IHDR{
- width = u32be(width),
- height = u32be(height),
- bit_depth = depth,
- compression_method = 0,
- filter_method = 0,
- interlace_method = .None,
- }
-
- switch channels {
- case 1: ihdr.color_type = Color_Type{}
- case 2: ihdr.color_type = Color_Type{.Alpha}
- case 3: ihdr.color_type = Color_Type{.Color}
- case 4: ihdr.color_type = Color_Type{.Color, .Alpha}
- case:// Unhandled
- return .Unknown_Color_Type
- }
- h := make_chunk(ihdr, .IHDR)
- write_chunk(fd, h)
-
- bytes_needed := width * height * int(channels) + height
- filter_bytes := mem.make_dynamic_array_len_cap([dynamic]u8, bytes_needed, bytes_needed, context.allocator)
- defer delete(filter_bytes)
-
- i := 0; j := 0
- // Add a filter byte 0 per pixel row
- for y := 0; y < height; y += 1 {
- filter_bytes[j] = 0; j += 1
- for x := 0; x < width; x += 1 {
- for z := 0; z < channels; z += 1 {
- filter_bytes[j+z] = image.pixels[i+z]
- }
- i += channels; j += channels
- }
- }
- assert(j == bytes_needed)
-
- a: []u8 = filter_bytes[:]
-
- out_buf: ^[dynamic]u8
- defer free(out_buf)
-
- ctx := zlib.ZLIB_Context{
- in_buf = &a,
- out_buf = out_buf,
- }
- err = zlib.write_zlib_stream_from_memory(&ctx)
-
- b: []u8
- if err == nil {
- b = ctx.out_buf[:]
- } else {
- return err
- }
-
- idat := make_chunk(b, .IDAT)
-
- write_chunk(fd, idat)
-
- iend := make_chunk([]u8{}, .IEND)
- write_chunk(fd, iend)
-
- return nil
- }
-}
+compute_buffer_size :: image.compute_buffer_size \ No newline at end of file
diff --git a/core/io/util.odin b/core/io/util.odin
index 296be7bc0..fdbbd5b9f 100644
--- a/core/io/util.odin
+++ b/core/io/util.odin
@@ -132,9 +132,13 @@ write_encoded_rune :: proc(w: Writer, r: rune, write_quote := true, n_written: ^
buf: [2]byte
s := strconv.append_bits(buf[:], u64(r), 16, true, 64, strconv.digits, nil)
switch len(s) {
- case 0: write_string(w, "00", &n) or_return
- case 1: write_byte(w, '0', &n) or_return
- case 2: write_string(w, s, &n) or_return
+ case 0:
+ write_string(w, "00", &n) or_return
+ case 1:
+ write_byte(w, '0', &n) or_return
+ fallthrough
+ case 2:
+ write_string(w, s, &n) or_return
}
} else {
write_rune(w, r, &n) or_return
diff --git a/core/math/linalg/general.odin b/core/math/linalg/general.odin
index 8c4f2954a..4a0150972 100644
--- a/core/math/linalg/general.odin
+++ b/core/math/linalg/general.odin
@@ -417,6 +417,13 @@ adjugate :: proc{
matrix4x4_adjugate,
}
+cofactor :: proc{
+ matrix1x1_cofactor,
+ matrix2x2_cofactor,
+ matrix3x3_cofactor,
+ matrix4x4_cofactor,
+}
+
inverse_transpose :: proc{
matrix1x1_inverse_transpose,
matrix2x2_inverse_transpose,
@@ -479,9 +486,9 @@ matrix3x3_determinant :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) #
}
@(require_results)
matrix4x4_determinant :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) #no_bounds_check {
- a := adjugate(m)
+ c := cofactor(m)
for i in 0..<4 {
- det += m[0, i] * a[0, i]
+ det += m[0, i] * c[0, i]
}
return
}
@@ -498,6 +505,47 @@ matrix1x1_adjugate :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) #no_bo
@(require_results)
matrix2x2_adjugate :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) #no_bounds_check {
y[0, 0] = +x[1, 1]
+ y[0, 1] = -x[0, 1]
+ y[1, 0] = -x[1, 0]
+ y[1, 1] = +x[0, 0]
+ return
+}
+
+@(require_results)
+matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
+ y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
+ y[1, 0] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
+ y[2, 0] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
+ y[0, 1] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
+ y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
+ y[2, 1] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
+ y[0, 2] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
+ y[1, 2] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
+ y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
+ return
+}
+
+@(require_results)
+matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
+ for i in 0..<4 {
+ for j in 0..<4 {
+ sign: T = 1 if (i + j) % 2 == 0 else -1
+ y[i, j] = sign * matrix_minor(x, j, i)
+ }
+ }
+ return
+}
+
+
+@(require_results)
+matrix1x1_cofactor :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) #no_bounds_check {
+ y = x
+ return
+}
+
+@(require_results)
+matrix2x2_cofactor :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) #no_bounds_check {
+ y[0, 0] = +x[1, 1]
y[0, 1] = -x[1, 0]
y[1, 0] = -x[0, 1]
y[1, 1] = +x[0, 0]
@@ -505,7 +553,7 @@ matrix2x2_adjugate :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) #no_bo
}
@(require_results)
-matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
+matrix3x3_cofactor :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
@@ -520,7 +568,7 @@ matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) #no_bo
@(require_results)
-matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
+matrix4x4_cofactor :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
for i in 0..<4 {
for j in 0..<4 {
sign: T = 1 if (i + j) % 2 == 0 else -1
@@ -556,19 +604,19 @@ matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
@(require_results)
matrix3x3_inverse_transpose :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d := determinant(x)
when intrinsics.type_is_integer(T) {
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[i, j] / d
+ y[i, j] = c[i, j] / d
}
}
} else {
id := 1/d
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[i, j] * id
+ y[i, j] = c[i, j] * id
}
}
}
@@ -577,22 +625,22 @@ matrix3x3_inverse_transpose :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y:
@(require_results)
matrix4x4_inverse_transpose :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d: T
for i in 0..<4 {
- d += x[0, i] * a[0, i]
+ d += x[0, i] * c[0, i]
}
when intrinsics.type_is_integer(T) {
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[i, j] / d
+ y[i, j] = c[i, j] / d
}
}
} else {
id := 1/d
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[i, j] * id
+ y[i, j] = c[i, j] * id
}
}
}
@@ -625,19 +673,19 @@ matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) #no_bou
@(require_results)
matrix3x3_inverse :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d := determinant(x)
when intrinsics.type_is_integer(T) {
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[j, i] / d
+ y[i, j] = c[j, i] / d
}
}
} else {
id := 1/d
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[j, i] * id
+ y[i, j] = c[j, i] * id
}
}
}
@@ -646,22 +694,22 @@ matrix3x3_inverse :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bou
@(require_results)
matrix4x4_inverse :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d: T
for i in 0..<4 {
- d += x[0, i] * a[0, i]
+ d += x[0, i] * c[0, i]
}
when intrinsics.type_is_integer(T) {
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[j, i] / d
+ y[i, j] = c[j, i] / d
}
}
} else {
id := 1/d
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[j, i] * id
+ y[i, j] = c[j, i] * id
}
}
}
diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin
index ca61891cb..bd2cf416a 100644
--- a/core/math/linalg/glsl/linalg_glsl.odin
+++ b/core/math/linalg/glsl/linalg_glsl.odin
@@ -1882,6 +1882,13 @@ adjugate :: proc{
adjugate_matrix4x4,
}
+cofactor :: proc{
+ cofactor_matrix1x1,
+ cofactor_matrix2x2,
+ cofactor_matrix3x3,
+ cofactor_matrix4x4,
+}
+
inverse_transpose :: proc{
inverse_transpose_matrix1x1,
inverse_transpose_matrix2x2,
@@ -1944,9 +1951,9 @@ determinant_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) {
}
@(require_results)
determinant_matrix4x4 :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
- a := adjugate(m)
+ c := cofactor(m)
#no_bounds_check for i in 0..<4 {
- det += m[0, i] * a[0, i]
+ det += m[0, i] * c[0, i]
}
return
}
@@ -1963,6 +1970,47 @@ adjugate_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
@(require_results)
adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
y[0, 0] = +x[1, 1]
+ y[0, 1] = -x[0, 1]
+ y[1, 0] = -x[1, 0]
+ y[1, 1] = +x[0, 0]
+ return
+}
+
+@(require_results)
+adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
+ y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
+ y[1, 0] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
+ y[2, 0] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
+ y[0, 1] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
+ y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
+ y[2, 1] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
+ y[0, 2] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
+ y[1, 2] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
+ y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
+ return
+}
+
+@(require_results)
+adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
+ for i in 0..<4 {
+ for j in 0..<4 {
+ sign: T = 1 if (i + j) % 2 == 0 else -1
+ y[i, j] = sign * matrix_minor(x, j, i)
+ }
+ }
+ return
+}
+
+
+@(require_results)
+cofactor_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
+ y = x
+ return
+}
+
+@(require_results)
+cofactor_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
+ y[0, 0] = +x[1, 1]
y[0, 1] = -x[1, 0]
y[1, 0] = -x[0, 1]
y[1, 1] = +x[0, 0]
@@ -1970,7 +2018,7 @@ adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
}
@(require_results)
-adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
+cofactor_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
@@ -1985,7 +2033,7 @@ adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
@(require_results)
-adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
+cofactor_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
for i in 0..<4 {
for j in 0..<4 {
sign: T = 1 if (i + j) % 2 == 0 else -1
@@ -2021,19 +2069,19 @@ inverse_transpose_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
@(require_results)
inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d := determinant(x)
when intrinsics.type_is_integer(T) {
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[i, j] / d
+ y[i, j] = c[i, j] / d
}
}
} else {
id := 1/d
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[i, j] * id
+ y[i, j] = c[i, j] * id
}
}
}
@@ -2042,22 +2090,22 @@ inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y:
@(require_results)
inverse_transpose_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d: T
for i in 0..<4 {
- d += x[0, i] * a[0, i]
+ d += x[0, i] * c[0, i]
}
when intrinsics.type_is_integer(T) {
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[i, j] / d
+ y[i, j] = c[i, j] / d
}
}
} else {
id := 1/d
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[i, j] * id
+ y[i, j] = c[i, j] * id
}
}
}
@@ -2090,19 +2138,19 @@ inverse_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
@(require_results)
inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d := determinant(x)
when intrinsics.type_is_integer(T) {
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[j, i] / d
+ y[i, j] = c[j, i] / d
}
}
} else {
id := 1/d
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[j, i] * id
+ y[i, j] = c[j, i] * id
}
}
}
@@ -2111,22 +2159,22 @@ inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bou
@(require_results)
inverse_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d: T
for i in 0..<4 {
- d += x[0, i] * a[0, i]
+ d += x[0, i] * c[0, i]
}
when intrinsics.type_is_integer(T) {
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[j, i] / d
+ y[i, j] = c[j, i] / d
}
}
} else {
id := 1/d
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[j, i] * id
+ y[i, j] = c[j, i] * id
}
}
}
diff --git a/core/math/linalg/hlsl/linalg_hlsl.odin b/core/math/linalg/hlsl/linalg_hlsl.odin
index a89fdddd3..cca70f9c8 100644
--- a/core/math/linalg/hlsl/linalg_hlsl.odin
+++ b/core/math/linalg/hlsl/linalg_hlsl.odin
@@ -1514,6 +1514,13 @@ adjugate :: proc{
adjugate_matrix4x4,
}
+cofactor :: proc{
+ cofactor_matrix1x1,
+ cofactor_matrix2x2,
+ cofactor_matrix3x3,
+ cofactor_matrix4x4,
+}
+
inverse_transpose :: proc{
inverse_transpose_matrix1x1,
inverse_transpose_matrix2x2,
@@ -1568,9 +1575,9 @@ determinant_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) {
}
@(require_results)
determinant_matrix4x4 :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
- a := adjugate(m)
+ c := cofactor(m)
#no_bounds_check for i in 0..<4 {
- det += m[0, i] * a[0, i]
+ det += m[0, i] * c[0, i]
}
return
}
@@ -1587,6 +1594,47 @@ adjugate_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
@(require_results)
adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
y[0, 0] = +x[1, 1]
+ y[0, 1] = -x[0, 1]
+ y[1, 0] = -x[1, 0]
+ y[1, 1] = +x[0, 0]
+ return
+}
+
+@(require_results)
+adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
+ y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
+ y[1, 0] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
+ y[2, 0] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
+ y[0, 1] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
+ y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
+ y[2, 1] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
+ y[0, 2] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
+ y[1, 2] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
+ y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
+ return
+}
+
+@(require_results)
+adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
+ for i in 0..<4 {
+ for j in 0..<4 {
+ sign: T = 1 if (i + j) % 2 == 0 else -1
+ y[i, j] = sign * matrix_minor(x, j, i)
+ }
+ }
+ return
+}
+
+
+@(require_results)
+cofactor_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
+ y = x
+ return
+}
+
+@(require_results)
+cofactor_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
+ y[0, 0] = +x[1, 1]
y[0, 1] = -x[1, 0]
y[1, 0] = -x[0, 1]
y[1, 1] = +x[0, 0]
@@ -1594,7 +1642,7 @@ adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
}
@(require_results)
-adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
+cofactor_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
@@ -1609,7 +1657,7 @@ adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
@(require_results)
-adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
+cofactor_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
for i in 0..<4 {
for j in 0..<4 {
sign: T = 1 if (i + j) % 2 == 0 else -1
@@ -1645,19 +1693,19 @@ inverse_transpose_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
@(require_results)
inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d := determinant(x)
when intrinsics.type_is_integer(T) {
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[i, j] / d
+ y[i, j] = c[i, j] / d
}
}
} else {
id := 1/d
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[i, j] * id
+ y[i, j] = c[i, j] * id
}
}
}
@@ -1666,22 +1714,22 @@ inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y:
@(require_results)
inverse_transpose_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d: T
for i in 0..<4 {
- d += x[0, i] * a[0, i]
+ d += x[0, i] * c[0, i]
}
when intrinsics.type_is_integer(T) {
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[i, j] / d
+ y[i, j] = c[i, j] / d
}
}
} else {
id := 1/d
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[i, j] * id
+ y[i, j] = c[i, j] * id
}
}
}
@@ -1714,19 +1762,19 @@ inverse_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
@(require_results)
inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d := determinant(x)
when intrinsics.type_is_integer(T) {
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[j, i] / d
+ y[i, j] = c[j, i] / d
}
}
} else {
id := 1/d
for i in 0..<3 {
for j in 0..<3 {
- y[i, j] = a[j, i] * id
+ y[i, j] = c[j, i] * id
}
}
}
@@ -1735,22 +1783,22 @@ inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bou
@(require_results)
inverse_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
- a := adjugate(x)
+ c := cofactor(x)
d: T
for i in 0..<4 {
- d += x[0, i] * a[0, i]
+ d += x[0, i] * c[0, i]
}
when intrinsics.type_is_integer(T) {
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[j, i] / d
+ y[i, j] = c[j, i] / d
}
}
} else {
id := 1/d
for i in 0..<4 {
for j in 0..<4 {
- y[i, j] = a[j, i] * id
+ y[i, j] = c[j, i] * id
}
}
}
diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin
index 474277e84..72d9400d7 100644
--- a/core/math/rand/rand.odin
+++ b/core/math/rand/rand.odin
@@ -34,30 +34,6 @@ Example:
import "core:fmt"
set_global_seed_example :: proc() {
- rand.set_global_seed(1)
- fmt.println(rand.uint64())
- }
-
-Possible Output:
-
- 10
-*/
-@(deprecated="Prefer `rand.reset`")
-set_global_seed :: proc(seed: u64) {
- runtime.random_generator_reset_u64(context.random_generator, seed)
-}
-
-/*
-Reset the seed used by the context.random_generator.
-
-Inputs:
-- seed: The seed value
-
-Example:
- import "core:math/rand"
- import "core:fmt"
-
- set_global_seed_example :: proc() {
rand.reset(1)
fmt.println(rand.uint64())
}
diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin
index 13d509f1e..028be58e3 100644
--- a/core/mem/allocators.odin
+++ b/core/mem/allocators.odin
@@ -140,14 +140,6 @@ arena_init :: proc(a: ^Arena, data: []byte) {
a.temp_count = 0
}
-@(deprecated="prefer 'mem.arena_init'")
-init_arena :: proc(a: ^Arena, data: []byte) {
- a.data = data
- a.offset = 0
- a.peak_used = 0
- a.temp_count = 0
-}
-
/*
Allocate memory from an arena.
@@ -786,14 +778,6 @@ stack_init :: proc(s: ^Stack, data: []byte) {
s.peak_used = 0
}
-@(deprecated="prefer 'mem.stack_init'")
-init_stack :: proc(s: ^Stack, data: []byte) {
- s.data = data
- s.prev_offset = 0
- s.curr_offset = 0
- s.peak_used = 0
-}
-
/*
Allocate memory from stack.
@@ -1162,13 +1146,6 @@ small_stack_init :: proc(s: ^Small_Stack, data: []byte) {
s.peak_used = 0
}
-@(deprecated="prefer 'small_stack_init'")
-init_small_stack :: proc(s: ^Small_Stack, data: []byte) {
- s.data = data
- s.offset = 0
- s.peak_used = 0
-}
-
/*
Small stack allocator.
diff --git a/core/mem/mem.odin b/core/mem/mem.odin
index ccbc77798..b2a7158a1 100644
--- a/core/mem/mem.odin
+++ b/core/mem/mem.odin
@@ -685,11 +685,4 @@ calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, he
}
}
return int(padding)
-}
-
-@(require_results, deprecated="prefer 'slice.clone'")
-clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> (new_slice: T) {
- new_slice, _ = make(T, len(slice), allocator, loc)
- runtime.copy(new_slice, slice)
- return new_slice
-}
+} \ No newline at end of file
diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin
index 79407d80d..4a0fff241 100644
--- a/core/mem/virtual/arena.odin
+++ b/core/mem/virtual/arena.odin
@@ -204,8 +204,9 @@ arena_free_all :: proc(arena: ^Arena, loc := #caller_location) {
}
// Zero the first block's memory
if arena.curr_block != nil {
- mem.zero(arena.curr_block.base, int(arena.curr_block.used))
+ curr_block_used := int(arena.curr_block.used)
arena.curr_block.used = 0
+ mem.zero(arena.curr_block.base, curr_block_used)
}
arena.total_used = 0
case .Static, .Buffer:
diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin
index eedf8570c..1a25472a1 100644
--- a/core/os/os2/file.odin
+++ b/core/os/os2/file.odin
@@ -115,7 +115,7 @@ open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File,
@(require_results)
new_file :: proc(handle: uintptr, name: string) -> ^File {
- file, err := _new_file(handle, name)
+ file, err := _new_file(handle, name, file_allocator())
if err != nil {
panic(error_string(err))
}
diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin
index e9ce13447..f8e4026da 100644
--- a/core/os/os2/file_linux.odin
+++ b/core/os/os2/file_linux.odin
@@ -39,37 +39,23 @@ _stderr := File{
@init
_standard_stream_init :: proc() {
- @static stdin_impl := File_Impl {
- name = "/proc/self/fd/0",
- fd = 0,
- }
-
- @static stdout_impl := File_Impl {
- name = "/proc/self/fd/1",
- fd = 1,
- }
-
- @static stderr_impl := File_Impl {
- name = "/proc/self/fd/2",
- fd = 2,
+ new_std :: proc(impl: ^File_Impl, fd: linux.Fd, name: string) -> ^File {
+ impl.file.impl = impl
+ impl.fd = linux.Fd(fd)
+ impl.allocator = runtime.nil_allocator()
+ impl.name = name
+ impl.file.stream = {
+ data = impl,
+ procedure = _file_stream_proc,
+ }
+ impl.file.fstat = _fstat
+ return &impl.file
}
- stdin_impl.allocator = file_allocator()
- stdout_impl.allocator = file_allocator()
- stderr_impl.allocator = file_allocator()
-
- _stdin.impl = &stdin_impl
- _stdout.impl = &stdout_impl
- _stderr.impl = &stderr_impl
-
- // cannot define these initially because cyclic reference
- _stdin.stream.data = &stdin_impl
- _stdout.stream.data = &stdout_impl
- _stderr.stream.data = &stderr_impl
-
- stdin = &_stdin
- stdout = &_stdout
- stderr = &_stderr
+ @(static) files: [3]File_Impl
+ stdin = new_std(&files[0], 0, "/proc/self/fd/0")
+ stdout = new_std(&files[1], 1, "/proc/self/fd/1")
+ stderr = new_std(&files[2], 2, "/proc/self/fd/2")
}
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
@@ -80,6 +66,9 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
// terminal would be incredibly rare. This has no effect on files while
// allowing us to open serial devices.
sys_flags: linux.Open_Flags = {.NOCTTY, .CLOEXEC}
+ when size_of(rawptr) == 4 {
+ sys_flags += {.LARGEFILE}
+ }
switch flags & (O_RDONLY|O_WRONLY|O_RDWR) {
case O_RDONLY:
case O_WRONLY: sys_flags += {.WRONLY}
@@ -97,18 +86,18 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
return nil, _get_platform_error(errno)
}
- return _new_file(uintptr(fd), name)
+ return _new_file(uintptr(fd), name, file_allocator())
}
-_new_file :: proc(fd: uintptr, _: string = "") -> (f: ^File, err: Error) {
- impl := new(File_Impl, file_allocator()) or_return
+_new_file :: proc(fd: uintptr, _: string, allocator: runtime.Allocator) -> (f: ^File, err: Error) {
+ impl := new(File_Impl, allocator) or_return
defer if err != nil {
- free(impl, file_allocator())
+ free(impl, allocator)
}
impl.file.impl = impl
impl.fd = linux.Fd(fd)
- impl.allocator = file_allocator()
- impl.name = _get_full_path(impl.fd, file_allocator()) or_return
+ impl.allocator = allocator
+ impl.name = _get_full_path(impl.fd, impl.allocator) or_return
impl.file.stream = {
data = impl,
procedure = _file_stream_proc,
@@ -272,28 +261,12 @@ _truncate :: proc(f: ^File, size: i64) -> Error {
}
_remove :: proc(name: string) -> Error {
- is_dir_fd :: proc(fd: linux.Fd) -> bool {
- s: linux.Stat
- if linux.fstat(fd, &s) != .NONE {
- return false
- }
- return linux.S_ISDIR(s.mode)
- }
-
TEMP_ALLOCATOR_GUARD()
name_cstr := temp_cstring(name) or_return
- fd, errno := linux.open(name_cstr, {.NOFOLLOW})
- #partial switch (errno) {
- case .ELOOP:
- /* symlink */
- case .NONE:
- defer linux.close(fd)
- if is_dir_fd(fd) {
- return _get_platform_error(linux.rmdir(name_cstr))
- }
- case:
- return _get_platform_error(errno)
+ if fd, errno := linux.open(name_cstr, _OPENDIR_FLAGS + {.NOFOLLOW}); errno == .NONE {
+ linux.close(fd)
+ return _get_platform_error(linux.rmdir(name_cstr))
}
return _get_platform_error(linux.unlink(name_cstr))
diff --git a/core/os/os2/file_posix.odin b/core/os/os2/file_posix.odin
index b7dc43287..184c89368 100644
--- a/core/os/os2/file_posix.odin
+++ b/core/os/os2/file_posix.odin
@@ -21,23 +21,29 @@ File_Impl :: struct {
name: string,
cname: cstring,
fd: posix.FD,
+ allocator: runtime.Allocator,
}
@(init)
init_std_files :: proc() {
- // NOTE: is this (paths) also the case on non darwin?
-
- stdin = __new_file(posix.STDIN_FILENO)
- (^File_Impl)(stdin.impl).name = "/dev/stdin"
- (^File_Impl)(stdin.impl).cname = "/dev/stdin"
-
- stdout = __new_file(posix.STDIN_FILENO)
- (^File_Impl)(stdout.impl).name = "/dev/stdout"
- (^File_Impl)(stdout.impl).cname = "/dev/stdout"
+ new_std :: proc(impl: ^File_Impl, fd: posix.FD, name: cstring) -> ^File {
+ impl.file.impl = impl
+ impl.fd = fd
+ impl.allocator = runtime.nil_allocator()
+ impl.cname = name
+ impl.name = string(name)
+ impl.file.stream = {
+ data = impl,
+ procedure = _file_stream_proc,
+ }
+ impl.file.fstat = _fstat
+ return &impl.file
+ }
- stderr = __new_file(posix.STDIN_FILENO)
- (^File_Impl)(stderr.impl).name = "/dev/stderr"
- (^File_Impl)(stderr.impl).cname = "/dev/stderr"
+ @(static) files: [3]File_Impl
+ stdin = new_std(&files[0], posix.STDIN_FILENO, "/dev/stdin")
+ stdout = new_std(&files[1], posix.STDOUT_FILENO, "/dev/stdout")
+ stderr = new_std(&files[2], posix.STDERR_FILENO, "/dev/stderr")
}
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
@@ -72,10 +78,10 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
return
}
- return _new_file(uintptr(fd), name)
+ return _new_file(uintptr(fd), name, file_allocator())
}
-_new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
+_new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) -> (f: ^File, err: Error) {
if name == "" {
err = .Invalid_Path
return
@@ -84,10 +90,10 @@ _new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
return
}
- crname := _posix_absolute_path(posix.FD(handle), name, file_allocator()) or_return
+ crname := _posix_absolute_path(posix.FD(handle), name, allocator) or_return
rname := string(crname)
- f = __new_file(posix.FD(handle))
+ f = __new_file(posix.FD(handle), allocator)
impl := (^File_Impl)(f.impl)
impl.name = rname
impl.cname = crname
@@ -95,10 +101,11 @@ _new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
return f, nil
}
-__new_file :: proc(handle: posix.FD) -> ^File {
- impl := new(File_Impl, file_allocator())
+__new_file :: proc(handle: posix.FD, allocator: runtime.Allocator) -> ^File {
+ impl := new(File_Impl, allocator)
impl.file.impl = impl
impl.fd = posix.FD(handle)
+ impl.allocator = allocator
impl.file.stream = {
data = impl,
procedure = _file_stream_proc,
@@ -114,8 +121,10 @@ _close :: proc(f: ^File_Impl) -> (err: Error) {
err = _get_platform_error()
}
- delete(f.cname, file_allocator())
- free(f, file_allocator())
+ allocator := f.allocator
+
+ delete(f.cname, allocator)
+ free(f, allocator)
return
}
diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin
index b91a1bc3b..f594cc72f 100644
--- a/core/os/os2/file_windows.odin
+++ b/core/os/os2/file_windows.odin
@@ -44,17 +44,38 @@ File_Impl :: struct {
@(init)
init_std_files :: proc() {
- stdin = new_file(uintptr(win32.GetStdHandle(win32.STD_INPUT_HANDLE)), "<stdin>")
- stdout = new_file(uintptr(win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)), "<stdout>")
- stderr = new_file(uintptr(win32.GetStdHandle(win32.STD_ERROR_HANDLE)), "<stderr>")
-}
-@(fini)
-fini_std_files :: proc() {
- _destroy((^File_Impl)(stdin.impl))
- _destroy((^File_Impl)(stdout.impl))
- _destroy((^File_Impl)(stderr.impl))
-}
+ new_std :: proc(impl: ^File_Impl, code: u32, name: string) -> ^File {
+ impl.file.impl = impl
+
+ impl.allocator = runtime.nil_allocator()
+ impl.fd = win32.GetStdHandle(code)
+ impl.name = name
+ impl.wname = nil
+
+ handle := _handle(&impl.file)
+ kind := File_Impl_Kind.File
+ if m: u32; win32.GetConsoleMode(handle, &m) {
+ kind = .Console
+ }
+ if win32.GetFileType(handle) == win32.FILE_TYPE_PIPE {
+ kind = .Pipe
+ }
+ impl.kind = kind
+ impl.file.stream = {
+ data = impl,
+ procedure = _file_stream_proc,
+ }
+ impl.file.fstat = _fstat
+
+ return &impl.file
+ }
+
+ @(static) files: [3]File_Impl
+ stdin = new_std(&files[0], win32.STD_INPUT_HANDLE, "<stdin>")
+ stdout = new_std(&files[1], win32.STD_OUTPUT_HANDLE, "<stdout>")
+ stderr = new_std(&files[2], win32.STD_ERROR_HANDLE, "<stderr>")
+}
_handle :: proc(f: ^File) -> win32.HANDLE {
return win32.HANDLE(_fd(f))
@@ -132,21 +153,21 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
flags := flags if flags != nil else {.Read}
handle := _open_internal(name, flags, perm) or_return
- return _new_file(handle, name)
+ return _new_file(handle, name, file_allocator())
}
-_new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
+_new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) -> (f: ^File, err: Error) {
if handle == INVALID_HANDLE {
return
}
- impl := new(File_Impl, file_allocator()) or_return
+ impl := new(File_Impl, allocator) or_return
defer if err != nil {
- free(impl, file_allocator())
+ free(impl, allocator)
}
impl.file.impl = impl
- impl.allocator = file_allocator()
+ impl.allocator = allocator
impl.fd = rawptr(handle)
impl.name = clone_string(name, impl.allocator) or_return
impl.wname = win32_utf8_to_wstring(name, impl.allocator) or_return
@@ -180,7 +201,7 @@ _open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Rea
}
_new_file_buffered :: proc(handle: uintptr, name: string, buffer_size: uint) -> (f: ^File, err: Error) {
- f, err = _new_file(handle, name)
+ f, err = _new_file(handle, name, file_allocator())
if f != nil && err == nil {
impl := (^File_Impl)(f.impl)
impl.r_buf = make([]byte, buffer_size, file_allocator())
diff --git a/core/os/os2/heap_linux.odin b/core/os/os2/heap_linux.odin
index ede5eb2ac..8819dfac7 100644
--- a/core/os/os2/heap_linux.odin
+++ b/core/os/os2/heap_linux.odin
@@ -415,7 +415,7 @@ _region_resize :: proc(alloc: ^Allocation_Header, new_size: int, alloc_is_free_l
back_idx := -1
idx: u16
infinite: for {
- for i := 0; i < len(region_iter.hdr.free_list); i += 1 {
+ for i := 0; i < int(region_iter.hdr.free_list_len); i += 1 {
idx = region_iter.hdr.free_list[i]
if _get_block_count(region_iter.memory[idx]) >= new_block_count {
break infinite
diff --git a/core/os/os2/path_linux.odin b/core/os/os2/path_linux.odin
index 7be4121ae..bfdb645ef 100644
--- a/core/os/os2/path_linux.odin
+++ b/core/os/os2/path_linux.odin
@@ -77,8 +77,6 @@ _mkdir_all :: proc(path: string, perm: int) -> Error {
}
_remove_all :: proc(path: string) -> Error {
- DT_DIR :: 4
-
remove_all_dir :: proc(dfd: linux.Fd) -> Error {
n := 64
buf := make([]u8, n)
diff --git a/core/os/os2/pipe_linux.odin b/core/os/os2/pipe_linux.odin
index 852674c69..bb4456e1c 100644
--- a/core/os/os2/pipe_linux.odin
+++ b/core/os/os2/pipe_linux.odin
@@ -10,8 +10,8 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
return nil, nil,_get_platform_error(errno)
}
- r = _new_file(uintptr(fds[0])) or_return
- w = _new_file(uintptr(fds[1])) or_return
+ r = _new_file(uintptr(fds[0]), "", file_allocator()) or_return
+ w = _new_file(uintptr(fds[1]), "", file_allocator()) or_return
return
}
diff --git a/core/os/os2/pipe_posix.odin b/core/os/os2/pipe_posix.odin
index df9425339..edead2ab3 100644
--- a/core/os/os2/pipe_posix.odin
+++ b/core/os/os2/pipe_posix.odin
@@ -21,7 +21,7 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
return
}
- r = __new_file(fds[0])
+ r = __new_file(fds[0], file_allocator())
ri := (^File_Impl)(r.impl)
rname := strings.builder_make(file_allocator())
@@ -31,7 +31,7 @@ _pipe :: proc() -> (r, w: ^File, err: Error) {
ri.name = strings.to_string(rname)
ri.cname = strings.to_cstring(&rname)
- w = __new_file(fds[1])
+ w = __new_file(fds[1], file_allocator())
wi := (^File_Impl)(w.impl)
wname := strings.builder_make(file_allocator())
diff --git a/core/os/os2/process.odin b/core/os/os2/process.odin
index 5b5a6e844..c90e3add2 100644
--- a/core/os/os2/process.odin
+++ b/core/os/os2/process.odin
@@ -290,12 +290,21 @@ process_open :: proc(pid: int, flags := Process_Open_Flags {}) -> (Process, Erro
return _process_open(pid, flags)
}
+
+/*
+OS-specific process attributes.
+*/
+Process_Attributes :: struct {
+ sys_attr: _Sys_Process_Attributes,
+}
+
/*
The description of how a process should be created.
*/
Process_Desc :: struct {
// OS-specific attributes.
- sys_attr: _Sys_Process_Attributes,
+ sys_attr: Process_Attributes,
+
// The working directory of the process. If the string has length 0, the
// working directory is assumed to be the current working directory of the
// current process.
diff --git a/core/os/os2/process_linux.odin b/core/os/os2/process_linux.odin
index 7eb4dfa44..936fbfc40 100644
--- a/core/os/os2/process_linux.odin
+++ b/core/os/os2/process_linux.odin
@@ -384,14 +384,6 @@ _Sys_Process_Attributes :: struct {}
@(private="package")
_process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
- has_executable_permissions :: proc(fd: linux.Fd) -> bool {
- backing: [48]u8
- b := strings.builder_from_bytes(backing[:])
- strings.write_string(&b, "/proc/self/fd/")
- strings.write_int(&b, int(fd))
- return linux.access(strings.to_cstring(&b), linux.X_OK) == .NONE
- }
-
TEMP_ALLOCATOR_GUARD()
if len(desc.command) == 0 {
@@ -411,7 +403,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
}
// search PATH if just a plain name is provided
- exe_fd: linux.Fd
+ exe_path: cstring
executable_name := desc.command[0]
if strings.index_byte(executable_name, '/') < 0 {
path_env := get_env("PATH", temp_allocator())
@@ -426,16 +418,11 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
strings.write_byte(&exe_builder, '/')
strings.write_string(&exe_builder, executable_name)
- exe_path := strings.to_cstring(&exe_builder)
- if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
- continue
- }
- if !has_executable_permissions(exe_fd) {
- linux.close(exe_fd)
- continue
+ exe_path = strings.to_cstring(&exe_builder)
+ if linux.access(exe_path, linux.X_OK) == .NONE {
+ found = true
+ break
}
- found = true
- break
}
if !found {
// check in cwd to match windows behavior
@@ -443,29 +430,18 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
strings.write_string(&exe_builder, "./")
strings.write_string(&exe_builder, executable_name)
- exe_path := strings.to_cstring(&exe_builder)
- if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
+ exe_path = strings.to_cstring(&exe_builder)
+ if linux.access(exe_path, linux.X_OK) != .NONE {
return process, .Not_Exist
}
- if !has_executable_permissions(exe_fd) {
- linux.close(exe_fd)
- return process, .Permission_Denied
- }
}
} else {
- exe_path := temp_cstring(executable_name) or_return
- if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
- return process, _get_platform_error(errno)
- }
- if !has_executable_permissions(exe_fd) {
- linux.close(exe_fd)
- return process, .Permission_Denied
+ exe_path = temp_cstring(executable_name) or_return
+ if linux.access(exe_path, linux.X_OK) != .NONE {
+ return process, .Not_Exist
}
}
- // At this point, we have an executable.
- defer linux.close(exe_fd)
-
// args and environment need to be a list of cstrings
// that are terminated by a nil pointer.
cargs := make([]cstring, len(desc.command) + 1, temp_allocator()) or_return
@@ -492,7 +468,6 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
}
defer linux.close(child_pipe_fds[READ])
-
// TODO: This is the traditional textbook implementation with fork.
// A more efficient implementation with vfork:
//
@@ -573,7 +548,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno)
}
- errno = linux.execveat(exe_fd, "", &cargs[0], env, {.AT_EMPTY_PATH})
+ errno = linux.execveat(dir_fd, exe_path, &cargs[0], env)
assert(errno != nil)
write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno)
}
diff --git a/core/prof/spall/doc.odin b/core/prof/spall/doc.odin
index c81bad05f..b007ad4cb 100644
--- a/core/prof/spall/doc.odin
+++ b/core/prof/spall/doc.odin
@@ -18,6 +18,8 @@ Example:
defer spall.context_destroy(&spall_ctx)
buffer_backing := make([]u8, spall.BUFFER_DEFAULT_SIZE)
+ defer delete(buffer_backing)
+
spall_buffer = spall.buffer_create(buffer_backing, u32(sync.current_thread_id()))
defer spall.buffer_destroy(&spall_ctx, &spall_buffer)
diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin
index 9ce2e206e..c304397de 100644
--- a/core/sys/linux/bits.odin
+++ b/core/sys/linux/bits.odin
@@ -152,43 +152,65 @@ Errno :: enum i32 {
RDONLY flag is not present, because it has the value of 0, i.e. it is the
default, unless WRONLY or RDWR is specified.
*/
-Open_Flags_Bits :: enum {
- WRONLY = 0,
- RDWR = 1,
- CREAT = 6,
- EXCL = 7,
- NOCTTY = 8,
- TRUNC = 9,
- APPEND = 10,
- NONBLOCK = 11,
- DSYNC = 12,
- ASYNC = 13,
- DIRECT = 14,
- LARGEFILE = 15,
- DIRECTORY = 16,
- NOFOLLOW = 17,
- NOATIME = 18,
- CLOEXEC = 19,
- PATH = 21,
-}
-// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19
-#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1)
-#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2)
-#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100)
-#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200)
-#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400)
-#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000)
-#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000)
-#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000)
-#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000)
-#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000)
-#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000)
-#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000)
-#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000)
-#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000)
-#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000)
-#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000)
-#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000)
+when ODIN_ARCH != .arm64 && ODIN_ARCH != .arm32 {
+ Open_Flags_Bits :: enum {
+ WRONLY = 0,
+ RDWR = 1,
+ CREAT = 6,
+ EXCL = 7,
+ NOCTTY = 8,
+ TRUNC = 9,
+ APPEND = 10,
+ NONBLOCK = 11,
+ DSYNC = 12,
+ ASYNC = 13,
+ DIRECT = 14,
+ LARGEFILE = 15,
+ DIRECTORY = 16,
+ NOFOLLOW = 17,
+ NOATIME = 18,
+ CLOEXEC = 19,
+ PATH = 21,
+ }
+ // https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19
+ #assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1)
+ #assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2)
+ #assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100)
+ #assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200)
+ #assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400)
+ #assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000)
+ #assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000)
+ #assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000)
+ #assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000)
+ #assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000)
+ #assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000)
+ #assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000)
+ #assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000)
+ #assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000)
+ #assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000)
+ #assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000)
+ #assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000)
+} else {
+ Open_Flags_Bits :: enum {
+ WRONLY = 0,
+ RDWR = 1,
+ CREAT = 6,
+ EXCL = 7,
+ NOCTTY = 8,
+ TRUNC = 9,
+ APPEND = 10,
+ NONBLOCK = 11,
+ DSYNC = 12,
+ ASYNC = 13,
+ DIRECTORY = 14,
+ NOFOLLOW = 15,
+ DIRECT = 16,
+ LARGEFILE = 17,
+ NOATIME = 18,
+ CLOEXEC = 19,
+ PATH = 21,
+ }
+}
/*
Bits for FD_Flags bitset
diff --git a/core/sys/linux/helpers.odin b/core/sys/linux/helpers.odin
index aefc1179e..9a7550d57 100644
--- a/core/sys/linux/helpers.odin
+++ b/core/sys/linux/helpers.odin
@@ -138,8 +138,8 @@ errno_unwrap :: proc {errno_unwrap2, errno_unwrap3}
when size_of(int) == 4 {
// xxx64 system calls take some parameters as pairs of ulongs rather than a single pointer
@(private)
- compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (hi: uint, lo: uint) {
- no_sign := uint(a)
+ compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (lo: uint, hi: uint) {
+ no_sign := u64(a)
hi = uint(no_sign >> 32)
lo = uint(no_sign & 0xffff_ffff)
return
diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin
index 690902f07..fee385fe8 100644
--- a/core/sys/linux/sys.odin
+++ b/core/sys/linux/sys.odin
@@ -151,7 +151,8 @@ lseek :: proc "contextless" (fd: Fd, off: i64, whence: Seek_Whence) -> (i64, Err
return errno_unwrap(ret, i64)
} else {
result: i64 = ---
- ret := syscall(SYS__llseek, fd, compat64_arg_pair(off), &result, whence)
+ lo, hi := compat64_arg_pair(off)
+ ret := syscall(SYS__llseek, fd, hi, lo, &result, whence)
return result, Errno(-ret)
}
}
@@ -251,7 +252,11 @@ ioctl :: proc "contextless" (fd: Fd, request: u32, arg: uintptr) -> (uintptr) {
Available since Linux 2.2.
*/
pread :: proc "contextless" (fd: Fd, buf: []u8, offset: i64) -> (int, Errno) {
- ret := syscall(SYS_pread64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset))
+ when ODIN_ARCH == .arm32 {
+ ret := syscall(SYS_pread64, fd, raw_data(buf), len(buf), 0, compat64_arg_pair(offset))
+ } else {
+ ret := syscall(SYS_pread64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset))
+ }
return errno_unwrap(ret, int)
}
@@ -261,7 +266,11 @@ pread :: proc "contextless" (fd: Fd, buf: []u8, offset: i64) -> (int, Errno) {
Available since Linux 2.2.
*/
pwrite :: proc "contextless" (fd: Fd, buf: []u8, offset: i64) -> (int, Errno) {
- ret := syscall(SYS_pwrite64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset))
+ when ODIN_ARCH == .arm32 {
+ ret := syscall(SYS_pwrite64, fd, raw_data(buf), len(buf), 0, compat64_arg_pair(offset))
+ } else {
+ ret := syscall(SYS_pwrite64, fd, raw_data(buf), len(buf), compat64_arg_pair(offset))
+ }
return errno_unwrap(ret, int)
}
@@ -1127,7 +1136,10 @@ fdatasync :: proc "contextless" (fd: Fd) -> (Errno) {
On 32-bit architectures available since Linux 2.4.
*/
truncate :: proc "contextless" (name: cstring, length: i64) -> (Errno) {
- when size_of(int) == 4 {
+ when ODIN_ARCH == .arm32 {
+ ret := syscall(SYS_truncate64, cast(rawptr) name, 0, compat64_arg_pair(length))
+ return Errno(-ret)
+ } else when size_of(int) == 4 {
ret := syscall(SYS_truncate64, cast(rawptr) name, compat64_arg_pair(length))
return Errno(-ret)
} else {
@@ -1141,7 +1153,10 @@ truncate :: proc "contextless" (name: cstring, length: i64) -> (Errno) {
On 32-bit architectures available since 2.4.
*/
ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) {
- when size_of(int) == 4 {
+ when ODIN_ARCH == .arm32 {
+ ret := syscall(SYS_ftruncate64, fd, 0, compat64_arg_pair(length))
+ return Errno(-ret)
+ } else when size_of(int) == 4 {
ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length))
return Errno(-ret)
} else {
@@ -1952,10 +1967,10 @@ sigaltstack :: proc "contextless" (stack: ^Sig_Stack, old_stack: ^Sig_Stack) ->
*/
mknod :: proc "contextless" (name: cstring, mode: Mode, dev: Dev) -> (Errno) {
when ODIN_ARCH == .arm64 || ODIN_ARCH == .riscv64 {
- ret := syscall(SYS_mknodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode, dev)
+ ret := syscall(SYS_mknodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode, cast(uint) dev)
return Errno(-ret)
} else {
- ret := syscall(SYS_mknod, cast(rawptr) name, transmute(u32) mode, dev)
+ ret := syscall(SYS_mknod, cast(rawptr) name, transmute(u32) mode, cast(uint) dev)
return Errno(-ret)
}
}
@@ -2586,7 +2601,7 @@ mkdirat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode) -> (Errno)
Available since Linux 2.6.16.
*/
mknodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, dev: Dev) -> (Errno) {
- ret := syscall(SYS_mknodat, dirfd, cast(rawptr) name, transmute(u32) mode, dev)
+ ret := syscall(SYS_mknodat, dirfd, cast(rawptr) name, transmute(u32) mode, cast(uint) dev)
return Errno(-ret)
}
@@ -2684,13 +2699,8 @@ faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) ->
Available since Linux 2.6.16.
*/
ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (i32, Errno) {
- when size_of(int) == 8 {
- ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
- return errno_unwrap(ret, i32)
- } else {
- ret := syscall(SYS_ppoll_time64, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
- return errno_unwrap(ret, i32)
- }
+ ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
+ return errno_unwrap(ret, i32)
}
// TODO(flysand): unshare
diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin
index 42d5cc988..dcc72f72b 100644
--- a/core/sys/linux/types.odin
+++ b/core/sys/linux/types.odin
@@ -3,7 +3,7 @@ package linux
/*
Type for storage device handle.
*/
-Dev :: distinct int
+Dev :: distinct u64
/*
Type for 32-bit User IDs.
@@ -153,6 +153,7 @@ when ODIN_ARCH == .amd64 {
uid: Uid,
gid: Gid,
rdev: Dev,
+ _: [4]u8,
size: i64,
blksize: uint,
blocks: u64,
@@ -516,79 +517,79 @@ Pid_FD_Flags :: bit_set[Pid_FD_Flags_Bits; i32]
Sig_Set :: [_SIGSET_NWORDS]uint
@private SI_MAX_SIZE :: 128
-@private SI_ARCH_PREAMBLE :: 4 * size_of(i32)
+@private SI_ARCH_PREAMBLE :: 4 * size_of(i32) when size_of(rawptr) == 8 else 3 * size_of(i32)
@private SI_PAD_SIZE :: SI_MAX_SIZE - SI_ARCH_PREAMBLE
Sig_Handler_Fn :: #type proc "c" (sig: Signal)
Sig_Restore_Fn :: #type proc "c" () -> !
-Sig_Info :: struct #packed {
- signo: Signal,
- errno: Errno,
- code: i32,
- _pad0: i32,
- using _union: struct #raw_union {
- _pad1: [SI_PAD_SIZE]u8,
- using _kill: struct {
- pid: Pid, /* sender's pid */
- uid: Uid, /* sender's uid */
- },
- using _timer: struct {
- timerid: i32, /* timer id */
- overrun: i32, /* overrun count */
- value: Sig_Val, /* timer value */
- },
- /* POSIX.1b signals */
- using _rt: struct {
- _pid0: Pid, /* sender's pid */
- _uid0: Uid, /* sender's uid */
- },
- /* SIGCHLD */
- using _sigchld: struct {
- _pid1: Pid, /* which child */
- _uid1: Uid, /* sender's uid */
- status: i32, /* exit code */
- utime: uint,
- stime: uint, //clock_t
- },
- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
- using _sigfault: struct {
- addr: rawptr, /* faulting insn/memory ref. */
- using _: struct #raw_union {
- trapno: i32, /* Trap number that caused signal */
- addr_lsb: i16, /* LSB of the reported address */
- using _addr_bnd: struct {
- _pad2: u64,
- lower: rawptr, /* lower bound during fault */
- upper: rawptr, /* upper bound during fault */
- },
- using _addr_pkey: struct {
- _pad3: u64,
- pkey: u32, /* protection key on PTE that faulted */
- },
- using _perf: struct {
- perf_data: u64,
- perf_type: u32,
- perf_flags: u32,
+when size_of(rawptr) == 8 {
+ Sig_Info :: struct #packed {
+ signo: Signal,
+ errno: Errno,
+ code: i32,
+ _pad0: i32,
+ using _union: struct #raw_union {
+ _pad1: [SI_PAD_SIZE]u8,
+ using _kill: struct {
+ pid: Pid, /* sender's pid */
+ uid: Uid, /* sender's uid */
+ },
+ using _timer: struct {
+ timerid: i32, /* timer id */
+ overrun: i32, /* overrun count */
+ value: Sig_Val, /* timer value */
+ },
+ /* POSIX.1b signals */
+ using _rt: struct {
+ _pid0: Pid, /* sender's pid */
+ _uid0: Uid, /* sender's uid */
+ },
+ /* SIGCHLD */
+ using _sigchld: struct {
+ _pid1: Pid, /* which child */
+ _uid1: Uid, /* sender's uid */
+ status: i32, /* exit code */
+ utime: uint,
+ stime: uint, //clock_t
+ },
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ using _sigfault: struct {
+ addr: rawptr, /* faulting insn/memory ref. */
+ using _: struct #raw_union {
+ trapno: i32, /* Trap number that caused signal */
+ addr_lsb: i16, /* LSB of the reported address */
+ using _addr_bnd: struct {
+ _pad2: u64,
+ lower: rawptr, /* lower bound during fault */
+ upper: rawptr, /* upper bound during fault */
+ },
+ using _addr_pkey: struct {
+ _pad3: u64,
+ pkey: u32, /* protection key on PTE that faulted */
+ },
+ using _perf: struct {
+ perf_data: u64,
+ perf_type: u32,
+ perf_flags: u32,
+ },
},
},
+ /* SIGPOLL */
+ using _sigpoll: struct {
+ band: int, /* POLL_IN, POLL_OUT, POLL_MSG */
+ fd: Fd,
+ },
+ /* SIGSYS */
+ using _sigsys: struct {
+ call_addr: rawptr, /* calling user insn */
+ syscall: i32, /* triggering system call number */
+ arch: u32, /* AUDIT_ARCH_* of syscall */
+ },
},
- /* SIGPOLL */
- using _sigpoll: struct {
- band: int, /* POLL_IN, POLL_OUT, POLL_MSG */
- fd: Fd,
- },
- /* SIGSYS */
- using _sigsys: struct {
- call_addr: rawptr, /* calling user insn */
- syscall: i32, /* triggering system call number */
- arch: u32, /* AUDIT_ARCH_* of syscall */
- },
- },
-}
+ }
-#assert(size_of(Sig_Info) == 128)
-when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
+ #assert(size_of(Sig_Info) == 128)
#assert(offset_of(Sig_Info, signo) == 0x00)
#assert(offset_of(Sig_Info, errno) == 0x04)
#assert(offset_of(Sig_Info, code) == 0x08)
@@ -615,7 +616,96 @@ when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
#assert(offset_of(Sig_Info, syscall) == 0x18)
#assert(offset_of(Sig_Info, arch) == 0x1C)
} else {
- // TODO
+ Sig_Info :: struct {
+ signo: Signal,
+ errno: Errno,
+ code: i32,
+ using _union: struct #raw_union {
+ _pad1: [SI_PAD_SIZE]u8,
+ using _kill: struct {
+ pid: Pid, /* sender's pid */
+ uid: Uid, /* sender's uid */
+ },
+ using _timer: struct {
+ timerid: i32, /* timer id */
+ overrun: i32, /* overrun count */
+ value: Sig_Val, /* timer value */
+ },
+ /* POSIX.1b signals */
+ using _rt: struct {
+ _pid0: Pid, /* sender's pid */
+ _uid0: Uid, /* sender's uid */
+ },
+ /* SIGCHLD */
+ using _sigchld: struct {
+ _pid1: Pid, /* which child */
+ _uid1: Uid, /* sender's uid */
+ status: i32, /* exit code */
+ utime: uint,
+ stime: uint, //clock_t
+ },
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ using _sigfault: struct {
+ addr: rawptr, /* faulting insn/memory ref. */
+ using _: struct #raw_union {
+ trapno: i32, /* Trap number that caused signal */
+ addr_lsb: i16, /* LSB of the reported address */
+ using _addr_bnd: struct {
+ _pad2: u32,
+ lower: rawptr, /* lower bound during fault */
+ upper: rawptr, /* upper bound during fault */
+ },
+ using _addr_pkey: struct {
+ _pad3: u32,
+ pkey: u32, /* protection key on PTE that faulted */
+ },
+ using _perf: struct {
+ perf_data: u32,
+ perf_type: u32,
+ perf_flags: u32,
+ },
+ },
+ },
+ /* SIGPOLL */
+ using _sigpoll: struct {
+ band: int, /* POLL_IN, POLL_OUT, POLL_MSG */
+ fd: Fd,
+ },
+ /* SIGSYS */
+ using _sigsys: struct {
+ call_addr: rawptr, /* calling user insn */
+ syscall: i32, /* triggering system call number */
+ arch: u32, /* AUDIT_ARCH_* of syscall */
+ },
+ },
+ }
+
+ #assert(size_of(Sig_Info) == 128)
+ #assert(offset_of(Sig_Info, signo) == 0x00)
+ #assert(offset_of(Sig_Info, errno) == 0x04)
+ #assert(offset_of(Sig_Info, code) == 0x08)
+ #assert(offset_of(Sig_Info, pid) == 0x0c)
+ #assert(offset_of(Sig_Info, uid) == 0x10)
+ #assert(offset_of(Sig_Info, timerid) == 0x0c)
+ #assert(offset_of(Sig_Info, overrun) == 0x10)
+ #assert(offset_of(Sig_Info, value) == 0x14)
+ #assert(offset_of(Sig_Info, status) == 0x14)
+ #assert(offset_of(Sig_Info, utime) == 0x18)
+ #assert(offset_of(Sig_Info, stime) == 0x1c)
+ #assert(offset_of(Sig_Info, addr) == 0x0c)
+ #assert(offset_of(Sig_Info, addr_lsb) == 0x10)
+ #assert(offset_of(Sig_Info, trapno) == 0x10)
+ #assert(offset_of(Sig_Info, lower) == 0x14)
+ #assert(offset_of(Sig_Info, upper) == 0x18)
+ #assert(offset_of(Sig_Info, pkey) == 0x14)
+ #assert(offset_of(Sig_Info, perf_data) == 0x10)
+ #assert(offset_of(Sig_Info, perf_type) == 0x14)
+ #assert(offset_of(Sig_Info, perf_flags) == 0x18)
+ #assert(offset_of(Sig_Info, band) == 0x0c)
+ #assert(offset_of(Sig_Info, fd) == 0x10)
+ #assert(offset_of(Sig_Info, call_addr) == 0x0c)
+ #assert(offset_of(Sig_Info, syscall) == 0x10)
+ #assert(offset_of(Sig_Info, arch) == 0x14)
}
SIGEV_MAX_SIZE :: 64
@@ -685,12 +775,21 @@ Address_Family :: distinct Protocol_Family
Socket_Msg :: bit_set[Socket_Msg_Bits; i32]
/*
+ Struct representing a generic socket address.
+*/
+Sock_Addr :: struct #packed {
+ sa_family: Address_Family,
+ sa_data: [14]u8,
+}
+
+/*
Struct representing IPv4 socket address.
*/
Sock_Addr_In :: struct #packed {
sin_family: Address_Family,
sin_port: u16be,
sin_addr: [4]u8,
+ sin_zero: [size_of(Sock_Addr) - size_of(Address_Family) - size_of(u16be) - size_of([4]u8)]u8,
}
/*
@@ -720,6 +819,7 @@ Sock_Addr_Any :: struct #raw_union {
family: Address_Family,
port: u16be,
},
+ using generic: Sock_Addr,
using ipv4: Sock_Addr_In,
using ipv6: Sock_Addr_In6,
using uds: Sock_Addr_Un,
diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin
index 8be50bceb..f1d7202da 100644
--- a/core/sys/windows/kernel32.odin
+++ b/core/sys/windows/kernel32.odin
@@ -20,6 +20,15 @@ COMMON_LVB_GRID_RVERTICAL :: WORD(0x1000)
COMMON_LVB_REVERSE_VIDEO :: WORD(0x4000)
COMMON_LVB_UNDERSCORE :: WORD(0x8000)
COMMON_LVB_SBCSDBCS :: WORD(0x0300)
+EV_BREAK :: DWORD(0x0040)
+EV_CTS :: DWORD(0x0008)
+EV_DSR :: DWORD(0x0010)
+EV_ERR :: DWORD(0x0080)
+EV_RING :: DWORD(0x0100)
+EV_RLSD :: DWORD(0x0020)
+EV_RXCHAR :: DWORD(0x0001)
+EV_RXFLAG :: DWORD(0x0002)
+EV_TXEMPTY :: DWORD(0x0004)
@(default_calling_convention="system")
foreign kernel32 {
@@ -109,7 +118,9 @@ foreign kernel32 {
ClearCommError :: proc(hFile: HANDLE, lpErrors: ^Com_Error, lpStat: ^COMSTAT) -> BOOL ---
GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
- GetCommPorts :: proc(lpPortNumbers: PULONG, uPortNumbersCount: ULONG, puPortNumbersFound: PULONG) -> ULONG ---
+ SetCommMask :: proc(handle: HANDLE, dwEvtMap: DWORD) -> BOOL ---
+ GetCommMask :: proc(handle: HANDLE, lpEvtMask: LPDWORD) -> BOOL ---
+ WaitCommEvent :: proc(handle: HANDLE, lpEvtMask: LPDWORD, lpOverlapped: LPOVERLAPPED) -> BOOL ---
GetCommandLineW :: proc() -> LPCWSTR ---
GetTempPathW :: proc(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD ---
GetCurrentProcess :: proc() -> HANDLE ---
@@ -239,6 +250,10 @@ foreign kernel32 {
hThread: HANDLE,
lpContext: LPCONTEXT,
) -> BOOL ---
+ SetThreadContext :: proc(
+ hThread: HANDLE,
+ lpContext: LPCONTEXT,
+ ) -> BOOL ---
CreateProcessW :: proc(
lpApplicationName: LPCWSTR,
lpCommandLine: LPWSTR,
@@ -1068,6 +1083,11 @@ foreign one_core {
PageProtection: ULONG,
PreferredNode: ULONG,
) -> PVOID ---
+ GetCommPorts :: proc(
+ lpPortNumbers: PULONG,
+ uPortNumbersCount: ULONG,
+ puPortNumbersFound: PULONG,
+ ) -> ULONG ---
}
diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin
index 5dcf09eab..aece4dc43 100644
--- a/core/sys/windows/types.odin
+++ b/core/sys/windows/types.odin
@@ -143,6 +143,7 @@ LPWSAPROTOCOL_INFO :: ^WSAPROTOCOL_INFO
LPSTR :: ^CHAR
LPWSTR :: ^WCHAR
OLECHAR :: WCHAR
+BSTR :: ^OLECHAR
LPOLESTR :: ^OLECHAR
LPCOLESTR :: LPCSTR
LPFILETIME :: ^FILETIME
@@ -2694,11 +2695,23 @@ EXCEPTION_MAXIMUM_PARAMETERS :: 15
EXCEPTION_DATATYPE_MISALIGNMENT :: 0x80000002
EXCEPTION_BREAKPOINT :: 0x80000003
+EXCEPTION_SINGLE_STEP :: 0x80000004
EXCEPTION_ACCESS_VIOLATION :: 0xC0000005
+EXCEPTION_IN_PAGE_ERROR :: 0xC0000006
EXCEPTION_ILLEGAL_INSTRUCTION :: 0xC000001D
+EXCEPTION_NONCONTINUABLE_EXCEPTION :: 0xC0000025
+EXCEPTION_INVALID_DISPOSITION :: 0xC0000026
EXCEPTION_ARRAY_BOUNDS_EXCEEDED :: 0xC000008C
+EXCEPTION_FLT_DENORMAL_OPERAND :: 0xC000008D
+EXCEPTION_FLT_DIVIDE_BY_ZERO :: 0xC000008E
+EXCEPTION_FLT_INEXACT_RESULT :: 0xC000008F
+EXCEPTION_FLT_INVALID_OPERATION :: 0xC0000090
+EXCEPTION_FLT_OVERFLOW :: 0xC0000091
+EXCEPTION_FLT_STACK_CHECK :: 0xC0000092
+EXCEPTION_FLT_UNDERFLOW :: 0xC0000093
EXCEPTION_INT_DIVIDE_BY_ZERO :: 0xC0000094
EXCEPTION_INT_OVERFLOW :: 0xC0000095
+EXCEPTION_PRIV_INSTRUCTION :: 0xC0000096
EXCEPTION_STACK_OVERFLOW :: 0xC00000FD
STATUS_PRIVILEGED_INSTRUCTION :: 0xC0000096
@@ -3415,8 +3428,6 @@ TIME_ZONE_INFORMATION :: struct {
DaylightBias: LONG,
}
-
-@(private="file")
IMAGE_DOS_HEADER :: struct {
e_magic: WORD,
e_cblp: WORD,
@@ -3534,6 +3545,19 @@ IMAGE_EXPORT_DIRECTORY :: struct {
AddressOfNameOrdinals: DWORD, // RVA from base of image
}
+IMAGE_DEBUG_DIRECTORY :: struct {
+ Characteristics: DWORD,
+ TimeDateStamp: DWORD,
+ MajorVersion: WORD,
+ MinorVersion: WORD,
+ Type: DWORD,
+ SizeOfData: DWORD,
+ AddressOfRawData: DWORD,
+ PointerToRawData: DWORD,
+}
+
+IMAGE_DEBUG_TYPE_CODEVIEW :: 2
+
SICHINTF :: DWORD
SHCONTF :: DWORD
SFGAOF :: ULONG
diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin
index 957d6ab70..da979a3e3 100644
--- a/core/sys/windows/user32.odin
+++ b/core/sys/windows/user32.odin
@@ -51,6 +51,7 @@ foreign user32 {
IsWindowVisible :: proc(hwnd: HWND) -> BOOL ---
IsWindowEnabled :: proc(hwnd: HWND) -> BOOL ---
IsIconic :: proc(hwnd: HWND) -> BOOL ---
+ IsZoomed :: proc(hwnd: HWND) -> BOOL ---
BringWindowToTop :: proc(hWnd: HWND) -> BOOL ---
GetTopWindow :: proc(hWnd: HWND) -> HWND ---
SetForegroundWindow :: proc(hWnd: HWND) -> BOOL ---
diff --git a/core/time/timezone/tz_windows.odin b/core/time/timezone/tz_windows.odin
index 238c4c933..8dc5f533c 100644
--- a/core/time/timezone/tz_windows.odin
+++ b/core/time/timezone/tz_windows.odin
@@ -11,146 +11,147 @@ TZ_Abbrev :: struct {
dst: string,
}
-tz_abbrevs := map[string]TZ_Abbrev {
- "Egypt Standard Time" = {"EET", "EEST"}, // Africa/Cairo
- "Morocco Standard Time" = {"+00", "+01"}, // Africa/Casablanca
- "South Africa Standard Time" = {"SAST", "SAST"}, // Africa/Johannesburg
- "South Sudan Standard Time" = {"CAT", "CAT"}, // Africa/Juba
- "Sudan Standard Time" = {"CAT", "CAT"}, // Africa/Khartoum
- "W. Central Africa Standard Time" = {"WAT", "WAT"}, // Africa/Lagos
- "E. Africa Standard Time" = {"EAT", "EAT"}, // Africa/Nairobi
- "Sao Tome Standard Time" = {"GMT", "GMT"}, // Africa/Sao_Tome
- "Libya Standard Time" = {"EET", "EET"}, // Africa/Tripoli
- "Namibia Standard Time" = {"CAT", "CAT"}, // Africa/Windhoek
- "Aleutian Standard Time" = {"HST", "HDT"}, // America/Adak
- "Alaskan Standard Time" = {"AKST", "AKDT"}, // America/Anchorage
- "Tocantins Standard Time" = {"-03", "-03"}, // America/Araguaina
- "Paraguay Standard Time" = {"-04", "-03"}, // America/Asuncion
- "Bahia Standard Time" = {"-03", "-03"}, // America/Bahia
- "SA Pacific Standard Time" = {"-05", "-05"}, // America/Bogota
- "Argentina Standard Time" = {"-03", "-03"}, // America/Buenos_Aires
- "Eastern Standard Time (Mexico)" = {"EST", "EST"}, // America/Cancun
- "Venezuela Standard Time" = {"-04", "-04"}, // America/Caracas
- "SA Eastern Standard Time" = {"-03", "-03"}, // America/Cayenne
- "Central Standard Time" = {"CST", "CDT"}, // America/Chicago
- "Central Brazilian Standard Time" = {"-04", "-04"}, // America/Cuiaba
- "Mountain Standard Time" = {"MST", "MDT"}, // America/Denver
- "Greenland Standard Time" = {"-03", "-02"}, // America/Godthab
- "Turks And Caicos Standard Time" = {"EST", "EDT"}, // America/Grand_Turk
- "Central America Standard Time" = {"CST", "CST"}, // America/Guatemala
- "Atlantic Standard Time" = {"AST", "ADT"}, // America/Halifax
- "Cuba Standard Time" = {"CST", "CDT"}, // America/Havana
- "US Eastern Standard Time" = {"EST", "EDT"}, // America/Indianapolis
- "SA Western Standard Time" = {"-04", "-04"}, // America/La_Paz
- "Pacific Standard Time" = {"PST", "PDT"}, // America/Los_Angeles
- "Mountain Standard Time (Mexico)" = {"MST", "MST"}, // America/Mazatlan
- "Central Standard Time (Mexico)" = {"CST", "CST"}, // America/Mexico_City
- "Saint Pierre Standard Time" = {"-03", "-02"}, // America/Miquelon
- "Montevideo Standard Time" = {"-03", "-03"}, // America/Montevideo
- "Eastern Standard Time" = {"EST", "EDT"}, // America/New_York
- "US Mountain Standard Time" = {"MST", "MST"}, // America/Phoenix
- "Haiti Standard Time" = {"EST", "EDT"}, // America/Port-au-Prince
- "Magallanes Standard Time" = {"-03", "-03"}, // America/Punta_Arenas
- "Canada Central Standard Time" = {"CST", "CST"}, // America/Regina
- "Pacific SA Standard Time" = {"-04", "-03"}, // America/Santiago
- "E. South America Standard Time" = {"-03", "-03"}, // America/Sao_Paulo
- "Newfoundland Standard Time" = {"NST", "NDT"}, // America/St_Johns
- "Pacific Standard Time (Mexico)" = {"PST", "PDT"}, // America/Tijuana
- "Yukon Standard Time" = {"MST", "MST"}, // America/Whitehorse
- "Central Asia Standard Time" = {"+06", "+06"}, // Asia/Almaty
- "Jordan Standard Time" = {"+03", "+03"}, // Asia/Amman
- "Arabic Standard Time" = {"+03", "+03"}, // Asia/Baghdad
- "Azerbaijan Standard Time" = {"+04", "+04"}, // Asia/Baku
- "SE Asia Standard Time" = {"+07", "+07"}, // Asia/Bangkok
- "Altai Standard Time" = {"+07", "+07"}, // Asia/Barnaul
- "Middle East Standard Time" = {"EET", "EEST"}, // Asia/Beirut
- "India Standard Time" = {"IST", "IST"}, // Asia/Calcutta
- "Transbaikal Standard Time" = {"+09", "+09"}, // Asia/Chita
- "Sri Lanka Standard Time" = {"+0530", "+0530"}, // Asia/Colombo
- "Syria Standard Time" = {"+03", "+03"}, // Asia/Damascus
- "Bangladesh Standard Time" = {"+06", "+06"}, // Asia/Dhaka
- "Arabian Standard Time" = {"+04", "+04"}, // Asia/Dubai
- "West Bank Standard Time" = {"EET", "EEST"}, // Asia/Hebron
- "W. Mongolia Standard Time" = {"+07", "+07"}, // Asia/Hovd
- "North Asia East Standard Time" = {"+08", "+08"}, // Asia/Irkutsk
- "Israel Standard Time" = {"IST", "IDT"}, // Asia/Jerusalem
- "Afghanistan Standard Time" = {"+0430", "+0430"}, // Asia/Kabul
- "Russia Time Zone 11" = {"+12", "+12"}, // Asia/Kamchatka
- "Pakistan Standard Time" = {"PKT", "PKT"}, // Asia/Karachi
- "Nepal Standard Time" = {"+0545", "+0545"}, // Asia/Katmandu
- "North Asia Standard Time" = {"+07", "+07"}, // Asia/Krasnoyarsk
- "Magadan Standard Time" = {"+11", "+11"}, // Asia/Magadan
- "N. Central Asia Standard Time" = {"+07", "+07"}, // Asia/Novosibirsk
- "Omsk Standard Time" = {"+06", "+06"}, // Asia/Omsk
- "North Korea Standard Time" = {"KST", "KST"}, // Asia/Pyongyang
- "Qyzylorda Standard Time" = {"+05", "+05"}, // Asia/Qyzylorda
- "Myanmar Standard Time" = {"+0630", "+0630"}, // Asia/Rangoon
- "Arab Standard Time" = {"+03", "+03"}, // Asia/Riyadh
- "Sakhalin Standard Time" = {"+11", "+11"}, // Asia/Sakhalin
- "Korea Standard Time" = {"KST", "KST"}, // Asia/Seoul
- "China Standard Time" = {"CST", "CST"}, // Asia/Shanghai
- "Singapore Standard Time" = {"+08", "+08"}, // Asia/Singapore
- "Russia Time Zone 10" = {"+11", "+11"}, // Asia/Srednekolymsk
- "Taipei Standard Time" = {"CST", "CST"}, // Asia/Taipei
- "West Asia Standard Time" = {"+05", "+05"}, // Asia/Tashkent
- "Georgian Standard Time" = {"+04", "+04"}, // Asia/Tbilisi
- "Iran Standard Time" = {"+0330", "+0330"}, // Asia/Tehran
- "Tokyo Standard Time" = {"JST", "JST"}, // Asia/Tokyo
- "Tomsk Standard Time" = {"+07", "+07"}, // Asia/Tomsk
- "Ulaanbaatar Standard Time" = {"+08", "+08"}, // Asia/Ulaanbaatar
- "Vladivostok Standard Time" = {"+10", "+10"}, // Asia/Vladivostok
- "Yakutsk Standard Time" = {"+09", "+09"}, // Asia/Yakutsk
- "Ekaterinburg Standard Time" = {"+05", "+05"}, // Asia/Yekaterinburg
- "Caucasus Standard Time" = {"+04", "+04"}, // Asia/Yerevan
- "Azores Standard Time" = {"-01", "+00"}, // Atlantic/Azores
- "Cape Verde Standard Time" = {"-01", "-01"}, // Atlantic/Cape_Verde
- "Greenwich Standard Time" = {"GMT", "GMT"}, // Atlantic/Reykjavik
- "Cen. Australia Standard Time" = {"ACST", "ACDT"}, // Australia/Adelaide
- "E. Australia Standard Time" = {"AEST", "AEST"}, // Australia/Brisbane
- "AUS Central Standard Time" = {"ACST", "ACST"}, // Australia/Darwin
- "Aus Central W. Standard Time" = {"+0845", "+0845"}, // Australia/Eucla
- "Tasmania Standard Time" = {"AEST", "AEDT"}, // Australia/Hobart
- "Lord Howe Standard Time" = {"+1030", "+11"}, // Australia/Lord_Howe
- "W. Australia Standard Time" = {"AWST", "AWST"}, // Australia/Perth
- "AUS Eastern Standard Time" = {"AEST", "AEDT"}, // Australia/Sydney
- "UTC-11" = {"-11", "-11"}, // Etc/GMT+11
- "Dateline Standard Time" = {"-12", "-12"}, // Etc/GMT+12
- "UTC-02" = {"-02", "-02"}, // Etc/GMT+2
- "UTC-08" = {"-08", "-08"}, // Etc/GMT+8
- "UTC-09" = {"-09", "-09"}, // Etc/GMT+9
- "UTC+12" = {"+12", "+12"}, // Etc/GMT-12
- "UTC+13" = {"+13", "+13"}, // Etc/GMT-13
- "UTC" = {"UTC", "UTC"}, // Etc/UTC
- "Astrakhan Standard Time" = {"+04", "+04"}, // Europe/Astrakhan
- "W. Europe Standard Time" = {"CET", "CEST"}, // Europe/Berlin
- "GTB Standard Time" = {"EET", "EEST"}, // Europe/Bucharest
- "Central Europe Standard Time" = {"CET", "CEST"}, // Europe/Budapest
- "E. Europe Standard Time" = {"EET", "EEST"}, // Europe/Chisinau
- "Turkey Standard Time" = {"+03", "+03"}, // Europe/Istanbul
- "Kaliningrad Standard Time" = {"EET", "EET"}, // Europe/Kaliningrad
- "FLE Standard Time" = {"EET", "EEST"}, // Europe/Kiev
- "GMT Standard Time" = {"GMT", "BST"}, // Europe/London
- "Belarus Standard Time" = {"+03", "+03"}, // Europe/Minsk
- "Russian Standard Time" = {"MSK", "MSK"}, // Europe/Moscow
- "Romance Standard Time" = {"CET", "CEST"}, // Europe/Paris
- "Russia Time Zone 3" = {"+04", "+04"}, // Europe/Samara
- "Saratov Standard Time" = {"+04", "+04"}, // Europe/Saratov
- "Volgograd Standard Time" = {"MSK", "MSK"}, // Europe/Volgograd
- "Central European Standard Time" = {"CET", "CEST"}, // Europe/Warsaw
- "Mauritius Standard Time" = {"+04", "+04"}, // Indian/Mauritius
- "Samoa Standard Time" = {"+13", "+13"}, // Pacific/Apia
- "New Zealand Standard Time" = {"NZST", "NZDT"}, // Pacific/Auckland
- "Bougainville Standard Time" = {"+11", "+11"}, // Pacific/Bougainville
- "Chatham Islands Standard Time" = {"+1245", "+1345"}, // Pacific/Chatham
- "Easter Island Standard Time" = {"-06", "-05"}, // Pacific/Easter
- "Fiji Standard Time" = {"+12", "+12"}, // Pacific/Fiji
- "Central Pacific Standard Time" = {"+11", "+11"}, // Pacific/Guadalcanal
- "Hawaiian Standard Time" = {"HST", "HST"}, // Pacific/Honolulu
- "Line Islands Standard Time" = {"+14", "+14"}, // Pacific/Kiritimati
- "Marquesas Standard Time" = {"-0930", "-0930"}, // Pacific/Marquesas
- "Norfolk Standard Time" = {"+11", "+12"}, // Pacific/Norfolk
- "West Pacific Standard Time" = {"+10", "+10"}, // Pacific/Port_Moresby
- "Tonga Standard Time" = {"+13", "+13"}, // Pacific/Tongatapu
+@(rodata)
+tz_abbrevs := [?]struct{key: string, value: TZ_Abbrev}{
+ {"Egypt Standard Time", {"EET", "EEST"}}, // Africa/Cairo
+ {"Morocco Standard Time", {"+00", "+01"}}, // Africa/Casablanca
+ {"South Africa Standard Time", {"SAST", "SAST"}}, // Africa/Johannesburg
+ {"South Sudan Standard Time", {"CAT", "CAT"}}, // Africa/Juba
+ {"Sudan Standard Time", {"CAT", "CAT"}}, // Africa/Khartoum
+ {"W. Central Africa Standard Time", {"WAT", "WAT"}}, // Africa/Lagos
+ {"E. Africa Standard Time", {"EAT", "EAT"}}, // Africa/Nairobi
+ {"Sao Tome Standard Time", {"GMT", "GMT"}}, // Africa/Sao_Tome
+ {"Libya Standard Time", {"EET", "EET"}}, // Africa/Tripoli
+ {"Namibia Standard Time", {"CAT", "CAT"}}, // Africa/Windhoek
+ {"Aleutian Standard Time", {"HST", "HDT"}}, // America/Adak
+ {"Alaskan Standard Time", {"AKST", "AKDT"}}, // America/Anchorage
+ {"Tocantins Standard Time", {"-03", "-03"}}, // America/Araguaina
+ {"Paraguay Standard Time", {"-04", "-03"}}, // America/Asuncion
+ {"Bahia Standard Time", {"-03", "-03"}}, // America/Bahia
+ {"SA Pacific Standard Time", {"-05", "-05"}}, // America/Bogota
+ {"Argentina Standard Time", {"-03", "-03"}}, // America/Buenos_Aires
+ {"Eastern Standard Time (Mexico)", {"EST", "EST"}}, // America/Cancun
+ {"Venezuela Standard Time", {"-04", "-04"}}, // America/Caracas
+ {"SA Eastern Standard Time", {"-03", "-03"}}, // America/Cayenne
+ {"Central Standard Time", {"CST", "CDT"}}, // America/Chicago
+ {"Central Brazilian Standard Time", {"-04", "-04"}}, // America/Cuiaba
+ {"Mountain Standard Time", {"MST", "MDT"}}, // America/Denver
+ {"Greenland Standard Time", {"-03", "-02"}}, // America/Godthab
+ {"Turks And Caicos Standard Time", {"EST", "EDT"}}, // America/Grand_Turk
+ {"Central America Standard Time", {"CST", "CST"}}, // America/Guatemala
+ {"Atlantic Standard Time", {"AST", "ADT"}}, // America/Halifax
+ {"Cuba Standard Time", {"CST", "CDT"}}, // America/Havana
+ {"US Eastern Standard Time", {"EST", "EDT"}}, // America/Indianapolis
+ {"SA Western Standard Time", {"-04", "-04"}}, // America/La_Paz
+ {"Pacific Standard Time", {"PST", "PDT"}}, // America/Los_Angeles
+ {"Mountain Standard Time (Mexico)", {"MST", "MST"}}, // America/Mazatlan
+ {"Central Standard Time (Mexico)", {"CST", "CST"}}, // America/Mexico_City
+ {"Saint Pierre Standard Time", {"-03", "-02"}}, // America/Miquelon
+ {"Montevideo Standard Time", {"-03", "-03"}}, // America/Montevideo
+ {"Eastern Standard Time", {"EST", "EDT"}}, // America/New_York
+ {"US Mountain Standard Time", {"MST", "MST"}}, // America/Phoenix
+ {"Haiti Standard Time", {"EST", "EDT"}}, // America/Port-au-Prince
+ {"Magallanes Standard Time", {"-03", "-03"}}, // America/Punta_Arenas
+ {"Canada Central Standard Time", {"CST", "CST"}}, // America/Regina
+ {"Pacific SA Standard Time", {"-04", "-03"}}, // America/Santiago
+ {"E. South America Standard Time", {"-03", "-03"}}, // America/Sao_Paulo
+ {"Newfoundland Standard Time", {"NST", "NDT"}}, // America/St_Johns
+ {"Pacific Standard Time (Mexico)", {"PST", "PDT"}}, // America/Tijuana
+ {"Yukon Standard Time", {"MST", "MST"}}, // America/Whitehorse
+ {"Central Asia Standard Time", {"+06", "+06"}}, // Asia/Almaty
+ {"Jordan Standard Time", {"+03", "+03"}}, // Asia/Amman
+ {"Arabic Standard Time", {"+03", "+03"}}, // Asia/Baghdad
+ {"Azerbaijan Standard Time", {"+04", "+04"}}, // Asia/Baku
+ {"SE Asia Standard Time", {"+07", "+07"}}, // Asia/Bangkok
+ {"Altai Standard Time", {"+07", "+07"}}, // Asia/Barnaul
+ {"Middle East Standard Time", {"EET", "EEST"}}, // Asia/Beirut
+ {"India Standard Time", {"IST", "IST"}}, // Asia/Calcutta
+ {"Transbaikal Standard Time", {"+09", "+09"}}, // Asia/Chita
+ {"Sri Lanka Standard Time", {"+0530", "+0530"}}, // Asia/Colombo
+ {"Syria Standard Time", {"+03", "+03"}}, // Asia/Damascus
+ {"Bangladesh Standard Time", {"+06", "+06"}}, // Asia/Dhaka
+ {"Arabian Standard Time", {"+04", "+04"}}, // Asia/Dubai
+ {"West Bank Standard Time", {"EET", "EEST"}}, // Asia/Hebron
+ {"W. Mongolia Standard Time", {"+07", "+07"}}, // Asia/Hovd
+ {"North Asia East Standard Time", {"+08", "+08"}}, // Asia/Irkutsk
+ {"Israel Standard Time", {"IST", "IDT"}}, // Asia/Jerusalem
+ {"Afghanistan Standard Time", {"+0430", "+0430"}}, // Asia/Kabul
+ {"Russia Time Zone 11", {"+12", "+12"}}, // Asia/Kamchatka
+ {"Pakistan Standard Time", {"PKT", "PKT"}}, // Asia/Karachi
+ {"Nepal Standard Time", {"+0545", "+0545"}}, // Asia/Katmandu
+ {"North Asia Standard Time", {"+07", "+07"}}, // Asia/Krasnoyarsk
+ {"Magadan Standard Time", {"+11", "+11"}}, // Asia/Magadan
+ {"N. Central Asia Standard Time", {"+07", "+07"}}, // Asia/Novosibirsk
+ {"Omsk Standard Time", {"+06", "+06"}}, // Asia/Omsk
+ {"North Korea Standard Time", {"KST", "KST"}}, // Asia/Pyongyang
+ {"Qyzylorda Standard Time", {"+05", "+05"}}, // Asia/Qyzylorda
+ {"Myanmar Standard Time", {"+0630", "+0630"}}, // Asia/Rangoon
+ {"Arab Standard Time", {"+03", "+03"}}, // Asia/Riyadh
+ {"Sakhalin Standard Time", {"+11", "+11"}}, // Asia/Sakhalin
+ {"Korea Standard Time", {"KST", "KST"}}, // Asia/Seoul
+ {"China Standard Time", {"CST", "CST"}}, // Asia/Shanghai
+ {"Singapore Standard Time", {"+08", "+08"}}, // Asia/Singapore
+ {"Russia Time Zone 10", {"+11", "+11"}}, // Asia/Srednekolymsk
+ {"Taipei Standard Time", {"CST", "CST"}}, // Asia/Taipei
+ {"West Asia Standard Time", {"+05", "+05"}}, // Asia/Tashkent
+ {"Georgian Standard Time", {"+04", "+04"}}, // Asia/Tbilisi
+ {"Iran Standard Time", {"+0330", "+0330"}}, // Asia/Tehran
+ {"Tokyo Standard Time", {"JST", "JST"}}, // Asia/Tokyo
+ {"Tomsk Standard Time", {"+07", "+07"}}, // Asia/Tomsk
+ {"Ulaanbaatar Standard Time", {"+08", "+08"}}, // Asia/Ulaanbaatar
+ {"Vladivostok Standard Time", {"+10", "+10"}}, // Asia/Vladivostok
+ {"Yakutsk Standard Time", {"+09", "+09"}}, // Asia/Yakutsk
+ {"Ekaterinburg Standard Time", {"+05", "+05"}}, // Asia/Yekaterinburg
+ {"Caucasus Standard Time", {"+04", "+04"}}, // Asia/Yerevan
+ {"Azores Standard Time", {"-01", "+00"}}, // Atlantic/Azores
+ {"Cape Verde Standard Time", {"-01", "-01"}}, // Atlantic/Cape_Verde
+ {"Greenwich Standard Time", {"GMT", "GMT"}}, // Atlantic/Reykjavik
+ {"Cen. Australia Standard Time", {"ACST", "ACDT"}}, // Australia/Adelaide
+ {"E. Australia Standard Time", {"AEST", "AEST"}}, // Australia/Brisbane
+ {"AUS Central Standard Time", {"ACST", "ACST"}}, // Australia/Darwin
+ {"Aus Central W. Standard Time", {"+0845", "+0845"}}, // Australia/Eucla
+ {"Tasmania Standard Time", {"AEST", "AEDT"}}, // Australia/Hobart
+ {"Lord Howe Standard Time", {"+1030", "+11"}}, // Australia/Lord_Howe
+ {"W. Australia Standard Time", {"AWST", "AWST"}}, // Australia/Perth
+ {"AUS Eastern Standard Time", {"AEST", "AEDT"}}, // Australia/Sydney
+ {"UTC-11", {"-11", "-11"}}, // Etc/GMT+11
+ {"Dateline Standard Time", {"-12", "-12"}}, // Etc/GMT+12
+ {"UTC-02", {"-02", "-02"}}, // Etc/GMT+2
+ {"UTC-08", {"-08", "-08"}}, // Etc/GMT+8
+ {"UTC-09", {"-09", "-09"}}, // Etc/GMT+9
+ {"UTC+12", {"+12", "+12"}}, // Etc/GMT-12
+ {"UTC+13", {"+13", "+13"}}, // Etc/GMT-13
+ {"UTC", {"UTC", "UTC"}}, // Etc/UTC
+ {"Astrakhan Standard Time", {"+04", "+04"}}, // Europe/Astrakhan
+ {"W. Europe Standard Time", {"CET", "CEST"}}, // Europe/Berlin
+ {"GTB Standard Time", {"EET", "EEST"}}, // Europe/Bucharest
+ {"Central Europe Standard Time", {"CET", "CEST"}}, // Europe/Budapest
+ {"E. Europe Standard Time", {"EET", "EEST"}}, // Europe/Chisinau
+ {"Turkey Standard Time", {"+03", "+03"}}, // Europe/Istanbul
+ {"Kaliningrad Standard Time", {"EET", "EET"}}, // Europe/Kaliningrad
+ {"FLE Standard Time", {"EET", "EEST"}}, // Europe/Kiev
+ {"GMT Standard Time", {"GMT", "BST"}}, // Europe/London
+ {"Belarus Standard Time", {"+03", "+03"}}, // Europe/Minsk
+ {"Russian Standard Time", {"MSK", "MSK"}}, // Europe/Moscow
+ {"Romance Standard Time", {"CET", "CEST"}}, // Europe/Paris
+ {"Russia Time Zone 3", {"+04", "+04"}}, // Europe/Samara
+ {"Saratov Standard Time", {"+04", "+04"}}, // Europe/Saratov
+ {"Volgograd Standard Time", {"MSK", "MSK"}}, // Europe/Volgograd
+ {"Central European Standard Time", {"CET", "CEST"}}, // Europe/Warsaw
+ {"Mauritius Standard Time", {"+04", "+04"}}, // Indian/Mauritius
+ {"Samoa Standard Time", {"+13", "+13"}}, // Pacific/Apia
+ {"New Zealand Standard Time", {"NZST", "NZDT"}}, // Pacific/Auckland
+ {"Bougainville Standard Time", {"+11", "+11"}}, // Pacific/Bougainville
+ {"Chatham Islands Standard Time", {"+1245", "+1345"}}, // Pacific/Chatham
+ {"Easter Island Standard Time", {"-06", "-05"}}, // Pacific/Easter
+ {"Fiji Standard Time", {"+12", "+12"}}, // Pacific/Fiji
+ {"Central Pacific Standard Time", {"+11", "+11"}}, // Pacific/Guadalcanal
+ {"Hawaiian Standard Time", {"HST", "HST"}}, // Pacific/Honolulu
+ {"Line Islands Standard Time", {"+14", "+14"}}, // Pacific/Kiritimati
+ {"Marquesas Standard Time", {"-0930", "-0930"}}, // Pacific/Marquesas
+ {"Norfolk Standard Time", {"+11", "+12"}}, // Pacific/Norfolk
+ {"West Pacific Standard Time", {"+10", "+10"}}, // Pacific/Port_Moresby
+ {"Tonga Standard Time", {"+13", "+13"}}, // Pacific/Tongatapu
}
iana_to_windows_tz :: proc(iana_name: string, allocator := context.allocator) -> (name: string, success: bool) {
@@ -269,7 +270,18 @@ _region_load :: proc(reg_str: string, allocator := context.allocator) -> (out_re
defer delete(wintz_name, allocator)
defer delete(iana_name, allocator)
- abbrevs := tz_abbrevs[wintz_name] or_return
+ abbrevs: TZ_Abbrev
+ abbrevs_ok: bool
+ for pair in tz_abbrevs {
+ if pair.key == wintz_name {
+ abbrevs = pair.value
+ abbrevs_ok = true
+ break
+ }
+ }
+ if !abbrevs_ok {
+ return
+ }
if abbrevs.std == "UTC" && abbrevs.dst == abbrevs.std {
return nil, true
}
diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin
index 36d1359ca..82b047103 100644
--- a/examples/demo/demo.odin
+++ b/examples/demo/demo.odin
@@ -1,4 +1,5 @@
#+vet !using-stmt !using-param
+#+feature dynamic-literals
package main
import "core:fmt"
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index 4c3f4b782..93168cf77 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -324,6 +324,18 @@ u64 get_vet_flag_from_name(String const &name) {
return VetFlag_NONE;
}
+enum OptInFeatureFlags : u64 {
+ OptInFeatureFlag_NONE = 0,
+ OptInFeatureFlag_DynamicLiterals = 1u<<0,
+};
+
+u64 get_feature_flag_from_name(String const &name) {
+ if (name == "dynamic-literals") {
+ return OptInFeatureFlag_DynamicLiterals;
+ }
+ return OptInFeatureFlag_NONE;
+}
+
enum SanitizerFlags : u32 {
SanitizerFlag_NONE = 0,
@@ -429,7 +441,6 @@ struct BuildContext {
bool ignore_unknown_attributes;
bool no_bounds_check;
bool no_type_assert;
- bool no_dynamic_literals;
bool no_output_files;
bool no_crt;
bool no_rpath;
@@ -1855,11 +1866,6 @@ gb_internal bool init_build_paths(String init_filename) {
produces_output_file = true;
}
- if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR ||
- build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
- bc->no_dynamic_literals = true;
- }
-
if (!produces_output_file) {
// Command doesn't produce output files. We're done.
return true;
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index 60eb030ff..1d792dad8 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -94,12 +94,14 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o
return nullptr;
}
if (e2->state.load() != EntityState_Resolved) {
- gbString str = type_to_string(t);
- defer (gb_string_free(str));
- error(e->token, "Invalid use of a polymorphic type '%s' in %.*s", str, LIT(context_name));
- e->type = t_invalid;
+ e->type = t;
return nullptr;
}
+ gbString str = type_to_string(t);
+ defer (gb_string_free(str));
+ error(operand->expr, "Invalid use of a non-specialized polymorphic type '%s' in %.*s", str, LIT(context_name));
+ e->type = t_invalid;
+ return nullptr;
} else if (is_type_empty_union(t)) {
gbString str = type_to_string(t);
defer (gb_string_free(str));
@@ -971,6 +973,43 @@ gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeCon
}
}
+gb_internal void check_foreign_procedure(CheckerContext *ctx, Entity *e, DeclInfo *d) {
+ GB_ASSERT(e != nullptr);
+ GB_ASSERT(e->kind == Entity_Procedure);
+ String name = e->Procedure.link_name;
+
+ mutex_lock(&ctx->info->foreign_mutex);
+
+ auto *fp = &ctx->info->foreigns;
+ StringHashKey key = string_hash_string(name);
+ Entity **found = string_map_get(fp, key);
+ if (found && e != *found) {
+ Entity *f = *found;
+ TokenPos pos = f->token.pos;
+ Type *this_type = base_type(e->type);
+ Type *other_type = base_type(f->type);
+ if (is_type_proc(this_type) && is_type_proc(other_type)) {
+ if (!are_signatures_similar_enough(this_type, other_type)) {
+ error(d->proc_lit,
+ "Redeclaration of foreign procedure '%.*s' with different type signatures\n"
+ "\tat %s",
+ LIT(name), token_pos_to_string(pos));
+ }
+ } else if (!signature_parameter_similar_enough(this_type, other_type)) {
+ error(d->proc_lit,
+ "Foreign entity '%.*s' previously declared elsewhere with a different type\n"
+ "\tat %s",
+ LIT(name), token_pos_to_string(pos));
+ }
+ } else if (name == "main") {
+ error(d->proc_lit, "The link name 'main' is reserved for internal use");
+ } else {
+ string_map_set(fp, key, e);
+ }
+
+ mutex_unlock(&ctx->info->foreign_mutex);
+}
+
gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
GB_ASSERT(e->type == nullptr);
if (d->proc_lit->kind != Ast_ProcLit) {
@@ -1307,57 +1346,16 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
name = e->Procedure.link_name;
}
Entity *foreign_library = init_entity_foreign_library(ctx, e);
-
- if (is_arch_wasm() && foreign_library != nullptr) {
- String module_name = str_lit("env");
- GB_ASSERT (foreign_library->kind == Entity_LibraryName);
- if (foreign_library->LibraryName.paths.count != 1) {
- error(foreign_library->token, "'foreign import' for '%.*s' architecture may only have one path, got %td",
- LIT(target_arch_names[build_context.metrics.arch]), foreign_library->LibraryName.paths.count);
- }
-
- if (foreign_library->LibraryName.paths.count >= 1) {
- module_name = foreign_library->LibraryName.paths[0];
- }
-
- if (!string_ends_with(module_name, str_lit(".o"))) {
- name = concatenate3_strings(permanent_allocator(), module_name, WASM_MODULE_NAME_SEPARATOR, name);
- }
- }
-
e->Procedure.is_foreign = true;
e->Procedure.link_name = name;
+ e->Procedure.foreign_library = foreign_library;
- mutex_lock(&ctx->info->foreign_mutex);
-
- auto *fp = &ctx->info->foreigns;
- StringHashKey key = string_hash_string(name);
- Entity **found = string_map_get(fp, key);
- if (found && e != *found) {
- Entity *f = *found;
- TokenPos pos = f->token.pos;
- Type *this_type = base_type(e->type);
- Type *other_type = base_type(f->type);
- if (is_type_proc(this_type) && is_type_proc(other_type)) {
- if (!are_signatures_similar_enough(this_type, other_type)) {
- error(d->proc_lit,
- "Redeclaration of foreign procedure '%.*s' with different type signatures\n"
- "\tat %s",
- LIT(name), token_pos_to_string(pos));
- }
- } else if (!signature_parameter_similar_enough(this_type, other_type)) {
- error(d->proc_lit,
- "Foreign entity '%.*s' previously declared elsewhere with a different type\n"
- "\tat %s",
- LIT(name), token_pos_to_string(pos));
- }
- } else if (name == "main") {
- error(d->proc_lit, "The link name 'main' is reserved for internal use");
+ if (is_arch_wasm() && foreign_library != nullptr) {
+ // NOTE(bill): this must be delayed because the foreign import paths might not be evaluated yet until much later
+ mpsc_enqueue(&ctx->info->foreign_decls_to_check, e);
} else {
- string_map_set(fp, key, e);
+ check_foreign_procedure(ctx, e, d);
}
-
- mutex_unlock(&ctx->info->foreign_mutex);
} else {
String name = e->token.string;
if (e->Procedure.link_name.len > 0) {
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index cc9483187..231ece2f4 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -3672,6 +3672,13 @@ gb_internal bool check_binary_array_expr(CheckerContext *c, Token op, Operand *x
}
}
}
+ if (is_type_simd_vector(x->type) && !is_type_simd_vector(y->type)) {
+ if (check_is_assignable_to(c, y, x->type)) {
+ if (check_binary_op(c, x, op)) {
+ return true;
+ }
+ }
+ }
return false;
}
@@ -4556,6 +4563,19 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
break;
}
+ case Type_SimdVector: {
+ Type *elem = base_array_type(t);
+ if (check_is_assignable_to(c, operand, elem)) {
+ operand->mode = Addressing_Value;
+ } else {
+ operand->mode = Addressing_Invalid;
+ convert_untyped_error(c, operand, target_type);
+ return;
+ }
+
+ break;
+ }
+
case Type_Matrix: {
Type *elem = base_array_type(t);
if (check_is_assignable_to(c, operand, elem)) {
@@ -8725,6 +8745,18 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A
error(node, "#caller_expression may only be used as a default argument parameter");
o->type = t_string;
o->mode = Addressing_Value;
+ } else if (name == "branch_location") {
+ if (!c->in_defer) {
+ error(node, "#branch_location may only be used within a 'defer' statement");
+ } else if (c->curr_proc_decl) {
+ Entity *e = c->curr_proc_decl->entity;
+ if (e != nullptr) {
+ GB_ASSERT(e->kind == Entity_Procedure);
+ e->Procedure.uses_branch_location = true;
+ }
+ }
+ o->type = t_source_code_location;
+ o->mode = Addressing_Value;
} else {
if (name == "location") {
init_core_source_code_location(c->checker);
@@ -9339,6 +9371,23 @@ gb_internal bool is_expr_inferred_fixed_array(Ast *type_expr) {
return false;
}
+gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCompoundLit *cl) {
+ if (cl->elems.count > 0 && (check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0) {
+ ERROR_BLOCK();
+ error(node, "Compound literals of dynamic types are disabled by default");
+ error_line("\tSuggestion: If you want to enable them for this specific file, add '#+feature dynamic-literals' at the top of the file\n");
+ error_line("\tWarning: Please understand that dynamic literals will implicitly allocate using the current 'context.allocator' in that scope\n");
+ if (build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR) {
+ error_line("\tWarning: As '-default-to-panic-allocator' has been set, the dynamic compound literal may not be initialized as expected\n");
+ } else if (build_context.ODIN_DEFAULT_TO_PANIC_ALLOCATOR) {
+ error_line("\tWarning: As '-default-to-panic-allocator' has been set, the dynamic compound literal may not be initialized as expected\n");
+ }
+ return false;
+ }
+
+ return cl->elems.count > 0;
+}
+
gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Expr;
ast_node(cl, CompoundLit, node);
@@ -9539,11 +9588,6 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
elem_type = t->DynamicArray.elem;
context_name = str_lit("dynamic array literal");
is_constant = false;
-
- if (!build_context.no_dynamic_literals) {
- add_package_dependency(c, "runtime", "__dynamic_array_reserve");
- add_package_dependency(c, "runtime", "__dynamic_array_append");
- }
} else if (t->kind == Type_SimdVector) {
elem_type = t->SimdVector.elem;
context_name = str_lit("simd vector literal");
@@ -9718,8 +9762,9 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
if (t->kind == Type_DynamicArray) {
- if (build_context.no_dynamic_literals && cl->elems.count) {
- error(node, "Compound literals of dynamic types have been disabled");
+ if (check_for_dynamic_literals(c, node, cl)) {
+ add_package_dependency(c, "runtime", "__dynamic_array_reserve");
+ add_package_dependency(c, "runtime", "__dynamic_array_append");
}
}
@@ -10108,9 +10153,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
}
}
- if (build_context.no_dynamic_literals && cl->elems.count) {
- error(node, "Compound literals of dynamic types have been disabled");
- } else {
+ if (check_for_dynamic_literals(c, node, cl)) {
add_map_reserve_dependencies(c);
add_map_set_dependencies(c);
}
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 13a6125ca..44108ccbe 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -2440,8 +2440,12 @@ gb_internal bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc
bool success = true;
isize specialization_count = 0;
Type *params = check_get_params(c, c->scope, pt->params, &variadic, &variadic_index, &success, &specialization_count, operands);
- Type *results = check_get_results(c, c->scope, pt->results);
+ bool no_poly_return = c->disallow_polymorphic_return_types;
+ c->disallow_polymorphic_return_types = c->scope == c->polymorphic_scope;
+ // NOTE(zen3ger): if the parapoly scope is the current proc's scope, then the return types shall not declare new poly vars
+ Type *results = check_get_results(c, c->scope, pt->results);
+ c->disallow_polymorphic_return_types = no_poly_return;
isize param_count = 0;
isize result_count = 0;
@@ -3383,6 +3387,9 @@ gb_internal bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, T
}
Type *t = alloc_type_generic(ctx->scope, 0, token.string, specific);
if (ctx->allow_polymorphic_types) {
+ if (ctx->disallow_polymorphic_return_types) {
+ error(ident, "Undeclared polymorphic parameter '%.*s' in return type", LIT(token.string));
+ }
Scope *ps = ctx->polymorphic_scope;
Scope *s = ctx->scope;
Scope *entity_scope = s;
diff --git a/src/checker.cpp b/src/checker.cpp
index b7cf343f8..5d3263789 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -542,6 +542,23 @@ gb_internal u64 check_vet_flags(Ast *node) {
return ast_file_vet_flags(file);
}
+gb_internal u64 check_feature_flags(CheckerContext *c, Ast *node) {
+ AstFile *file = c->file;
+ if (file == nullptr &&
+ c->curr_proc_decl &&
+ c->curr_proc_decl->proc_lit) {
+ file = c->curr_proc_decl->proc_lit->file();
+ }
+ if (file == nullptr) {
+ file = node->file();
+ }
+ if (file != nullptr && file->feature_flags_set) {
+ return file->feature_flags;
+ }
+ return 0;
+}
+
+
enum VettedEntityKind {
VettedEntity_Invalid,
@@ -1164,7 +1181,6 @@ gb_internal void init_universal(void) {
add_global_bool_constant("ODIN_NO_BOUNDS_CHECK", build_context.no_bounds_check);
add_global_bool_constant("ODIN_NO_TYPE_ASSERT", build_context.no_type_assert);
add_global_bool_constant("ODIN_DEFAULT_TO_PANIC_ALLOCATOR", bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR);
- add_global_bool_constant("ODIN_NO_DYNAMIC_LITERALS", bc->no_dynamic_literals);
add_global_bool_constant("ODIN_NO_CRT", bc->no_crt);
add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules);
add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test);
@@ -1356,6 +1372,7 @@ gb_internal void init_checker_info(CheckerInfo *i) {
mpsc_init(&i->required_global_variable_queue, a); // 1<<10);
mpsc_init(&i->required_foreign_imports_through_force_queue, a); // 1<<10);
mpsc_init(&i->foreign_imports_to_check_fullpaths, a); // 1<<10);
+ mpsc_init(&i->foreign_decls_to_check, a); // 1<<10);
mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used
string_map_init(&i->load_directory_cache);
@@ -1382,6 +1399,7 @@ gb_internal void destroy_checker_info(CheckerInfo *i) {
mpsc_destroy(&i->required_global_variable_queue);
mpsc_destroy(&i->required_foreign_imports_through_force_queue);
mpsc_destroy(&i->foreign_imports_to_check_fullpaths);
+ mpsc_destroy(&i->foreign_decls_to_check);
map_destroy(&i->objc_msgSend_types);
string_map_destroy(&i->load_file_cache);
@@ -5094,6 +5112,38 @@ gb_internal void check_foreign_import_fullpaths(Checker *c) {
e->LibraryName.paths = fl->fullpaths;
}
+
+ for (Entity *e = nullptr; mpsc_dequeue(&c->info.foreign_decls_to_check, &e); /**/) {
+ GB_ASSERT(e != nullptr);
+ if (e->kind != Entity_Procedure) {
+ continue;
+ }
+ if (!is_arch_wasm()) {
+ continue;
+ }
+ Entity *foreign_library = e->Procedure.foreign_library;
+ GB_ASSERT(foreign_library != nullptr);
+
+ String name = e->Procedure.link_name;
+
+ String module_name = str_lit("env");
+ GB_ASSERT (foreign_library->kind == Entity_LibraryName);
+ if (foreign_library->LibraryName.paths.count != 1) {
+ error(foreign_library->token, "'foreign import' for '%.*s' architecture may only have one path, got %td",
+ LIT(target_arch_names[build_context.metrics.arch]), foreign_library->LibraryName.paths.count);
+ }
+
+ if (foreign_library->LibraryName.paths.count >= 1) {
+ module_name = foreign_library->LibraryName.paths[0];
+ }
+
+ if (!string_ends_with(module_name, str_lit(".o"))) {
+ name = concatenate3_strings(permanent_allocator(), module_name, WASM_MODULE_NAME_SEPARATOR, name);
+ }
+ e->Procedure.link_name = name;
+
+ check_foreign_procedure(&ctx, e, e->decl_info);
+ }
}
gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
diff --git a/src/checker.hpp b/src/checker.hpp
index 438156f18..3951fcefe 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -461,6 +461,7 @@ struct CheckerInfo {
MPSCQueue<Entity *> required_global_variable_queue;
MPSCQueue<Entity *> required_foreign_imports_through_force_queue;
MPSCQueue<Entity *> foreign_imports_to_check_fullpaths;
+ MPSCQueue<Entity *> foreign_decls_to_check;
MPSCQueue<Ast *> intrinsics_entry_point_usage;
@@ -521,6 +522,7 @@ struct CheckerContext {
bool in_enum_type;
bool collect_delayed_decls;
bool allow_polymorphic_types;
+ bool disallow_polymorphic_return_types; // NOTE(zen3ger): no poly type decl in return types
bool no_polymorphic_errors;
bool hide_polymorphic_errors;
bool in_polymorphic_specialization;
diff --git a/src/entity.cpp b/src/entity.cpp
index 0c4a20df4..802b381f9 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -256,6 +256,7 @@ struct Entity {
bool entry_point_only : 1;
bool has_instrumentation : 1;
bool is_memcpy_like : 1;
+ bool uses_branch_location : 1;
} Procedure;
struct {
Array<Entity *> entities;
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 01ded321e..696ced0df 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -1096,8 +1096,6 @@ gb_internal void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_
}
gb_internal lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const capacity, TokenPos const &pos) {
- GB_ASSERT(!build_context.no_dynamic_literals);
-
TEMPORARY_ALLOCATOR_GUARD();
String proc_name = {};
diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp
index e84ffd1cd..42d283a1e 100644
--- a/src/llvm_backend.hpp
+++ b/src/llvm_backend.hpp
@@ -359,6 +359,10 @@ struct lbProcedure {
bool in_multi_assignment;
Array<LLVMValueRef> raw_input_parameters;
+ bool uses_branch_location;
+ TokenPos branch_location_pos;
+ TokenPos curr_token_pos;
+
Array<lbVariadicReuseSlices> variadic_reuses;
lbAddr variadic_reuse_base_array_ptr;
@@ -444,7 +448,8 @@ gb_internal lbValue lb_emit_matrix_ev(lbProcedure *p, lbValue s, isize row, isiz
gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type);
gb_internal lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *end_type);
-gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block);
+gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, TokenPos pos);
+gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node);
gb_internal lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t);
gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right);
gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, ProcInlining inlining = ProcInlining_none);
@@ -742,3 +747,5 @@ gb_global char const *llvm_linkage_strings[] = {
};
#define ODIN_METADATA_IS_PACKED str_lit("odin-is-packed")
+#define ODIN_METADATA_MIN_ALIGN str_lit("odin-min-align")
+#define ODIN_METADATA_MAX_ALIGN str_lit("odin-max-align")
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index 9c325e088..df9dca801 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -3502,7 +3502,13 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
case_ast_node(bd, BasicDirective, expr);
TokenPos pos = bd->token.pos;
- GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(bd->name.string));
+ String name = bd->name.string;
+ if (name == "branch_location") {
+ GB_ASSERT(p->uses_branch_location);
+ String proc_name = p->entity->token.string;
+ return lb_emit_source_code_location_as_global(p, proc_name, p->branch_location_pos);
+ }
+ GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(name));
case_end;
case_ast_node(i, Implicit, expr);
@@ -3668,7 +3674,7 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
lb_start_block(p, else_);
- lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
+ lb_emit_defer_stmts(p, lbDeferExit_Branch, block, expr);
lb_emit_jump(p, block);
lb_start_block(p, then);
@@ -4807,7 +4813,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (cl->elems.count == 0) {
break;
}
- GB_ASSERT(!build_context.no_dynamic_literals);
+ GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals);
lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos);
gb_unused(err);
@@ -4896,7 +4902,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (cl->elems.count == 0) {
break;
}
- GB_ASSERT(!build_context.no_dynamic_literals);
+ GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals);
Type *et = bt->DynamicArray.elem;
lbValue size = lb_const_int(p->module, t_int, type_size_of(et));
@@ -5493,7 +5499,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
lb_start_block(p, else_);
- lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
+ lb_emit_defer_stmts(p, lbDeferExit_Branch, block, expr);
lb_emit_jump(p, block);
lb_start_block(p, then);
diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp
index bab330da7..762256258 100644
--- a/src/llvm_backend_general.cpp
+++ b/src/llvm_backend_general.cpp
@@ -734,6 +734,17 @@ gb_internal LLVMValueRef OdinLLVMBuildLoad(lbProcedure *p, LLVMTypeRef type, LLV
if (is_packed != 0) {
LLVMSetAlignment(result, 1);
}
+ u64 align = LLVMGetAlignment(result);
+ u64 align_min = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MIN_ALIGN);
+ u64 align_max = lb_get_metadata_custom_u64(p->module, value, ODIN_METADATA_MAX_ALIGN);
+ if (align_min != 0 && align < align_min) {
+ align = align_min;
+ }
+ if (align_max != 0 && align > align_max) {
+ align = align_max;
+ }
+ GB_ASSERT(align <= UINT_MAX);
+ LLVMSetAlignment(result, (unsigned int)align);
}
return result;
@@ -2121,6 +2132,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
}
i64 prev_offset = 0;
+ bool requires_packing = type->Struct.is_packed;
for (i32 field_index : struct_fields_index_by_increasing_offset(temporary_allocator(), type)) {
Entity *field = type->Struct.fields[field_index];
i64 offset = type->Struct.offsets[field_index];
@@ -2141,6 +2153,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
field_type = t_rawptr;
}
+ // max_field_align might misalign items in a way that requires packing
+ // so check the alignment of all fields to see if packing is required.
+ requires_packing = requires_packing || ((offset % type_align_of(field_type)) != 0);
+
array_add(&fields, lb_type(m, field_type));
prev_offset = offset + type_size_of(field->type);
@@ -2155,7 +2171,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
GB_ASSERT(fields[i] != nullptr);
}
- LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, type->Struct.is_packed);
+ LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing);
map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping);
map_set(&m->struct_field_remapping, cast(void *)type, field_remapping);
#if 0
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp
index 712e13592..7e44a0046 100644
--- a/src/llvm_backend_proc.cpp
+++ b/src/llvm_backend_proc.cpp
@@ -125,6 +125,10 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i
// map_init(&p->selector_addr, 0);
// map_init(&p->tuple_fix_map, 0);
+ if (p->entity != nullptr && p->entity->Procedure.uses_branch_location) {
+ p->uses_branch_location = true;
+ }
+
if (p->is_foreign) {
lb_add_foreign_library_path(p->module, entity->Procedure.foreign_library);
}
@@ -757,7 +761,7 @@ gb_internal void lb_end_procedure_body(lbProcedure *p) {
if (p->type->Proc.result_count == 0) {
instr = LLVMGetLastInstruction(p->curr_block->block);
if (!lb_is_instr_terminating(instr)) {
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, p->body);
lb_set_debug_position_to_procedure_end(p);
LLVMBuildRetVoid(p->builder);
}
diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp
index 9a5f25712..a2f0d2f4a 100644
--- a/src/llvm_backend_stmt.cpp
+++ b/src/llvm_backend_stmt.cpp
@@ -208,8 +208,8 @@ gb_internal void lb_open_scope(lbProcedure *p, Scope *s) {
}
-gb_internal void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, bool pop_stack=true) {
- lb_emit_defer_stmts(p, kind, block);
+gb_internal void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node, bool pop_stack=true) {
+ lb_emit_defer_stmts(p, kind, block, node);
GB_ASSERT(p->scope_index > 0);
// NOTE(bill): Remove `context`s made in that scope
@@ -721,7 +721,7 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node,
lb_build_stmt(p, rs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, node->left);
lb_pop_target_list(p);
if (check != nullptr) {
@@ -854,7 +854,7 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s
lb_build_stmt(p, rs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -976,7 +976,7 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs
lb_build_stmt(p, rs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -1192,7 +1192,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
lb_build_stmt(p, rs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -1363,7 +1363,7 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
}
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
}
gb_internal bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, bool *default_found_) {
@@ -1433,6 +1433,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
ast_node(body, BlockStmt, ss->body);
isize case_count = body->stmts.count;
+ Ast *default_clause = nullptr;
Slice<Ast *> default_stmts = {};
lbBlock *default_fall = nullptr;
lbBlock *default_block = nullptr;
@@ -1482,6 +1483,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
if (cc->list.count == 0) {
// default case
+ default_clause = clause;
default_stmts = cc->stmts;
default_fall = fall;
if (switch_instr == nullptr) {
@@ -1552,7 +1554,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
lb_push_target_list(p, ss->label, done, nullptr, fall);
lb_open_scope(p, body->scope);
lb_build_stmt_list(p, cc->stmts);
- lb_close_scope(p, lbDeferExit_Default, body);
+ lb_close_scope(p, lbDeferExit_Default, body, clause);
lb_pop_target_list(p);
lb_emit_jump(p, done);
@@ -1570,13 +1572,13 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
lb_push_target_list(p, ss->label, done, nullptr, default_fall);
lb_open_scope(p, default_block->scope);
lb_build_stmt_list(p, default_stmts);
- lb_close_scope(p, lbDeferExit_Default, default_block);
+ lb_close_scope(p, lbDeferExit_Default, default_block, default_clause);
lb_pop_target_list(p);
}
lb_emit_jump(p, done);
lb_start_block(p, done);
- lb_close_scope(p, lbDeferExit_Default, done);
+ lb_close_scope(p, lbDeferExit_Default, done, ss->body);
}
gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value, bool is_default_case) {
@@ -1627,7 +1629,7 @@ gb_internal void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBl
lb_push_target_list(p, label, done, nullptr, nullptr);
lb_build_stmt_list(p, cc->stmts);
- lb_close_scope(p, lbDeferExit_Default, body);
+ lb_close_scope(p, lbDeferExit_Default, body, clause);
lb_pop_target_list(p);
lb_emit_jump(p, done);
@@ -1835,7 +1837,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
lb_emit_jump(p, done);
lb_start_block(p, done);
- lb_close_scope(p, lbDeferExit_Default, done);
+ lb_close_scope(p, lbDeferExit_Default, done, ss->body);
}
@@ -1959,7 +1961,7 @@ gb_internal void lb_build_assignment(lbProcedure *p, Array<lbAddr> &lvals, Slice
p->in_multi_assignment = prev_in_assignment;
}
-gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
+gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res, TokenPos pos) {
lbFunctionType *ft = lb_get_function_type(p->module, p->type);
bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
bool split_returns = ft->multiple_return_original_type != nullptr;
@@ -1982,7 +1984,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value);
}
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2012,7 +2014,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
ret_val = OdinLLVMBuildTransmute(p, ret_val, ret_type);
}
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2021,7 +2023,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
}
}
}
-gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results) {
+gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results, TokenPos pos) {
lb_ensure_abi_function_type(p->module, p);
isize return_count = p->type->Proc.result_count;
@@ -2029,7 +2031,7 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
if (return_count == 0) {
// No return values
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2138,11 +2140,11 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
GB_ASSERT(result_values.count-1 == result_eps.count);
lb_addr_store(p, p->return_ptr, result_values[result_values.count-1]);
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
LLVMBuildRetVoid(p->builder);
return;
} else {
- return lb_build_return_stmt_internal(p, result_values[result_values.count-1]);
+ return lb_build_return_stmt_internal(p, result_values[result_values.count-1], pos);
}
} else {
@@ -2169,7 +2171,7 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
}
if (return_by_pointer) {
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
LLVMBuildRetVoid(p->builder);
return;
}
@@ -2177,13 +2179,13 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
res = lb_emit_load(p, res);
}
}
- lb_build_return_stmt_internal(p, res);
+ lb_build_return_stmt_internal(p, res, pos);
}
gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
ast_node(is, IfStmt, node);
lb_open_scope(p, is->scope); // Scope #1
- defer (lb_close_scope(p, lbDeferExit_Default, nullptr));
+ defer (lb_close_scope(p, lbDeferExit_Default, nullptr, node));
lbBlock *then = lb_create_block(p, "if.then");
lbBlock *done = lb_create_block(p, "if.done");
@@ -2234,7 +2236,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, scope_of_node(is->else_stmt));
lb_build_stmt(p, is->else_stmt);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, is->else_stmt);
}
lb_emit_jump(p, done);
@@ -2251,7 +2253,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, scope_of_node(is->else_stmt));
lb_build_stmt(p, is->else_stmt);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, is->else_stmt);
lb_emit_jump(p, done);
}
@@ -2322,7 +2324,7 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) {
}
lb_start_block(p, done);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, node);
}
gb_internal void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr const &lhs, lbValue const &value) {
@@ -2588,7 +2590,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, bs->scope);
lb_build_stmt_list(p, bs->stmts);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, node);
if (done != nullptr) {
lb_emit_jump(p, done);
@@ -2702,7 +2704,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
case_end;
case_ast_node(rs, ReturnStmt, node);
- lb_build_return_stmt(p, rs->results);
+ lb_build_return_stmt(p, rs->results, ast_token(node).pos);
case_end;
case_ast_node(is, IfStmt, node);
@@ -2755,7 +2757,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
}
}
if (block != nullptr) {
- lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
+ lb_emit_defer_stmts(p, lbDeferExit_Branch, block, node);
}
lb_emit_jump(p, block);
lb_start_block(p, lb_create_block(p, "unreachable"));
@@ -2795,7 +2797,13 @@ gb_internal void lb_build_defer_stmt(lbProcedure *p, lbDefer const &d) {
}
}
-gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block) {
+gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, TokenPos pos) {
+ TokenPos prev_token_pos = p->branch_location_pos;
+ if (p->uses_branch_location) {
+ p->branch_location_pos = pos;
+ }
+ defer (p->branch_location_pos = prev_token_pos);
+
isize count = p->defer_stmts.count;
isize i = count;
while (i --> 0) {
@@ -2822,6 +2830,21 @@ gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlo
}
}
+gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node) {
+ TokenPos pos = {};
+ if (node) {
+ if (node->kind == Ast_BlockStmt) {
+ pos = ast_end_token(node).pos;
+ } else if (node->kind == Ast_CaseClause) {
+ pos = ast_end_token(node).pos;
+ } else {
+ pos = ast_token(node).pos;
+ }
+ }
+ return lb_emit_defer_stmts(p, kind, block, pos);
+}
+
+
gb_internal void lb_add_defer_node(lbProcedure *p, isize scope_index, Ast *stmt) {
Type *pt = base_type(p->type);
GB_ASSERT(pt->kind == Type_Proc);
diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp
index a2a0ba4cc..7b7c9d6e9 100644
--- a/src/llvm_backend_utility.cpp
+++ b/src/llvm_backend_utility.cpp
@@ -476,8 +476,8 @@ gb_internal lbValue lb_emit_or_else(lbProcedure *p, Ast *arg, Ast *else_expr, Ty
}
}
-gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results);
-gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res);
+gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results, TokenPos pos);
+gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res, TokenPos pos);
gb_internal lbValue lb_emit_or_return(lbProcedure *p, Ast *arg, TypeAndValue const &tv) {
lbValue lhs = {};
@@ -506,10 +506,10 @@ gb_internal lbValue lb_emit_or_return(lbProcedure *p, Ast *arg, TypeAndValue con
lbValue found = map_must_get(&p->module->values, end_entity);
lb_emit_store(p, found, rhs);
- lb_build_return_stmt(p, {});
+ lb_build_return_stmt(p, {}, ast_token(arg).pos);
} else {
GB_ASSERT(tuple->variables.count == 1);
- lb_build_return_stmt_internal(p, rhs);
+ lb_build_return_stmt_internal(p, rhs, ast_token(arg).pos);
}
}
lb_start_block(p, continue_block);
@@ -1200,9 +1200,22 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
lbValue gep = lb_emit_struct_ep_internal(p, s, index, result_type);
Type *bt = base_type(t);
- if (bt->kind == Type_Struct && bt->Struct.is_packed) {
- lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
- GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
+ if (bt->kind == Type_Struct) {
+ if (bt->Struct.is_packed) {
+ lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED, 1);
+ GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_IS_PACKED) == 1);
+ }
+ u64 align_max = bt->Struct.custom_max_field_align;
+ u64 align_min = bt->Struct.custom_min_field_align;
+ GB_ASSERT(align_min == 0 || align_max == 0 || align_min <= align_max);
+ if (align_max) {
+ lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MAX_ALIGN, align_max);
+ GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MAX_ALIGN) == align_max);
+ }
+ if (align_min) {
+ lb_set_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MIN_ALIGN, align_min);
+ GB_ASSERT(lb_get_metadata_custom_u64(p->module, gep.value, ODIN_METADATA_MIN_ALIGN) == align_min);
+ }
}
return gep;
diff --git a/src/main.cpp b/src/main.cpp
index 4d85a9e72..41c7170f6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1192,7 +1192,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
build_context.no_type_assert = true;
break;
case BuildFlag_NoDynamicLiterals:
- build_context.no_dynamic_literals = true;
+ gb_printf_err("Warning: Use of -no-dynamic-literals is now redundant\n");
break;
case BuildFlag_NoCRT:
build_context.no_crt = true;
@@ -2120,7 +2120,7 @@ gb_internal void export_dependencies(Checker *c) {
for_array(i, files) {
AstFile *file = files[i];
gb_fprintf(&f, "\t\t\"%.*s\"", LIT(file->fullpath));
- if (i+1 == files.count) {
+ if (i+1 < files.count) {
gb_fprintf(&f, ",");
}
gb_fprintf(&f, "\n");
@@ -2133,7 +2133,7 @@ gb_internal void export_dependencies(Checker *c) {
for_array(i, load_files) {
LoadFileCache *cache = load_files[i];
gb_fprintf(&f, "\t\t\"%.*s\"", LIT(cache->path));
- if (i+1 == load_files.count) {
+ if (i+1 < load_files.count) {
gb_fprintf(&f, ",");
}
gb_fprintf(&f, "\n");
diff --git a/src/parser.cpp b/src/parser.cpp
index aa90651d3..03c5a5962 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -6265,10 +6265,16 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) {
syntax_error(token_for_pos, "Invalid vet flag name: %.*s", LIT(p));
error_line("\tExpected one of the following\n");
error_line("\tunused\n");
+ error_line("\tunused-variables\n");
+ error_line("\tunused-imports\n");
+ error_line("\tunused-procedures\n");
error_line("\tshadowing\n");
error_line("\tusing-stmt\n");
error_line("\tusing-param\n");
+ error_line("\tstyle\n");
error_line("\textra\n");
+ error_line("\tcast\n");
+ error_line("\ttabs\n");
return build_context.vet_flags;
}
}
@@ -6286,6 +6292,63 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) {
return vet_flags &~ vet_not_flags;
}
+gb_internal u64 parse_feature_tag(Token token_for_pos, String s) {
+ String const prefix = str_lit("feature");
+ GB_ASSERT(string_starts_with(s, prefix));
+ s = string_trim_whitespace(substring(s, prefix.len, s.len));
+
+ if (s.len == 0) {
+ return OptInFeatureFlag_NONE;
+ }
+
+ u64 feature_flags = 0;
+ u64 feature_not_flags = 0;
+
+ while (s.len > 0) {
+ String p = string_trim_whitespace(vet_tag_get_token(s, &s));
+ if (p.len == 0) {
+ break;
+ }
+
+ bool is_notted = false;
+ if (p[0] == '!') {
+ is_notted = true;
+ p = substring(p, 1, p.len);
+ if (p.len == 0) {
+ syntax_error(token_for_pos, "Expected a feature flag name after '!'");
+ return OptInFeatureFlag_NONE;
+ }
+ }
+
+ u64 flag = get_feature_flag_from_name(p);
+ if (flag != OptInFeatureFlag_NONE) {
+ if (is_notted) {
+ feature_not_flags |= flag;
+ } else {
+ feature_flags |= flag;
+ }
+ } else {
+ ERROR_BLOCK();
+ syntax_error(token_for_pos, "Invalid feature flag name: %.*s", LIT(p));
+ error_line("\tExpected one of the following\n");
+ error_line("\tdynamic-literals\n");
+ return OptInFeatureFlag_NONE;
+ }
+ }
+
+ if (feature_flags == 0 && feature_not_flags == 0) {
+ return OptInFeatureFlag_NONE;
+ }
+ if (feature_flags == 0 && feature_not_flags != 0) {
+ return OptInFeatureFlag_NONE &~ feature_not_flags;
+ }
+ if (feature_flags != 0 && feature_not_flags == 0) {
+ return feature_flags;
+ }
+ GB_ASSERT(feature_flags != 0 && feature_not_flags != 0);
+ return feature_flags &~ feature_not_flags;
+}
+
gb_internal String dir_from_path(String path) {
String base_dir = path;
for (isize i = path.len-1; i >= 0; i--) {
@@ -6399,6 +6462,9 @@ gb_internal bool parse_file_tag(const String &lc, const Token &tok, AstFile *f)
} else if (command == "file") {
f->flags |= AstFile_IsPrivateFile;
}
+ } else if (string_starts_with(lc, str_lit("feature"))) {
+ f->feature_flags |= parse_feature_tag(tok, lc);
+ f->feature_flags_set = true;
} else if (lc == "lazy") {
if (build_context.ignore_lazy) {
// Ignore
@@ -6493,9 +6559,7 @@ gb_internal bool parse_file(Parser *p, AstFile *f) {
}
f->package_name = package_name.string;
- // TODO: Shouldn't single file only matter for build tags? no-instrumentation for example
- // should be respected even when in single file mode.
- if (!f->pkg->is_single_file) {
+ {
if (docs != nullptr && docs->list.count > 0) {
for (Token const &tok : docs->list) {
GB_ASSERT(tok.kind == Token_Comment);
diff --git a/src/parser.hpp b/src/parser.hpp
index e332fed50..bbf70d03e 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -108,7 +108,9 @@ struct AstFile {
String package_name;
u64 vet_flags;
+ u64 feature_flags;
bool vet_flags_set;
+ bool feature_flags_set;
// >= 0: In Expression
// < 0: In Control Clause
diff --git a/tests/core/encoding/cbor/test_core_cbor.odin b/tests/core/encoding/cbor/test_core_cbor.odin
index c614727b9..ee853ebac 100644
--- a/tests/core/encoding/cbor/test_core_cbor.odin
+++ b/tests/core/encoding/cbor/test_core_cbor.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package test_encoding_cbor
import "base:intrinsics"
diff --git a/tests/core/fmt/test_core_fmt.odin b/tests/core/fmt/test_core_fmt.odin
index 3a1eb37e7..c79a15e85 100644
--- a/tests/core/fmt/test_core_fmt.odin
+++ b/tests/core/fmt/test_core_fmt.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package test_core_fmt
import "base:runtime"
diff --git a/tests/core/hash/test_core_hash.odin b/tests/core/hash/test_core_hash.odin
index c3f0bee91..adb55d2d8 100644
--- a/tests/core/hash/test_core_hash.odin
+++ b/tests/core/hash/test_core_hash.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package test_core_hash
import "core:hash/xxhash"
diff --git a/tests/core/hash/test_vectors_xxhash.odin b/tests/core/hash/test_vectors_xxhash.odin
index f72e2699a..04e2d4f1f 100644
--- a/tests/core/hash/test_vectors_xxhash.odin
+++ b/tests/core/hash/test_vectors_xxhash.odin
@@ -1,4 +1,5 @@
// Hash Test Vectors
+#+feature dynamic-literals
package test_core_hash
XXHASH_Test_Vectors :: struct #packed {
diff --git a/tests/core/image/test_core_image.odin b/tests/core/image/test_core_image.odin
index 899596229..8f6091481 100644
--- a/tests/core/image/test_core_image.odin
+++ b/tests/core/image/test_core_image.odin
@@ -7,6 +7,7 @@
A test suite for PNG, TGA, NetPBM, QOI and BMP.
*/
+#+feature dynamic-literals
package test_core_image
import "core:testing"
diff --git a/tests/core/net/test_core_net.odin b/tests/core/net/test_core_net.odin
index bc3ff5c46..0d57bd94a 100644
--- a/tests/core/net/test_core_net.odin
+++ b/tests/core/net/test_core_net.odin
@@ -12,6 +12,7 @@
*/
#+build !netbsd
#+build !openbsd
+#+feature dynamic-literals
package test_core_net
import "core:testing"
diff --git a/tests/core/runtime/test_core_runtime.odin b/tests/core/runtime/test_core_runtime.odin
index 84fd044cf..be6c24c72 100644
--- a/tests/core/runtime/test_core_runtime.odin
+++ b/tests/core/runtime/test_core_runtime.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package test_core_runtime
import "base:intrinsics"
@@ -63,4 +64,101 @@ test_init_cap_map_dynarray :: proc(t: ^testing.T) {
defer delete(d2)
testing.expect(t, cap(d2) == 0)
testing.expect(t, d2.allocator.procedure == ally.procedure)
-} \ No newline at end of file
+}
+
+@(test)
+test_map_get :: proc(t: ^testing.T) {
+ check :: proc(t: ^testing.T, m: map[$K]$V, loc := #caller_location) {
+ for k, v in m {
+ got_key, got_val, ok := runtime.map_get(m, k)
+ testing.expect_value(t, got_key, k, loc = loc)
+ testing.expect_value(t, got_val, v, loc = loc)
+ testing.expect(t, ok, loc = loc)
+ }
+ }
+
+ // small keys & values
+ {
+ m := map[int]int{
+ 1 = 10,
+ 2 = 20,
+ 3 = 30,
+ }
+ defer delete(m)
+ check(t, m)
+ }
+
+ // small keys; 2 values per cell
+ {
+ m := map[int][3]int{
+ 1 = [3]int{10, 100, 1000},
+ 2 = [3]int{20, 200, 2000},
+ 3 = [3]int{30, 300, 3000},
+ }
+ defer delete(m)
+ check(t, m)
+ }
+
+ // 2 keys per cell; small values
+ {
+ m := map[[3]int]int{
+ [3]int{10, 100, 1000} = 1,
+ [3]int{20, 200, 2000} = 2,
+ [3]int{30, 300, 3000} = 3,
+ }
+ defer delete(m)
+ check(t, m)
+ }
+
+
+ // small keys; 3 values per cell
+ {
+ val :: struct #packed {
+ a, b: int,
+ c: i32,
+ }
+ m := map[int]val{
+ 1 = val{10, 100, 1000},
+ 2 = val{20, 200, 2000},
+ 3 = val{30, 300, 3000},
+ }
+ defer delete(m)
+ check(t, m)
+ }
+
+ // 3 keys per cell; small values
+ {
+ key :: struct #packed {
+ a, b: int,
+ c: i32,
+ }
+ m := map[key]int{
+ key{10, 100, 1000} = 1,
+ key{20, 200, 2000} = 2,
+ key{30, 300, 3000} = 3,
+ }
+ defer delete(m)
+ check(t, m)
+ }
+
+ // small keys; value bigger than a chacheline
+ {
+ m := map[int][9]int{
+ 1 = [9]int{10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000},
+ 2 = [9]int{20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000},
+ 3 = [9]int{30, 300, 3000, 30000, 300000, 3000000, 30000000, 300000000, 3000000000},
+ }
+ defer delete(m)
+ check(t, m)
+ }
+ // keys bigger than a chacheline; small values
+ {
+ m := map[[9]int]int{
+ [9]int{10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000} = 1,
+ [9]int{20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000} = 2,
+ [9]int{30, 300, 3000, 30000, 300000, 3000000, 30000000, 300000000, 3000000000} = 3,
+ }
+ defer delete(m)
+ check(t, m)
+ }
+}
diff --git a/tests/core/slice/test_core_slice.odin b/tests/core/slice/test_core_slice.odin
index 9c77f872d..98cb8dbac 100644
--- a/tests/core/slice/test_core_slice.odin
+++ b/tests/core/slice/test_core_slice.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package test_core_slice
import "core:slice"
diff --git a/tests/issues/run.bat b/tests/issues/run.bat
index dcea3d483..7ed43205d 100644
--- a/tests/issues/run.bat
+++ b/tests/issues/run.bat
@@ -16,6 +16,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style
..\..\..\odin test ..\test_issue_2637.odin %COMMON% || exit /b
..\..\..\odin test ..\test_issue_2666.odin %COMMON% || exit /b
..\..\..\odin test ..\test_issue_4210.odin %COMMON% || exit /b
+..\..\..\odin test ..\test_issue_4584.odin %COMMON% || exit /b
@echo off
diff --git a/tests/issues/run.sh b/tests/issues/run.sh
index c3bc00e24..54543980e 100755
--- a/tests/issues/run.sh
+++ b/tests/issues/run.sh
@@ -17,6 +17,7 @@ $ODIN test ../test_issue_2615.odin $COMMON
$ODIN test ../test_issue_2637.odin $COMMON
$ODIN test ../test_issue_2666.odin $COMMON
$ODIN test ../test_issue_4210.odin $COMMON
+$ODIN test ../test_issue_4584.odin $COMMON
if [[ $($ODIN build ../test_issue_2395.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]] ; then
echo "SUCCESSFUL 1/1"
else
diff --git a/tests/issues/test_issue_4584.odin b/tests/issues/test_issue_4584.odin
new file mode 100644
index 000000000..9eea23420
--- /dev/null
+++ b/tests/issues/test_issue_4584.odin
@@ -0,0 +1,198 @@
+// Tests issue #4584 https://github.com/odin-lang/Odin/issues/4584
+package test_issues
+
+import "core:testing"
+import "core:log"
+import "core:math/linalg"
+import glm "core:math/linalg/glsl"
+import hlm "core:math/linalg/hlsl"
+
+@test
+test_adjugate_2x2 :: proc(t: ^testing.T) {
+ I := linalg.identity(matrix[2,2]int)
+ m := matrix[2,2]int {
+ -3, 2,
+ -1, 0,
+ }
+ expected := matrix[2,2]int {
+ 0, -2,
+ 1, -3,
+ }
+ testing.expect_value(t, linalg.adjugate(m), expected)
+ testing.expect_value(t, linalg.determinant(m), 2)
+ testing.expect_value(t, linalg.adjugate(m) * m, 2 * I)
+ testing.expect_value(t, m * linalg.adjugate(m), 2 * I)
+
+ testing.expect_value(t, glm.adjugate(m), expected)
+ testing.expect_value(t, glm.determinant(m), 2)
+ testing.expect_value(t, glm.adjugate(m) * m, 2 * I)
+ testing.expect_value(t, m * glm.adjugate(m), 2 * I)
+
+ testing.expect_value(t, hlm.adjugate(m), expected)
+ testing.expect_value(t, hlm.determinant(m), 2)
+ testing.expect_value(t, hlm.adjugate(m) * m, 2 * I)
+ testing.expect_value(t, m * hlm.adjugate(m), 2 * I)
+}
+
+@test
+test_adjugate_3x3 :: proc(t: ^testing.T) {
+ I := linalg.identity(matrix[3,3]int)
+ m := matrix[3,3]int {
+ -3, 2, -5,
+ -1, 0, -2,
+ 3, -4, 1,
+ }
+ expected := matrix[3,3]int {
+ -8, 18, -4,
+ -5, 12, -1,
+ 4, -6, 2,
+ }
+ testing.expect_value(t, linalg.adjugate(m), expected)
+ testing.expect_value(t, linalg.determinant(m), -6)
+ testing.expect_value(t, linalg.adjugate(m) * m, -6 * I)
+ testing.expect_value(t, m * linalg.adjugate(m), -6 * I)
+
+ testing.expect_value(t, glm.adjugate(m), expected)
+ testing.expect_value(t, glm.determinant(m), -6)
+ testing.expect_value(t, glm.adjugate(m) * m, -6 * I)
+ testing.expect_value(t, m * glm.adjugate(m), -6 * I)
+
+ testing.expect_value(t, hlm.adjugate(m), expected)
+ testing.expect_value(t, hlm.determinant(m), -6)
+ testing.expect_value(t, hlm.adjugate(m) * m, -6 * I)
+ testing.expect_value(t, m * hlm.adjugate(m), -6 * I)
+}
+
+@test
+test_adjugate_4x4 :: proc(t: ^testing.T) {
+ I := linalg.identity(matrix[4,4]int)
+ m := matrix[4,4]int {
+ -3, 2, -5, 1,
+ -1, 0, -2, 2,
+ 3, -4, 1, 3,
+ 4, 5, 6, 7,
+ }
+ expected := matrix[4,4]int {
+ -144, 266, -92, -16,
+ -57, 92, -5, -16,
+ 105, -142, 55, 2,
+ 33, -96, 9, -6,
+ }
+ testing.expect_value(t, linalg.adjugate(m), expected)
+ testing.expect_value(t, linalg.determinant(m), -174)
+ testing.expect_value(t, linalg.adjugate(m) * m, -174 * I)
+ testing.expect_value(t, m * linalg.adjugate(m), -174 * I)
+
+ testing.expect_value(t, glm.adjugate(m), expected)
+ testing.expect_value(t, glm.determinant(m), -174)
+ testing.expect_value(t, glm.adjugate(m) * m, -174 * I)
+ testing.expect_value(t, m * glm.adjugate(m), -174 * I)
+
+ testing.expect_value(t, hlm.adjugate(m), expected)
+ testing.expect_value(t, hlm.determinant(m), -174)
+ testing.expect_value(t, hlm.adjugate(m) * m, -174 * I)
+ testing.expect_value(t, m * hlm.adjugate(m), -174 * I)
+}
+
+@test
+test_inverse_regression_2x2 :: proc(t: ^testing.T) {
+ I := linalg.identity(matrix[2,2]f32)
+ m := matrix[2,2]f32 {
+ -3, 2,
+ -1, 0,
+ }
+ expected := matrix[2,2]f32 {
+ 0.0, -1.0,
+ 1.0/2.0, -3.0/2.0,
+ }
+ expect_float_matrix_value(t, linalg.inverse(m), expected)
+ expect_float_matrix_value(t, linalg.inverse_transpose(m), linalg.transpose(expected))
+ expect_float_matrix_value(t, linalg.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * linalg.inverse(m), I)
+
+ expect_float_matrix_value(t, glm.inverse(m), expected)
+ expect_float_matrix_value(t, glm.inverse_transpose(m), glm.transpose(expected))
+ expect_float_matrix_value(t, glm.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * glm.inverse(m), I)
+
+ expect_float_matrix_value(t, hlm.inverse(m), expected)
+ expect_float_matrix_value(t, hlm.inverse_transpose(m), hlm.transpose(expected))
+ expect_float_matrix_value(t, hlm.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * hlm.inverse(m), I)
+}
+
+@test
+test_inverse_regression_3x3 :: proc(t: ^testing.T) {
+ I := linalg.identity(matrix[3,3]f32)
+ m := matrix[3,3]f32 {
+ -3, 2, -5,
+ -1, 0, -2,
+ 3, -4, 1,
+ }
+ expected := matrix[3,3]f32 {
+ 4.0/3.0, -3.0, 2.0/3.0,
+ 5.0/6.0, -2.0, 1.0/6.0,
+ -2.0/3.0, 1.0, -1.0/3.0,
+ }
+ expect_float_matrix_value(t, linalg.inverse(m), expected)
+ expect_float_matrix_value(t, linalg.inverse_transpose(m), linalg.transpose(expected))
+ expect_float_matrix_value(t, linalg.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * linalg.inverse(m), I)
+
+ expect_float_matrix_value(t, glm.inverse(m), expected)
+ expect_float_matrix_value(t, glm.inverse_transpose(m), glm.transpose(expected))
+ expect_float_matrix_value(t, glm.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * glm.inverse(m), I)
+
+ expect_float_matrix_value(t, hlm.inverse(m), expected)
+ expect_float_matrix_value(t, hlm.inverse_transpose(m), hlm.transpose(expected))
+ expect_float_matrix_value(t, hlm.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * hlm.inverse(m), I)
+}
+
+@test
+test_inverse_regression_4x4 :: proc(t: ^testing.T) {
+ I := linalg.identity(matrix[4,4]f32)
+ m := matrix[4,4]f32 {
+ -3, 2, -5, 1,
+ -1, 0, -2, 2,
+ 3, -4, 1, 3,
+ 4, 5, 6, 7,
+ }
+ expected := matrix[4,4]f32 {
+ 24.0/29.0, -133.0/87.0, 46.0/87.0, 8.0/87.0,
+ 19.0/58.0, -46.0/87.0, 5.0/174.0, 8.0/87.0,
+ -35.0/58.0, 71.0/87.0, -55.0/174.0, -1.0/87.0,
+ -11.0/58.0, 16.0/29.0, -3.0/58.0, 1.0/29.0,
+ }
+ expect_float_matrix_value(t, linalg.inverse(m), expected)
+ expect_float_matrix_value(t, linalg.inverse_transpose(m), linalg.transpose(expected))
+ expect_float_matrix_value(t, linalg.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * linalg.inverse(m), I)
+
+ expect_float_matrix_value(t, glm.inverse(m), expected)
+ expect_float_matrix_value(t, glm.inverse_transpose(m), glm.transpose(expected))
+ expect_float_matrix_value(t, glm.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * glm.inverse(m), I)
+
+ expect_float_matrix_value(t, hlm.inverse(m), expected)
+ expect_float_matrix_value(t, hlm.inverse_transpose(m), hlm.transpose(expected))
+ expect_float_matrix_value(t, hlm.inverse(m) * m, I)
+ expect_float_matrix_value(t, m * hlm.inverse(m), I)
+}
+
+@(private="file")
+expect_float_matrix_value :: proc(t: ^testing.T, value, expected: $M/matrix[$N, N]f32, loc := #caller_location, value_expr := #caller_expression(value)) -> bool {
+ ok := true
+ outer: for i in 0..<N {
+ for j in 0..<N {
+ diff := abs(value[i, j] - expected[i, j])
+ if diff > 1e-6 {
+ ok = false
+ break outer
+ }
+ }
+ }
+ if !ok do log.errorf("expected %v to be %v, got %v", value_expr, expected, value, location=loc)
+ return ok
+} \ No newline at end of file
diff --git a/tests/issues/test_issue_829.odin b/tests/issues/test_issue_829.odin
index 229d8e9b4..3287c49fe 100644
--- a/tests/issues/test_issue_829.odin
+++ b/tests/issues/test_issue_829.odin
@@ -1,4 +1,5 @@
// Tests issue #829 https://github.com/odin-lang/Odin/issues/829
+#+feature dynamic-literals
package test_issues
import "core:testing"
diff --git a/vendor/box2d/box2d.odin b/vendor/box2d/box2d.odin
index e7da34a45..8abf6ce03 100644
--- a/vendor/box2d/box2d.odin
+++ b/vendor/box2d/box2d.odin
@@ -24,19 +24,11 @@ when ODIN_OS == .Windows {
}
when !#exists(LIB_PATH) {
- #panic("Could not find the compiled box2d libraries at \"" + LIB_PATH + "\", they can be compiled by running the `build.sh` script at `" + ODIN_ROOT + "vendor/box2d/build_box2d.sh\"`")
+ #panic("Could not find the compiled box2d libraries at \"" + LIB_PATH + "\", they can be compiled by running the `build_box2d.sh` script at `" + ODIN_ROOT + "vendor/box2d/build_box2d.sh\"`")
}
-when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
- when VECTOR_EXT == "_simd" {
- foreign import lib "lib/box2d_wasm_simd.o"
- } else {
- foreign import lib "lib/box2d_wasm.o"
- }
-} else {
- foreign import lib {
- LIB_PATH,
- }
+foreign import lib {
+ LIB_PATH,
}
diff --git a/vendor/box2d/build_box2d.sh b/vendor/box2d/build_box2d.sh
index 0c5ff999d..74d75eb57 100755
--- a/vendor/box2d/build_box2d.sh
+++ b/vendor/box2d/build_box2d.sh
@@ -68,7 +68,12 @@ esac
cd ..
+set +e
make -f wasm.Makefile
+if [[ $? -ne 0 ]]; then
+ printf "\e[30;43mwarning:\e[0m Native Box2D libraries were built successfully, the WASM build failed, likely because your default C compiler and/or linker doesn't support WASM, you can set the CC and LD environment variables to point to a compiler and linker that support it\n"
+fi
+set -e
rm -rf v3.0.0.tar.gz
rm -rf box2d-3.0.0
diff --git a/vendor/box2d/wasm.Makefile b/vendor/box2d/wasm.Makefile
index 929b61aea..e8ecb485e 100644
--- a/vendor/box2d/wasm.Makefile
+++ b/vendor/box2d/wasm.Makefile
@@ -2,6 +2,8 @@
# I tried to make a cmake toolchain file for this / use cmake but this is far easier.
# NOTE: We are pretending to be emscripten to box2d so it takes WASM code paths, but we don't actually use emscripten.
+# WARN: wasm is probably not supported by your default C compiler and linker, overwrite the CC and LD environment variables accordingly.
+# Example for MacOS:
# CC = $(shell brew --prefix llvm)/bin/clang
# LD = $(shell brew --prefix llvm)/bin/wasm-ld
@@ -10,7 +12,7 @@ SRCS = $(wildcard box2d-$(VERSION)/src/*.c)
OBJS_SIMD = $(SRCS:.c=_simd.o)
OBJS = $(SRCS:.c=.o)
SYSROOT = $(shell odin root)/vendor/libc
-CFLAGS = -Ibox2d-$(VERSION)/include -Ibox2d-$(VERSION)/Extern/simde --target=wasm32 -D__EMSCRIPTEN__ -DNDEBUG -O3 --sysroot=$(SYSROOT)
+CFLAGS = -Ibox2d-$(VERSION)/include -Ibox2d-$(VERSION)/extern/simde --target=wasm32 -D__EMSCRIPTEN__ -DNDEBUG -O3 --sysroot=$(SYSROOT)
all: lib/box2d_wasm.o lib/box2d_wasm_simd.o clean
diff --git a/vendor/cgltf/cgltf.odin b/vendor/cgltf/cgltf.odin
index a24c36d64..e9dc7ef84 100644
--- a/vendor/cgltf/cgltf.odin
+++ b/vendor/cgltf/cgltf.odin
@@ -105,6 +105,7 @@ type :: enum c.int {
}
primitive_type :: enum c.int {
+ invalid,
points,
lines,
line_loop,
@@ -222,15 +223,6 @@ accessor_sparse :: struct {
indices_component_type: component_type,
values_buffer_view: ^buffer_view,
values_byte_offset: uint,
- extras: extras_t,
- indices_extras: extras_t,
- values_extras: extras_t,
- extensions_count: uint,
- extensions: [^]extension `fmt:"v,extensions_count"`,
- indices_extensions_count: uint,
- indices_extensions: [^]extension `fmt:"v,indices_extensions_count"`,
- values_extensions_count: uint,
- values_extensions: [^]extension `fmt:"v,values_extensions_count"`,
}
accessor :: struct {
@@ -306,9 +298,6 @@ texture_view :: struct {
scale: f32, /* equivalent to strength for occlusion_texture */
has_transform: b32,
transform: texture_transform,
- extras: extras_t,
- extensions_count: uint,
- extensions: [^]extension `fmt:"v,extensions_count"`,
}
pbr_metallic_roughness :: struct {
@@ -381,6 +370,16 @@ iridescence :: struct {
iridescence_thickness_texture: texture_view,
}
+anisotropy :: struct {
+ anisotropy_strength: f32,
+ anisotropy_rotation: f32,
+ anisotropy_texture: texture_view,
+}
+
+dispersion :: struct {
+ dispersion: f32,
+}
+
material :: struct {
name: cstring,
has_pbr_metallic_roughness: b32,
@@ -393,6 +392,8 @@ material :: struct {
has_sheen: b32,
has_emissive_strength: b32,
has_iridescence: b32,
+ has_anisotropy: b32,
+ has_dispersion: b32,
pbr_metallic_roughness: pbr_metallic_roughness,
pbr_specular_glossiness: pbr_specular_glossiness,
clearcoat: clearcoat,
@@ -403,6 +404,8 @@ material :: struct {
volume: volume,
emissive_strength: emissive_strength,
iridescence: iridescence,
+ anisotropy: anisotropy,
+ dispersion: dispersion,
normal_texture: texture_view,
occlusion_texture: texture_view,
emissive_texture: texture_view,
@@ -432,7 +435,6 @@ draco_mesh_compression :: struct {
}
mesh_gpu_instancing :: struct {
- buffer_view: ^buffer_view,
attributes: []attribute,
}
@@ -684,6 +686,9 @@ foreign lib {
node_transform_world :: proc(node: ^node, out_matrix: [^]f32) ---
@(require_results)
+ buffer_view_data :: proc(view: ^/*const*/buffer_view) -> [^]byte ---
+
+ @(require_results)
accessor_read_float :: proc(accessor: ^/*const*/accessor, index: uint, out: [^]f32, element_size: uint) -> b32 ---
@(require_results)
accessor_read_uint :: proc(accessor: ^/*const*/accessor, index: uint, out: [^]c.uint, element_size: uint) -> b32 ---
@@ -694,13 +699,53 @@ foreign lib {
num_components :: proc(type: type) -> uint ---
@(require_results)
+ component_size :: proc(component_type: component_type) -> uint ---
+ @(require_results)
+ calc_size :: proc(type: type, component_type: component_type) -> uint ---
+
+ @(require_results)
accessor_unpack_floats :: proc(accessor: ^/*const*/accessor, out: [^]f32, float_count: uint) -> uint ---
+ @(require_results)
+ accessor_unpack_indices :: proc(accessor: ^/*const*/accessor , out: rawptr, out_component_size: uint, index_count: uint) -> uint ---
/* this function is deprecated and will be removed in the future; use cgltf_extras::data instead */
@(require_results)
copy_extras_json :: proc(data: ^data, extras: ^extras_t, dest: [^]byte, dest_size: ^uint) -> result ---
@(require_results)
+ mesh_index :: proc(data: ^/*const*/data, object: ^/*const*/mesh) -> uint ---
+ @(require_results)
+ material_index :: proc(data: ^/*const*/data, object: ^/*const*/material) -> uint ---
+ @(require_results)
+ accessor_index :: proc(data: ^/*const*/data, object: ^/*const*/accessor) -> uint ---
+ @(require_results)
+ buffer_view_index :: proc(data: ^/*const*/data, object: ^/*const*/buffer_view) -> uint ---
+ @(require_results)
+ buffer_index :: proc(data: ^/*const*/data, object: ^/*const*/buffer) -> uint ---
+ @(require_results)
+ image_index :: proc(data: ^/*const*/data, object: ^/*const*/image) -> uint ---
+ @(require_results)
+ texture_index :: proc(data: ^/*const*/data, object: ^/*const*/texture) -> uint ---
+ @(require_results)
+ sampler_index :: proc(data: ^/*const*/data, object: ^/*const*/sampler) -> uint ---
+ @(require_results)
+ skin_index :: proc(data: ^/*const*/data, object: ^/*const*/skin) -> uint ---
+ @(require_results)
+ camera_index :: proc(data: ^/*const*/data, object: ^/*const*/camera) -> uint ---
+ @(require_results)
+ light_index :: proc(data: ^/*const*/data, object: ^/*const*/light) -> uint ---
+ @(require_results)
+ node_index :: proc(data: ^/*const*/data, object: ^/*const*/node) -> uint ---
+ @(require_results)
+ scene_index :: proc(data: ^/*const*/data, object: ^/*const*/scene) -> uint ---
+ @(require_results)
+ animation_index :: proc(data: ^/*const*/data, object: ^/*const*/animation) -> uint ---
+ @(require_results)
+ animation_sampler_index :: proc(animation: ^/*const*/animation, object: ^/*const*/animation_sampler) -> uint ---
+ @(require_results)
+ animation_channel_index :: proc(animation: ^/*const*/animation, object: ^/*const*/animation_channel) -> uint ---
+
+ @(require_results)
write_file :: proc(#by_ptr options: options, path: cstring, data: ^data) -> result ---
@(require_results)
write :: proc(#by_ptr options: options, buffer: [^]byte, size: uint, data: ^data) -> uint ---
diff --git a/vendor/cgltf/lib/cgltf.lib b/vendor/cgltf/lib/cgltf.lib
index 0d7ea6f9b..b14f79142 100644
--- a/vendor/cgltf/lib/cgltf.lib
+++ b/vendor/cgltf/lib/cgltf.lib
Binary files differ
diff --git a/vendor/cgltf/lib/cgltf_wasm.o b/vendor/cgltf/lib/cgltf_wasm.o
index 54346d176..077d480a8 100644
--- a/vendor/cgltf/lib/cgltf_wasm.o
+++ b/vendor/cgltf/lib/cgltf_wasm.o
Binary files differ
diff --git a/vendor/cgltf/src/cgltf.h b/vendor/cgltf/src/cgltf.h
index a534cefb4..17dc0ca5d 100644
--- a/vendor/cgltf/src/cgltf.h
+++ b/vendor/cgltf/src/cgltf.h
@@ -1,7 +1,7 @@
/**
* cgltf - a single-file glTF 2.0 parser written in C99.
*
- * Version: 1.13
+ * Version: 1.14
*
* Website: https://github.com/jkuhlmann/cgltf
*
@@ -63,9 +63,15 @@
* By passing null for the output pointer, users can find out how many floats are required in the
* output buffer.
*
+ * `cgltf_accessor_unpack_indices` reads in the index data from an accessor. Assumes that
+ * `cgltf_load_buffers` has already been called. By passing null for the output pointer, users can
+ * find out how many indices are required in the output buffer. Returns 0 if the accessor is
+ * sparse or if the output component size is less than the accessor's component size.
+ *
* `cgltf_num_components` is a tiny utility that tells you the dimensionality of
* a certain accessor type. This can be used before `cgltf_accessor_unpack_floats` to help allocate
- * the necessary amount of memory.
+ * the necessary amount of memory. `cgltf_component_size` and `cgltf_calc_size` exist for
+ * similar purposes.
*
* `cgltf_accessor_read_float` reads a certain element from a non-sparse accessor and converts it to
* floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element
@@ -74,7 +80,7 @@
*
* `cgltf_accessor_read_uint` is similar to its floating-point counterpart, but limited to reading
* vector types and does not support matrix types. The passed-in element size is the number of uints
- * in the output buffer, which should be in the range [1, 4]. Returns false if the passed-in
+ * in the output buffer, which should be in the range [1, 4]. Returns false if the passed-in
* element_size is too small, or if the accessor is sparse.
*
* `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t
@@ -89,6 +95,7 @@
#define CGLTF_H_INCLUDED__
#include <stddef.h>
+#include <stdint.h> /* For uint8_t, uint32_t */
#ifdef __cplusplus
extern "C" {
@@ -195,6 +202,7 @@ typedef enum cgltf_type
typedef enum cgltf_primitive_type
{
+ cgltf_primitive_type_invalid,
cgltf_primitive_type_points,
cgltf_primitive_type_lines,
cgltf_primitive_type_line_loop,
@@ -326,15 +334,6 @@ typedef struct cgltf_accessor_sparse
cgltf_component_type indices_component_type;
cgltf_buffer_view* values_buffer_view;
cgltf_size values_byte_offset;
- cgltf_extras extras;
- cgltf_extras indices_extras;
- cgltf_extras values_extras;
- cgltf_size extensions_count;
- cgltf_extension* extensions;
- cgltf_size indices_extensions_count;
- cgltf_extension* indices_extensions;
- cgltf_size values_extensions_count;
- cgltf_extension* values_extensions;
} cgltf_accessor_sparse;
typedef struct cgltf_accessor
@@ -417,9 +416,6 @@ typedef struct cgltf_texture_view
cgltf_float scale; /* equivalent to strength for occlusion_texture */
cgltf_bool has_transform;
cgltf_texture_transform transform;
- cgltf_extras extras;
- cgltf_size extensions_count;
- cgltf_extension* extensions;
} cgltf_texture_view;
typedef struct cgltf_pbr_metallic_roughness
@@ -502,6 +498,18 @@ typedef struct cgltf_iridescence
cgltf_texture_view iridescence_thickness_texture;
} cgltf_iridescence;
+typedef struct cgltf_anisotropy
+{
+ cgltf_float anisotropy_strength;
+ cgltf_float anisotropy_rotation;
+ cgltf_texture_view anisotropy_texture;
+} cgltf_anisotropy;
+
+typedef struct cgltf_dispersion
+{
+ cgltf_float dispersion;
+} cgltf_dispersion;
+
typedef struct cgltf_material
{
char* name;
@@ -515,6 +523,8 @@ typedef struct cgltf_material
cgltf_bool has_sheen;
cgltf_bool has_emissive_strength;
cgltf_bool has_iridescence;
+ cgltf_bool has_anisotropy;
+ cgltf_bool has_dispersion;
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
cgltf_pbr_specular_glossiness pbr_specular_glossiness;
cgltf_clearcoat clearcoat;
@@ -525,6 +535,8 @@ typedef struct cgltf_material
cgltf_volume volume;
cgltf_emissive_strength emissive_strength;
cgltf_iridescence iridescence;
+ cgltf_anisotropy anisotropy;
+ cgltf_dispersion dispersion;
cgltf_texture_view normal_texture;
cgltf_texture_view occlusion_texture;
cgltf_texture_view emissive_texture;
@@ -557,7 +569,6 @@ typedef struct cgltf_draco_mesh_compression {
} cgltf_draco_mesh_compression;
typedef struct cgltf_mesh_gpu_instancing {
- cgltf_buffer_view* buffer_view;
cgltf_attribute* attributes;
cgltf_size attributes_count;
} cgltf_mesh_gpu_instancing;
@@ -829,17 +840,39 @@ void cgltf_free(cgltf_data* data);
void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix);
void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix);
+const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
+
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
cgltf_size cgltf_num_components(cgltf_type type);
+cgltf_size cgltf_component_size(cgltf_component_type component_type);
+cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
+cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* out, cgltf_size out_component_size, cgltf_size index_count);
/* this function is deprecated and will be removed in the future; use cgltf_extras::data instead */
cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size);
+cgltf_size cgltf_mesh_index(const cgltf_data* data, const cgltf_mesh* object);
+cgltf_size cgltf_material_index(const cgltf_data* data, const cgltf_material* object);
+cgltf_size cgltf_accessor_index(const cgltf_data* data, const cgltf_accessor* object);
+cgltf_size cgltf_buffer_view_index(const cgltf_data* data, const cgltf_buffer_view* object);
+cgltf_size cgltf_buffer_index(const cgltf_data* data, const cgltf_buffer* object);
+cgltf_size cgltf_image_index(const cgltf_data* data, const cgltf_image* object);
+cgltf_size cgltf_texture_index(const cgltf_data* data, const cgltf_texture* object);
+cgltf_size cgltf_sampler_index(const cgltf_data* data, const cgltf_sampler* object);
+cgltf_size cgltf_skin_index(const cgltf_data* data, const cgltf_skin* object);
+cgltf_size cgltf_camera_index(const cgltf_data* data, const cgltf_camera* object);
+cgltf_size cgltf_light_index(const cgltf_data* data, const cgltf_light* object);
+cgltf_size cgltf_node_index(const cgltf_data* data, const cgltf_node* object);
+cgltf_size cgltf_scene_index(const cgltf_data* data, const cgltf_scene* object);
+cgltf_size cgltf_animation_index(const cgltf_data* data, const cgltf_animation* object);
+cgltf_size cgltf_animation_sampler_index(const cgltf_animation* animation, const cgltf_animation_sampler* object);
+cgltf_size cgltf_animation_channel_index(const cgltf_animation* animation, const cgltf_animation_channel* object);
+
#ifdef __cplusplus
}
#endif
@@ -860,7 +893,7 @@ cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras*
#ifdef CGLTF_IMPLEMENTATION
-#include <stdint.h> /* For uint8_t, uint32_t */
+#include <assert.h> /* For assert */
#include <string.h> /* For strncpy */
#include <stdio.h> /* For fopen */
#include <limits.h> /* For UINT_MAX etc */
@@ -870,10 +903,6 @@ cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras*
#include <stdlib.h> /* For malloc, free, atoi, atof */
#endif
-#if CGLTF_VALIDATE_ENABLE_ASSERTS
-#include <assert.h>
-#endif
-
/* JSMN_PARENT_LINKS is necessary to make parsing large structures linear in input size */
#define JSMN_PARENT_LINKS
@@ -902,15 +931,15 @@ enum jsmnerr {
};
typedef struct {
jsmntype_t type;
- int start;
- int end;
+ ptrdiff_t start;
+ ptrdiff_t end;
int size;
#ifdef JSMN_PARENT_LINKS
int parent;
#endif
} jsmntok_t;
typedef struct {
- unsigned int pos; /* offset in the JSON string */
+ size_t pos; /* offset in the JSON string */
unsigned int toknext; /* next token to allocate */
int toksuper; /* superior token node, e.g parent object or array */
} jsmn_parser;
@@ -922,8 +951,8 @@ static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t
#ifndef CGLTF_CONSTS
-static const cgltf_size GlbHeaderSize = 12;
-static const cgltf_size GlbChunkHeaderSize = 8;
+#define GlbHeaderSize 12
+#define GlbChunkHeaderSize 8
static const uint32_t GlbVersion = 2;
static const uint32_t GlbMagic = 0x46546C67;
static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
@@ -995,7 +1024,7 @@ static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* m
{
fseek(file, 0, SEEK_END);
-#ifdef _WIN32
+#ifdef _MSC_VER
__int64 length = _ftelli64(file);
#else
long length = ftell(file);
@@ -1017,7 +1046,7 @@ static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* m
fclose(file);
return cgltf_result_out_of_memory;
}
-
+
cgltf_size read_size = fread(file_data, 1, file_size, file);
fclose(file);
@@ -1125,7 +1154,7 @@ cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_s
// JSON chunk: length
uint32_t json_length;
memcpy(&json_length, json_chunk, 4);
- if (GlbHeaderSize + GlbChunkHeaderSize + json_length > size)
+ if (json_length > size - GlbHeaderSize - GlbChunkHeaderSize)
{
return cgltf_result_data_too_short;
}
@@ -1139,10 +1168,10 @@ cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_s
json_chunk += GlbChunkHeaderSize;
- const void* bin = 0;
+ const void* bin = NULL;
cgltf_size bin_size = 0;
- if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize <= size)
+ if (GlbChunkHeaderSize <= size - GlbHeaderSize - GlbChunkHeaderSize - json_length)
{
// We can read another chunk
const uint8_t* bin_chunk = json_chunk + json_length;
@@ -1150,7 +1179,7 @@ cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_s
// Bin chunk: length
uint32_t bin_length;
memcpy(&bin_length, bin_chunk, 4);
- if (GlbHeaderSize + GlbChunkHeaderSize + json_length + GlbChunkHeaderSize + bin_length > size)
+ if (bin_length > size - GlbHeaderSize - GlbChunkHeaderSize - json_length - GlbChunkHeaderSize)
{
return cgltf_result_data_too_short;
}
@@ -1486,8 +1515,6 @@ cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data,
return cgltf_result_success;
}
-static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
-
static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
{
char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset;
@@ -1538,6 +1565,9 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
cgltf_accessor* accessor = &data->accessors[i];
+ CGLTF_ASSERT_IF(data->accessors[i].component_type == cgltf_component_type_invalid, cgltf_result_invalid_gltf);
+ CGLTF_ASSERT_IF(data->accessors[i].type == cgltf_type_invalid, cgltf_result_invalid_gltf);
+
cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type);
if (accessor->buffer_view)
@@ -1551,7 +1581,7 @@ cgltf_result cgltf_validate(cgltf_data* data)
{
cgltf_accessor_sparse* sparse = &accessor->sparse;
- cgltf_size indices_component_size = cgltf_calc_size(cgltf_type_scalar, sparse->indices_component_type);
+ cgltf_size indices_component_size = cgltf_component_size(sparse->indices_component_type);
cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
@@ -1617,43 +1647,48 @@ cgltf_result cgltf_validate(cgltf_data* data)
for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
{
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].type == cgltf_primitive_type_invalid, cgltf_result_invalid_gltf);
CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf);
- if (data->meshes[i].primitives[j].attributes_count)
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes_count == 0, cgltf_result_invalid_gltf);
+
+ cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data;
+
+ CGLTF_ASSERT_IF(first->count == 0, cgltf_result_invalid_gltf);
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
{
- cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data;
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
+ }
- for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
+ {
+ for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
{
- CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
}
+ }
- for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
- {
- for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
- {
- CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
- }
- }
+ cgltf_accessor* indices = data->meshes[i].primitives[j].indices;
- cgltf_accessor* indices = data->meshes[i].primitives[j].indices;
+ CGLTF_ASSERT_IF(indices &&
+ indices->component_type != cgltf_component_type_r_8u &&
+ indices->component_type != cgltf_component_type_r_16u &&
+ indices->component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
- CGLTF_ASSERT_IF(indices &&
- indices->component_type != cgltf_component_type_r_8u &&
- indices->component_type != cgltf_component_type_r_16u &&
- indices->component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
+ CGLTF_ASSERT_IF(indices && indices->type != cgltf_type_scalar, cgltf_result_invalid_gltf);
+ CGLTF_ASSERT_IF(indices && indices->stride != cgltf_component_size(indices->component_type), cgltf_result_invalid_gltf);
- if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
- {
- cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
+ if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
+ {
+ cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
- CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
- }
+ CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
+ }
- for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
- {
- CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
- }
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
+ {
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
}
}
}
@@ -1710,10 +1745,15 @@ cgltf_result cgltf_validate(cgltf_data* data)
cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1;
- CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_data_too_short);
+ CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_invalid_gltf);
}
}
+ for (cgltf_size i = 0; i < data->variants_count; ++i)
+ {
+ CGLTF_ASSERT_IF(!data->variants[i].name, cgltf_result_invalid_gltf);
+ }
+
return cgltf_result_success;
}
@@ -1760,12 +1800,6 @@ static void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions,
data->memory.free_func(data->memory.user_data, extensions);
}
-static void cgltf_free_texture_view(cgltf_data* data, cgltf_texture_view* view)
-{
- cgltf_free_extensions(data, view->extensions, view->extensions_count);
- cgltf_free_extras(data, &view->extras);
-}
-
void cgltf_free(cgltf_data* data)
{
if (!data)
@@ -1787,15 +1821,6 @@ void cgltf_free(cgltf_data* data)
{
data->memory.free_func(data->memory.user_data, data->accessors[i].name);
- if(data->accessors[i].is_sparse)
- {
- cgltf_free_extensions(data, data->accessors[i].sparse.extensions, data->accessors[i].sparse.extensions_count);
- cgltf_free_extensions(data, data->accessors[i].sparse.indices_extensions, data->accessors[i].sparse.indices_extensions_count);
- cgltf_free_extensions(data, data->accessors[i].sparse.values_extensions, data->accessors[i].sparse.values_extensions_count);
- cgltf_free_extras(data, &data->accessors[i].sparse.extras);
- cgltf_free_extras(data, &data->accessors[i].sparse.indices_extras);
- cgltf_free_extras(data, &data->accessors[i].sparse.values_extras);
- }
cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
cgltf_free_extras(data, &data->accessors[i].extras);
}
@@ -1897,57 +1922,13 @@ void cgltf_free(cgltf_data* data)
{
data->memory.free_func(data->memory.user_data, data->materials[i].name);
- if(data->materials[i].has_pbr_metallic_roughness)
- {
- cgltf_free_texture_view(data, &data->materials[i].pbr_metallic_roughness.metallic_roughness_texture);
- cgltf_free_texture_view(data, &data->materials[i].pbr_metallic_roughness.base_color_texture);
- }
- if(data->materials[i].has_pbr_specular_glossiness)
- {
- cgltf_free_texture_view(data, &data->materials[i].pbr_specular_glossiness.diffuse_texture);
- cgltf_free_texture_view(data, &data->materials[i].pbr_specular_glossiness.specular_glossiness_texture);
- }
- if(data->materials[i].has_clearcoat)
- {
- cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_texture);
- cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_roughness_texture);
- cgltf_free_texture_view(data, &data->materials[i].clearcoat.clearcoat_normal_texture);
- }
- if(data->materials[i].has_specular)
- {
- cgltf_free_texture_view(data, &data->materials[i].specular.specular_texture);
- cgltf_free_texture_view(data, &data->materials[i].specular.specular_color_texture);
- }
- if(data->materials[i].has_transmission)
- {
- cgltf_free_texture_view(data, &data->materials[i].transmission.transmission_texture);
- }
- if (data->materials[i].has_volume)
- {
- cgltf_free_texture_view(data, &data->materials[i].volume.thickness_texture);
- }
- if(data->materials[i].has_sheen)
- {
- cgltf_free_texture_view(data, &data->materials[i].sheen.sheen_color_texture);
- cgltf_free_texture_view(data, &data->materials[i].sheen.sheen_roughness_texture);
- }
- if(data->materials[i].has_iridescence)
- {
- cgltf_free_texture_view(data, &data->materials[i].iridescence.iridescence_texture);
- cgltf_free_texture_view(data, &data->materials[i].iridescence.iridescence_thickness_texture);
- }
-
- cgltf_free_texture_view(data, &data->materials[i].normal_texture);
- cgltf_free_texture_view(data, &data->materials[i].occlusion_texture);
- cgltf_free_texture_view(data, &data->materials[i].emissive_texture);
-
cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
cgltf_free_extras(data, &data->materials[i].extras);
}
data->memory.free_func(data->memory.user_data, data->materials);
- for (cgltf_size i = 0; i < data->images_count; ++i)
+ for (cgltf_size i = 0; i < data->images_count; ++i)
{
data->memory.free_func(data->memory.user_data, data->images[i].name);
data->memory.free_func(data->memory.user_data, data->images[i].uri);
@@ -2195,8 +2176,6 @@ static cgltf_ssize cgltf_component_read_integer(const void* in, cgltf_component_
return *((const uint16_t*) in);
case cgltf_component_type_r_32u:
return *((const uint32_t*) in);
- case cgltf_component_type_r_32f:
- return (cgltf_ssize)*((const float*) in);
case cgltf_component_type_r_8:
return *((const int8_t*) in);
case cgltf_component_type_r_8u:
@@ -2214,8 +2193,6 @@ static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_typ
return *((const uint16_t*) in);
case cgltf_component_type_r_32u:
return *((const uint32_t*) in);
- case cgltf_component_type_r_32f:
- return (cgltf_size)*((const float*) in);
case cgltf_component_type_r_8u:
return *((const uint8_t*) in);
default:
@@ -2251,8 +2228,6 @@ static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_ty
return (cgltf_float)cgltf_component_read_integer(in, component_type);
}
-static cgltf_size cgltf_component_size(cgltf_component_type component_type);
-
static cgltf_bool cgltf_element_read_float(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_bool normalized, cgltf_float* out, cgltf_size element_size)
{
cgltf_size num_components = cgltf_num_components(type);
@@ -2355,21 +2330,41 @@ cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_fl
cgltf_size element_count = float_count / floats_per_element;
// First pass: convert each element in the base accessor.
- cgltf_float* dest = out;
- cgltf_accessor dense = *accessor;
- dense.is_sparse = 0;
- for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element)
+ if (accessor->buffer_view == NULL)
{
- if (!cgltf_accessor_read_float(&dense, index, dest, floats_per_element))
+ memset(out, 0, element_count * floats_per_element * sizeof(cgltf_float));
+ }
+ else
+ {
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
{
return 0;
}
+ element += accessor->offset;
+
+ if (accessor->component_type == cgltf_component_type_r_32f && accessor->stride == floats_per_element * sizeof(cgltf_float))
+ {
+ memcpy(out, element, element_count * floats_per_element * sizeof(cgltf_float));
+ }
+ else
+ {
+ cgltf_float* dest = out;
+
+ for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element, element += accessor->stride)
+ {
+ if (!cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, dest, floats_per_element))
+ {
+ return 0;
+ }
+ }
+ }
}
// Second pass: write out each element in the sparse accessor.
if (accessor->is_sparse)
{
- const cgltf_accessor_sparse* sparse = &dense.sparse;
+ const cgltf_accessor_sparse* sparse = &accessor->sparse;
const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view);
@@ -2383,17 +2378,15 @@ cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_fl
reader_head += sparse->values_byte_offset;
cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
- for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride)
+ for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride, reader_head += accessor->stride)
{
size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
float* writer_head = out + writer_index * floats_per_element;
- if (!cgltf_element_read_float(reader_head, dense.type, dense.component_type, dense.normalized, writer_head, floats_per_element))
+ if (!cgltf_element_read_float(reader_head, accessor->type, accessor->component_type, accessor->normalized, writer_head, floats_per_element))
{
return 0;
}
-
- reader_head += dense.stride;
}
}
@@ -2487,12 +2480,165 @@ cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size
return cgltf_component_read_index(element, accessor->component_type);
}
+cgltf_size cgltf_mesh_index(const cgltf_data* data, const cgltf_mesh* object)
+{
+ assert(object && (cgltf_size)(object - data->meshes) < data->meshes_count);
+ return (cgltf_size)(object - data->meshes);
+}
+
+cgltf_size cgltf_material_index(const cgltf_data* data, const cgltf_material* object)
+{
+ assert(object && (cgltf_size)(object - data->materials) < data->materials_count);
+ return (cgltf_size)(object - data->materials);
+}
+
+cgltf_size cgltf_accessor_index(const cgltf_data* data, const cgltf_accessor* object)
+{
+ assert(object && (cgltf_size)(object - data->accessors) < data->accessors_count);
+ return (cgltf_size)(object - data->accessors);
+}
+
+cgltf_size cgltf_buffer_view_index(const cgltf_data* data, const cgltf_buffer_view* object)
+{
+ assert(object && (cgltf_size)(object - data->buffer_views) < data->buffer_views_count);
+ return (cgltf_size)(object - data->buffer_views);
+}
+
+cgltf_size cgltf_buffer_index(const cgltf_data* data, const cgltf_buffer* object)
+{
+ assert(object && (cgltf_size)(object - data->buffers) < data->buffers_count);
+ return (cgltf_size)(object - data->buffers);
+}
+
+cgltf_size cgltf_image_index(const cgltf_data* data, const cgltf_image* object)
+{
+ assert(object && (cgltf_size)(object - data->images) < data->images_count);
+ return (cgltf_size)(object - data->images);
+}
+
+cgltf_size cgltf_texture_index(const cgltf_data* data, const cgltf_texture* object)
+{
+ assert(object && (cgltf_size)(object - data->textures) < data->textures_count);
+ return (cgltf_size)(object - data->textures);
+}
+
+cgltf_size cgltf_sampler_index(const cgltf_data* data, const cgltf_sampler* object)
+{
+ assert(object && (cgltf_size)(object - data->samplers) < data->samplers_count);
+ return (cgltf_size)(object - data->samplers);
+}
+
+cgltf_size cgltf_skin_index(const cgltf_data* data, const cgltf_skin* object)
+{
+ assert(object && (cgltf_size)(object - data->skins) < data->skins_count);
+ return (cgltf_size)(object - data->skins);
+}
+
+cgltf_size cgltf_camera_index(const cgltf_data* data, const cgltf_camera* object)
+{
+ assert(object && (cgltf_size)(object - data->cameras) < data->cameras_count);
+ return (cgltf_size)(object - data->cameras);
+}
+
+cgltf_size cgltf_light_index(const cgltf_data* data, const cgltf_light* object)
+{
+ assert(object && (cgltf_size)(object - data->lights) < data->lights_count);
+ return (cgltf_size)(object - data->lights);
+}
+
+cgltf_size cgltf_node_index(const cgltf_data* data, const cgltf_node* object)
+{
+ assert(object && (cgltf_size)(object - data->nodes) < data->nodes_count);
+ return (cgltf_size)(object - data->nodes);
+}
+
+cgltf_size cgltf_scene_index(const cgltf_data* data, const cgltf_scene* object)
+{
+ assert(object && (cgltf_size)(object - data->scenes) < data->scenes_count);
+ return (cgltf_size)(object - data->scenes);
+}
+
+cgltf_size cgltf_animation_index(const cgltf_data* data, const cgltf_animation* object)
+{
+ assert(object && (cgltf_size)(object - data->animations) < data->animations_count);
+ return (cgltf_size)(object - data->animations);
+}
+
+cgltf_size cgltf_animation_sampler_index(const cgltf_animation* animation, const cgltf_animation_sampler* object)
+{
+ assert(object && (cgltf_size)(object - animation->samplers) < animation->samplers_count);
+ return (cgltf_size)(object - animation->samplers);
+}
+
+cgltf_size cgltf_animation_channel_index(const cgltf_animation* animation, const cgltf_animation_channel* object)
+{
+ assert(object && (cgltf_size)(object - animation->channels) < animation->channels_count);
+ return (cgltf_size)(object - animation->channels);
+}
+
+cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* out, cgltf_size out_component_size, cgltf_size index_count)
+{
+ if (out == NULL)
+ {
+ return accessor->count;
+ }
+
+ index_count = accessor->count < index_count ? accessor->count : index_count;
+ cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
+
+ if (accessor->is_sparse)
+ {
+ return 0;
+ }
+ if (accessor->buffer_view == NULL)
+ {
+ return 0;
+ }
+ if (index_component_size > out_component_size)
+ {
+ return 0;
+ }
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
+ {
+ return 0;
+ }
+ element += accessor->offset;
+
+ if (index_component_size == out_component_size && accessor->stride == out_component_size)
+ {
+ memcpy(out, element, index_count * index_component_size);
+ return index_count;
+ }
+
+ // The component size of the output array is larger than the component size of the index data, so index data will be padded.
+ switch (out_component_size)
+ {
+ case 2:
+ for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
+ {
+ ((uint16_t*)out)[index] = (uint16_t)cgltf_component_read_index(element, accessor->component_type);
+ }
+ break;
+ case 4:
+ for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
+ {
+ ((uint32_t*)out)[index] = (uint32_t)cgltf_component_read_index(element, accessor->component_type);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return index_count;
+}
+
#define CGLTF_ERROR_JSON -1
#define CGLTF_ERROR_NOMEM -2
#define CGLTF_ERROR_LEGACY -3
#define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; }
-#define CGLTF_CHECK_TOKTYPE_RETTYPE(tok_, type_, ret_) if ((tok_).type != (type_)) { return (ret_)CGLTF_ERROR_JSON; }
+#define CGLTF_CHECK_TOKTYPE_RET(tok_, type_, ret_) if ((tok_).type != (type_)) { return ret_; }
#define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; } /* checking size for 0 verifies that a value follows the key */
#define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1)
@@ -2503,7 +2649,7 @@ static int cgltf_json_strcmp(jsmntok_t const* tok, const uint8_t* json_chunk, co
{
CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
size_t const str_len = strlen(str);
- size_t const name_length = tok->end - tok->start;
+ size_t const name_length = (size_t)(tok->end - tok->start);
return (str_len == name_length) ? strncmp((const char*)json_chunk + tok->start, str, str_len) : 128;
}
@@ -2511,7 +2657,7 @@ static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk)
{
CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
char tmp[128];
- int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
+ int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
strncpy(tmp, (const char*)json_chunk + tok->start, size);
tmp[size] = 0;
return CGLTF_ATOI(tmp);
@@ -2519,19 +2665,20 @@ static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk)
static cgltf_size cgltf_json_to_size(jsmntok_t const* tok, const uint8_t* json_chunk)
{
- CGLTF_CHECK_TOKTYPE_RETTYPE(*tok, JSMN_PRIMITIVE, cgltf_size);
+ CGLTF_CHECK_TOKTYPE_RET(*tok, JSMN_PRIMITIVE, 0);
char tmp[128];
- int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
+ int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
strncpy(tmp, (const char*)json_chunk + tok->start, size);
tmp[size] = 0;
- return (cgltf_size)CGLTF_ATOLL(tmp);
+ long long res = CGLTF_ATOLL(tmp);
+ return res < 0 ? 0 : (cgltf_size)res;
}
static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json_chunk)
{
CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
char tmp[128];
- int size = (cgltf_size)(tok->end - tok->start) < sizeof(tmp) ? tok->end - tok->start : (int)(sizeof(tmp) - 1);
+ int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
strncpy(tmp, (const char*)json_chunk + tok->start, size);
tmp[size] = 0;
return (cgltf_float)CGLTF_ATOF(tmp);
@@ -2539,7 +2686,7 @@ static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json
static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk)
{
- int size = tok->end - tok->start;
+ int size = (int)(tok->end - tok->start);
return size == 4 && memcmp(json_chunk + tok->start, "true", 4) == 0;
}
@@ -2605,7 +2752,7 @@ static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* toke
{
return CGLTF_ERROR_JSON;
}
- int size = tokens[i].end - tokens[i].start;
+ int size = (int)(tokens[i].end - tokens[i].start);
char* result = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
if (!result)
{
@@ -2706,6 +2853,11 @@ static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* o
if (us && *out_type != cgltf_attribute_type_invalid)
{
*out_index = CGLTF_ATOI(us + 1);
+ if (*out_index < 0)
+ {
+ *out_type = cgltf_attribute_type_invalid;
+ *out_index = 0;
+ }
}
}
@@ -2863,6 +3015,10 @@ static int cgltf_parse_json_draco_mesh_compression(cgltf_options* options, jsmnt
out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
++i;
}
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
if (i < 0)
{
@@ -2888,11 +3044,9 @@ static int cgltf_parse_json_mesh_gpu_instancing(cgltf_options* options, jsmntok_
{
i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_mesh_gpu_instancing->attributes, &out_mesh_gpu_instancing->attributes_count);
}
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0)
+ else
{
- ++i;
- out_mesh_gpu_instancing->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
- ++i;
+ i = cgltf_skip_json(tokens, i+1);
}
if (i < 0)
@@ -3036,6 +3190,31 @@ static int cgltf_parse_json_material_mappings(cgltf_options* options, jsmntok_t
return i;
}
+static cgltf_primitive_type cgltf_json_to_primitive_type(jsmntok_t const* tok, const uint8_t* json_chunk)
+{
+ int type = cgltf_json_to_int(tok, json_chunk);
+
+ switch (type)
+ {
+ case 0:
+ return cgltf_primitive_type_points;
+ case 1:
+ return cgltf_primitive_type_lines;
+ case 2:
+ return cgltf_primitive_type_line_loop;
+ case 3:
+ return cgltf_primitive_type_line_strip;
+ case 4:
+ return cgltf_primitive_type_triangles;
+ case 5:
+ return cgltf_primitive_type_triangle_strip;
+ case 6:
+ return cgltf_primitive_type_triangle_fan;
+ default:
+ return cgltf_primitive_type_invalid;
+ }
+}
+
static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -3052,9 +3231,7 @@ static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* t
if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
{
++i;
- out_prim->type
- = (cgltf_primitive_type)
- cgltf_json_to_int(tokens+i, json_chunk);
+ out_prim->type = cgltf_json_to_primitive_type(tokens+i, json_chunk);
++i;
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
@@ -3290,7 +3467,7 @@ static cgltf_component_type cgltf_json_to_component_type(jsmntok_t const* tok, c
}
}
-static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse)
+static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -3304,7 +3481,7 @@ static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t co
if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
{
++i;
- out_sparse->count = cgltf_json_to_int(tokens + i, json_chunk);
+ out_sparse->count = cgltf_json_to_size(tokens + i, json_chunk);
++i;
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
@@ -3337,14 +3514,6 @@ static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t co
out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
++i;
}
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
- {
- i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->indices_extras);
- }
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
- {
- i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->indices_extensions_count, &out_sparse->indices_extensions);
- }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -3380,14 +3549,6 @@ static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t co
out_sparse->values_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
++i;
}
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
- {
- i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->values_extras);
- }
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
- {
- i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->values_extensions_count, &out_sparse->values_extensions);
- }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -3399,14 +3560,6 @@ static int cgltf_parse_json_accessor_sparse(cgltf_options* options, jsmntok_t co
}
}
}
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
- {
- i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sparse->extras);
- }
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
- {
- i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sparse->extensions_count, &out_sparse->extensions);
- }
else
{
i = cgltf_skip_json(tokens, i+1);
@@ -3464,8 +3617,7 @@ static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* to
else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
{
++i;
- out_accessor->count =
- cgltf_json_to_int(tokens+i, json_chunk);
+ out_accessor->count = cgltf_json_to_size(tokens+i, json_chunk);
++i;
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
@@ -3520,7 +3672,7 @@ static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* to
else if (cgltf_json_strcmp(tokens + i, json_chunk, "sparse") == 0)
{
out_accessor->is_sparse = 1;
- i = cgltf_parse_json_accessor_sparse(options, tokens, i + 1, json_chunk, &out_accessor->sparse);
+ i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
{
@@ -3592,6 +3744,8 @@ static int cgltf_parse_json_texture_transform(jsmntok_t const* tokens, int i, co
static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_view* out_texture_view)
{
+ (void)options;
+
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
out_texture_view->scale = 1.0f;
@@ -3616,7 +3770,7 @@ static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const
out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
++i;
}
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
{
++i;
out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
@@ -3628,28 +3782,12 @@ static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const
out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
++i;
}
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
- {
- i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture_view->extras);
- }
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
{
++i;
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
- if(out_texture_view->extensions)
- {
- return CGLTF_ERROR_JSON;
- }
-
int extensions_size = tokens[i].size;
- out_texture_view->extensions_count = 0;
- out_texture_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
-
- if (!out_texture_view->extensions)
- {
- return CGLTF_ERROR_NOMEM;
- }
++i;
@@ -3664,7 +3802,7 @@ static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const
}
else
{
- i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture_view->extensions[out_texture_view->extensions_count++]));
+ i = cgltf_skip_json(tokens, i + 1);
}
if (i < 0)
@@ -3701,11 +3839,11 @@ static int cgltf_parse_json_pbr_metallic_roughness(cgltf_options* options, jsmnt
if (cgltf_json_strcmp(tokens+i, json_chunk, "metallicFactor") == 0)
{
++i;
- out_pbr->metallic_factor =
+ out_pbr->metallic_factor =
cgltf_json_to_float(tokens + i, json_chunk);
++i;
}
- else if (cgltf_json_strcmp(tokens+i, json_chunk, "roughnessFactor") == 0)
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "roughnessFactor") == 0)
{
++i;
out_pbr->roughness_factor =
@@ -3718,13 +3856,11 @@ static int cgltf_parse_json_pbr_metallic_roughness(cgltf_options* options, jsmnt
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorTexture") == 0)
{
- i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
- &out_pbr->base_color_texture);
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->base_color_texture);
}
else if (cgltf_json_strcmp(tokens + i, json_chunk, "metallicRoughnessTexture") == 0)
{
- i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
- &out_pbr->metallic_roughness_texture);
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->metallic_roughness_texture);
}
else
{
@@ -4127,6 +4263,78 @@ static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const*
return i;
}
+static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyStrength") == 0)
+ {
+ ++i;
+ out_anisotropy->anisotropy_strength = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyRotation") == 0)
+ {
+ ++i;
+ out_anisotropy->anisotropy_rotation = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_anisotropy->anisotropy_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_dispersion(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_dispersion* out_dispersion)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "dispersion") == 0)
+ {
+ ++i;
+ out_dispersion->dispersion = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image)
{
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
@@ -4134,11 +4342,11 @@ static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* token
int size = tokens[i].size;
++i;
- for (int j = 0; j < size; ++j)
+ for (int j = 0; j < size; ++j)
{
CGLTF_CHECK_KEY(tokens[i]);
- if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0)
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0)
{
i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri);
}
@@ -4218,7 +4426,7 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
= cgltf_json_to_int(tokens + i, json_chunk);
++i;
}
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
{
++i;
out_sampler->wrap_t
@@ -4268,7 +4476,7 @@ static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tok
out_texture->sampler = CGLTF_PTRINDEX(cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk));
++i;
}
- else if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
{
++i;
out_texture->image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
@@ -4515,6 +4723,16 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
out_material->has_iridescence = 1;
i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
}
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0)
+ {
+ out_material->has_anisotropy = 1;
+ i = cgltf_parse_json_anisotropy(options, tokens, i + 1, json_chunk, &out_material->anisotropy);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_dispersion") == 0)
+ {
+ out_material->has_dispersion = 1;
+ i = cgltf_parse_json_dispersion(tokens, i + 1, json_chunk, &out_material->dispersion);
+ }
else
{
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
@@ -4674,7 +4892,7 @@ static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_
else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
{
++i;
- out_meshopt_compression->count = cgltf_json_to_int(tokens+i, json_chunk);
+ out_meshopt_compression->count = cgltf_json_to_size(tokens+i, json_chunk);
++i;
}
else if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
@@ -5963,7 +6181,7 @@ cgltf_size cgltf_num_components(cgltf_type type) {
}
}
-static cgltf_size cgltf_component_size(cgltf_component_type component_type) {
+cgltf_size cgltf_component_size(cgltf_component_type component_type) {
switch (component_type)
{
case cgltf_component_type_r_8:
@@ -5981,7 +6199,7 @@ static cgltf_size cgltf_component_size(cgltf_component_type component_type) {
}
}
-static cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
+cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
{
cgltf_size component_size = cgltf_component_size(component_type);
if (type == cgltf_type_mat2 && component_size == 1)
@@ -6366,6 +6584,8 @@ static int cgltf_fixup_pointers(cgltf_data* data)
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
}
for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
@@ -6410,7 +6630,6 @@ static int cgltf_fixup_pointers(cgltf_data* data)
if (data->nodes[i].has_mesh_gpu_instancing)
{
- CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.buffer_view, data->buffer_views, data->buffer_views_count);
for (cgltf_size m = 0; m < data->nodes[i].mesh_gpu_instancing.attributes_count; ++m)
{
CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.attributes[m].data, data->accessors, data->accessors_count);
@@ -6499,7 +6718,7 @@ static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
* Fills token type and boundaries.
*/
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
- int start, int end) {
+ ptrdiff_t start, ptrdiff_t end) {
token->type = type;
token->start = start;
token->end = end;
@@ -6512,7 +6731,7 @@ static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
size_t len, jsmntok_t *tokens, size_t num_tokens) {
jsmntok_t *token;
- int start;
+ ptrdiff_t start;
start = parser->pos;
@@ -6562,7 +6781,7 @@ static int jsmn_parse_string(jsmn_parser *parser, const char *js,
size_t len, jsmntok_t *tokens, size_t num_tokens) {
jsmntok_t *token;
- int start = parser->pos;
+ ptrdiff_t start = parser->pos;
parser->pos++;
diff --git a/vendor/cgltf/src/cgltf_write.h b/vendor/cgltf/src/cgltf_write.h
index 033b0d1cc..aa648a479 100644
--- a/vendor/cgltf/src/cgltf_write.h
+++ b/vendor/cgltf/src/cgltf_write.h
@@ -1,7 +1,7 @@
/**
* cgltf_write - a single-file glTF 2.0 writer written in C99.
*
- * Version: 1.13
+ * Version: 1.14
*
* Website: https://github.com/jkuhlmann/cgltf
*
@@ -85,6 +85,8 @@ cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size si
#define CGLTF_EXTENSION_FLAG_MATERIALS_EMISSIVE_STRENGTH (1 << 13)
#define CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING (1 << 14)
#define CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE (1 << 15)
+#define CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY (1 << 16)
+#define CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION (1 << 17)
typedef struct {
char* buffer;
@@ -152,7 +154,6 @@ typedef struct {
context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
cgltf_write_texture_transform(context, &info.transform); \
} \
- cgltf_write_extras(context, &info.extras); \
cgltf_write_line(context, "}"); }
#define CGLTF_WRITE_NORMAL_TEXTURE_INFO(label, info) if (info.texture) { \
@@ -164,7 +165,6 @@ typedef struct {
context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
cgltf_write_texture_transform(context, &info.transform); \
} \
- cgltf_write_extras(context, &info.extras); \
cgltf_write_line(context, "}"); }
#define CGLTF_WRITE_OCCLUSION_TEXTURE_INFO(label, info) if (info.texture) { \
@@ -176,12 +176,11 @@ typedef struct {
context->extension_flags |= CGLTF_EXTENSION_FLAG_TEXTURE_TRANSFORM; \
cgltf_write_texture_transform(context, &info.transform); \
} \
- cgltf_write_extras(context, &info.extras); \
cgltf_write_line(context, "}"); }
#ifndef CGLTF_CONSTS
-static const cgltf_size GlbHeaderSize = 12;
-static const cgltf_size GlbChunkHeaderSize = 8;
+#define GlbHeaderSize 12
+#define GlbChunkHeaderSize 8
static const uint32_t GlbVersion = 2;
static const uint32_t GlbMagic = 0x46546C67;
static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
@@ -360,6 +359,21 @@ static int cgltf_int_from_component_type(cgltf_component_type ctype)
}
}
+static int cgltf_int_from_primitive_type(cgltf_primitive_type ctype)
+{
+ switch (ctype)
+ {
+ case cgltf_primitive_type_points: return 0;
+ case cgltf_primitive_type_lines: return 1;
+ case cgltf_primitive_type_line_loop: return 2;
+ case cgltf_primitive_type_line_strip: return 3;
+ case cgltf_primitive_type_triangles: return 4;
+ case cgltf_primitive_type_triangle_strip: return 5;
+ case cgltf_primitive_type_triangle_fan: return 6;
+ default: return -1;
+ }
+}
+
static const char* cgltf_str_from_alpha_mode(cgltf_alpha_mode alpha_mode)
{
switch (alpha_mode)
@@ -455,7 +469,7 @@ static void cgltf_write_asset(cgltf_write_context* context, const cgltf_asset* a
static void cgltf_write_primitive(cgltf_write_context* context, const cgltf_primitive* prim)
{
- cgltf_write_intprop(context, "mode", (int) prim->type, 4);
+ cgltf_write_intprop(context, "mode", cgltf_int_from_primitive_type(prim->type), 4);
CGLTF_WRITE_IDXPROP("indices", prim->indices, context->data->accessors);
CGLTF_WRITE_IDXPROP("material", prim->material, context->data->materials);
cgltf_write_line(context, "\"attributes\": {");
@@ -641,6 +655,16 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE;
}
+ if (material->has_anisotropy)
+ {
+ context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY;
+ }
+
+ if (material->has_dispersion)
+ {
+ context->extension_flags |= CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION;
+ }
+
if (material->has_pbr_metallic_roughness)
{
const cgltf_pbr_metallic_roughness* params = &material->pbr_metallic_roughness;
@@ -656,7 +680,7 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
cgltf_write_line(context, "}");
}
- if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_specular || material->has_transmission || material->has_sheen || material->has_volume || material->has_emissive_strength || material->has_iridescence)
+ if (material->unlit || material->has_pbr_specular_glossiness || material->has_clearcoat || material->has_ior || material->has_specular || material->has_transmission || material->has_sheen || material->has_volume || material->has_emissive_strength || material->has_iridescence || material->has_anisotropy || material->has_dispersion)
{
cgltf_write_line(context, "\"extensions\": {");
if (material->has_clearcoat)
@@ -767,6 +791,22 @@ static void cgltf_write_material(cgltf_write_context* context, const cgltf_mater
CGLTF_WRITE_TEXTURE_INFO("iridescenceThicknessTexture", params->iridescence_thickness_texture);
cgltf_write_line(context, "}");
}
+ if (material->has_anisotropy)
+ {
+ cgltf_write_line(context, "\"KHR_materials_anisotropy\": {");
+ const cgltf_anisotropy* params = &material->anisotropy;
+ cgltf_write_floatprop(context, "anisotropyFactor", params->anisotropy_strength, 0.f);
+ cgltf_write_floatprop(context, "anisotropyRotation", params->anisotropy_rotation, 0.f);
+ CGLTF_WRITE_TEXTURE_INFO("anisotropyTexture", params->anisotropy_texture);
+ cgltf_write_line(context, "}");
+ }
+ if (material->has_dispersion)
+ {
+ cgltf_write_line(context, "\"KHR_materials_dispersion\": {");
+ const cgltf_dispersion* params = &material->dispersion;
+ cgltf_write_floatprop(context, "dispersion", params->dispersion, 0.f);
+ cgltf_write_line(context, "}");
+ }
cgltf_write_line(context, "}");
}
@@ -977,7 +1017,6 @@ static void cgltf_write_node(cgltf_write_context* context, const cgltf_node* nod
cgltf_write_line(context, "\"EXT_mesh_gpu_instancing\": {");
{
- CGLTF_WRITE_IDXPROP("bufferView", node->mesh_gpu_instancing.buffer_view, context->data->buffer_views);
cgltf_write_line(context, "\"attributes\": {");
{
for (cgltf_size i = 0; i < node->mesh_gpu_instancing.attributes_count; ++i)
@@ -1044,14 +1083,11 @@ static void cgltf_write_accessor(cgltf_write_context* context, const cgltf_acces
cgltf_write_sizeprop(context, "byteOffset", (int)accessor->sparse.indices_byte_offset, 0);
CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.indices_buffer_view, context->data->buffer_views);
cgltf_write_intprop(context, "componentType", cgltf_int_from_component_type(accessor->sparse.indices_component_type), 0);
- cgltf_write_extras(context, &accessor->sparse.indices_extras);
cgltf_write_line(context, "}");
cgltf_write_line(context, "\"values\": {");
cgltf_write_sizeprop(context, "byteOffset", (int)accessor->sparse.values_byte_offset, 0);
CGLTF_WRITE_IDXPROP("bufferView", accessor->sparse.values_buffer_view, context->data->buffer_views);
- cgltf_write_extras(context, &accessor->sparse.values_extras);
cgltf_write_line(context, "}");
- cgltf_write_extras(context, &accessor->sparse.extras);
cgltf_write_line(context, "}");
}
cgltf_write_extras(context, &accessor->extras);
@@ -1123,6 +1159,7 @@ static void cgltf_write_light(cgltf_write_context* context, const cgltf_light* l
cgltf_write_floatprop(context, "outerConeAngle", light->spot_outer_cone_angle, 3.14159265358979323846f/4.0f);
cgltf_write_line(context, "}");
}
+ cgltf_write_extras( context, &light->extras );
cgltf_write_line(context, "}");
}
@@ -1249,9 +1286,15 @@ static void cgltf_write_extensions(cgltf_write_context* context, uint32_t extens
if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_IRIDESCENCE) {
cgltf_write_stritem(context, "KHR_materials_iridescence");
}
+ if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_ANISOTROPY) {
+ cgltf_write_stritem(context, "KHR_materials_anisotropy");
+ }
if (extension_flags & CGLTF_EXTENSION_FLAG_MESH_GPU_INSTANCING) {
cgltf_write_stritem(context, "EXT_mesh_gpu_instancing");
}
+ if (extension_flags & CGLTF_EXTENSION_FLAG_MATERIALS_DISPERSION) {
+ cgltf_write_stritem(context, "KHR_materials_dispersion");
+ }
}
cgltf_size cgltf_write(const cgltf_options* options, char* buffer, cgltf_size size, const cgltf_data* data)
diff --git a/vendor/libc/include/math.h b/vendor/libc/include/math.h
index 3f60d698f..9d486da11 100644
--- a/vendor/libc/include/math.h
+++ b/vendor/libc/include/math.h
@@ -17,5 +17,5 @@ double fabs(double x);
int abs(int);
double ldexp(double, int);
double exp(double);
-float log(float);
-float sin(float);
+double log(double);
+double sin(double);
diff --git a/vendor/libc/math.odin b/vendor/libc/math.odin
index 59f42dd67..af319ac6d 100644
--- a/vendor/libc/math.odin
+++ b/vendor/libc/math.odin
@@ -90,11 +90,11 @@ exp :: proc "c" (x: f64) -> f64 {
}
@(require, linkage="strong", link_name="log")
-log :: proc "c" (x: f32) -> f32 {
+log :: proc "c" (x: f64) -> f64 {
return math.ln(x)
}
@(require, linkage="strong", link_name="sin")
-sin :: proc "c" (x: f32) -> f32 {
+sin :: proc "c" (x: f64) -> f64 {
return math.sin(x)
}
diff --git a/vendor/libc/stdio.odin b/vendor/libc/stdio.odin
index 10b95b96b..97667a5c8 100644
--- a/vendor/libc/stdio.odin
+++ b/vendor/libc/stdio.odin
@@ -1,3 +1,4 @@
+#+build !freestanding
package odin_libc
import "core:c"
diff --git a/vendor/raylib/raygui.odin b/vendor/raylib/raygui.odin
index a15467ae8..559437a60 100644
--- a/vendor/raylib/raygui.odin
+++ b/vendor/raylib/raygui.odin
@@ -3,6 +3,7 @@ package raylib
import "core:c"
RAYGUI_SHARED :: #config(RAYGUI_SHARED, false)
+RAYGUI_WASM_LIB :: #config(RAYGUI_WASM_LIB, "wasm/libraygui.a")
when ODIN_OS == .Windows {
foreign import lib {
@@ -22,6 +23,10 @@ when ODIN_OS == .Windows {
"macos/libraygui.dylib" when RAYGUI_SHARED else "macos/libraygui.a",
}
}
+} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
+ foreign import lib {
+ RAYGUI_WASM_LIB,
+ }
} else {
foreign import lib "system:raygui"
}
diff --git a/vendor/raylib/raylib.odin b/vendor/raylib/raylib.odin
index 34a803b99..bb51f105f 100644
--- a/vendor/raylib/raylib.odin
+++ b/vendor/raylib/raylib.odin
@@ -100,6 +100,7 @@ MAX_TEXT_BUFFER_LENGTH :: #config(RAYLIB_MAX_TEXT_BUFFER_LENGTH, 1024)
#assert(size_of(rune) == size_of(c.int))
RAYLIB_SHARED :: #config(RAYLIB_SHARED, false)
+RAYLIB_WASM_LIB :: #config(RAYLIB_WASM_LIB, "wasm/libraylib.a")
when ODIN_OS == .Windows {
@(extra_linker_flags="/NODEFAULTLIB:" + ("msvcrt" when RAYLIB_SHARED else "libcmt"))
@@ -127,6 +128,10 @@ when ODIN_OS == .Windows {
"system:OpenGL.framework",
"system:IOKit.framework",
}
+} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
+ foreign import lib {
+ RAYLIB_WASM_LIB,
+ }
} else {
foreign import lib "system:raylib"
}
diff --git a/vendor/raylib/raymath.odin b/vendor/raylib/raymath.odin
index c66498e41..c8420d60a 100644
--- a/vendor/raylib/raymath.odin
+++ b/vendor/raylib/raymath.odin
@@ -523,7 +523,7 @@ Vector3Unproject :: proc "c" (source: Vector3, projection: Matrix, view: Matrix)
quat: Quaternion
quat.x = source.x
- quat.y = source.z
+ quat.y = source.y
quat.z = source.z
quat.w = 1
diff --git a/vendor/raylib/rlgl/rlgl.odin b/vendor/raylib/rlgl/rlgl.odin
index 40913cd50..6ac19695d 100644
--- a/vendor/raylib/rlgl/rlgl.odin
+++ b/vendor/raylib/rlgl/rlgl.odin
@@ -113,6 +113,7 @@ import rl "../."
VERSION :: "5.0"
RAYLIB_SHARED :: #config(RAYLIB_SHARED, false)
+RAYLIB_WASM_LIB :: #config(RAYLIB_WASM_LIB, "../wasm/libraylib.a")
// Note: We pull in the full raylib library. If you want a truly stand-alone rlgl, then:
// - Compile a separate rlgl library and use that in the foreign import blocks below.
@@ -145,6 +146,10 @@ when ODIN_OS == .Windows {
"system:OpenGL.framework",
"system:IOKit.framework",
}
+} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
+ foreign import lib {
+ RAYLIB_WASM_LIB,
+ }
} else {
foreign import lib "system:raylib"
}
@@ -509,7 +514,7 @@ foreign lib {
UpdateVertexBufferElements :: proc(id: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update vertex buffer elements with new data
UnloadVertexArray :: proc(vaoId: c.uint) ---
UnloadVertexBuffer :: proc(vboId: c.uint) ---
- SetVertexAttribute :: proc(index: c.uint, compSize: c.int, type: c.int, normalized: bool, stride: c.int, pointer: rawptr) ---
+ SetVertexAttribute :: proc(index: c.uint, compSize: c.int, type: c.int, normalized: bool, stride: c.int, offset: c.int) ---
SetVertexAttributeDivisor :: proc(index: c.uint, divisor: c.int) ---
SetVertexAttributeDefault :: proc(locIndex: c.int, value: rawptr, attribType: c.int, count: c.int) --- // Set vertex attribute default value
DrawVertexArray :: proc(offset: c.int, count: c.int) ---
diff --git a/vendor/raylib/wasm/libraygui.a b/vendor/raylib/wasm/libraygui.a
new file mode 100644
index 000000000..cfde78a93
--- /dev/null
+++ b/vendor/raylib/wasm/libraygui.a
Binary files differ
diff --git a/vendor/raylib/wasm/libraylib.a b/vendor/raylib/wasm/libraylib.a
new file mode 100644
index 000000000..4cdbfa694
--- /dev/null
+++ b/vendor/raylib/wasm/libraylib.a
Binary files differ
diff --git a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py
index 1a4f96901..407e6371c 100644
--- a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py
+++ b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py
@@ -16,6 +16,8 @@ file_and_urls = [
("vulkan_macos.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_macos.h', False),
("vulkan_ios.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_ios.h', False),
("vulkan_wayland.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_wayland.h', False),
+ ("vulkan_xlib.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_xlib.h', False),
+ ("vulkan_xcb.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vulkan/vulkan_xcb.h', False),
# Vulkan Video
("vulkan_video_codec_av1std.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std.h', False),
("vulkan_video_codec_av1std_decode.h", 'https://raw.githubusercontent.com/KhronosGroup/Vulkan-Headers/main/include/vk_video/vulkan_video_codec_av1std_decode.h', False),
@@ -46,17 +48,18 @@ def no_vk(t):
t = t.replace('PFN_', 'Proc')
t = t.replace('PFN_', 'Proc')
- t = re.sub('(?:Vk|VK_)?(\w+)', '\\1', t)
+ t = re.sub('(?:Vk|VK_)?(\\w+)', '\\1', t)
# Vulkan Video
- t = re.sub('(?:Std|STD_|VK_STD)?(\w+)', '\\1', t)
+ t = re.sub('(?:Std|STD_|VK_STD)?(\\w+)', '\\1', t)
return t
OPAQUE_STRUCTS = """
-wl_surface :: struct {} // Opaque struct defined by Wayland
-wl_display :: struct {} // Opaque struct defined by Wayland
-IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
-"""
+wl_surface :: struct {} // Opaque struct defined by Wayland
+wl_display :: struct {} // Opaque struct defined by Wayland
+xcb_connection_t :: struct {} // Opaque struct defined by xcb
+IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
+"""
def convert_type(t, prev_name, curr_name):
table = {
@@ -91,6 +94,9 @@ def convert_type(t, prev_name, curr_name):
"struct BaseInStructure": "BaseInStructure",
"struct wl_display": "wl_display",
"struct wl_surface": "wl_surface",
+ "Display": "XlibDisplay",
+ "Window": "XlibWindow",
+ "VisualID": "XlibVisualID",
'v': '',
}
@@ -106,7 +112,7 @@ def convert_type(t, prev_name, curr_name):
elif t.endswith("*"):
pointer = "^"
ttype = t[:len(t)-1]
- elem = convert_type(ttype, prev_name, curr_name)
+ elem = convert_type(ttype, prev_name, curr_name)
if curr_name.endswith("s") or curr_name.endswith("Table"):
if prev_name.endswith("Count") or prev_name.endswith("Counts"):
@@ -445,7 +451,7 @@ def parse_enums(f):
def parse_fake_enums(f):
data = re.findall(r"static const Vk(\w+FlagBits2) VK_(\w+?) = (\w+);", src, re.S)
-
+
data.sort(key=lambda x: x[0])
fake_enums = {}
@@ -507,7 +513,7 @@ def parse_fake_enums(f):
continue
ff.append((n, v))
-
+
max_flag_value = max([int(v) for n, v in ff if is_int(v)] + [0])
max_group_value = max([int(v) for n, v in groups if is_int(v)] + [0])
if max_flag_value < max_group_value:
@@ -575,13 +581,13 @@ def parse_structs(f):
ffields.append(tuple([bit_field_name, bit_field_type, comment]))
prev_name = ""
continue
-
+
# The second way has many fields that are each 1 bit
elif int(fname) == 1:
bit_field_type = do_type(bit_field[0], prev_name, fname)
ffields.append(tuple(["bitfield", bit_field_type, comment]))
break
-
+
if '[' in fname:
@@ -894,6 +900,10 @@ import "core:c"
import win32 "core:sys/windows"
_ :: win32
+
+import "vendor:x11/xlib"
+_ :: xlib
+
when ODIN_OS == .Windows {
\tHINSTANCE :: win32.HINSTANCE
\tHWND :: win32.HWND
@@ -919,7 +929,19 @@ when ODIN_OS == .Windows {
\t}
}
-CAMetalLayer :: struct {}
+when xlib.IS_SUPPORTED {
+\tXlibDisplay :: xlib.Display
+\tXlibWindow :: xlib.Window
+\tXlibVisualID :: xlib.VisualID
+} else {
+\tXlibDisplay :: struct {} // Opaque struct defined by Xlib
+\tXlibWindow :: c.ulong
+\tXlibVisualID :: c.ulong
+}
+
+xcb_visualid_t :: u32
+xcb_window_t :: u32
+CAMetalLayer :: struct {}
MTLBuffer_id :: rawptr
MTLTexture_id :: rawptr
diff --git a/vendor/vulkan/_gen/vulkan_xcb.h b/vendor/vulkan/_gen/vulkan_xcb.h
new file mode 100644
index 000000000..cdf6b5269
--- /dev/null
+++ b/vendor/vulkan/_gen/vulkan_xcb.h
@@ -0,0 +1,56 @@
+#ifndef VULKAN_XCB_H_
+#define VULKAN_XCB_H_ 1
+
+/*
+** Copyright 2015-2024 The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+// VK_KHR_xcb_surface is a preprocessor guard. Do not pass it to API calls.
+#define VK_KHR_xcb_surface 1
+#define VK_KHR_XCB_SURFACE_SPEC_VERSION 6
+#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface"
+typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
+typedef struct VkXcbSurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkXcbSurfaceCreateFlagsKHR flags;
+ xcb_connection_t* connection;
+ xcb_window_t window;
+} VkXcbSurfaceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
+ VkInstance instance,
+ const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ xcb_connection_t* connection,
+ xcb_visualid_t visual_id);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vendor/vulkan/_gen/vulkan_xlib.h b/vendor/vulkan/_gen/vulkan_xlib.h
new file mode 100644
index 000000000..b3c3e27d7
--- /dev/null
+++ b/vendor/vulkan/_gen/vulkan_xlib.h
@@ -0,0 +1,56 @@
+#ifndef VULKAN_XLIB_H_
+#define VULKAN_XLIB_H_ 1
+
+/*
+** Copyright 2015-2024 The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+// VK_KHR_xlib_surface is a preprocessor guard. Do not pass it to API calls.
+#define VK_KHR_xlib_surface 1
+#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6
+#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
+typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
+typedef struct VkXlibSurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkXlibSurfaceCreateFlagsKHR flags;
+ Display* dpy;
+ Window window;
+} VkXlibSurfaceCreateInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
+ VkInstance instance,
+ const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ Display* dpy,
+ VisualID visualID);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vendor/vulkan/core.odin b/vendor/vulkan/core.odin
index a335018f9..f90b65008 100644
--- a/vendor/vulkan/core.odin
+++ b/vendor/vulkan/core.odin
@@ -1161,6 +1161,12 @@ EXT_METAL_OBJECTS_EXTENSION_NAME :: "VK_EXT_metal_objec
KHR_wayland_surface :: 1
KHR_WAYLAND_SURFACE_SPEC_VERSION :: 6
KHR_WAYLAND_SURFACE_EXTENSION_NAME :: "VK_KHR_wayland_surface"
+KHR_xlib_surface :: 1
+KHR_XLIB_SURFACE_SPEC_VERSION :: 6
+KHR_XLIB_SURFACE_EXTENSION_NAME :: "VK_KHR_xlib_surface"
+KHR_xcb_surface :: 1
+KHR_XCB_SURFACE_SPEC_VERSION :: 6
+KHR_XCB_SURFACE_EXTENSION_NAME :: "VK_KHR_xcb_surface"
// Handles types
Instance :: distinct Handle
diff --git a/vendor/vulkan/enums.odin b/vendor/vulkan/enums.odin
index 5ac8d1612..a55ba9e58 100644
--- a/vendor/vulkan/enums.odin
+++ b/vendor/vulkan/enums.odin
@@ -4585,6 +4585,10 @@ WaylandSurfaceCreateFlagsKHR :: distinct bit_set[Wayland
WaylandSurfaceCreateFlagKHR :: enum u32 {}
Win32SurfaceCreateFlagsKHR :: distinct bit_set[Win32SurfaceCreateFlagKHR; Flags]
Win32SurfaceCreateFlagKHR :: enum u32 {}
+XcbSurfaceCreateFlagsKHR :: distinct bit_set[XcbSurfaceCreateFlagKHR; Flags]
+XcbSurfaceCreateFlagKHR :: enum u32 {}
+XlibSurfaceCreateFlagsKHR :: distinct bit_set[XlibSurfaceCreateFlagKHR; Flags]
+XlibSurfaceCreateFlagKHR :: enum u32 {}
AccessFlags2 :: distinct bit_set[AccessFlag2; Flags64]
AccessFlag2 :: enum Flags64 {
INDIRECT_COMMAND_READ = 0,
diff --git a/vendor/vulkan/procedures.odin b/vendor/vulkan/procedures.odin
index dc03275a2..19f70fc85 100644
--- a/vendor/vulkan/procedures.odin
+++ b/vendor/vulkan/procedures.odin
@@ -36,6 +36,8 @@ ProcCreateMacOSSurfaceMVK :: #type pr
ProcCreateMetalSurfaceEXT :: #type proc "system" (instance: Instance, pCreateInfo: ^MetalSurfaceCreateInfoEXT, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
ProcCreateWaylandSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^WaylandSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
ProcCreateWin32SurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^Win32SurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
+ProcCreateXcbSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^XcbSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
+ProcCreateXlibSurfaceKHR :: #type proc "system" (instance: Instance, pCreateInfo: ^XlibSurfaceCreateInfoKHR, pAllocator: ^AllocationCallbacks, pSurface: ^SurfaceKHR) -> Result
ProcDebugReportMessageEXT :: #type proc "system" (instance: Instance, flags: DebugReportFlagsEXT, objectType: DebugReportObjectTypeEXT, object: u64, location: int, messageCode: i32, pLayerPrefix: cstring, pMessage: cstring)
ProcDestroyDebugReportCallbackEXT :: #type proc "system" (instance: Instance, callback: DebugReportCallbackEXT, pAllocator: ^AllocationCallbacks)
ProcDestroyDebugUtilsMessengerEXT :: #type proc "system" (instance: Instance, messenger: DebugUtilsMessengerEXT, pAllocator: ^AllocationCallbacks)
@@ -113,6 +115,8 @@ ProcGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR :: #type pr
ProcGetPhysicalDeviceVideoFormatPropertiesKHR :: #type proc "system" (physicalDevice: PhysicalDevice, pVideoFormatInfo: ^PhysicalDeviceVideoFormatInfoKHR, pVideoFormatPropertyCount: ^u32, pVideoFormatProperties: [^]VideoFormatPropertiesKHR) -> Result
ProcGetPhysicalDeviceWaylandPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, display: ^wl_display) -> b32
ProcGetPhysicalDeviceWin32PresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32) -> b32
+ProcGetPhysicalDeviceXcbPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, connection: ^xcb_connection_t, visual_id: xcb_visualid_t) -> b32
+ProcGetPhysicalDeviceXlibPresentationSupportKHR :: #type proc "system" (physicalDevice: PhysicalDevice, queueFamilyIndex: u32, dpy: ^XlibDisplay, visualID: XlibVisualID) -> b32
ProcGetWinrtDisplayNV :: #type proc "system" (physicalDevice: PhysicalDevice, deviceRelativeId: u32, pDisplay: ^DisplayKHR) -> Result
ProcReleaseDisplayEXT :: #type proc "system" (physicalDevice: PhysicalDevice, display: DisplayKHR) -> Result
ProcSubmitDebugUtilsMessageEXT :: #type proc "system" (instance: Instance, messageSeverity: DebugUtilsMessageSeverityFlagsEXT, messageTypes: DebugUtilsMessageTypeFlagsEXT, pCallbackData: ^DebugUtilsMessengerCallbackDataEXT)
@@ -730,6 +734,8 @@ CreateMacOSSurfaceMVK: ProcCreateMacO
CreateMetalSurfaceEXT: ProcCreateMetalSurfaceEXT
CreateWaylandSurfaceKHR: ProcCreateWaylandSurfaceKHR
CreateWin32SurfaceKHR: ProcCreateWin32SurfaceKHR
+CreateXcbSurfaceKHR: ProcCreateXcbSurfaceKHR
+CreateXlibSurfaceKHR: ProcCreateXlibSurfaceKHR
DebugReportMessageEXT: ProcDebugReportMessageEXT
DestroyDebugReportCallbackEXT: ProcDestroyDebugReportCallbackEXT
DestroyDebugUtilsMessengerEXT: ProcDestroyDebugUtilsMessengerEXT
@@ -806,6 +812,8 @@ GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR: ProcGetPhysica
GetPhysicalDeviceVideoFormatPropertiesKHR: ProcGetPhysicalDeviceVideoFormatPropertiesKHR
GetPhysicalDeviceWaylandPresentationSupportKHR: ProcGetPhysicalDeviceWaylandPresentationSupportKHR
GetPhysicalDeviceWin32PresentationSupportKHR: ProcGetPhysicalDeviceWin32PresentationSupportKHR
+GetPhysicalDeviceXcbPresentationSupportKHR: ProcGetPhysicalDeviceXcbPresentationSupportKHR
+GetPhysicalDeviceXlibPresentationSupportKHR: ProcGetPhysicalDeviceXlibPresentationSupportKHR
GetWinrtDisplayNV: ProcGetWinrtDisplayNV
ReleaseDisplayEXT: ProcReleaseDisplayEXT
SubmitDebugUtilsMessageEXT: ProcSubmitDebugUtilsMessageEXT
@@ -1423,6 +1431,8 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) {
set_proc_address(&CreateMetalSurfaceEXT, "vkCreateMetalSurfaceEXT")
set_proc_address(&CreateWaylandSurfaceKHR, "vkCreateWaylandSurfaceKHR")
set_proc_address(&CreateWin32SurfaceKHR, "vkCreateWin32SurfaceKHR")
+ set_proc_address(&CreateXcbSurfaceKHR, "vkCreateXcbSurfaceKHR")
+ set_proc_address(&CreateXlibSurfaceKHR, "vkCreateXlibSurfaceKHR")
set_proc_address(&DebugReportMessageEXT, "vkDebugReportMessageEXT")
set_proc_address(&DestroyDebugReportCallbackEXT, "vkDestroyDebugReportCallbackEXT")
set_proc_address(&DestroyDebugUtilsMessengerEXT, "vkDestroyDebugUtilsMessengerEXT")
@@ -1499,6 +1509,8 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) {
set_proc_address(&GetPhysicalDeviceVideoFormatPropertiesKHR, "vkGetPhysicalDeviceVideoFormatPropertiesKHR")
set_proc_address(&GetPhysicalDeviceWaylandPresentationSupportKHR, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")
set_proc_address(&GetPhysicalDeviceWin32PresentationSupportKHR, "vkGetPhysicalDeviceWin32PresentationSupportKHR")
+ set_proc_address(&GetPhysicalDeviceXcbPresentationSupportKHR, "vkGetPhysicalDeviceXcbPresentationSupportKHR")
+ set_proc_address(&GetPhysicalDeviceXlibPresentationSupportKHR, "vkGetPhysicalDeviceXlibPresentationSupportKHR")
set_proc_address(&GetWinrtDisplayNV, "vkGetWinrtDisplayNV")
set_proc_address(&ReleaseDisplayEXT, "vkReleaseDisplayEXT")
set_proc_address(&SubmitDebugUtilsMessageEXT, "vkSubmitDebugUtilsMessageEXT")
@@ -3879,6 +3891,8 @@ load_proc_addresses_instance :: proc(instance: Instance) {
CreateMetalSurfaceEXT = auto_cast GetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT")
CreateWaylandSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR")
CreateWin32SurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR")
+ CreateXcbSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR")
+ CreateXlibSurfaceKHR = auto_cast GetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR")
DebugReportMessageEXT = auto_cast GetInstanceProcAddr(instance, "vkDebugReportMessageEXT")
DestroyDebugReportCallbackEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT")
DestroyDebugUtilsMessengerEXT = auto_cast GetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT")
@@ -3955,6 +3969,8 @@ load_proc_addresses_instance :: proc(instance: Instance) {
GetPhysicalDeviceVideoFormatPropertiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoFormatPropertiesKHR")
GetPhysicalDeviceWaylandPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR")
GetPhysicalDeviceWin32PresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR")
+ GetPhysicalDeviceXcbPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR")
+ GetPhysicalDeviceXlibPresentationSupportKHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR")
GetWinrtDisplayNV = auto_cast GetInstanceProcAddr(instance, "vkGetWinrtDisplayNV")
ReleaseDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkReleaseDisplayEXT")
SubmitDebugUtilsMessageEXT = auto_cast GetInstanceProcAddr(instance, "vkSubmitDebugUtilsMessageEXT")
diff --git a/vendor/vulkan/structs.odin b/vendor/vulkan/structs.odin
index 3c41d1923..611a99ed7 100644
--- a/vendor/vulkan/structs.odin
+++ b/vendor/vulkan/structs.odin
@@ -7,6 +7,10 @@ import "core:c"
import win32 "core:sys/windows"
_ :: win32
+
+import "vendor:x11/xlib"
+_ :: xlib
+
when ODIN_OS == .Windows {
HINSTANCE :: win32.HINSTANCE
HWND :: win32.HWND
@@ -32,7 +36,19 @@ when ODIN_OS == .Windows {
}
}
-CAMetalLayer :: struct {}
+when xlib.IS_SUPPORTED {
+ XlibDisplay :: xlib.Display
+ XlibWindow :: xlib.Window
+ XlibVisualID :: xlib.VisualID
+} else {
+ XlibDisplay :: struct {} // Opaque struct defined by Xlib
+ XlibWindow :: c.ulong
+ XlibVisualID :: c.ulong
+}
+
+xcb_visualid_t :: u32
+xcb_window_t :: u32
+CAMetalLayer :: struct {}
MTLBuffer_id :: rawptr
MTLTexture_id :: rawptr
@@ -8910,6 +8926,22 @@ WaylandSurfaceCreateInfoKHR :: struct {
surface: ^wl_surface,
}
+XlibSurfaceCreateInfoKHR :: struct {
+ sType: StructureType,
+ pNext: rawptr,
+ flags: XlibSurfaceCreateFlagsKHR,
+ dpy: ^XlibDisplay,
+ window: XlibWindow,
+}
+
+XcbSurfaceCreateInfoKHR :: struct {
+ sType: StructureType,
+ pNext: rawptr,
+ flags: XcbSurfaceCreateFlagsKHR,
+ connection: ^xcb_connection_t,
+ window: xcb_window_t,
+}
+
VideoAV1ColorConfigFlags :: struct {
bitfield: u32,
}
@@ -9753,9 +9785,10 @@ VideoEncodeH265ReferenceInfo :: struct {
// Opaque structs
-wl_surface :: struct {} // Opaque struct defined by Wayland
-wl_display :: struct {} // Opaque struct defined by Wayland
-IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
+wl_surface :: struct {} // Opaque struct defined by Wayland
+wl_display :: struct {} // Opaque struct defined by Wayland
+xcb_connection_t :: struct {} // Opaque struct defined by xcb
+IOSurfaceRef :: struct {} // Opaque struct defined by Apple’s CoreGraphics framework
// Aliases
PhysicalDeviceVariablePointerFeatures :: PhysicalDeviceVariablePointersFeatures
PhysicalDeviceShaderDrawParameterFeatures :: PhysicalDeviceShaderDrawParametersFeatures
diff --git a/vendor/x11/xlib/xlib.odin b/vendor/x11/xlib/xlib.odin
new file mode 100644
index 000000000..bd9ba3b59
--- /dev/null
+++ b/vendor/x11/xlib/xlib.odin
@@ -0,0 +1,4 @@
+package xlib
+
+// Value, specifying whether `vendor:x11/xlib` is available on the current platform.
+IS_SUPPORTED :: ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD