mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 06:38:47 +00:00
Merge branch 'master' into static_builds
This commit is contained in:
@@ -169,22 +169,23 @@ jobs:
|
|||||||
run: python -c "import sys; print(sys.version)"
|
run: python -c "import sys; print(sys.version)"
|
||||||
|
|
||||||
- name: Download Windows artifacts
|
- name: Download Windows artifacts
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
|
uses: actions/download-artifact@v4.1.7
|
||||||
with:
|
with:
|
||||||
name: windows_artifacts
|
name: windows_artifacts
|
||||||
|
|
||||||
- name: Download Ubuntu artifacts
|
- name: Download Ubuntu artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4.1.7
|
||||||
with:
|
with:
|
||||||
name: linux_artifacts
|
name: linux_artifacts
|
||||||
|
|
||||||
- name: Download macOS artifacts
|
- name: Download macOS artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4.1.7
|
||||||
with:
|
with:
|
||||||
name: macos_artifacts
|
name: macos_artifacts
|
||||||
|
|
||||||
- name: Download macOS arm artifacts
|
- name: Download macOS arm artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4.1.7
|
||||||
with:
|
with:
|
||||||
name: macos_arm_artifacts
|
name: macos_arm_artifacts
|
||||||
|
|
||||||
|
|||||||
@@ -476,11 +476,9 @@ last_index_byte :: proc(s: []byte, c: byte) -> int #no_bounds_check {
|
|||||||
// worth vectorizing assuming there is a hardware vector unit, and
|
// worth vectorizing assuming there is a hardware vector unit, and
|
||||||
// the data size is large enough.
|
// the data size is large enough.
|
||||||
if i < SIMD_REG_SIZE_128 {
|
if i < SIMD_REG_SIZE_128 {
|
||||||
if i > 0 { // Handle s == nil.
|
#reverse for ch, j in s {
|
||||||
for /**/; i >= 0; i -= 1 {
|
if ch == c {
|
||||||
if s[i] == c {
|
return j
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
//+build !windows !linux !darwin
|
//+build !windows
|
||||||
|
//+build !linux
|
||||||
|
//+build !darwin
|
||||||
package debug_trace
|
package debug_trace
|
||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//+build !netbsd !openbsd
|
//+build !netbsd
|
||||||
|
//+build !openbsd
|
||||||
package flags
|
package flags
|
||||||
|
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
//+private
|
//+private
|
||||||
//+build !netbsd !openbsd
|
//+build !netbsd
|
||||||
|
//+build !openbsd
|
||||||
package flags
|
package flags
|
||||||
|
|
||||||
import "core:net"
|
import "core:net"
|
||||||
|
|||||||
+3
-3
@@ -444,11 +444,11 @@ bias :: proc "contextless" (t, b: $T) -> T where intrinsics.type_is_numeric(T) {
|
|||||||
return t / (((1/b) - 2) * (1 - t) + 1)
|
return t / (((1/b) - 2) * (1 - t) + 1)
|
||||||
}
|
}
|
||||||
@(require_results)
|
@(require_results)
|
||||||
gain :: proc "contextless" (t, g: $T) -> T where intrinsics.type_is_numeric(T) {
|
gain :: proc "contextless" (t, g: $T) -> T where intrinsics.type_is_float(T) {
|
||||||
if t < 0.5 {
|
if t < 0.5 {
|
||||||
return bias(t*2, g)*0.5
|
return bias(t*2, g) * 0.5
|
||||||
}
|
}
|
||||||
return bias(t*2 - 1, 1 - g)*0.5 + 0.5
|
return bias(t*2 - 1, 1 - g) * 0.5 + 0.5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+35
-38
@@ -1,17 +1,10 @@
|
|||||||
//+private
|
//+private
|
||||||
package os2
|
package os2
|
||||||
|
|
||||||
import "base:runtime"
|
|
||||||
|
|
||||||
import "core:sys/linux"
|
import "core:sys/linux"
|
||||||
import "core:sync"
|
import "core:sync"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
|
|
||||||
// Use the experimental custom heap allocator (over calling `malloc` etc.).
|
|
||||||
// This is a switch because there are thread-safety problems that need to be fixed.
|
|
||||||
// See: https://github.com/odin-lang/Odin/issues/4161
|
|
||||||
USE_EXPERIMENTAL_ALLOCATOR :: #config(OS2_LINUX_USE_EXPERIMENTAL_ALLOCATOR, false)
|
|
||||||
|
|
||||||
// NOTEs
|
// NOTEs
|
||||||
//
|
//
|
||||||
// All allocations below DIRECT_MMAP_THRESHOLD exist inside of memory "Regions." A region
|
// All allocations below DIRECT_MMAP_THRESHOLD exist inside of memory "Regions." A region
|
||||||
@@ -146,8 +139,6 @@ Region :: struct {
|
|||||||
memory: [BLOCKS_PER_REGION]Allocation_Header,
|
memory: [BLOCKS_PER_REGION]Allocation_Header,
|
||||||
}
|
}
|
||||||
|
|
||||||
when USE_EXPERIMENTAL_ALLOCATOR {
|
|
||||||
|
|
||||||
_heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
_heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
||||||
size, alignment: int,
|
size, alignment: int,
|
||||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, mem.Allocator_Error) {
|
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, mem.Allocator_Error) {
|
||||||
@@ -228,10 +219,6 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
_heap_allocator_proc :: runtime.heap_allocator_proc
|
|
||||||
}
|
|
||||||
|
|
||||||
heap_alloc :: proc(size: int) -> rawptr {
|
heap_alloc :: proc(size: int) -> rawptr {
|
||||||
if size >= DIRECT_MMAP_THRESHOLD {
|
if size >= DIRECT_MMAP_THRESHOLD {
|
||||||
return _direct_mmap_alloc(size)
|
return _direct_mmap_alloc(size)
|
||||||
@@ -293,7 +280,8 @@ heap_alloc :: proc(size: int) -> rawptr {
|
|||||||
_local_region, back_idx = _region_retrieve_with_space(blocks_needed, local_region_idx, back_idx)
|
_local_region, back_idx = _region_retrieve_with_space(blocks_needed, local_region_idx, back_idx)
|
||||||
}
|
}
|
||||||
user_ptr, used := _region_get_block(_local_region, idx, blocks_needed)
|
user_ptr, used := _region_get_block(_local_region, idx, blocks_needed)
|
||||||
_local_region.hdr.free_blocks -= (used + 1)
|
|
||||||
|
sync.atomic_sub_explicit(&_local_region.hdr.free_blocks, used + 1, .Release)
|
||||||
|
|
||||||
// If this memory was ever used before, it now needs to be zero'd.
|
// If this memory was ever used before, it now needs to be zero'd.
|
||||||
if idx < _local_region.hdr.last_used {
|
if idx < _local_region.hdr.last_used {
|
||||||
@@ -320,7 +308,7 @@ heap_resize :: proc(old_memory: rawptr, new_size: int) -> rawptr #no_bounds_chec
|
|||||||
|
|
||||||
heap_free :: proc(memory: rawptr) {
|
heap_free :: proc(memory: rawptr) {
|
||||||
alloc := _get_allocation_header(memory)
|
alloc := _get_allocation_header(memory)
|
||||||
if alloc.requested & IS_DIRECT_MMAP == IS_DIRECT_MMAP {
|
if sync.atomic_load(&alloc.requested) & IS_DIRECT_MMAP == IS_DIRECT_MMAP {
|
||||||
_direct_mmap_free(alloc)
|
_direct_mmap_free(alloc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -475,25 +463,31 @@ _region_local_free :: proc(alloc: ^Allocation_Header) #no_bounds_check {
|
|||||||
alloc := alloc
|
alloc := alloc
|
||||||
add_to_free_list := true
|
add_to_free_list := true
|
||||||
|
|
||||||
_local_region.hdr.free_blocks += _get_block_count(alloc^) + 1
|
idx := sync.atomic_load(&alloc.idx)
|
||||||
|
prev := sync.atomic_load(&alloc.prev)
|
||||||
|
next := sync.atomic_load(&alloc.next)
|
||||||
|
block_count := next - idx - 1
|
||||||
|
free_blocks := sync.atomic_load(&_local_region.hdr.free_blocks) + block_count + 1
|
||||||
|
sync.atomic_store_explicit(&_local_region.hdr.free_blocks, free_blocks, .Release)
|
||||||
|
|
||||||
// try to merge with prev
|
// try to merge with prev
|
||||||
if alloc.idx > 0 && _local_region.memory[alloc.prev].free_idx != NOT_FREE {
|
if idx > 0 && sync.atomic_load(&_local_region.memory[prev].free_idx) != NOT_FREE {
|
||||||
_local_region.memory[alloc.prev].next = alloc.next
|
sync.atomic_store_explicit(&_local_region.memory[prev].next, next, .Release)
|
||||||
_local_region.memory[alloc.next].prev = alloc.prev
|
_local_region.memory[next].prev = prev
|
||||||
alloc = &_local_region.memory[alloc.prev]
|
alloc = &_local_region.memory[prev]
|
||||||
add_to_free_list = false
|
add_to_free_list = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to merge with next
|
// try to merge with next
|
||||||
if alloc.next < BLOCKS_PER_REGION - 1 && _local_region.memory[alloc.next].free_idx != NOT_FREE {
|
if next < BLOCKS_PER_REGION - 1 && sync.atomic_load(&_local_region.memory[next].free_idx) != NOT_FREE {
|
||||||
old_next := alloc.next
|
old_next := next
|
||||||
alloc.next = _local_region.memory[old_next].next
|
sync.atomic_store_explicit(&alloc.next, sync.atomic_load(&_local_region.memory[old_next].next), .Release)
|
||||||
_local_region.memory[alloc.next].prev = alloc.idx
|
|
||||||
|
sync.atomic_store_explicit(&_local_region.memory[next].prev, idx, .Release)
|
||||||
|
|
||||||
if add_to_free_list {
|
if add_to_free_list {
|
||||||
_local_region.hdr.free_list[_local_region.memory[old_next].free_idx] = alloc.idx
|
sync.atomic_store_explicit(&_local_region.hdr.free_list[_local_region.memory[old_next].free_idx], idx, .Release)
|
||||||
alloc.free_idx = _local_region.memory[old_next].free_idx
|
sync.atomic_store_explicit(&alloc.free_idx, _local_region.memory[old_next].free_idx, .Release)
|
||||||
} else {
|
} else {
|
||||||
// NOTE: We have aleady merged with prev, and now merged with next.
|
// NOTE: We have aleady merged with prev, and now merged with next.
|
||||||
// Now, we are actually going to remove from the free_list.
|
// Now, we are actually going to remove from the free_list.
|
||||||
@@ -505,10 +499,11 @@ _region_local_free :: proc(alloc: ^Allocation_Header) #no_bounds_check {
|
|||||||
// This is the only place where anything is appended to the free list.
|
// This is the only place where anything is appended to the free list.
|
||||||
if add_to_free_list {
|
if add_to_free_list {
|
||||||
fl := _local_region.hdr.free_list
|
fl := _local_region.hdr.free_list
|
||||||
alloc.free_idx = _local_region.hdr.free_list_len
|
fl_len := sync.atomic_load(&_local_region.hdr.free_list_len)
|
||||||
fl[alloc.free_idx] = alloc.idx
|
sync.atomic_store_explicit(&alloc.free_idx, fl_len, .Release)
|
||||||
_local_region.hdr.free_list_len += 1
|
fl[alloc.free_idx] = idx
|
||||||
if int(_local_region.hdr.free_list_len) == len(fl) {
|
sync.atomic_store_explicit(&_local_region.hdr.free_list_len, fl_len + 1, .Release)
|
||||||
|
if int(fl_len + 1) == len(fl) {
|
||||||
free_alloc := _get_allocation_header(mem.raw_data(_local_region.hdr.free_list))
|
free_alloc := _get_allocation_header(mem.raw_data(_local_region.hdr.free_list))
|
||||||
_region_resize(free_alloc, len(fl) * 2 * size_of(fl[0]), true)
|
_region_resize(free_alloc, len(fl) * 2 * size_of(fl[0]), true)
|
||||||
}
|
}
|
||||||
@@ -525,8 +520,8 @@ _region_assign_free_list :: proc(region: ^Region, memory: rawptr, blocks: u16) {
|
|||||||
_region_retrieve_with_space :: proc(blocks: u16, local_idx: int = -1, back_idx: int = -1) -> (^Region, int) {
|
_region_retrieve_with_space :: proc(blocks: u16, local_idx: int = -1, back_idx: int = -1) -> (^Region, int) {
|
||||||
r: ^Region
|
r: ^Region
|
||||||
idx: int
|
idx: int
|
||||||
for r = global_regions; r != nil; r = r.hdr.next_region {
|
for r = sync.atomic_load(&global_regions); r != nil; r = r.hdr.next_region {
|
||||||
if idx == local_idx || idx < back_idx || r.hdr.free_blocks < blocks {
|
if idx == local_idx || idx < back_idx || sync.atomic_load(&r.hdr.free_blocks) < blocks {
|
||||||
idx += 1
|
idx += 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -594,7 +589,7 @@ _region_segment :: proc(region: ^Region, alloc: ^Allocation_Header, blocks, new_
|
|||||||
|
|
||||||
_region_get_local_idx :: proc() -> int {
|
_region_get_local_idx :: proc() -> int {
|
||||||
idx: int
|
idx: int
|
||||||
for r := global_regions; r != nil; r = r.hdr.next_region {
|
for r := sync.atomic_load(&global_regions); r != nil; r = r.hdr.next_region {
|
||||||
if r == _local_region {
|
if r == _local_region {
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
@@ -610,9 +605,10 @@ _region_find_and_assign_local :: proc(alloc: ^Allocation_Header) {
|
|||||||
_local_region = _region_retrieve_from_addr(alloc)
|
_local_region = _region_retrieve_from_addr(alloc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, _local_region is set correctly. Spin until acquired
|
// At this point, _local_region is set correctly. Spin until acquire
|
||||||
res: ^^Region
|
res := CURRENTLY_ACTIVE
|
||||||
for res != &_local_region {
|
|
||||||
|
for res == CURRENTLY_ACTIVE {
|
||||||
res = sync.atomic_compare_exchange_strong_explicit(
|
res = sync.atomic_compare_exchange_strong_explicit(
|
||||||
&_local_region.hdr.local_addr,
|
&_local_region.hdr.local_addr,
|
||||||
&_local_region,
|
&_local_region,
|
||||||
@@ -634,9 +630,9 @@ _region_contains_mem :: proc(r: ^Region, memory: rawptr) -> bool #no_bounds_chec
|
|||||||
_region_free_list_remove :: proc(region: ^Region, free_idx: u16) #no_bounds_check {
|
_region_free_list_remove :: proc(region: ^Region, free_idx: u16) #no_bounds_check {
|
||||||
// pop, swap and update allocation hdr
|
// pop, swap and update allocation hdr
|
||||||
if n := region.hdr.free_list_len - 1; free_idx != n {
|
if n := region.hdr.free_list_len - 1; free_idx != n {
|
||||||
region.hdr.free_list[free_idx] = region.hdr.free_list[n]
|
region.hdr.free_list[free_idx] = sync.atomic_load(®ion.hdr.free_list[n])
|
||||||
alloc_idx := region.hdr.free_list[free_idx]
|
alloc_idx := region.hdr.free_list[free_idx]
|
||||||
region.memory[alloc_idx].free_idx = free_idx
|
sync.atomic_store_explicit(®ion.memory[alloc_idx].free_idx, free_idx, .Release)
|
||||||
}
|
}
|
||||||
region.hdr.free_list_len -= 1
|
region.hdr.free_list_len -= 1
|
||||||
}
|
}
|
||||||
@@ -727,3 +723,4 @@ _get_allocation_header :: #force_inline proc(raw_mem: rawptr) -> ^Allocation_Hea
|
|||||||
_round_up_to_nearest :: #force_inline proc(size, round: int) -> int {
|
_round_up_to_nearest :: #force_inline proc(size, round: int) -> int {
|
||||||
return (size-1) + round - (size-1) % round
|
return (size-1) + round - (size-1) % round
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -7,8 +7,8 @@ Parses a boolean value from the input string
|
|||||||
|
|
||||||
**Inputs**
|
**Inputs**
|
||||||
- s: The input string
|
- s: The input string
|
||||||
- true: "1", "t", "T", "true", "TRUE", "True"
|
- true: "1", "t", "T", "true", "TRUE", "True"
|
||||||
- false: "0", "f", "F", "false", "FALSE", "False"
|
- false: "0", "f", "F", "false", "FALSE", "False"
|
||||||
- n: An optional pointer to an int to store the length of the parsed substring (default: nil)
|
- n: An optional pointer to an int to store the length of the parsed substring (default: nil)
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
@@ -203,7 +203,7 @@ Parses an unsigned 64-bit integer value from the input string without a prefix,
|
|||||||
**Inputs**
|
**Inputs**
|
||||||
- str: The input string to parse
|
- str: The input string to parse
|
||||||
- base: The base of the number system to use for parsing
|
- base: The base of the number system to use for parsing
|
||||||
- Must be between 1 and 16 (inclusive)
|
- Must be between 1 and 16 (inclusive)
|
||||||
- n: An optional pointer to an int to store the length of the parsed substring (default: nil)
|
- n: An optional pointer to an int to store the length of the parsed substring (default: nil)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -264,8 +264,8 @@ Parses an unsigned 64-bit integer value from the input string, using the specifi
|
|||||||
**Inputs**
|
**Inputs**
|
||||||
- str: The input string to parse
|
- str: The input string to parse
|
||||||
- base: The base of the number system to use for parsing (default: 0)
|
- base: The base of the number system to use for parsing (default: 0)
|
||||||
- If base is 0, it will be inferred based on the prefix in the input string (e.g. '0x' for hexadecimal)
|
- If base is 0, it will be inferred based on the prefix in the input string (e.g. '0x' for hexadecimal)
|
||||||
- If base is not 0, it will be used for parsing regardless of any prefix in the input string
|
- If base is not 0, it will be used for parsing regardless of any prefix in the input string
|
||||||
- n: An optional pointer to an int to store the length of the parsed substring (default: nil)
|
- n: An optional pointer to an int to store the length of the parsed substring (default: nil)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -339,8 +339,8 @@ Parses a signed integer value from the input string, using the specified base or
|
|||||||
**Inputs**
|
**Inputs**
|
||||||
- s: The input string to parse
|
- s: The input string to parse
|
||||||
- base: The base of the number system to use for parsing (default: 0)
|
- base: The base of the number system to use for parsing (default: 0)
|
||||||
- If base is 0, it will be inferred based on the prefix in the input string (e.g. '0x' for hexadecimal)
|
- If base is 0, it will be inferred based on the prefix in the input string (e.g. '0x' for hexadecimal)
|
||||||
- If base is not 0, it will be used for parsing regardless of any prefix in the input string
|
- If base is not 0, it will be used for parsing regardless of any prefix in the input string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -382,8 +382,8 @@ Parses an unsigned integer value from the input string, using the specified base
|
|||||||
**Inputs**
|
**Inputs**
|
||||||
- s: The input string to parse
|
- s: The input string to parse
|
||||||
- base: The base of the number system to use for parsing (default: 0, inferred)
|
- base: The base of the number system to use for parsing (default: 0, inferred)
|
||||||
- If base is 0, it will be inferred based on the prefix in the input string (e.g. '0x' for hexadecimal)
|
- If base is 0, it will be inferred based on the prefix in the input string (e.g. '0x' for hexadecimal)
|
||||||
- If base is not 0, it will be used for parsing regardless of any prefix in the input string
|
- If base is not 0, it will be used for parsing regardless of any prefix in the input string
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -1729,7 +1729,7 @@ quote_rune :: proc(buf: []byte, r: rune) -> string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if buf == nil {
|
if buf == nil || r < 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -421,21 +421,20 @@ raw_queue_pop :: proc "contextless" (q: ^Raw_Queue) -> (data: rawptr) {
|
|||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
can_recv :: proc "contextless" (c: ^Raw_Chan) -> bool {
|
can_recv :: proc "contextless" (c: ^Raw_Chan) -> bool {
|
||||||
|
sync.guard(&c.mutex)
|
||||||
if is_buffered(c) {
|
if is_buffered(c) {
|
||||||
return len(c) > 0
|
return len(c) > 0
|
||||||
}
|
}
|
||||||
sync.guard(&c.mutex)
|
|
||||||
return sync.atomic_load(&c.w_waiting) > 0
|
return sync.atomic_load(&c.w_waiting) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
can_send :: proc "contextless" (c: ^Raw_Chan) -> bool {
|
can_send :: proc "contextless" (c: ^Raw_Chan) -> bool {
|
||||||
if is_buffered(c) {
|
|
||||||
sync.guard(&c.mutex)
|
|
||||||
return len(c) < cap(c)
|
|
||||||
}
|
|
||||||
sync.guard(&c.mutex)
|
sync.guard(&c.mutex)
|
||||||
|
if is_buffered(c) {
|
||||||
|
return c.queue.len < c.queue.cap
|
||||||
|
}
|
||||||
return sync.atomic_load(&c.r_waiting) > 0
|
return sync.atomic_load(&c.r_waiting) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
//+private
|
//+private
|
||||||
//+build !windows !linux !darwin !freebsd !openbsd !netbsd !haiku
|
//+build !windows
|
||||||
|
//+build !linux
|
||||||
|
//+build !darwin
|
||||||
|
//+build !freebsd
|
||||||
|
//+build !openbsd
|
||||||
|
//+build !netbsd
|
||||||
|
//+build !haiku
|
||||||
package testing
|
package testing
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -430,6 +430,7 @@ struct BuildContext {
|
|||||||
bool json_errors;
|
bool json_errors;
|
||||||
bool has_ansi_terminal_colours;
|
bool has_ansi_terminal_colours;
|
||||||
|
|
||||||
|
bool fast_isel;
|
||||||
bool ignore_lazy;
|
bool ignore_lazy;
|
||||||
bool ignore_llvm_build;
|
bool ignore_llvm_build;
|
||||||
bool ignore_panic;
|
bool ignore_panic;
|
||||||
@@ -2048,10 +2049,11 @@ gb_internal bool init_build_paths(String init_filename) {
|
|||||||
gbFile output_file_test;
|
gbFile output_file_test;
|
||||||
const char* output_file_name = (const char*)output_file.text;
|
const char* output_file_name = (const char*)output_file.text;
|
||||||
gbFileError output_test_err = gb_file_open_mode(&output_file_test, gbFileMode_Append | gbFileMode_Rw, output_file_name);
|
gbFileError output_test_err = gb_file_open_mode(&output_file_test, gbFileMode_Append | gbFileMode_Rw, output_file_name);
|
||||||
gb_file_close(&output_file_test);
|
|
||||||
gb_file_remove(output_file_name);
|
|
||||||
|
|
||||||
if (output_test_err != 0) {
|
if (output_test_err == 0) {
|
||||||
|
gb_file_close(&output_file_test);
|
||||||
|
gb_file_remove(output_file_name);
|
||||||
|
} else {
|
||||||
String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
|
String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
|
||||||
defer (gb_free(ha, output_file.text));
|
defer (gb_free(ha, output_file.text));
|
||||||
gb_printf_err("No write permissions for output path: %.*s\n", LIT(output_file));
|
gb_printf_err("No write permissions for output path: %.*s\n", LIT(output_file));
|
||||||
|
|||||||
@@ -5203,6 +5203,16 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sz >= 64) {
|
||||||
|
if (is_type_unsigned(x.type)) {
|
||||||
|
add_package_dependency(c, "runtime", "umodti3", true);
|
||||||
|
add_package_dependency(c, "runtime", "udivti3", true);
|
||||||
|
} else {
|
||||||
|
add_package_dependency(c, "runtime", "modti3", true);
|
||||||
|
add_package_dependency(c, "runtime", "divti3", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
operand->type = x.type;
|
operand->type = x.type;
|
||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -3615,7 +3615,7 @@ gb_internal bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type
|
|||||||
if (is_type_integer(src_t) && is_type_integer(dst_t)) {
|
if (is_type_integer(src_t) && is_type_integer(dst_t)) {
|
||||||
if (types_have_same_internal_endian(src_t, dst_t)) {
|
if (types_have_same_internal_endian(src_t, dst_t)) {
|
||||||
ExactValue src_v = exact_value_to_integer(o->value);
|
ExactValue src_v = exact_value_to_integer(o->value);
|
||||||
GB_ASSERT(src_v.kind == ExactValue_Integer);
|
GB_ASSERT(src_v.kind == ExactValue_Integer || src_v.kind == ExactValue_Invalid);
|
||||||
BigInt v = src_v.value_integer;
|
BigInt v = src_v.value_integer;
|
||||||
|
|
||||||
BigInt smax = {};
|
BigInt smax = {};
|
||||||
|
|||||||
@@ -3081,6 +3081,13 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
|
|||||||
lbModule *m = entry.value;
|
lbModule *m = entry.value;
|
||||||
m->target_machine = target_machine;
|
m->target_machine = target_machine;
|
||||||
LLVMSetModuleDataLayout(m->mod, LLVMCreateTargetDataLayout(target_machine));
|
LLVMSetModuleDataLayout(m->mod, LLVMCreateTargetDataLayout(target_machine));
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR >= 18
|
||||||
|
if (build_context.fast_isel) {
|
||||||
|
LLVMSetTargetMachineFastISel(m->target_machine, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
array_add(&target_machines, target_machine);
|
array_add(&target_machines, target_machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,13 +82,36 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
|
|||||||
parameter_count += 1;
|
parameter_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LLVMMetadataRef *parameters = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, parameter_count);
|
|
||||||
|
|
||||||
unsigned param_index = 0;
|
auto parameters = array_make<LLVMMetadataRef>(permanent_allocator(), 0, type->Proc.param_count+type->Proc.result_count+2);
|
||||||
if (type->Proc.result_count == 0) {
|
|
||||||
parameters[param_index++] = nullptr;
|
array_add(¶meters, cast(LLVMMetadataRef)nullptr);
|
||||||
} else {
|
|
||||||
parameters[param_index++] = lb_debug_procedure_parameters(m, type->Proc.results);
|
bool return_is_tuple = false;
|
||||||
|
if (type->Proc.result_count != 0) {
|
||||||
|
Type *single_ret = reduce_tuple_to_single_type(type->Proc.results);
|
||||||
|
if (is_type_proc(single_ret)) {
|
||||||
|
single_ret = t_rawptr;
|
||||||
|
}
|
||||||
|
if (is_type_tuple(single_ret) && is_calling_convention_odin(type->Proc.calling_convention)) {
|
||||||
|
LLVMTypeRef actual = lb_type_internal_for_procedures_raw(m, type);
|
||||||
|
actual = LLVMGetReturnType(actual);
|
||||||
|
if (actual == nullptr) {
|
||||||
|
// results were passed as a single pointer
|
||||||
|
parameters[0] = lb_debug_procedure_parameters(m, single_ret);
|
||||||
|
} else {
|
||||||
|
LLVMTypeRef possible = lb_type(m, type->Proc.results);
|
||||||
|
if (possible == actual) {
|
||||||
|
// results were returned directly
|
||||||
|
parameters[0] = lb_debug_procedure_parameters(m, single_ret);
|
||||||
|
} else {
|
||||||
|
// resulsts were returned separately
|
||||||
|
return_is_tuple = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parameters[0] = lb_debug_procedure_parameters(m, single_ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMMetadataRef file = nullptr;
|
LLVMMetadataRef file = nullptr;
|
||||||
@@ -98,8 +121,22 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
|
|||||||
if (e->kind != Entity_Variable) {
|
if (e->kind != Entity_Variable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
parameters[param_index] = lb_debug_procedure_parameters(m, e->type);
|
array_add(¶meters, lb_debug_procedure_parameters(m, e->type));
|
||||||
param_index += 1;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (return_is_tuple) {
|
||||||
|
Type *results = type->Proc.results;
|
||||||
|
GB_ASSERT(results != nullptr && results->kind == Type_Tuple);
|
||||||
|
isize count = results->Tuple.variables.count;
|
||||||
|
parameters[0] = lb_debug_procedure_parameters(m, results->Tuple.variables[count-1]->type);
|
||||||
|
for (isize i = 0; i < count-1; i++) {
|
||||||
|
array_add(¶meters, lb_debug_procedure_parameters(m, results->Tuple.variables[i]->type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type->Proc.calling_convention == ProcCC_Odin) {
|
||||||
|
array_add(¶meters, lb_debug_type(m, t_context_ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMDIFlags flags = LLVMDIFlagZero;
|
LLVMDIFlags flags = LLVMDIFlagZero;
|
||||||
@@ -107,7 +144,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
|
|||||||
flags = LLVMDIFlagNoReturn;
|
flags = LLVMDIFlagNoReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LLVMDIBuilderCreateSubroutineType(m->debug_builder, file, parameters, parameter_count, flags);
|
return LLVMDIBuilderCreateSubroutineType(m->debug_builder, file, parameters.data, cast(unsigned)parameters.count, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal LLVMMetadataRef lb_debug_struct_field(lbModule *m, String const &name, Type *type, u64 offset_in_bits) {
|
gb_internal LLVMMetadataRef lb_debug_struct_field(lbModule *m, String const &name, Type *type, u64 offset_in_bits) {
|
||||||
|
|||||||
+27
-21
@@ -705,31 +705,37 @@ gb_internal lbValue lb_emit_matrix_flatten(lbProcedure *p, lbValue m, Type *type
|
|||||||
|
|
||||||
lbAddr res = lb_add_local_generated(p, type, true);
|
lbAddr res = lb_add_local_generated(p, type, true);
|
||||||
|
|
||||||
i64 row_count = mt->Matrix.row_count;
|
GB_ASSERT(type_size_of(type) == type_size_of(m.type));
|
||||||
i64 column_count = mt->Matrix.column_count;
|
|
||||||
TEMPORARY_ALLOCATOR_GUARD();
|
|
||||||
|
|
||||||
auto srcs = array_make<lbValue>(temporary_allocator(), 0, row_count*column_count);
|
lbValue m_ptr = lb_address_from_load_or_generate_local(p, m);
|
||||||
auto dsts = array_make<lbValue>(temporary_allocator(), 0, row_count*column_count);
|
lbValue n = lb_const_int(p->module, t_int, type_size_of(type));
|
||||||
|
lb_mem_copy_non_overlapping(p, res.addr, m_ptr, n);
|
||||||
|
|
||||||
for (i64 j = 0; j < column_count; j++) {
|
// i64 row_count = mt->Matrix.row_count;
|
||||||
for (i64 i = 0; i < row_count; i++) {
|
// i64 column_count = mt->Matrix.column_count;
|
||||||
lbValue src = lb_emit_matrix_ev(p, m, i, j);
|
// TEMPORARY_ALLOCATOR_GUARD();
|
||||||
array_add(&srcs, src);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i64 j = 0; j < column_count; j++) {
|
// auto srcs = array_make<lbValue>(temporary_allocator(), 0, row_count*column_count);
|
||||||
for (i64 i = 0; i < row_count; i++) {
|
// auto dsts = array_make<lbValue>(temporary_allocator(), 0, row_count*column_count);
|
||||||
lbValue dst = lb_emit_array_epi(p, res.addr, i + j*row_count);
|
|
||||||
array_add(&dsts, dst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GB_ASSERT(srcs.count == dsts.count);
|
// for (i64 j = 0; j < column_count; j++) {
|
||||||
for_array(i, srcs) {
|
// for (i64 i = 0; i < row_count; i++) {
|
||||||
lb_emit_store(p, dsts[i], srcs[i]);
|
// lbValue src = lb_emit_matrix_ev(p, m, i, j);
|
||||||
}
|
// array_add(&srcs, src);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (i64 j = 0; j < column_count; j++) {
|
||||||
|
// for (i64 i = 0; i < row_count; i++) {
|
||||||
|
// lbValue dst = lb_emit_array_epi(p, res.addr, i + j*row_count);
|
||||||
|
// array_add(&dsts, dst);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// GB_ASSERT(srcs.count == dsts.count);
|
||||||
|
// for_array(i, srcs) {
|
||||||
|
// lb_emit_store(p, dsts[i], srcs[i]);
|
||||||
|
// }
|
||||||
return lb_addr_load(p, res);
|
return lb_addr_load(p, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ enum BuildFlagKind {
|
|||||||
BuildFlag_PrintLinkerFlags,
|
BuildFlag_PrintLinkerFlags,
|
||||||
|
|
||||||
// internal use only
|
// internal use only
|
||||||
|
BuildFlag_InternalFastISel,
|
||||||
BuildFlag_InternalIgnoreLazy,
|
BuildFlag_InternalIgnoreLazy,
|
||||||
BuildFlag_InternalIgnoreLLVMBuild,
|
BuildFlag_InternalIgnoreLLVMBuild,
|
||||||
BuildFlag_InternalIgnorePanic,
|
BuildFlag_InternalIgnorePanic,
|
||||||
@@ -594,6 +595,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
|||||||
|
|
||||||
add_flag(&build_flags, BuildFlag_PrintLinkerFlags, str_lit("print-linker-flags"), BuildFlagParam_None, Command_build);
|
add_flag(&build_flags, BuildFlag_PrintLinkerFlags, str_lit("print-linker-flags"), BuildFlagParam_None, Command_build);
|
||||||
|
|
||||||
|
add_flag(&build_flags, BuildFlag_InternalFastISel, str_lit("internal-fast-isel"), BuildFlagParam_None, Command_all);
|
||||||
add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all);
|
add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all);
|
||||||
add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all);
|
add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all);
|
||||||
add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all);
|
add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all);
|
||||||
@@ -1408,6 +1410,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
|
|||||||
build_context.print_linker_flags = true;
|
build_context.print_linker_flags = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BuildFlag_InternalFastISel:
|
||||||
|
build_context.fast_isel = true;
|
||||||
|
break;
|
||||||
case BuildFlag_InternalIgnoreLazy:
|
case BuildFlag_InternalIgnoreLazy:
|
||||||
build_context.ignore_lazy = true;
|
build_context.ignore_lazy = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
+13
-5
@@ -1474,6 +1474,7 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) {
|
|||||||
|
|
||||||
Type *elem = t->Matrix.elem;
|
Type *elem = t->Matrix.elem;
|
||||||
i64 row_count = gb_max(t->Matrix.row_count, 1);
|
i64 row_count = gb_max(t->Matrix.row_count, 1);
|
||||||
|
i64 column_count = gb_max(t->Matrix.column_count, 1);
|
||||||
|
|
||||||
bool pop = type_path_push(tp, elem);
|
bool pop = type_path_push(tp, elem);
|
||||||
if (tp->failure) {
|
if (tp->failure) {
|
||||||
@@ -1491,7 +1492,7 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) {
|
|||||||
// could be maximally aligned but as a compromise, having no padding will be
|
// could be maximally aligned but as a compromise, having no padding will be
|
||||||
// beneficial to third libraries that assume no padding
|
// beneficial to third libraries that assume no padding
|
||||||
|
|
||||||
i64 total_expected_size = row_count*t->Matrix.column_count*elem_size;
|
i64 total_expected_size = row_count*column_count*elem_size;
|
||||||
// i64 min_alignment = prev_pow2(elem_align * row_count);
|
// i64 min_alignment = prev_pow2(elem_align * row_count);
|
||||||
i64 min_alignment = prev_pow2(total_expected_size);
|
i64 min_alignment = prev_pow2(total_expected_size);
|
||||||
while (total_expected_size != 0 && (total_expected_size % min_alignment) != 0) {
|
while (total_expected_size != 0 && (total_expected_size % min_alignment) != 0) {
|
||||||
@@ -1523,12 +1524,15 @@ gb_internal i64 matrix_type_stride_in_bytes(Type *t, struct TypePath *tp) {
|
|||||||
i64 stride_in_bytes = 0;
|
i64 stride_in_bytes = 0;
|
||||||
|
|
||||||
// NOTE(bill, 2021-10-25): The alignment strategy here is to have zero padding
|
// NOTE(bill, 2021-10-25): The alignment strategy here is to have zero padding
|
||||||
// It would be better for performance to pad each column so that each column
|
// It would be better for performance to pad each column/row so that each column/row
|
||||||
// could be maximally aligned but as a compromise, having no padding will be
|
// could be maximally aligned but as a compromise, having no padding will be
|
||||||
// beneficial to third libraries that assume no padding
|
// beneficial to third libraries that assume no padding
|
||||||
i64 row_count = t->Matrix.row_count;
|
|
||||||
stride_in_bytes = elem_size*row_count;
|
|
||||||
|
|
||||||
|
if (t->Matrix.is_row_major) {
|
||||||
|
stride_in_bytes = elem_size*t->Matrix.column_count;
|
||||||
|
} else {
|
||||||
|
stride_in_bytes = elem_size*t->Matrix.row_count;
|
||||||
|
}
|
||||||
t->Matrix.stride_in_bytes = stride_in_bytes;
|
t->Matrix.stride_in_bytes = stride_in_bytes;
|
||||||
return stride_in_bytes;
|
return stride_in_bytes;
|
||||||
}
|
}
|
||||||
@@ -4217,7 +4221,11 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
|
|||||||
|
|
||||||
case Type_Matrix: {
|
case Type_Matrix: {
|
||||||
i64 stride_in_bytes = matrix_type_stride_in_bytes(t, path);
|
i64 stride_in_bytes = matrix_type_stride_in_bytes(t, path);
|
||||||
return stride_in_bytes * t->Matrix.column_count;
|
if (t->Matrix.is_row_major) {
|
||||||
|
return stride_in_bytes * t->Matrix.row_count;
|
||||||
|
} else {
|
||||||
|
return stride_in_bytes * t->Matrix.column_count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case Type_BitField:
|
case Type_BitField:
|
||||||
|
|||||||
@@ -87,3 +87,11 @@ test_index_byte_zero :: proc(t: ^testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
test_last_index_byte_bounds :: proc(t: ^testing.T) {
|
||||||
|
input := "helloworld.odin."
|
||||||
|
assert(len(input) == 16)
|
||||||
|
idx := bytes.last_index_byte(transmute([]byte)(input[:len(input)-1]), '.')
|
||||||
|
testing.expect_value(t, idx, 10)
|
||||||
|
}
|
||||||
@@ -10,7 +10,8 @@
|
|||||||
|
|
||||||
A test suite for `core:net`
|
A test suite for `core:net`
|
||||||
*/
|
*/
|
||||||
//+build !netbsd !openbsd
|
//+build !netbsd
|
||||||
|
//+build !openbsd
|
||||||
package test_core_net
|
package test_core_net
|
||||||
|
|
||||||
import "core:testing"
|
import "core:testing"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style
|
|||||||
..\..\..\odin test ..\test_issue_2615.odin %COMMON% || exit /b
|
..\..\..\odin test ..\test_issue_2615.odin %COMMON% || exit /b
|
||||||
..\..\..\odin test ..\test_issue_2637.odin %COMMON% || exit /b
|
..\..\..\odin test ..\test_issue_2637.odin %COMMON% || exit /b
|
||||||
..\..\..\odin test ..\test_issue_2666.odin %COMMON% || exit /b
|
..\..\..\odin test ..\test_issue_2666.odin %COMMON% || exit /b
|
||||||
|
..\..\..\odin test ..\test_issue_4210.odin %COMMON% || exit /b
|
||||||
|
|
||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ $ODIN test ../test_issue_2466.odin $COMMON
|
|||||||
$ODIN test ../test_issue_2615.odin $COMMON
|
$ODIN test ../test_issue_2615.odin $COMMON
|
||||||
$ODIN test ../test_issue_2637.odin $COMMON
|
$ODIN test ../test_issue_2637.odin $COMMON
|
||||||
$ODIN test ../test_issue_2666.odin $COMMON
|
$ODIN test ../test_issue_2666.odin $COMMON
|
||||||
|
$ODIN test ../test_issue_4210.odin $COMMON
|
||||||
if [[ $($ODIN build ../test_issue_2395.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]] ; then
|
if [[ $($ODIN build ../test_issue_2395.odin $COMMON 2>&1 >/dev/null | grep -c "Error:") -eq 2 ]] ; then
|
||||||
echo "SUCCESSFUL 1/1"
|
echo "SUCCESSFUL 1/1"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// Tests issue #4210 https://github.com/odin-lang/Odin/issues/4210
|
||||||
|
package test_issues
|
||||||
|
|
||||||
|
import "core:testing"
|
||||||
|
import "base:intrinsics"
|
||||||
|
|
||||||
|
@test
|
||||||
|
test_row_major_matrix :: proc(t: ^testing.T) {
|
||||||
|
row_major34: #row_major matrix[3,4]int = {
|
||||||
|
11,12,13,14,
|
||||||
|
21,22,23,24,
|
||||||
|
31,32,33,34,
|
||||||
|
}
|
||||||
|
row_major34_expected := [?]int{11,12,13,14, 21,22,23,24, 31,32,33,34}
|
||||||
|
|
||||||
|
row_major43: #row_major matrix[4,3]int = {
|
||||||
|
11,12,13,
|
||||||
|
21,22,23,
|
||||||
|
31,32,33,
|
||||||
|
41,42,43,
|
||||||
|
}
|
||||||
|
row_major43_expected := [?]int{11,12,13, 21,22,23, 31,32,33, 41,42,43}
|
||||||
|
|
||||||
|
major34_flattened := intrinsics.matrix_flatten(row_major34)
|
||||||
|
major34_from_ptr := intrinsics.unaligned_load((^[3 * 4]int)(&row_major34))
|
||||||
|
|
||||||
|
for row in 0..<3 {
|
||||||
|
for column in 0..<4 {
|
||||||
|
idx := row * 4 + column
|
||||||
|
testing.expect_value(t, major34_flattened[idx], row_major34_expected[idx])
|
||||||
|
testing.expect_value(t, major34_from_ptr [idx], row_major34_expected[idx])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
major43_flattened := intrinsics.matrix_flatten(row_major43)
|
||||||
|
major43_from_ptr := intrinsics.unaligned_load((^[4 * 3]int)(&row_major43))
|
||||||
|
|
||||||
|
for row in 0..<4 {
|
||||||
|
for column in 0..<3 {
|
||||||
|
idx := row * 3 + column
|
||||||
|
testing.expect_value(t, major43_flattened[idx], row_major43_expected[idx])
|
||||||
|
testing.expect_value(t, major43_from_ptr [idx], row_major43_expected[idx])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
test_row_minor_matrix :: proc(t: ^testing.T) {
|
||||||
|
row_minor34: matrix[3,4]int = {
|
||||||
|
11,12,13,14,
|
||||||
|
21,22,23,24,
|
||||||
|
31,32,33,34,
|
||||||
|
}
|
||||||
|
row_minor34_expected := [?]int{11,21,31, 12,22,32, 13,23,33, 14,24,34}
|
||||||
|
|
||||||
|
row_minor43: matrix[4,3]int = {
|
||||||
|
11,12,13,
|
||||||
|
21,22,23,
|
||||||
|
31,32,33,
|
||||||
|
41,42,43,
|
||||||
|
}
|
||||||
|
row_minor43_expected := [?]int{11,21,31,41, 12,22,32,42, 13,23,33,43}
|
||||||
|
|
||||||
|
minor34_flattened := intrinsics.matrix_flatten(row_minor34)
|
||||||
|
minor34_from_ptr := intrinsics.unaligned_load((^[3 * 4]int)(&row_minor34))
|
||||||
|
|
||||||
|
for row in 0..<3 {
|
||||||
|
for column in 0..<4 {
|
||||||
|
idx := row * 4 + column
|
||||||
|
testing.expect_value(t, minor34_flattened[idx], row_minor34_expected[idx])
|
||||||
|
testing.expect_value(t, minor34_from_ptr [idx], row_minor34_expected[idx])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minor43_flattened := intrinsics.matrix_flatten(row_minor43)
|
||||||
|
minor43_from_ptr := intrinsics.unaligned_load((^[4 * 3]int)(&row_minor43))
|
||||||
|
|
||||||
|
for row in 0..<4 {
|
||||||
|
for column in 0..<3 {
|
||||||
|
idx := row * 3 + column
|
||||||
|
testing.expect_value(t, minor43_flattened[idx], row_minor43_expected[idx])
|
||||||
|
testing.expect_value(t, minor43_from_ptr [idx], row_minor43_expected[idx])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
+1
-1
@@ -8,7 +8,7 @@ endif
|
|||||||
|
|
||||||
wasm:
|
wasm:
|
||||||
mkdir -p ../lib
|
mkdir -p ../lib
|
||||||
clang -c -Os --target=wasm32 -nostdlib stb_truetype_wasm.c -o ../lib/stb_truetype_wasm.o
|
$(CC) -c -Os --target=wasm32 -nostdlib stb_truetype_wasm.c -o ../lib/stb_truetype_wasm.o
|
||||||
|
|
||||||
unix:
|
unix:
|
||||||
mkdir -p ../lib
|
mkdir -p ../lib
|
||||||
|
|||||||
Vendored
-3
@@ -1,5 +1,2 @@
|
|||||||
#define STB_RECT_PACK_IMPLEMENTATION
|
|
||||||
#include "stb_rect_pack.h"
|
|
||||||
|
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
#include "stb_truetype.h"
|
#include "stb_truetype.h"
|
||||||
Vendored
+2
@@ -27,6 +27,8 @@ when ODIN_OS == .Windows {
|
|||||||
"system:advapi32.lib",
|
"system:advapi32.lib",
|
||||||
"system:user32.lib",
|
"system:user32.lib",
|
||||||
"system:gdi32.lib",
|
"system:gdi32.lib",
|
||||||
|
"system:ole32.lib",
|
||||||
|
"system:oleaut32.lib",
|
||||||
}
|
}
|
||||||
} else when ODIN_OS == .Darwin {
|
} else when ODIN_OS == .Darwin {
|
||||||
@(private) ARCH :: "x86_64" when ODIN_ARCH == .amd64 else "aarch64" when ODIN_ARCH == .arm64 else #panic("unsupported WGPU Native architecture")
|
@(private) ARCH :: "x86_64" when ODIN_ARCH == .amd64 else "aarch64" when ODIN_ARCH == .arm64 else #panic("unsupported WGPU Native architecture")
|
||||||
|
|||||||
Reference in New Issue
Block a user