Merge branch 'master' into allocator-mode-alloc-non-zeroed

This commit is contained in:
gingerBill
2022-11-03 12:47:11 +00:00
93 changed files with 3803 additions and 2576 deletions
-17
View File
@@ -38,11 +38,6 @@ jobs:
cd tests/vendor
make
timeout-minutes: 10
- name: Odin issues tests
run: |
cd tests/issues
./run.sh
timeout-minutes: 10
- name: Odin check examples/all for Linux i386
run: ./odin check examples/all -vet -strict-style -target:linux_i386
timeout-minutes: 10
@@ -92,11 +87,6 @@ jobs:
cd tests/vendor
make
timeout-minutes: 10
- name: Odin issues tests
run: |
cd tests/issues
./run.sh
timeout-minutes: 10
- name: Odin check examples/all for Darwin arm64
run: ./odin check examples/all -vet -strict-style -target:darwin_arm64
timeout-minutes: 10
@@ -163,13 +153,6 @@ jobs:
cd tests\core\math\big
call build.bat
timeout-minutes: 10
- name: Odin issues tests
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\issues
call run.bat
timeout-minutes: 10
- name: Odin check examples/all for Windows 32bits
shell: cmd
run: |
+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
run: |
mkdir dist
cp odin dist
cp libLLVM*.so dist
cp libLLVM* dist
cp -r shared dist
cp -r core dist
cp -r vendor dist
+1 -1
View File
@@ -271,7 +271,7 @@ odin
odin.dSYM
*.bin
demo.bin
libLLVM*.so
libLLVM*.so*
# shared collection
shared/
+1 -1
View File
@@ -82,7 +82,7 @@ A wiki maintained by the Odin community.
#### [Odin Discord](https://discord.gg/sVBPHEv)
Get live support and talk with other odiners on the Odin Discord.
Get live support and talk with other Odin programmers on the Odin Discord.
### Articles
+25 -1
View File
@@ -44,6 +44,12 @@ config_darwin() {
fi
fi
MAX_LLVM_VERSION=("14.999.999")
if [ $(version $($LLVM_CONFIG --version)) -gt $(version $MAX_LLVM_VERSION) ]; then
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
panic "Requirement: llvm-config must be base version smaller than 15"
fi
LDFLAGS="$LDFLAGS -liconv -ldl"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -lLLVM-C"
@@ -97,10 +103,20 @@ config_linux() {
panic "Requirement: llvm-config must be base version greater than 11"
fi
MAX_LLVM_VERSION=("14.999.999")
if [ $(version $($LLVM_CONFIG --version)) -gt $(version $MAX_LLVM_VERSION) ]; then
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
panic "Requirement: llvm-config must be base version smaller than 15"
fi
LDFLAGS="$LDFLAGS -ldl"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs --libfiles) -Wl,-rpath=\$ORIGIN"
cp $($LLVM_CONFIG --libfiles) ./
# Creates a copy of the llvm library in the build dir, this is meant to support compiler explorer.
# The annoyance is that this copy can be cluttering the development folder. TODO: split staging folders
# for development and compiler explorer builds
cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./
}
build_odin() {
@@ -130,6 +146,14 @@ run_demo() {
./odin run examples/demo/demo.odin -file
}
have_which() {
if ! which which > /dev/null 2>&1; then
panic "Could not find \`which\`"
fi
}
have_which
case $OS in
Linux)
config_linux
+2 -5
View File
@@ -240,14 +240,11 @@ buffer_read_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.
buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
b.last_read = .Invalid
if offset < 0 || offset >= len(b.buf) {
if uint(offset) >= len(b.buf) {
err = .Invalid_Offset
return
}
if 0 <= offset && offset < len(b.buf) {
n = copy(p, b.buf[offset:])
}
n = copy(p, b.buf[offset:])
if n > 0 {
b.last_read = .Read
}
+1 -1
View File
@@ -638,7 +638,7 @@ trim_left_proc :: proc(s: []byte, p: proc(rune) -> bool) -> []byte {
index_rune :: proc(s: []byte, r: rune) -> int {
switch {
case 0 <= r && r < utf8.RUNE_SELF:
case u32(r) < utf8.RUNE_SELF:
return index_byte(s, byte(r))
case r == utf8.RUNE_ERROR:
+15 -2
View File
@@ -14,11 +14,24 @@ when ODIN_OS == .Windows {
// EDOM,
// EILSEQ
// ERANGE
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD {
when ODIN_OS == .Linux {
@(private="file")
@(default_calling_convention="c")
foreign libc {
@(link_name="__libc_errno_location")
@(link_name="__errno_location")
_get_errno :: proc() -> ^int ---
}
EDOM :: 33
EILSEQ :: 84
ERANGE :: 34
}
when ODIN_OS == .FreeBSD {
@(private="file")
@(default_calling_convention="c")
foreign libc {
@(link_name="__error")
_get_errno :: proc() -> ^int ---
}
+4 -1
View File
@@ -1,7 +1,10 @@
package libc
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
foreign import libc {
"system:libucrt.lib",
"system:legacy_stdio_definitions.lib",
}
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
+7 -9
View File
@@ -380,20 +380,18 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm
field := any{field_ptr, type.id}
unmarshal_value(p, field) or_return
if parse_comma(p) {
break struct_loop
}
continue struct_loop
} else {
// allows skipping unused struct fields
parse_value(p) or_return
if parse_comma(p) {
break struct_loop
}
continue struct_loop
}
// NOTE(bill, 2022-09-14): Previously this would not be allowed
// {"foo": 123, "bar": 456}
// T :: struct{foo: int}
// `T` is missing the `bar` field
// The line below is commented out to ignore fields in an object which
// do not have a corresponding target field
//
// return Unsupported_Type_Error{v.id, p.curr_token}
}
case reflect.Type_Info_Map:
+1 -1
View File
@@ -975,7 +975,7 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) {
}
}
else {
io.write_string(fi.writer, s[:fi.width], &fi.n)
io.write_string(fi.writer, s, &fi.n)
}
}
else
+3 -3
View File
@@ -16,7 +16,7 @@ fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
w := io.to_writer(os.stream_from_handle(fd))
return wprintln(w=w, args=args, sep=sep)
}
// fprintf formats according to the specififed format string and writes to fd
// fprintf formats according to the specified format string and writes to fd
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
w := io.to_writer(os.stream_from_handle(fd))
return wprintf(w, fmt, ..args)
@@ -34,12 +34,12 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) }
// println formats using the default print settings and writes to os.stdout
println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) }
// printf formats according to the specififed format string and writes to os.stdout
// printf formats according to the specified format string and writes to os.stdout
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
// eprint formats using the default print settings and writes to os.stderr
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) }
// eprintln formats using the default print settings and writes to os.stderr
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) }
// eprintf formats according to the specififed format string and writes to os.stderr
// eprintf formats according to the specified format string and writes to os.stderr
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
+4 -2
View File
@@ -72,8 +72,9 @@ djbx33a :: proc(data: []byte, seed := u32(5381)) -> (result: [16]byte) #no_bound
return
}
// If you have a choice, prefer fnv32a
@(optimization_mode="speed")
fnv32 :: proc(data: []byte, seed := u32(0x811c9dc5)) -> u32 {
fnv32_no_a :: proc(data: []byte, seed := u32(0x811c9dc5)) -> u32 {
h: u32 = seed
for b in data {
h = (h * 0x01000193) ~ u32(b)
@@ -81,8 +82,9 @@ fnv32 :: proc(data: []byte, seed := u32(0x811c9dc5)) -> u32 {
return h
}
// If you have a choice, prefer fnv64a
@(optimization_mode="speed")
fnv64 :: proc(data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
fnv64_no_a :: proc(data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
h: u64 = seed
for b in data {
h = (h * 0x100000001b3) ~ u64(b)
+9
View File
@@ -182,3 +182,12 @@ shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
array[i], array[j] = array[j], array[i]
}
}
// Returns a random element from the given slice
choice :: proc(array: $T/[]$E, r: ^Rand = nil) -> (res: E) {
n := i64(len(array))
if n < 1 {
return E{}
}
return array[int63_max(n, r)]
}
+2 -6
View File
@@ -1,5 +1,6 @@
package mem
import "core:builtin"
import "core:runtime"
Raw_Any :: runtime.Raw_Any
@@ -21,12 +22,7 @@ make_any :: proc "contextless" (data: rawptr, id: typeid) -> any {
return transmute(any)Raw_Any{data, id}
}
raw_array_data :: runtime.raw_array_data
raw_simd_data :: runtime.raw_simd_data
raw_string_data :: runtime.raw_string_data
raw_slice_data :: runtime.raw_slice_data
raw_dynamic_array_data :: runtime.raw_dynamic_array_data
raw_data :: runtime.raw_data
raw_data :: builtin.raw_data
Poly_Raw_Map_Entry :: struct($Key, $Value: typeid) {
+331
View File
@@ -0,0 +1,331 @@
package mem_virtual
import "core:mem"
Arena_Kind :: enum uint {
Growing = 0, // Chained memory blocks (singly linked list).
Static = 1, // Fixed reservation sized.
Buffer = 2, // Uses a fixed sized buffer.
}
Arena :: struct {
kind: Arena_Kind,
curr_block: ^Memory_Block,
total_used: uint,
total_reserved: uint,
minimum_block_size: uint,
temp_count: uint,
}
// 1 MiB should be enough to start with
DEFAULT_ARENA_STATIC_COMMIT_SIZE :: 1<<20
DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE :: DEFAULT_ARENA_STATIC_COMMIT_SIZE
// 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default
DEFAULT_ARENA_STATIC_RESERVE_SIZE :: 1<<30 when size_of(uintptr) == 8 else 1<<27
@(require_results)
arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) {
arena.kind = .Growing
arena.curr_block = memory_block_alloc(0, reserved, {}) or_return
arena.total_used = 0
arena.total_reserved = arena.curr_block.reserved
return
}
@(require_results)
arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = DEFAULT_ARENA_STATIC_COMMIT_SIZE) -> (err: Allocator_Error) {
arena.kind = .Static
arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return
arena.total_used = 0
arena.total_reserved = arena.curr_block.reserved
return
}
@(require_results)
arena_init_buffer :: proc(arena: ^Arena, buffer: []byte) -> (err: Allocator_Error) {
if len(buffer) < size_of(Memory_Block) {
return .Out_Of_Memory
}
arena.kind = .Buffer
mem.zero_slice(buffer)
block_base := raw_data(buffer)
block := (^Memory_Block)(block_base)
block.base = block_base[size_of(Memory_Block):]
block.reserved = len(buffer) - size_of(Memory_Block)
block.committed = block.reserved
block.used = 0
arena.curr_block = block
arena.total_used = 0
arena.total_reserved = arena.curr_block.reserved
return
}
@(require_results)
arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
assert(alignment & (alignment-1) == 0, "non-power of two alignment", loc)
size := size
if size == 0 {
return nil, nil
}
switch arena.kind {
case .Growing:
if arena.curr_block == nil || (safe_add(arena.curr_block.used, size) or_else 0) > arena.curr_block.reserved {
size = mem.align_forward_uint(size, alignment)
if arena.minimum_block_size == 0 {
arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE
}
block_size := max(size, arena.minimum_block_size)
new_block := memory_block_alloc(size, block_size, {}) or_return
new_block.prev = arena.curr_block
arena.curr_block = new_block
arena.total_reserved += new_block.reserved
}
prev_used := arena.curr_block.used
data, err = alloc_from_memory_block(arena.curr_block, size, alignment)
arena.total_used += arena.curr_block.used - prev_used
case .Static:
if arena.curr_block == nil {
if arena.minimum_block_size == 0 {
arena.minimum_block_size = DEFAULT_ARENA_STATIC_RESERVE_SIZE
}
arena_init_static(arena=arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return
}
fallthrough
case .Buffer:
if arena.curr_block == nil {
return nil, .Out_Of_Memory
}
data, err = alloc_from_memory_block(arena.curr_block, size, alignment)
arena.total_used = arena.curr_block.used
}
return
}
arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) -> bool {
if arena.curr_block != nil {
assert(arena.kind != .Growing, "expected a non .Growing arena", loc)
prev_pos := arena.curr_block.used
arena.curr_block.used = clamp(pos, 0, arena.curr_block.reserved)
if prev_pos < pos {
mem.zero_slice(arena.curr_block.base[arena.curr_block.used:][:pos-prev_pos])
}
arena.total_used = arena.curr_block.used
return true
} else if pos == 0 {
arena.total_used = 0
return true
}
return false
}
arena_growing_free_last_memory_block :: proc(arena: ^Arena, loc := #caller_location) {
if free_block := arena.curr_block; free_block != nil {
assert(arena.kind == .Growing, "expected a .Growing arena", loc)
arena.curr_block = free_block.prev
memory_block_dealloc(free_block)
}
}
arena_free_all :: proc(arena: ^Arena) {
switch arena.kind {
case .Growing:
for arena.curr_block != nil {
arena_growing_free_last_memory_block(arena)
}
arena.total_reserved = 0
case .Static, .Buffer:
arena_static_reset_to(arena, 0)
}
arena.total_used = 0
}
arena_destroy :: proc(arena: ^Arena) {
arena_free_all(arena)
if arena.kind != .Buffer {
memory_block_dealloc(arena.curr_block)
}
arena.curr_block = nil
arena.total_used = 0
arena.total_reserved = 0
arena.temp_count = 0
}
arena_growing_bootstrap_new :: proc{
arena_growing_bootstrap_new_by_offset,
arena_growing_bootstrap_new_by_name,
}
arena_static_bootstrap_new :: proc{
arena_static_bootstrap_new_by_offset,
arena_static_bootstrap_new_by_name,
}
@(require_results)
arena_growing_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) {
bootstrap: Arena
bootstrap.kind = .Growing
bootstrap.minimum_block_size = minimum_block_size
data := arena_alloc(&bootstrap, size_of(T), align_of(T)) or_return
ptr = (^T)(raw_data(data))
(^Arena)(uintptr(ptr) + offset_to_arena)^ = bootstrap
return
}
@(require_results)
arena_growing_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) {
return arena_growing_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size)
}
@(require_results)
arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, reserved: uint) -> (ptr: ^T, err: Allocator_Error) {
bootstrap: Arena
bootstrap.kind = .Static
bootstrap.minimum_block_size = reserved
data := arena_alloc(&bootstrap, size_of(T), align_of(T)) or_return
ptr = (^T)(raw_data(data))
(^Arena)(uintptr(ptr) + offset_to_arena)^ = bootstrap
return
}
@(require_results)
arena_static_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, reserved: uint) -> (ptr: ^T, err: Allocator_Error) {
return arena_static_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), reserved)
}
@(require_results)
arena_allocator :: proc(arena: ^Arena) -> mem.Allocator {
return mem.Allocator{arena_allocator_proc, arena}
}
arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int,
location := #caller_location) -> (data: []byte, err: Allocator_Error) {
arena := (^Arena)(allocator_data)
size, alignment := uint(size), uint(alignment)
old_size := uint(old_size)
switch mode {
case .Alloc, .Alloc_Non_Zeroed:
return arena_alloc(arena, size, alignment)
case .Free:
err = .Mode_Not_Implemented
case .Free_All:
arena_free_all(arena)
case .Resize:
old_data := ([^]byte)(old_memory)
switch {
case old_data == nil:
return arena_alloc(arena, size, alignment)
case size == old_size:
// return old memory
data = old_data[:size]
return
case size == 0:
err = .Mode_Not_Implemented
return
case (uintptr(old_data) & uintptr(alignment-1) == 0) && size < old_size:
// shrink data in-place
data = old_data[:size]
return
}
new_memory := arena_alloc(arena, size, alignment) or_return
if new_memory == nil {
return
}
copy(new_memory, old_data[:old_size])
return new_memory, nil
case .Query_Features:
set := (^mem.Allocator_Mode_Set)(old_memory)
if set != nil {
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Query_Features}
}
case .Query_Info:
err = .Mode_Not_Implemented
}
return
}
Arena_Temp :: struct {
arena: ^Arena,
block: ^Memory_Block,
used: uint,
}
@(require_results)
arena_temp_begin :: proc(arena: ^Arena, loc := #caller_location) -> (temp: Arena_Temp) {
assert(arena != nil, "nil arena", loc)
temp.arena = arena
temp.block = arena.curr_block
if arena.curr_block != nil {
temp.used = arena.curr_block.used
}
arena.temp_count += 1
return
}
arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) {
assert(temp.arena != nil, "nil arena", loc)
arena := temp.arena
memory_block_found := false
for block := arena.curr_block; block != nil; block = block.prev {
if block == temp.block {
memory_block_found = true
break
}
}
if !memory_block_found {
assert(arena.curr_block == temp.block, "memory block stored within Arena_Temp not owned by Arena", loc)
}
for arena.curr_block != temp.block {
arena_growing_free_last_memory_block(arena)
}
if block := arena.curr_block; block != nil {
assert(block.used >= temp.used, "out of order use of arena_temp_end", loc)
amount_to_zero := min(block.used-temp.used, block.reserved-block.used)
mem.zero_slice(block.base[temp.used:][:amount_to_zero])
block.used = temp.used
}
assert(arena.temp_count > 0, "double-use of arena_temp_end", loc)
arena.temp_count -= 1
}
arena_check_temp :: proc(arena: ^Arena, loc := #caller_location) {
assert(arena.temp_count == 0, "Arena_Temp not been ended", loc)
}
-41
View File
@@ -1,41 +0,0 @@
package mem_virtual
arena_init :: proc{
static_arena_init,
growing_arena_init,
}
arena_temp_begin :: proc{
static_arena_temp_begin,
growing_arena_temp_begin,
}
arena_temp_end :: proc{
static_arena_temp_end,
growing_arena_temp_end,
}
arena_check_temp :: proc{
static_arena_check_temp,
growing_arena_check_temp,
}
arena_allocator :: proc{
static_arena_allocator,
growing_arena_allocator,
}
arena_alloc :: proc{
static_arena_alloc,
growing_arena_alloc,
}
arena_free_all :: proc{
static_arena_free_all,
growing_arena_free_all,
}
arena_destroy :: proc{
static_arena_destroy,
growing_arena_destroy,
}
-171
View File
@@ -1,171 +0,0 @@
package mem_virtual
import "core:mem"
Growing_Arena :: struct {
curr_block: ^Memory_Block,
total_used: uint,
total_reserved: uint,
minimum_block_size: uint,
temp_count: int,
}
DEFAULT_MINIMUM_BLOCK_SIZE :: 1<<20 // 1 MiB should be enough
growing_arena_init :: proc(arena: ^Growing_Arena, reserved: uint = DEFAULT_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) {
arena.curr_block = memory_block_alloc(0, reserved, {}) or_return
arena.total_used = 0
arena.total_reserved = arena.curr_block.reserved
return
}
growing_arena_alloc :: proc(arena: ^Growing_Arena, min_size: int, alignment: int) -> (data: []byte, err: Allocator_Error) {
align_forward_offset :: proc "contextless" (arena: ^Growing_Arena, alignment: int) -> uint #no_bounds_check {
alignment_offset := uint(0)
ptr := uintptr(arena.curr_block.base[arena.curr_block.used:])
mask := uintptr(alignment-1)
if ptr & mask != 0 {
alignment_offset = uint(alignment) - uint(ptr & mask)
}
return alignment_offset
}
assert(mem.is_power_of_two(uintptr(alignment)))
size := uint(0)
if arena.curr_block != nil {
size = uint(min_size) + align_forward_offset(arena, alignment)
}
if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved {
size = uint(mem.align_forward_int(min_size, alignment))
arena.minimum_block_size = max(DEFAULT_MINIMUM_BLOCK_SIZE, arena.minimum_block_size)
block_size := max(size, arena.minimum_block_size)
new_block := memory_block_alloc(size, block_size, {}) or_return
new_block.prev = arena.curr_block
arena.curr_block = new_block
arena.total_reserved += new_block.reserved
}
data, err = alloc_from_memory_block(arena.curr_block, int(size), alignment)
if err == nil {
arena.total_used += size
}
return
}
growing_arena_free_last_memory_block :: proc(arena: ^Growing_Arena) {
free_block := arena.curr_block
arena.curr_block = free_block.prev
memory_block_dealloc(free_block)
}
growing_arena_free_all :: proc(arena: ^Growing_Arena) {
for arena.curr_block != nil {
growing_arena_free_last_memory_block(arena)
}
arena.total_used = 0
arena.total_reserved = 0
}
growing_arena_destroy :: proc(arena: ^Growing_Arena) {
growing_arena_free_all(arena)
}
growing_arena_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size := DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) {
bootstrap: Growing_Arena
bootstrap.minimum_block_size = minimum_block_size
data := growing_arena_alloc(&bootstrap, size_of(T), align_of(T)) or_return
ptr = (^T)(raw_data(data))
(^Growing_Arena)(uintptr(ptr) + offset_to_arena)^ = bootstrap
return
}
growing_arena_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size := DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) {
return growing_arena_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size)
}
growing_arena_bootstrap_new :: proc{
growing_arena_bootstrap_new_by_offset,
growing_arena_bootstrap_new_by_name,
}
growing_arena_allocator :: proc(arena: ^Growing_Arena) -> mem.Allocator {
return mem.Allocator{growing_arena_allocator_proc, arena}
}
growing_arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int,
location := #caller_location) -> (data: []byte, err: Allocator_Error) {
arena := (^Growing_Arena)(allocator_data)
switch mode {
case .Alloc, .Alloc_Non_Zeroed:
return growing_arena_alloc(arena, size, alignment)
case .Free:
err = .Mode_Not_Implemented
return
case .Free_All:
growing_arena_free_all(arena)
return
case .Resize:
return mem.default_resize_bytes_align(mem.byte_slice(old_memory, old_size), size, alignment, growing_arena_allocator(arena), location)
case .Query_Features, .Query_Info:
err = .Mode_Not_Implemented
return
}
err = .Mode_Not_Implemented
return
}
Growing_Arena_Temp :: struct {
arena: ^Growing_Arena,
block: ^Memory_Block,
used: uint,
}
growing_arena_temp_begin :: proc(arena: ^Growing_Arena) -> (temp: Growing_Arena_Temp) {
temp.arena = arena
temp.block = arena.curr_block
if arena.curr_block != nil {
temp.used = arena.curr_block.used
}
arena.temp_count += 1
return
}
growing_arena_temp_end :: proc(temp: Growing_Arena_Temp, loc := #caller_location) {
assert(temp.arena != nil, "nil arena", loc)
arena := temp.arena
for arena.curr_block != temp.block {
growing_arena_free_last_memory_block(arena)
}
if block := arena.curr_block; block != nil {
assert(block.used >= temp.used, "out of order use of growing_arena_temp_end", loc)
amount_to_zero := min(block.used-temp.used, block.reserved-block.used)
mem.zero_slice(block.base[temp.used:][:amount_to_zero])
block.used = temp.used
}
assert(arena.temp_count > 0, "double-use of growing_arena_temp_end", loc)
arena.temp_count -= 1
}
growing_arena_check_temp :: proc(arena: ^Growing_Arena, loc := #caller_location) {
assert(arena.temp_count == 0, "Growing_Arena_Temp not been ended", loc)
}
-153
View File
@@ -1,153 +0,0 @@
package mem_virtual
import "core:mem"
Static_Arena :: struct {
block: ^Memory_Block,
total_used: uint,
total_reserved: uint,
minimum_block_size: uint,
temp_count: int,
}
STATIC_ARENA_DEFAULT_COMMIT_SIZE :: 1<<20 // 1 MiB should be enough to start with
// 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default
STATIC_ARENA_DEFAULT_RESERVE_SIZE :: 1<<30 when size_of(uintptr) == 8 else 1<<27
static_arena_init :: proc(arena: ^Static_Arena, reserved: uint, commit_size: uint = STATIC_ARENA_DEFAULT_COMMIT_SIZE) -> (err: Allocator_Error) {
arena.block = memory_block_alloc(commit_size, reserved, {}) or_return
arena.total_used = 0
arena.total_reserved = arena.block.reserved
return
}
static_arena_destroy :: proc(arena: ^Static_Arena) {
memory_block_dealloc(arena.block)
arena^ = {}
}
static_arena_alloc :: proc(arena: ^Static_Arena, size: int, alignment: int) -> (data: []byte, err: Allocator_Error) {
align_forward :: #force_inline proc "contextless" (ptr: uint, align: uint) -> uint {
mask := align-1
return (ptr + mask) &~ mask
}
if arena.block == nil {
reserve_size := max(arena.minimum_block_size, STATIC_ARENA_DEFAULT_RESERVE_SIZE)
static_arena_init(arena, reserve_size, STATIC_ARENA_DEFAULT_COMMIT_SIZE) or_return
}
MINIMUM_ALIGN :: 2*align_of(uintptr)
defer arena.total_used = arena.block.used
return alloc_from_memory_block(arena.block, size, max(MINIMUM_ALIGN, alignment))
}
static_arena_reset_to :: proc(arena: ^Static_Arena, pos: uint) -> bool {
if arena.block != nil {
prev_pos := arena.block.used
arena.block.used = clamp(pos, 0, arena.block.reserved)
if prev_pos < pos {
mem.zero_slice(arena.block.base[arena.block.used:][:pos-prev_pos])
}
return true
} else if pos == 0 {
return true
}
return false
}
static_arena_free_all :: proc(arena: ^Static_Arena) {
static_arena_reset_to(arena, 0)
}
static_arena_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, reserved: uint) -> (ptr: ^T, err: Allocator_Error) {
bootstrap: Static_Arena
bootstrap.minimum_block_size = reserved
data := static_arena_alloc(&bootstrap, size_of(T), align_of(T)) or_return
ptr = (^T)(raw_data(data))
(^Static_Arena)(uintptr(ptr) + offset_to_arena)^ = bootstrap
return
}
static_arena_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, reserved: uint) -> (ptr: ^T, err: Allocator_Error) {
return static_arena_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), reserved)
}
static_arena_bootstrap_new :: proc{
static_arena_bootstrap_new_by_offset,
static_arena_bootstrap_new_by_name,
}
static_arena_allocator :: proc(arena: ^Static_Arena) -> mem.Allocator {
return mem.Allocator{static_arena_allocator_proc, arena}
}
static_arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int,
location := #caller_location) -> (data: []byte, err: Allocator_Error) {
arena := (^Static_Arena)(allocator_data)
switch mode {
case .Alloc, .Alloc_Non_Zeroed:
return static_arena_alloc(arena, size, alignment)
case .Free:
err = .Mode_Not_Implemented
return
case .Free_All:
static_arena_free_all(arena)
return
case .Resize:
return mem.default_resize_bytes_align(mem.byte_slice(old_memory, old_size), size, alignment, static_arena_allocator(arena), location)
case .Query_Features, .Query_Info:
err = .Mode_Not_Implemented
return
}
err = .Mode_Not_Implemented
return
}
Static_Arena_Temp :: struct {
arena: ^Static_Arena,
used: uint,
}
static_arena_temp_begin :: proc(arena: ^Static_Arena) -> (temp: Static_Arena_Temp) {
temp.arena = arena
temp.used = arena.block.used if arena.block != nil else 0
arena.temp_count += 1
return
}
static_arena_temp_end :: proc(temp: Static_Arena_Temp, loc := #caller_location) {
assert(temp.arena != nil, "nil arena", loc)
arena := temp.arena
used := arena.block.used if arena.block != nil else 0
assert(temp.used >= used, "invalid Static_Arena_Temp", loc)
static_arena_reset_to(arena, temp.used)
assert(arena.temp_count > 0, "double-use of static_arena_temp_end", loc)
arena.temp_count -= 1
}
static_arena_check_temp :: proc(arena: ^Static_Arena, loc := #caller_location) {
assert(arena.temp_count == 0, "Static_Arena_Temp not been ended", loc)
}
+18 -15
View File
@@ -1,6 +1,7 @@
package mem_virtual
import "core:mem"
import "core:intrinsics"
DEFAULT_PAGE_SIZE := uint(4096)
@@ -95,18 +96,11 @@ memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags)
pmblock.block.committed = committed
pmblock.block.reserved = reserved
sentinel := &global_platform_memory_block_sentinel
platform_mutex_lock()
pmblock.next = sentinel
pmblock.prev = sentinel.prev
pmblock.prev.next = pmblock
pmblock.next.prev = pmblock
platform_mutex_unlock()
return &pmblock.block, nil
}
alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: int) -> (data: []byte, err: Allocator_Error) {
alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) -> (data: []byte, err: Allocator_Error) {
calc_alignment_offset :: proc "contextless" (block: ^Memory_Block, alignment: uintptr) -> uint {
alignment_offset := uint(0)
ptr := uintptr(block.base[block.used:])
@@ -134,11 +128,18 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: int)
return nil
}
if block == nil {
return nil, .Out_Of_Memory
}
alignment_offset := calc_alignment_offset(block, uintptr(alignment))
size := uint(min_size) + alignment_offset
size, size_ok := safe_add(min_size, alignment_offset)
if !size_ok {
err = .Out_Of_Memory
return
}
if block.used + size > block.reserved {
if to_be_used, ok := safe_add(block.used, size); !ok || to_be_used > block.reserved {
err = .Out_Of_Memory
return
}
@@ -153,12 +154,14 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: int)
memory_block_dealloc :: proc(block_to_free: ^Memory_Block) {
if block := (^Platform_Memory_Block)(block_to_free); block != nil {
platform_mutex_lock()
block.prev.next = block.next
block.next.prev = block.prev
platform_mutex_unlock()
platform_memory_free(block)
}
}
@(private)
safe_add :: #force_inline proc "contextless" (x, y: uint) -> (uint, bool) {
z, did_overflow := intrinsics.overflow_add(x, y)
return z, !did_overflow
}
-26
View File
@@ -1,13 +1,10 @@
//+private
package mem_virtual
import "core:sync"
Platform_Memory_Block :: struct {
block: Memory_Block,
committed: uint,
reserved: uint,
prev, next: ^Platform_Memory_Block,
}
platform_memory_alloc :: proc "contextless" (to_commit, to_reserve: uint) -> (block: ^Platform_Memory_Block, err: Allocator_Error) {
@@ -33,28 +30,6 @@ platform_memory_free :: proc "contextless" (block: ^Platform_Memory_Block) {
}
}
platform_mutex_lock :: proc() {
sync.mutex_lock(&global_memory_block_mutex)
}
platform_mutex_unlock :: proc() {
sync.mutex_unlock(&global_memory_block_mutex)
}
global_memory_block_mutex: sync.Mutex
global_platform_memory_block_sentinel: Platform_Memory_Block
global_platform_memory_block_sentinel_set: bool
@(init)
platform_memory_init :: proc() {
if !global_platform_memory_block_sentinel_set {
_platform_memory_init()
global_platform_memory_block_sentinel.prev = &global_platform_memory_block_sentinel
global_platform_memory_block_sentinel.next = &global_platform_memory_block_sentinel
global_platform_memory_block_sentinel_set = true
}
}
platform_memory_commit :: proc "contextless" (block: ^Platform_Memory_Block, to_commit: uint) -> (err: Allocator_Error) {
if to_commit < block.committed {
return nil
@@ -63,7 +38,6 @@ platform_memory_commit :: proc "contextless" (block: ^Platform_Memory_Block, to_
return .Out_Of_Memory
}
commit(block, to_commit) or_return
block.committed = to_commit
return nil
+1 -4
View File
@@ -2,7 +2,6 @@ package os
import win32 "core:sys/windows"
import "core:strings"
import "core:time"
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) {
@@ -41,9 +40,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F
// fi.mode |= file_type_mode(h);
}
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
windows_set_file_info_times(&fi, d)
fi.is_dir = fi.mode & File_Mode_Dir != 0
return
+4 -2
View File
@@ -162,7 +162,8 @@ read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
total_read: int
length := len(data)
to_read := min(win32.DWORD(length), MAX_RW)
// NOTE(Jeroen): `length` can't be casted to win32.DWORD here because it'll overflow if > 4 GiB and return 0 if exactly that.
to_read := min(i64(length), MAX_RW)
e: win32.BOOL
if is_console {
@@ -172,7 +173,8 @@ read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
return int(total_read), err
}
} else {
e = win32.ReadFile(handle, &data[total_read], to_read, &single_read_length, nil)
// NOTE(Jeroen): So we cast it here *after* we've ensured that `to_read` is at most MAX_RW (1 GiB)
e = win32.ReadFile(handle, &data[total_read], win32.DWORD(to_read), &single_read_length, nil)
}
if single_read_length <= 0 || !e {
err := Errno(win32.GetLastError())
+1 -1
View File
@@ -130,7 +130,7 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File {
f := new(File, _file_allocator())
f.impl.allocator = _file_allocator()
f.impl.fd = rawptr(fd)
f.impl.fd = rawptr(handle)
f.impl.name = strings.clone(name, f.impl.allocator)
f.impl.wname = win32.utf8_to_wstring(name, f.impl.allocator)
+32 -11
View File
@@ -369,27 +369,48 @@ close :: proc(fd: Handle) -> bool {
return _unix_close(fd) == 0
}
@(private)
MAX_RW :: 0x7fffffff // The limit on Darwin is max(i32), trying to read/write more than that fails.
write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
assert(fd != -1)
if len(data) == 0 {
return 0, 0
bytes_total := len(data)
bytes_written_total := 0
for bytes_written_total < bytes_total {
bytes_to_write := min(bytes_total - bytes_written_total, MAX_RW)
slice := data[bytes_written_total:bytes_written_total + bytes_to_write]
bytes_written := _unix_write(fd, raw_data(slice), bytes_to_write)
if bytes_written == -1 {
return bytes_written_total, 1
}
bytes_written_total += bytes_written
}
bytes_written := _unix_write(fd, raw_data(data), len(data))
if bytes_written == -1 {
return 0, 1
}
return bytes_written, 0
return bytes_written_total, 0
}
read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
assert(fd != -1)
bytes_read := _unix_read(fd, raw_data(data), len(data))
if bytes_read == -1 {
return 0, 1
bytes_total := len(data)
bytes_read_total := 0
for bytes_read_total < bytes_total {
bytes_to_read := min(bytes_total - bytes_read_total, MAX_RW)
slice := data[bytes_read_total:bytes_read_total + bytes_to_read]
bytes_read := _unix_read(fd, raw_data(slice), bytes_to_read)
if bytes_read == -1 {
return bytes_read_total, 1
}
if bytes_read == 0 {
break
}
bytes_read_total += bytes_read
}
return bytes_read, 0
return bytes_read_total, 0
}
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
+32 -3
View File
@@ -24,7 +24,7 @@ O_CLOEXEC :: 0x80000
stdin: Handle = 0
stdout: Handle = 1
stderr: Handle = 2
current_dir: Handle = 3
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
iovs := wasi.ciovec_t(data)
@@ -47,7 +47,36 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
return int(n), Errno(err)
}
open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
return 0, -1
oflags: wasi.oflags_t
if mode & O_CREATE == O_CREATE {
oflags += {.CREATE}
}
if mode & O_EXCL == O_EXCL {
oflags += {.EXCL}
}
if mode & O_TRUNC == O_TRUNC {
oflags += {.TRUNC}
}
rights: wasi.rights_t = {.FD_SEEK, .FD_FILESTAT_GET}
switch mode & (O_RDONLY|O_WRONLY|O_RDWR) {
case O_RDONLY: rights += {.FD_READ}
case O_WRONLY: rights += {.FD_WRITE}
case O_RDWR: rights += {.FD_READ, .FD_WRITE}
}
fdflags: wasi.fdflags_t
if mode & O_APPEND == O_APPEND {
fdflags += {.APPEND}
}
if mode & O_NONBLOCK == O_NONBLOCK {
fdflags += {.NONBLOCK}
}
if mode & O_SYNC == O_SYNC {
fdflags += {.SYNC}
}
fd, err := wasi.path_open(wasi.fd_t(current_dir),{.SYMLINK_FOLLOW},path,oflags,rights,{},fdflags)
return Handle(fd), Errno(err)
}
close :: proc(fd: Handle) -> Errno {
err := wasi.fd_close(wasi.fd_t(fd))
@@ -96,4 +125,4 @@ heap_free :: proc(ptr: rawptr) {
exit :: proc "contextless" (code: int) -> ! {
runtime._cleanup_runtime_contextless()
wasi.proc_exit(wasi.exitcode_t(code))
}
}
+10 -10
View File
@@ -228,6 +228,13 @@ file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HAN
return
}
@(private)
windows_set_file_info_times :: proc(fi: ^File_Info, d: ^$T) {
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
}
@(private)
file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string) -> (fi: File_Info, e: Errno) {
fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
@@ -235,9 +242,7 @@ file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_
fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0)
fi.is_dir = fi.mode & File_Mode_Dir != 0
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
windows_set_file_info_times(&fi, d)
fi.fullpath, e = full_path_from_name(name)
fi.name = basename(fi.fullpath)
@@ -252,9 +257,7 @@ file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string)
fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0)
fi.is_dir = fi.mode & File_Mode_Dir != 0
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
windows_set_file_info_times(&fi, d)
fi.fullpath, e = full_path_from_name(name)
fi.name = basename(fi.fullpath)
@@ -290,10 +293,7 @@ file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HAN
fi.mode |= file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag)
fi.is_dir = fi.mode & File_Mode_Dir != 0
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
windows_set_file_info_times(&fi, &d)
return fi, ERROR_NONE
}
+1 -29
View File
@@ -672,7 +672,7 @@ shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #call
@builtin
map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (ptr: ^V) {
key, value := key, value
h := __get_map_header(T)
h := __get_map_header_table(T)
e := __dynamic_map_set(m, h, __get_map_key_hash(&key), &key, &value, loc)
return (^V)(uintptr(e) + h.value_offset)
@@ -731,34 +731,6 @@ card :: proc(s: $S/bit_set[$E; $U]) -> int {
@builtin
raw_array_data :: proc "contextless" (a: $P/^($T/[$N]$E)) -> [^]E {
return ([^]E)(a)
}
@builtin
raw_simd_data :: proc "contextless" (a: $P/^($T/#simd[$N]$E)) -> [^]E {
return ([^]E)(a)
}
@builtin
raw_slice_data :: proc "contextless" (s: $S/[]$E) -> [^]E {
ptr := (transmute(Raw_Slice)s).data
return ([^]E)(ptr)
}
@builtin
raw_dynamic_array_data :: proc "contextless" (s: $S/[dynamic]$E) -> [^]E {
ptr := (transmute(Raw_Dynamic_Array)s).data
return ([^]E)(ptr)
}
@builtin
raw_string_data :: proc "contextless" (s: $S/string) -> [^]u8 {
return (transmute(Raw_String)s).data
}
@builtin
raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_string_data, raw_simd_data}
@builtin
@(disabled=ODIN_DISABLE_ASSERT)
assert :: proc(condition: bool, message := "", loc := #caller_location) {
+3 -3
View File
@@ -18,7 +18,7 @@ type_assertion_trap :: proc "contextless" () -> ! {
bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) {
if 0 <= index && index < count {
if uint(index) < uint(count) {
return
}
@(cold)
@@ -99,8 +99,8 @@ dynamic_array_expr_error :: proc "contextless" (file: string, line, column: i32,
matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32, row_index, column_index, row_count, column_count: int) {
if 0 <= row_index && row_index < row_count &&
0 <= column_index && column_index < column_count {
if uint(row_index) < uint(row_count) &&
uint(column_index) < uint(column_count) {
return
}
@(cold)
+1 -1
View File
@@ -12,7 +12,7 @@ objc_SEL :: ^intrinsics.objc_selector
foreign Foundation {
objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class ---
sel_registerName :: proc "c" (name: cstring) -> objc_SEL ---
objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) ---
objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) -> objc_Class ---
objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 ---
+2 -2
View File
@@ -321,14 +321,14 @@ last_ptr :: proc(array: $T/[]$E) -> ^E {
}
get :: proc(array: $T/[]$E, index: int) -> (value: E, ok: bool) {
if 0 <= index && index < len(array) {
if uint(index) < len(array) {
value = array[index]
ok = true
}
return
}
get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) {
if 0 <= index && index < len(array) {
if uint(index) < len(array) {
value = &array[index]
ok = true
}
+3 -2
View File
@@ -177,7 +177,6 @@ _quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND
}
// merge sort
_stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check {
less :: #force_inline proc(a, b: E, call: P) -> bool {
when KIND == .Ordered {
@@ -190,7 +189,9 @@ _stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (O
#panic("unhandled Sort_Kind")
}
}
// insertion sort
// TODO(bill): use a different algorithm as insertion sort is O(n^2)
n := len(data)
for i in 1..<n {
for j := i; j > 0 && less(data[j], data[j-1], call); j -= 1 {
+41 -2
View File
@@ -567,7 +567,7 @@ parse_f32 :: proc(s: string, n: ^int = nil) -> (value: f32, ok: bool) {
// ```
parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
s := str
defer if n != nil { n^ = len(str)-len(s) }
defer if n != nil { n^ = len(str) - len(s) }
if s == "" {
return
}
@@ -575,9 +575,11 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
i := 0
sign: f64 = 1
seen_sign := true
switch s[i] {
case '-': i += 1; sign = -1
case '+': i += 1
case: seen_sign = false
}
for ; i < len(s); i += 1 {
@@ -588,6 +590,38 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
v := _digit_value(r)
if v >= 10 {
if r == '.' || r == 'e' || r == 'E' { // Skip parsing NaN and Inf if it's probably a regular float
break
}
if len(s) >= 3 + i {
buf: [4]u8
copy(buf[:], s[i:][:3])
v2 := transmute(u32)buf
v2 &= 0xDFDFDFDF // Knock out lower-case bits
buf = transmute([4]u8)v2
when ODIN_ENDIAN == .Little {
if v2 == 0x464e49 { // "INF"
s = s[3+i:]
value = 0h7ff00000_00000000 if sign == 1 else 0hfff00000_00000000
return value, len(s) == 0
} else if v2 == 0x4e414e { // "NAN"
s = s[3+i:]
return 0h7ff80000_00000001, len(s) == 0
}
} else {
if v2 == 0x494e4600 { // "\0FNI"
s = s[3+i:]
value = 0h7ff00000_00000000 if sign == 1 else 0hfff00000_00000000
return value, len(s) == 0
} else if v2 == 0x4e414e00 { // "\0NAN"
s = s[3+i:]
return 0h7ff80000_00000001, len(s) == 0
}
}
}
break
}
value *= 10
@@ -645,8 +679,13 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
for exp > 0 { scale *= 10; exp -= 1 }
}
}
s = s[i:]
// If we only consumed a sign, return false
if i == 1 && seen_sign {
return 0, false
}
s = s[i:]
if frac {
value = sign * (value/scale)
} else {
+1 -1
View File
@@ -760,7 +760,7 @@ last_index_byte :: proc(s: string, c: byte) -> int {
*/
index_rune :: proc(s: string, r: rune) -> int {
switch {
case 0 <= r && r < utf8.RUNE_SELF:
case u32(r) < utf8.RUNE_SELF:
return index_byte(s, byte(r))
case r == utf8.RUNE_ERROR:
+1
View File
@@ -464,6 +464,7 @@ macos_release_map: map[string]Darwin_To_Release = {
"21F2092" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}},
"21G72" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 0}}},
"21G83" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 1}}},
"21G115" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 0}}},
}
@(private)
+30
View File
@@ -128,4 +128,34 @@ foreign advapi32 {
lpData: LPCVOID,
cbData: DWORD,
) -> LSTATUS ---
GetFileSecurityW :: proc(
lpFileName: LPCWSTR,
RequestedInformation: SECURITY_INFORMATION,
pSecurityDescriptor: PSECURITY_DESCRIPTOR,
nLength: DWORD,
lpnLengthNeeded: LPDWORD,
) -> BOOL ---
DuplicateToken :: proc(
ExistingTokenHandle: HANDLE,
ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL,
DuplicateTokenHandle: PHANDLE,
) -> BOOL ---
MapGenericMask :: proc(
AccessMask: PDWORD,
GenericMapping: PGENERIC_MAPPING,
) ---
AccessCheck :: proc(
pSecurityDescriptor: PSECURITY_DESCRIPTOR,
ClientToken: HANDLE,
DesiredAccess: DWORD,
GenericMapping: PGENERIC_MAPPING,
PrivilegeSet: PPRIVILEGE_SET,
PrivilegeSetLength: LPDWORD,
GrantedAccess: LPDWORD,
AccessStatus: LPBOOL,
) -> BOOL ---
}
+9
View File
@@ -0,0 +1,9 @@
// +build windows
package sys_windows
foreign import "system:Comctl32.lib"
@(default_calling_convention="stdcall")
foreign Comctl32 {
LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT ---
}
+1
View File
@@ -77,6 +77,7 @@ foreign gdi32 {
) -> HFONT ---
TextOutW :: proc(hdc: HDC, x, y: c_int, lpString: LPCWSTR, c: c_int) -> BOOL ---
GetTextExtentPoint32W :: proc(hdc: HDC, lpString: LPCWSTR, c: c_int, psizl: LPSIZE) -> BOOL ---
GetTextMetricsW :: proc(hdc: HDC, lptm: LPTEXTMETRICW) -> BOOL ---
}
RGB :: #force_inline proc "contextless" (r, g, b: u8) -> COLORREF {
+173
View File
@@ -248,6 +248,17 @@ foreign kernel32 {
GetModuleHandleW :: proc(lpModuleName: LPCWSTR) -> HMODULE ---
GetModuleHandleA :: proc(lpModuleName: LPCSTR) -> HMODULE ---
GetSystemTimeAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) ---
GetSystemTimePreciseAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) ---
FileTimeToSystemTime :: proc(lpFileTime: ^FILETIME, lpSystemTime: ^SYSTEMTIME) -> BOOL ---
SystemTimeToTzSpecificLocalTime :: proc(
lpTimeZoneInformation: ^TIME_ZONE_INFORMATION,
lpUniversalTime: ^SYSTEMTIME,
lpLocalTime: ^SYSTEMTIME,
) -> BOOL ---
SystemTimeToFileTime :: proc(
lpSystemTime: ^SYSTEMTIME,
lpFileTime: LPFILETIME,
) -> BOOL ---
CreateEventW :: proc(
lpEventAttributes: LPSECURITY_ATTRIBUTES,
bManualReset: BOOL,
@@ -346,6 +357,13 @@ foreign kernel32 {
GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL ---
FreeConsole :: proc() -> BOOL ---
GetConsoleWindow :: proc() -> HWND ---
GetDiskFreeSpaceExW :: proc(
lpDirectoryName: LPCWSTR,
lpFreeBytesAvailableToCaller: PULARGE_INTEGER,
lpTotalNumberOfBytes: PULARGE_INTEGER,
lpTotalNumberOfFreeBytes: PULARGE_INTEGER,
) -> BOOL ---
}
@@ -820,3 +838,158 @@ foreign kernel32 {
HandlerRoutine :: proc "stdcall" (dwCtrlType: DWORD) -> BOOL
PHANDLER_ROUTINE :: HandlerRoutine
DCB_Config :: struct {
fParity: bool,
fOutxCtsFlow: bool,
fOutxDsrFlow: bool,
fDtrControl: DTR_Control,
fDsrSensitivity: bool,
fTXContinueOnXoff: bool,
fOutX: bool,
fInX: bool,
fErrorChar: bool,
fNull: bool,
fRtsControl: RTS_Control,
fAbortOnError: bool,
BaudRate: DWORD,
ByteSize: BYTE,
Parity: Parity,
StopBits: Stop_Bits,
XonChar: byte,
XoffChar: byte,
ErrorChar: byte,
EvtChar: byte,
}
DTR_Control :: enum byte {
Disable = 0,
Enable = 1,
Handshake = 2,
}
RTS_Control :: enum byte {
Disable = 0,
Enable = 1,
Handshake = 2,
Toggle = 3,
}
Parity :: enum byte {
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4,
}
Stop_Bits :: enum byte {
One = 0,
One_And_A_Half = 1,
Two = 2,
}
// A helper procedure to set the values of a DCB structure.
init_dcb_with_config :: proc "contextless" (dcb: ^DCB, config: DCB_Config) {
out: u32
// NOTE(tetra, 2022-09-21): On both Clang 14 on Windows, and MSVC, the bits in the bitfield
// appear to be defined from LSB to MSB order.
// i.e: `fBinary` (the first bitfield in the C source) is the LSB in the `settings` u32.
out |= u32(1) << 0 // fBinary must always be true on Windows.
out |= u32(config.fParity) << 1
out |= u32(config.fOutxCtsFlow) << 2
out |= u32(config.fOutxDsrFlow) << 3
out |= u32(config.fDtrControl) << 4
out |= u32(config.fDsrSensitivity) << 6
out |= u32(config.fTXContinueOnXoff) << 7
out |= u32(config.fOutX) << 8
out |= u32(config.fInX) << 9
out |= u32(config.fErrorChar) << 10
out |= u32(config.fNull) << 11
out |= u32(config.fRtsControl) << 12
out |= u32(config.fAbortOnError) << 14
dcb.settings = out
dcb.BaudRate = config.BaudRate
dcb.ByteSize = config.ByteSize
dcb.Parity = config.Parity
dcb.StopBits = config.StopBits
dcb.XonChar = config.XonChar
dcb.XoffChar = config.XoffChar
dcb.ErrorChar = config.ErrorChar
dcb.EvtChar = config.EvtChar
dcb.DCBlength = size_of(DCB)
}
get_dcb_config :: proc "contextless" (dcb: DCB) -> (config: DCB_Config) {
config.fParity = bool((dcb.settings >> 1) & 0x01)
config.fOutxCtsFlow = bool((dcb.settings >> 2) & 0x01)
config.fOutxDsrFlow = bool((dcb.settings >> 3) & 0x01)
config.fDtrControl = DTR_Control((dcb.settings >> 4) & 0x02)
config.fDsrSensitivity = bool((dcb.settings >> 6) & 0x01)
config.fTXContinueOnXoff = bool((dcb.settings >> 7) & 0x01)
config.fOutX = bool((dcb.settings >> 8) & 0x01)
config.fInX = bool((dcb.settings >> 9) & 0x01)
config.fErrorChar = bool((dcb.settings >> 10) & 0x01)
config.fNull = bool((dcb.settings >> 11) & 0x01)
config.fRtsControl = RTS_Control((dcb.settings >> 12) & 0x02)
config.fAbortOnError = bool((dcb.settings >> 14) & 0x01)
config.BaudRate = dcb.BaudRate
config.ByteSize = dcb.ByteSize
config.Parity = dcb.Parity
config.StopBits = dcb.StopBits
config.XonChar = dcb.XonChar
config.XoffChar = dcb.XoffChar
config.ErrorChar = dcb.ErrorChar
config.EvtChar = dcb.EvtChar
return
}
// NOTE(tetra): See get_dcb_config() and init_dcb_with_config() for help with initializing this.
DCB :: struct {
DCBlength: DWORD, // NOTE(tetra): Must be set to size_of(DCB).
BaudRate: DWORD,
settings: u32, // NOTE(tetra): These are bitfields in the C struct.
wReserved: WORD,
XOnLim: WORD,
XOffLim: WORD,
ByteSize: BYTE,
Parity: Parity,
StopBits: Stop_Bits,
XonChar: byte,
XoffChar: byte,
ErrorChar: byte,
EofChar: byte,
EvtChar: byte,
wReserved1: WORD,
}
@(default_calling_convention="stdcall")
foreign kernel32 {
GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
}
LPFIBER_START_ROUTINE :: #type proc "stdcall" (lpFiberParameter: LPVOID)
@(default_calling_convention = "stdcall")
foreign kernel32 {
CreateFiber :: proc(dwStackSize: SIZE_T, lpStartAddress: LPFIBER_START_ROUTINE, lpParameter: LPVOID) -> LPVOID ---
DeleteFiber :: proc(lpFiber: LPVOID) ---
ConvertThreadToFiber :: proc(lpParameter: LPVOID) -> LPVOID ---
SwitchToFiber :: proc(lpFiber: LPVOID) ---
}
+6
View File
@@ -14,4 +14,10 @@ foreign shell32 {
lpDirectory: LPCWSTR,
nShowCmd: INT,
) -> HINSTANCE ---
SHCreateDirectoryExW :: proc(
hwnd: HWND,
pszPath: LPCWSTR,
psa: ^SECURITY_ATTRIBUTES,
) -> c_int ---
SHFileOperationW :: proc(lpFileOp: LPSHFILEOPSTRUCTW) -> c_int ---
}
+1
View File
@@ -8,4 +8,5 @@ foreign shlwapi {
PathFileExistsW :: proc(pszPath: wstring) -> BOOL ---
PathFindExtensionW :: proc(pszPath: wstring) -> wstring ---
PathFindFileNameW :: proc(pszPath: wstring) -> wstring ---
SHAutoComplete :: proc(hwndEdit: HWND, dwFlags: DWORD) -> LWSTDAPI ---
}
+280 -4
View File
@@ -20,6 +20,7 @@ DWORD :: c_ulong
DWORDLONG :: c.ulonglong
QWORD :: c.ulonglong
HANDLE :: distinct LPVOID
PHANDLE :: ^HANDLE
HINSTANCE :: HANDLE
HMODULE :: distinct HINSTANCE
HRESULT :: distinct LONG
@@ -43,6 +44,7 @@ BOOLEAN :: distinct b8
GROUP :: distinct c_uint
LARGE_INTEGER :: distinct c_longlong
ULARGE_INTEGER :: distinct c_ulonglong
PULARGE_INTEGER :: ^ULARGE_INTEGER
LONG :: c_long
UINT :: c_uint
INT :: c_int
@@ -133,6 +135,11 @@ LPWSAOVERLAPPED :: distinct rawptr
LPWSAOVERLAPPED_COMPLETION_ROUTINE :: distinct rawptr
LPCVOID :: rawptr
PACCESS_TOKEN :: PVOID
PSECURITY_DESCRIPTOR :: PVOID
PSID :: PVOID
PCLAIMS_BLOB :: PVOID
PCONDITION_VARIABLE :: ^CONDITION_VARIABLE
PLARGE_INTEGER :: ^LARGE_INTEGER
PSRWLOCK :: ^SRWLOCK
@@ -175,6 +182,7 @@ FILE_SHARE_DELETE: DWORD : 0x00000004
FILE_GENERIC_ALL: DWORD : 0x10000000
FILE_GENERIC_EXECUTE: DWORD : 0x20000000
FILE_GENERIC_READ: DWORD : 0x80000000
FILE_ALL_ACCESS :: STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF
FILE_ACTION_ADDED :: 0x00000001
FILE_ACTION_REMOVED :: 0x00000002
@@ -230,6 +238,20 @@ SECURITY_SQOS_PRESENT: DWORD : 0x00100000
FIONBIO: c_ulong : 0x8004667e
OWNER_SECURITY_INFORMATION :: 0x00000001
GROUP_SECURITY_INFORMATION :: 0x00000002
DACL_SECURITY_INFORMATION :: 0x00000004
SACL_SECURITY_INFORMATION :: 0x00000008
LABEL_SECURITY_INFORMATION :: 0x00000010
ATTRIBUTE_SECURITY_INFORMATION :: 0x00000020
SCOPE_SECURITY_INFORMATION :: 0x00000040
PROCESS_TRUST_LABEL_SECURITY_INFORMATION :: 0x00000080
ACCESS_FILTER_SECURITY_INFORMATION :: 0x00000100
BACKUP_SECURITY_INFORMATION :: 0x00010000
PROTECTED_DACL_SECURITY_INFORMATION :: 0x80000000
PROTECTED_SACL_SECURITY_INFORMATION :: 0x40000000
UNPROTECTED_DACL_SECURITY_INFORMATION :: 0x20000000
UNPROTECTED_SACL_SECURITY_INFORMATION :: 0x10000000
GET_FILEEX_INFO_LEVELS :: distinct i32
GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0
@@ -773,6 +795,30 @@ MSG :: struct {
LPMSG :: ^MSG
TEXTMETRICW :: struct {
tmHeight: LONG,
tmAscent: LONG,
tmDescent: LONG,
tmInternalLeading: LONG,
tmExternalLeading: LONG,
tmAveCharWidth: LONG,
tmMaxCharWidth: LONG,
tmWeight: LONG,
tmOverhang: LONG,
tmDigitizedAspectX: LONG,
tmDigitizedAspectY: LONG,
tmFirstChar: WCHAR,
tmLastChar: WCHAR,
tmDefaultChar: WCHAR,
tmBreakChar: WCHAR,
tmItalic: BYTE,
tmUnderlined: BYTE,
tmStruckOut: BYTE,
tmPitchAndFamily: BYTE,
tmCharSet: BYTE,
}
LPTEXTMETRICW :: ^TEXTMETRICW
PAINTSTRUCT :: struct {
hdc: HDC,
fErase: BOOL,
@@ -879,6 +925,48 @@ NM_FONTCHANGED :: NM_OUTOFMEMORY-22
NM_CUSTOMTEXT :: NM_OUTOFMEMORY-23 // uses NMCUSTOMTEXT struct
NM_TVSTATEIMAGECHANGING :: NM_OUTOFMEMORY-23 // uses NMTVSTATEIMAGECHANGING struct, defined after HTREEITEM
PCZZWSTR :: ^WCHAR
SHFILEOPSTRUCTW :: struct {
hwnd: HWND,
wFunc: UINT,
pFrom: PCZZWSTR,
pTo: PCZZWSTR,
fFlags: FILEOP_FLAGS,
fAnyOperationsAborted: BOOL,
hNameMappings: LPVOID,
lpszProgressTitle: PCWSTR, // only used if FOF_SIMPLEPROGRESS
}
LPSHFILEOPSTRUCTW :: ^SHFILEOPSTRUCTW
// Shell File Operations
FO_MOVE :: 0x0001
FO_COPY :: 0x0002
FO_DELETE :: 0x0003
FO_RENAME :: 0x0004
// SHFILEOPSTRUCT.fFlags and IFileOperation::SetOperationFlags() flag values
FOF_MULTIDESTFILES :: 0x0001
FOF_CONFIRMMOUSE :: 0x0002
FOF_SILENT :: 0x0004 // don't display progress UI (confirm prompts may be displayed still)
FOF_RENAMEONCOLLISION :: 0x0008 // automatically rename the source files to avoid the collisions
FOF_NOCONFIRMATION :: 0x0010 // don't display confirmation UI, assume "yes" for cases that can be bypassed, "no" for those that can not
FOF_WANTMAPPINGHANDLE :: 0x0020 // Fill in SHFILEOPSTRUCT.hNameMappings
// Must be freed using SHFreeNameMappings
FOF_ALLOWUNDO :: 0x0040 // enable undo including Recycle behavior for IFileOperation::Delete()
FOF_FILESONLY :: 0x0080 // only operate on the files (non folders), both files and folders are assumed without this
FOF_SIMPLEPROGRESS :: 0x0100 // means don't show names of files
FOF_NOCONFIRMMKDIR :: 0x0200 // don't dispplay confirmatino UI before making any needed directories, assume "Yes" in these cases
FOF_NOERRORUI :: 0x0400 // don't put up error UI, other UI may be displayed, progress, confirmations
FOF_NOCOPYSECURITYATTRIBS :: 0x0800 // dont copy file security attributes (ACLs)
FOF_NORECURSION :: 0x1000 // don't recurse into directories for operations that would recurse
FOF_NO_CONNECTED_ELEMENTS :: 0x2000 // don't operate on connected elements ("xxx_files" folders that go with .htm files)
FOF_WANTNUKEWARNING :: 0x4000 // during delete operation, warn if object is being permanently destroyed instead of recycling (partially overrides FOF_NOCONFIRMATION)
FOF_NORECURSEREPARSE :: 0x8000 // deprecated; the operations engine always does the right thing on FolderLink objects (symlinks, reparse points, folder shortcuts)
FOF_NO_UI :: (FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR) // don't display any UI at all
FILEOP_FLAGS :: WORD
DEVMODEW :: struct {
dmDeviceName: [32]wchar_t,
dmSpecVersion: WORD,
@@ -1066,8 +1154,14 @@ WS_EX_TOPMOST : UINT : 0x0000_0008
WS_EX_TRANSPARENT : UINT : 0x0000_0020
WS_EX_WINDOWEDGE : UINT : 0x0000_0100
PBS_SMOOTH :: 0x01
PBS_VERTICAL :: 0x04
PBS_SMOOTH :: 0x01
PBS_VERTICAL :: 0x04
PBS_MARQUEE :: 0x08
PBS_SMOOTHREVERSE :: 0x10
PBST_NORMAL :: 0x0001
PBST_ERROR :: 0x0002
PBST_PAUSED :: 0x0003
QS_ALLEVENTS : UINT : QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY
QS_ALLINPUT : UINT : QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE
@@ -1462,6 +1556,24 @@ IDI_WARNING := IDI_EXCLAMATION
IDI_ERROR := IDI_HAND
IDI_INFORMATION := IDI_ASTERISK
IMAGE_BITMAP :: 0
IMAGE_ICON :: 1
IMAGE_CURSOR :: 2
IMAGE_ENHMETAFILE :: 3
LR_DEFAULTCOLOR :: 0x00000000
LR_MONOCHROME :: 0x00000001
LR_COLOR :: 0x00000002
LR_COPYRETURNORG :: 0x00000004
LR_COPYDELETEORG :: 0x00000008
LR_LOADFROMFILE :: 0x00000010
LR_LOADTRANSPARENT :: 0x00000020
LR_DEFAULTSIZE :: 0x00000040
LR_VGACOLOR :: 0x00000080
LR_LOADMAP3DCOLORS :: 0x00001000
LR_CREATEDIBSECTION :: 0x00002000
LR_COPYFROMRESOURCE :: 0x00004000
LR_SHARED :: 0x00008000
// DIB color table identifiers
DIB_RGB_COLORS :: 0
@@ -1662,6 +1774,7 @@ WSAENOTCONN: c_int : 10057
WSAESHUTDOWN: c_int : 10058
WSAETIMEDOUT: c_int : 10060
WSAECONNREFUSED: c_int : 10061
WSATRY_AGAIN: c_int : 11002
MAX_PROTOCOL_CHAIN: DWORD : 7
@@ -1773,12 +1886,15 @@ WAIT_FAILED: DWORD : 0xFFFFFFFF
PIPE_ACCESS_INBOUND: DWORD : 0x00000001
PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002
PIPE_ACCESS_DUPLEX: DWORD : 0x00000003
FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000
FILE_FLAG_OVERLAPPED: DWORD : 0x40000000
PIPE_WAIT: DWORD : 0x00000000
PIPE_TYPE_BYTE: DWORD : 0x00000000
PIPE_TYPE_MESSAGE: DWORD : 0x00000004
PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008
PIPE_READMODE_BYTE: DWORD : 0x00000000
PIPE_READMODE_MESSAGE: DWORD : 0x00000002
PIPE_ACCEPT_REMOTE_CLIENTS: DWORD : 0x00000000
FD_SETSIZE :: 64
@@ -1792,7 +1908,58 @@ HEAP_ZERO_MEMORY: DWORD : 0x00000008
HANDLE_FLAG_INHERIT: DWORD : 0x00000001
HANDLE_FLAG_PROTECT_FROM_CLOSE :: 0x00000002
TOKEN_READ: DWORD : 0x20008
GENERIC_MAPPING :: struct {
GenericRead: ACCESS_MASK,
GenericWrite: ACCESS_MASK,
GenericExecute: ACCESS_MASK,
GenericAll: ACCESS_MASK,
}
PGENERIC_MAPPING :: ^GENERIC_MAPPING
SECURITY_IMPERSONATION_LEVEL :: enum {
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation,
}
SECURITY_INFORMATION :: DWORD
ANYSIZE_ARRAY :: 1
LUID_AND_ATTRIBUTES :: struct {
Luid: LUID,
Attributes: DWORD,
}
PRIVILEGE_SET :: struct {
PrivilegeCount: DWORD,
Control: DWORD,
Privilege: [ANYSIZE_ARRAY]LUID_AND_ATTRIBUTES,
}
PPRIVILEGE_SET :: ^PRIVILEGE_SET
// Token Specific Access Rights.
TOKEN_ASSIGN_PRIMARY :: 0x0001
TOKEN_DUPLICATE :: 0x0002
TOKEN_IMPERSONATE :: 0x0004
TOKEN_QUERY :: 0x0008
TOKEN_QUERY_SOURCE :: 0x0010
TOKEN_ADJUST_PRIVILEGES :: 0x0020
TOKEN_ADJUST_GROUPS :: 0x0040
TOKEN_ADJUST_DEFAULT :: 0x0080
TOKEN_ADJUST_SESSIONID :: 0x0100
TOKEN_ALL_ACCESS_P :: STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY |\
TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT
TOKEN_ALL_ACCESS :: TOKEN_ALL_ACCESS_P | TOKEN_ADJUST_SESSIONID
TOKEN_READ :: STANDARD_RIGHTS_READ | TOKEN_QUERY
TOKEN_WRITE :: STANDARD_RIGHTS_WRITE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT
TOKEN_EXECUTE :: STANDARD_RIGHTS_EXECUTE
TOKEN_TRUST_CONSTRAINT_MASK :: STANDARD_RIGHTS_READ | TOKEN_QUERY | TOKEN_QUERY_SOURCE
TOKEN_ACCESS_PSEUDO_HANDLE_WIN8 :: TOKEN_QUERY | TOKEN_QUERY_SOURCE
TOKEN_ACCESS_PSEUDO_HANDLE :: TOKEN_ACCESS_PSEUDO_HANDLE_WIN8
CP_ACP :: 0 // default to ANSI code page
CP_OEMCP :: 1 // default to OEM code page
@@ -2100,9 +2267,10 @@ FILETIME :: struct {
FILETIME_as_unix_nanoseconds :: proc "contextless" (ft: FILETIME) -> i64 {
t := i64(u64(ft.dwLowDateTime) | u64(ft.dwHighDateTime) << 32)
return (t - 0x019db1ded53e8000) * 100
return (t - 116444736000000000) * 100
}
OVERLAPPED :: struct {
Internal: ^c_ulong,
InternalHigh: ^c_ulong,
@@ -2776,6 +2944,16 @@ SYSTEMTIME :: struct {
milliseconds: WORD,
}
TIME_ZONE_INFORMATION :: struct {
Bias: LONG,
StandardName: [32]WCHAR,
StandardDate: SYSTEMTIME,
StandardBias: LONG,
DaylightName: [32]WCHAR,
DaylightDate: SYSTEMTIME,
DaylightBias: LONG,
}
@(private="file")
IMAGE_DOS_HEADER :: struct {
@@ -3047,12 +3225,32 @@ SHCONTF_FLATLIST :: 0x4000
SHCONTF_ENABLE_ASYNC :: 0x8000
SHCONTF_INCLUDESUPERHIDDEN :: 0x10000
SHACF_DEFAULT :: 0x00000000 // Currently (SHACF_FILESYSTEM | SHACF_URLALL)
SHACF_FILESYSTEM :: 0x00000001 // This includes the File System as well as the rest of the shell (Desktop\My Computer\Control Panel\)
SHACF_URLALL :: (SHACF_URLHISTORY | SHACF_URLMRU)
SHACF_URLHISTORY :: 0x00000002 // URLs in the User's History
SHACF_URLMRU :: 0x00000004 // URLs in the User's Recently Used list.
SHACF_USETAB :: 0x00000008 // Use the tab to move thru the autocomplete possibilities instead of to the next dialog/window control.
SHACF_FILESYS_ONLY :: 0x00000010 // This includes the File System
SHACF_FILESYS_DIRS :: 0x00000020 // Same as SHACF_FILESYS_ONLY except it only includes directories, UNC servers, and UNC server shares.
SHACF_VIRTUAL_NAMESPACE :: 0x00000040 // Also include the virtual namespace
SHACF_AUTOSUGGEST_FORCE_ON :: 0x10000000 // Ignore the registry default and force the feature on.
SHACF_AUTOSUGGEST_FORCE_OFF :: 0x20000000 // Ignore the registry default and force the feature off.
SHACF_AUTOAPPEND_FORCE_ON :: 0x40000000 // Ignore the registry default and force the feature on. (Also know as AutoComplete)
SHACF_AUTOAPPEND_FORCE_OFF :: 0x80000000 // Ignore the registry default and force the feature off. (Also know as AutoComplete)
LWSTDAPI :: HRESULT
CLSID_FileOpenDialog := &GUID{0xDC1C5A9C, 0xE88A, 0x4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}}
CLSID_FileSaveDialog := &GUID{0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}}
CLSID_TaskbarList := &GUID{0x56FDF344, 0xFD6D, 0x11d0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}}
IID_IFileDialog := &GUID{0x42F85136, 0xDB7E, 0x439C, {0x85, 0xF1, 0xE4, 0x07, 0x5D, 0x13, 0x5F, 0xC8}}
IID_IFileSaveDialog := &GUID{0x84BCCD23, 0x5FDE, 0x4CDB, {0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB}}
IID_IFileOpenDialog := &GUID{0xD57C7288, 0xD4AD, 0x4768, {0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60}}
IID_ITaskbarList := &GUID{0x56FDF342, 0xFD6D, 0x11d0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}}
IID_ITaskbarList2 := &GUID{0x602D4995, 0xB13A, 0x429b, {0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17}}
IID_ITaskbarList3 := &GUID{0xea1afb91, 0x9e28, 0x4b86, {0x90, 0xe9, 0x9e, 0x9f, 0x8a, 0x5e, 0xef, 0xaf}}
IModalWindow :: struct #raw_union {
#subtype IUnknown: IUnknown,
@@ -3357,6 +3555,84 @@ IFileSaveDialogVtbl :: struct {
ApplyProperties: proc "stdcall" (this: ^IFileSaveDialog, psi: ^IShellItem, pStore: ^IPropertyStore, hwnd: HWND, pSink: ^IFileOperationProgressSink) -> HRESULT,
}
ITaskbarList :: struct #raw_union {
#subtype IUnknown: IUnknown,
using Vtbl: ^ITaskbarListVtbl,
}
ITaskbarListVtbl :: struct {
using IUnknownVtbl: IUnknownVtbl,
HrInit: proc "stdcall" (this: ^ITaskbarList) -> HRESULT,
AddTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT,
DeleteTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT,
ActivateTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT,
SetActiveAlt: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT,
}
ITaskbarList2 :: struct #raw_union {
#subtype ITaskbarList: ITaskbarList,
using Vtbl: ^ITaskbarList2Vtbl,
}
ITaskbarList2Vtbl :: struct {
using ITaskbarListVtbl: ITaskbarListVtbl,
MarkFullscreenWindow: proc "stdcall" (this: ^ITaskbarList2, hwnd: HWND, fFullscreen: BOOL) -> HRESULT,
}
TBPFLAG :: enum c_int {
NOPROGRESS = 0,
INDETERMINATE = 0x1,
NORMAL = 0x2,
ERROR = 0x4,
PAUSED = 0x8,
}
THUMBBUTTONFLAGS :: enum c_int {
ENABLED = 0,
DISABLED = 0x1,
DISMISSONCLICK = 0x2,
NOBACKGROUND = 0x4,
HIDDEN = 0x8,
NONINTERACTIVE = 0x10,
}
THUMBBUTTONMASK :: enum c_int {
BITMAP = 0x1,
ICON = 0x2,
TOOLTIP = 0x4,
FLAGS = 0x8,
}
THUMBBUTTON :: struct {
dwMask: THUMBBUTTONMASK,
iId: UINT,
iBitmap: UINT,
hIcon: HICON,
szTip: [260]WCHAR,
dwFlags: THUMBBUTTONFLAGS,
}
LPTHUMBBUTTON :: ^THUMBBUTTON
HIMAGELIST :: ^IUnknown
ITaskbarList3 :: struct #raw_union {
#subtype ITaskbarList2: ITaskbarList2,
using Vtbl: ^ITaskbarList3Vtbl,
}
ITaskbarList3Vtbl :: struct {
using ITaskbarList2Vtbl: ITaskbarList2Vtbl,
SetProgressValue: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, ullCompleted: ULONGLONG, ullTotal: ULONGLONG) -> HRESULT,
SetProgressState: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, tbpFlags: TBPFLAG) -> HRESULT,
RegisterTab: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndMDI: HWND) -> HRESULT,
UnregisterTab: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND) -> HRESULT,
SetTabOrder: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndInsertBefore: HWND) -> HRESULT,
SetTabActive: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndMDI: HWND, dwReserved: DWORD) -> HRESULT,
ThumbBarAddButtons: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, cButtons: UINT, pButton: LPTHUMBBUTTON) -> HRESULT,
ThumbBarUpdateButtons: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, cButtons: UINT, pButton: LPTHUMBBUTTON) -> HRESULT,
ThumbBarSetImageList: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, himl: HIMAGELIST) -> HRESULT,
SetOverlayIcon: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, hIcon: HICON, pszDescription: LPCWSTR) -> HRESULT,
SetThumbnailTooltip: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, pszTip: LPCWSTR) -> HRESULT,
SetThumbnailClip: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, prcClip: ^RECT) -> HRESULT,
}
MEMORYSTATUSEX :: struct {
dwLength: DWORD,
dwMemoryLoad: DWORD,
+4
View File
@@ -78,6 +78,7 @@ foreign user32 {
LoadIconW :: proc(hInstance: HINSTANCE, lpIconName: LPCWSTR) -> HICON ---
LoadCursorA :: proc(hInstance: HINSTANCE, lpCursorName: LPCSTR) -> HCURSOR ---
LoadCursorW :: proc(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> HCURSOR ---
LoadImageW :: proc(hInst: HINSTANCE, name: LPCWSTR, type: UINT, cx: c_int, cy: c_int, fuLoad: UINT) -> HANDLE ---
GetWindowRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL ---
GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL ---
@@ -104,6 +105,9 @@ foreign user32 {
GetDC :: proc(hWnd: HWND) -> HDC ---
ReleaseDC :: proc(hWnd: HWND, hDC: HDC) -> c_int ---
GetDlgCtrlID :: proc(hWnd: HWND) -> c_int ---
GetDlgItem :: proc(hDlg: HWND, nIDDlgItem: c_int) -> HWND ---
GetUpdateRect :: proc(hWnd: HWND, lpRect: LPRECT, bErase: BOOL) -> BOOL ---
ValidateRect :: proc(hWnd: HWND, lpRect: ^RECT) -> BOOL ---
InvalidateRect :: proc(hWnd: HWND, lpRect: ^RECT, bErase: BOOL) -> BOOL ---
+4 -4
View File
@@ -62,19 +62,19 @@ utf8_to_wstring :: proc(s: string, allocator := context.temp_allocator) -> wstri
wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) {
context.allocator = allocator
if N <= 0 {
if N == 0 {
return
}
n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), nil, 0, nil, nil)
n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N) if N > 0 else -1, nil, 0, nil, nil)
if n == 0 {
return
}
// If N == -1 the call to WideCharToMultiByte assume the wide string is null terminated
// If N < 0 the call to WideCharToMultiByte assume the wide string is null terminated
// and will scan it to find the first null terminated character. The resulting string will
// also be null terminated.
// If N != -1 it assumes the wide string is not null terminated and the resulting string
// If N > 0 it assumes the wide string is not null terminated and the resulting string
// will not be null terminated.
text := make([]byte, n) or_return
File diff suppressed because it is too large Load Diff
+34 -32
View File
@@ -17,7 +17,7 @@ MAX_DURATION :: Duration(1<<63 - 1)
IS_SUPPORTED :: _IS_SUPPORTED
Time :: struct {
_nsec: i64, // zero is 1970-01-01 00:00:00
_nsec: i64, // Measured in UNIX nanonseconds
}
Month :: enum int {
@@ -59,36 +59,36 @@ sleep :: proc "contextless" (d: Duration) {
_sleep(d)
}
stopwatch_start :: proc(using stopwatch: ^Stopwatch) {
stopwatch_start :: proc "contextless" (using stopwatch: ^Stopwatch) {
if !running {
_start_time = tick_now()
running = true
}
}
stopwatch_stop :: proc(using stopwatch: ^Stopwatch) {
stopwatch_stop :: proc "contextless" (using stopwatch: ^Stopwatch) {
if running {
_accumulation += tick_diff(_start_time, tick_now())
running = false
}
}
stopwatch_reset :: proc(using stopwatch: ^Stopwatch) {
stopwatch_reset :: proc "contextless" (using stopwatch: ^Stopwatch) {
_accumulation = {}
running = false
}
stopwatch_duration :: proc(using stopwatch: Stopwatch) -> Duration {
stopwatch_duration :: proc "contextless" (using stopwatch: Stopwatch) -> Duration {
if !running { return _accumulation }
return _accumulation + tick_diff(_start_time, tick_now())
}
diff :: proc(start, end: Time) -> Duration {
diff :: proc "contextless" (start, end: Time) -> Duration {
d := end._nsec - start._nsec
return Duration(d)
}
since :: proc(start: Time) -> Duration {
since :: proc "contextless" (start: Time) -> Duration {
return diff(start, now())
}
@@ -117,8 +117,8 @@ duration_hours :: proc "contextless" (d: Duration) -> f64 {
return f64(hour) + f64(nsec)/(60*60*1e9)
}
duration_round :: proc(d, m: Duration) -> Duration {
_less_than_half :: #force_inline proc(x, y: Duration) -> bool {
duration_round :: proc "contextless" (d, m: Duration) -> Duration {
_less_than_half :: #force_inline proc "contextless" (x, y: Duration) -> bool {
return u64(x)+u64(x) < u64(y)
}
@@ -146,45 +146,45 @@ duration_round :: proc(d, m: Duration) -> Duration {
return MAX_DURATION
}
duration_truncate :: proc(d, m: Duration) -> Duration {
duration_truncate :: proc "contextless" (d, m: Duration) -> Duration {
return d if m <= 0 else d - d%m
}
date :: proc(t: Time) -> (year: int, month: Month, day: int) {
date :: proc "contextless" (t: Time) -> (year: int, month: Month, day: int) {
year, month, day, _ = _abs_date(_time_abs(t), true)
return
}
year :: proc(t: Time) -> (year: int) {
year :: proc "contextless" (t: Time) -> (year: int) {
year, _, _, _ = _date(t, true)
return
}
month :: proc(t: Time) -> (month: Month) {
month :: proc "contextless" (t: Time) -> (month: Month) {
_, month, _, _ = _date(t, true)
return
}
day :: proc(t: Time) -> (day: int) {
day :: proc "contextless" (t: Time) -> (day: int) {
_, _, day, _ = _date(t, true)
return
}
clock :: proc { clock_from_time, clock_from_duration, clock_from_stopwatch }
clock_from_time :: proc(t: Time) -> (hour, min, sec: int) {
clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) {
return clock_from_seconds(_time_abs(t))
}
clock_from_duration :: proc(d: Duration) -> (hour, min, sec: int) {
clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, sec: int) {
return clock_from_seconds(u64(d/1e9))
}
clock_from_stopwatch :: proc(s: Stopwatch) -> (hour, min, sec: int) {
clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, sec: int) {
return clock_from_duration(stopwatch_duration(s))
}
clock_from_seconds :: proc(nsec: u64) -> (hour, min, sec: int) {
clock_from_seconds :: proc "contextless" (nsec: u64) -> (hour, min, sec: int) {
sec = int(nsec % SECONDS_PER_DAY)
hour = sec / SECONDS_PER_HOUR
sec -= hour * SECONDS_PER_HOUR
@@ -193,11 +193,11 @@ clock_from_seconds :: proc(nsec: u64) -> (hour, min, sec: int) {
return
}
read_cycle_counter :: proc() -> u64 {
read_cycle_counter :: proc "contextless" () -> u64 {
return u64(intrinsics.read_cycle_counter())
}
unix :: proc(sec: i64, nsec: i64) -> Time {
unix :: proc "contextless" (sec: i64, nsec: i64) -> Time {
sec, nsec := sec, nsec
if nsec < 0 || nsec >= 1e9 {
n := nsec / 1e9
@@ -208,20 +208,20 @@ unix :: proc(sec: i64, nsec: i64) -> Time {
sec -= 1
}
}
return Time{(sec*1e9 + nsec) + UNIX_TO_INTERNAL}
return Time{(sec*1e9 + nsec)}
}
to_unix_seconds :: time_to_unix
time_to_unix :: proc(t: Time) -> i64 {
time_to_unix :: proc "contextless" (t: Time) -> i64 {
return t._nsec/1e9
}
to_unix_nanoseconds :: time_to_unix_nano
time_to_unix_nano :: proc(t: Time) -> i64 {
time_to_unix_nano :: proc "contextless" (t: Time) -> i64 {
return t._nsec
}
time_add :: proc(t: Time, d: Duration) -> Time {
time_add :: proc "contextless" (t: Time, d: Duration) -> Time {
return Time{t._nsec + i64(d)}
}
@@ -231,7 +231,7 @@ time_add :: proc(t: Time, d: Duration) -> Time {
// On Windows it depends but is comparable with regular sleep in the worst case.
// To get the same kind of accuracy as on Linux, have your program call `win32.time_begin_period(1)` to
// tell Windows to use a more accurate timer for your process.
accurate_sleep :: proc(d: Duration) {
accurate_sleep :: proc "contextless" (d: Duration) {
to_sleep, estimate, mean, m2, count: Duration
to_sleep = d
@@ -279,19 +279,19 @@ ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE
@(private)
_date :: proc(t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) {
_date :: proc "contextless" (t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) {
year, month, day, yday = _abs_date(_time_abs(t), full)
return
}
@(private)
_time_abs :: proc(t: Time) -> u64 {
_time_abs :: proc "contextless" (t: Time) -> u64 {
return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE)
}
@(private)
_abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) {
_is_leap_year :: proc(year: int) -> bool {
_abs_date :: proc "contextless" (abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) {
_is_leap_year :: proc "contextless" (year: int) -> bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}
@@ -352,9 +352,11 @@ _abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, y
return
}
datetime_to_time :: proc(year, month, day, hour, minute, second: int, nsec := int(0)) -> (t: Time, ok: bool) {
divmod :: proc(year: int, divisor: int) -> (div: int, mod: int) {
assert(divisor > 0)
datetime_to_time :: proc "contextless" (year, month, day, hour, minute, second: int, nsec := int(0)) -> (t: Time, ok: bool) {
divmod :: proc "contextless" (year: int, divisor: int) -> (div: int, mod: int) {
if divisor <= 0 {
intrinsics.debug_trap()
}
div = int(year / divisor)
mod = year % divisor
return
+2
View File
@@ -22,3 +22,5 @@ _tick_now :: proc "contextless" () -> Tick {
return {}
}
_yield :: proc "contextless" () {
}
+10 -3
View File
@@ -7,9 +7,16 @@ _IS_SUPPORTED :: true
_now :: proc "contextless" () -> Time {
file_time: win32.FILETIME
win32.GetSystemTimeAsFileTime(&file_time)
ns := win32.FILETIME_as_unix_nanoseconds(file_time)
return Time{_nsec=ns}
ns: i64
// monotonic
win32.GetSystemTimePreciseAsFileTime(&file_time)
dt := u64(transmute(u64le)file_time) // in 100ns units
ns = i64((dt - 116444736000000000) * 100) // convert to ns
return unix(0, ns)
}
_sleep :: proc "contextless" (d: Duration) {
+1 -1
View File
@@ -71,7 +71,7 @@ void big_int_and (BigInt *dst, BigInt const *x, BigInt const *y);
void big_int_and_not(BigInt *dst, BigInt const *x, BigInt const *y);
void big_int_xor (BigInt *dst, BigInt const *x, BigInt const *y);
void big_int_or (BigInt *dst, BigInt const *x, BigInt const *y);
void big_int_not (BigInt *dst, BigInt const *x, u64 bit_count, bool is_signed);
void big_int_not (BigInt *dst, BigInt const *x, i32 bit_count, bool is_signed);
void big_int_add_eq(BigInt *dst, BigInt const *x);
+12 -9
View File
@@ -298,17 +298,17 @@ struct BuildContext {
bool ignore_microsoft_magic;
bool linker_map_file;
bool use_separate_modules;
bool threaded_checker;
bool use_separate_modules;
bool threaded_checker;
bool show_debug_messages;
bool show_debug_messages;
bool copy_file_contents;
bool copy_file_contents;
bool disallow_rtti;
bool disallow_rtti;
RelocMode reloc_mode;
bool disable_red_zone;
bool disable_red_zone;
u32 cmd_doc_flags;
@@ -326,7 +326,7 @@ struct BuildContext {
BlockingMutex target_features_mutex;
StringSet target_features_set;
String target_features_string;
String minimum_os_version_string;
};
gb_global BuildContext build_context = {0};
@@ -1311,13 +1311,16 @@ void enable_target_feature(TokenPos pos, String const &target_feature_list) {
defer (mutex_unlock(&bc->target_features_mutex));
auto items = split_by_comma(target_feature_list);
array_free(&items);
for_array(i, items) {
String const &item = items.data[i];
if (!check_target_feature_is_valid(pos, item)) {
error(pos, "Target feature '%.*s' is not valid", LIT(item));
continue;
}
string_set_add(&bc->target_features_set, item);
}
array_free(&items);
}
@@ -1340,7 +1343,7 @@ char const *target_features_set_to_cstring(gbAllocator allocator, bool with_quot
if (with_quotes) features[len++] = '"';
String feature = build_context.target_features_set.entries[i].value;
gb_memmove(features, feature.text, feature.len);
gb_memmove(features + len, feature.text, feature.len);
len += feature.len;
if (with_quotes) features[len++] = '"';
}
+141 -3
View File
@@ -1533,10 +1533,10 @@ bool check_builtin_procedure_directive(CheckerContext *c, Operand *operand, Ast
}
bool is_defined = check_identifier_exists(c->scope, arg);
gb_unused(is_defined);
// gb_unused(is_defined);
operand->type = t_untyped_bool;
operand->mode = Addressing_Constant;
operand->value = exact_value_bool(false);
operand->value = exact_value_bool(is_defined);
} else if (name == "config") {
if (ce->args.count != 2) {
@@ -3651,6 +3651,59 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
operand->mode = Addressing_NoValue;
break;
case BuiltinProc_raw_data:
{
Operand x = {};
check_expr(c, &x, ce->args[0]);
if (x.mode == Addressing_Invalid) {
return false;
}
if (!is_operand_value(x)) {
gbString s = expr_to_string(x.expr);
error(call, "'%.*s' expects a string, slice, dynamic array, or pointer to array type, got %s", LIT(builtin_name), s);
gb_string_free(s);
return false;
}
Type *t = base_type(x.type);
operand->mode = Addressing_Value;
operand->type = nullptr;
switch (t->kind) {
case Type_Slice:
operand->type = alloc_type_multi_pointer(t->MultiPointer.elem);
break;
case Type_DynamicArray:
operand->type = alloc_type_multi_pointer(t->DynamicArray.elem);
break;
case Type_Basic:
if (t->Basic.kind == Basic_string) {
operand->type = alloc_type_multi_pointer(t_u8);
}
break;
case Type_Pointer:
case Type_MultiPointer:
{
Type *base = base_type(type_deref(t, true));
switch (base->kind) {
case Type_Array:
case Type_EnumeratedArray:
case Type_SimdVector:
operand->type = alloc_type_multi_pointer(base_array_type(base));
break;
}
}
break;
}
if (operand->type == nullptr) {
gbString s = type_to_string(x.type);
error(call, "'%.*s' expects a string, slice, dynamic array, or pointer to array type, got %s", LIT(builtin_name), s);
gb_string_free(s);
return false;
}
}
break;
case BuiltinProc_read_cycle_counter:
operand->mode = Addressing_Value;
operand->type = t_i64;
@@ -3685,8 +3738,92 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
gb_string_free(xts);
}
Type *type = default_type(x.type);
operand->mode = Addressing_Value;
operand->type = default_type(x.type);
operand->type = type;
if (id == BuiltinProc_reverse_bits) {
// make runtime only for the time being
} else if (x.mode == Addressing_Constant && x.value.kind == ExactValue_Integer) {
convert_to_typed(c, &x, type);
if (x.mode == Addressing_Invalid) {
return false;
}
ExactValue res = {};
i64 sz = type_size_of(x.type);
u64 bit_size = sz*8;
u64 rop64[4] = {}; // 2 u64 is the maximum we will ever need, so doubling it will ne fine
u8 *rop = cast(u8 *)rop64;
size_t max_count = 0;
size_t written = 0;
size_t size = 1;
size_t nails = 0;
mp_endian endian = MP_LITTLE_ENDIAN;
max_count = mp_pack_count(&x.value.value_integer, nails, size);
GB_ASSERT(sz >= cast(i64)max_count);
mp_err err = mp_pack(rop, max_count, &written, MP_LSB_FIRST, size, endian, nails, &x.value.value_integer);
GB_ASSERT(err == MP_OKAY);
if (id == BuiltinProc_reverse_bits) {
// TODO(bill): Should this even be allowed at compile time?
} else {
u64 v = 0;
switch (id) {
case BuiltinProc_count_ones:
case BuiltinProc_count_zeros:
switch (sz) {
case 1: v = bit_set_count(cast(u32)rop[0]); break;
case 2: v = bit_set_count(cast(u32)*(u16 *)rop); break;
case 4: v = bit_set_count(*(u32 *)rop); break;
case 8: v = bit_set_count(rop64[0]); break;
case 16:
v += bit_set_count(rop64[0]);
v += bit_set_count(rop64[1]);
break;
default: GB_PANIC("Unhandled sized");
}
if (id == BuiltinProc_count_zeros) {
// flip the result
v = bit_size - v;
}
break;
case BuiltinProc_count_trailing_zeros:
for (u64 i = 0; i < bit_size; i++) {
u8 b = cast(u8)(i & 7);
u8 j = cast(u8)(i >> 3);
if (rop[j] & (1 << b)) {
break;
}
v += 1;
}
break;
case BuiltinProc_count_leading_zeros:
for (u64 i = bit_size-1; i < bit_size; i--) {
u8 b = cast(u8)(i & 7);
u8 j = cast(u8)(i >> 3);
if (rop[j] & (1 << b)) {
break;
}
v += 1;
}
break;
}
res = exact_value_u64(v);
}
if (res.kind != ExactValue_Invalid) {
operand->mode = Addressing_Constant;
operand->value = res;
}
}
}
break;
@@ -4667,6 +4804,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
new_type->Union.variants = variants;
// NOTE(bill): Is this even correct?
new_type->Union.node = operand->expr;
new_type->Union.scope = bt->Union.scope;
operand->type = new_type;
+5
View File
@@ -1488,6 +1488,11 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
if (!(e->flags & EntityFlag_Using)) {
continue;
}
if (is_blank_ident(e->token)) {
error(e->token, "'using' a procedure parameter requires a non blank identifier");
break;
}
bool is_value = (e->flags & EntityFlag_Value) != 0 && !is_type_pointer(e->type);
String name = e->token.string;
Type *t = base_type(type_deref(e->type));
+64 -16
View File
@@ -821,11 +821,12 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
if (are_types_identical(src, dst)) {
return 5;
}
Type *dst_elem = base_array_type(dst);
i64 distance = check_distance_between_types(c, operand, dst_elem);
if (distance >= 0) {
return distance + 7;
if (dst->Matrix.row_count == dst->Matrix.column_count) {
Type *dst_elem = base_array_type(dst);
i64 distance = check_distance_between_types(c, operand, dst_elem);
if (distance >= 0) {
return distance + 7;
}
}
}
@@ -2916,7 +2917,12 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
// return false;
// }
if (is_type_untyped(o->type)) {
Type *src_t = o->type;
Type *dst_t = t;
Type *src_bt = base_type(src_t);
Type *dst_bt = base_type(dst_t);
if (is_type_untyped(src_t)) {
gbString expr_str = expr_to_string(o->expr);
error(o->expr, "Cannot transmute untyped expression: '%s'", expr_str);
gb_string_free(expr_str);
@@ -2925,7 +2931,6 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
return false;
}
Type *dst_bt = base_type(t);
if (dst_bt == nullptr || dst_bt == t_invalid) {
GB_ASSERT(global_error_collector.count != 0);
@@ -2934,21 +2939,21 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
return false;
}
Type *src_bt = base_type(o->type);
if (src_bt == nullptr || src_bt == t_invalid) {
// NOTE(bill): this should be an error
GB_ASSERT(global_error_collector.count != 0);
o->mode = Addressing_Value;
o->expr = node;
o->type = t;
o->type = dst_t;
return true;
}
i64 srcz = type_size_of(o->type);
i64 dstz = type_size_of(t);
i64 srcz = type_size_of(src_t);
i64 dstz = type_size_of(dst_t);
if (srcz != dstz) {
gbString expr_str = expr_to_string(o->expr);
gbString type_str = type_to_string(t);
gbString type_str = type_to_string(dst_t);
error(o->expr, "Cannot transmute '%s' to '%s', %lld vs %lld bytes", expr_str, type_str, srcz, dstz);
gb_string_free(type_str);
gb_string_free(expr_str);
@@ -2958,16 +2963,53 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
}
if (build_context.vet_extra) {
if (are_types_identical(o->type, t)) {
gbString str = type_to_string(t);
if (are_types_identical(o->type, dst_t)) {
gbString str = type_to_string(dst_t);
warning(o->expr, "Unneeded transmute to the same type '%s'", str);
gb_string_free(str);
}
}
o->expr = node;
o->type = dst_t;
if (o->mode == Addressing_Constant) {
if (are_types_identical(src_bt, dst_bt)) {
return true;
}
if (is_type_integer(src_t) && is_type_integer(dst_t)) {
if (types_have_same_internal_endian(src_t, dst_t)) {
ExactValue src_v = exact_value_to_integer(o->value);
GB_ASSERT(src_v.kind == ExactValue_Integer);
BigInt v = src_v.value_integer;
BigInt smax = {};
BigInt umax = {};
big_int_from_u64(&smax, 0);
big_int_not(&smax, &smax, cast(i32)(srcz*8 - 1), false);
big_int_from_u64(&umax, 1);
BigInt sz_in_bits = big_int_make_i64(srcz*8);
big_int_shl_eq(&umax, &sz_in_bits);
if (is_type_unsigned(src_t) && !is_type_unsigned(dst_t)) {
if (big_int_cmp(&v, &smax) >= 0) {
big_int_sub_eq(&v, &umax);
}
} else if (!is_type_unsigned(src_t) && is_type_unsigned(dst_t)) {
if (big_int_is_neg(&v)) {
big_int_add_eq(&v, &umax);
}
}
o->value.kind = ExactValue_Integer;
o->value.value_integer = v;
return true;
}
}
}
o->mode = Addressing_Value;
o->type = t;
o->value = {};
return true;
}
@@ -6413,7 +6455,9 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
if (e->kind == Entity_TypeName) {
if (o->mode != Addressing_Type) {
if (show_error) {
error(o->expr, "Expected a type for the argument '%.*s'", LIT(e->token.string));
gbString expr = expr_to_string(o->expr);
error(o->expr, "Expected a type for the argument '%.*s', got %s", LIT(e->token.string), expr);
gb_string_free(expr);
}
err = CallArgumentError_WrongTypes;
}
@@ -6456,6 +6500,10 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
// add_type_info_type(c, o->type);
}
if (show_error && err) {
return err;
}
{
bool failure = false;
Entity *found_entity = find_polymorphic_record_entity(c, original_type, param_count, ordered_operands, &failure);
+5 -1
View File
@@ -584,7 +584,11 @@ void check_label(CheckerContext *ctx, Ast *label, Ast *parent) {
// Returns 'true' for 'continue', 'false' for 'return'
bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, bool is_selector, Entity *e) {
if (e == nullptr) {
error(us->token, "'using' applied to an unknown entity");
if (is_blank_ident(expr)) {
error(us->token, "'using' in a statement is not allowed with the blank identifier '_'");
} else {
error(us->token, "'using' applied to an unknown entity");
}
return true;
}
+12 -1
View File
@@ -1673,7 +1673,18 @@ bool could_entity_be_lazy(Entity *e, DeclInfo *d) {
}
void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, DeclInfo *d, bool is_exported) {
GB_ASSERT(identifier->kind == Ast_Ident);
if (identifier == nullptr) {
// NOTE(bill): Should only happen on errors
error(e->token, "Invalid variable declaration");
return;
}
if (identifier->kind != Ast_Ident) {
// NOTE(bill): This is a safety check
gbString s = expr_to_string(identifier);
error(identifier, "A variable declaration must be an identifer, got %s", s);
gb_string_free(s);
return;
}
GB_ASSERT(e != nullptr && d != nullptr);
GB_ASSERT(identifier->Ident.token.string == e->token.string);
+4
View File
@@ -42,6 +42,8 @@ enum BuiltinProcId {
BuiltinProc_unreachable,
BuiltinProc_raw_data,
BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
// "Intrinsics"
@@ -338,6 +340,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("unreachable"), 0, false, Expr_Expr, BuiltinProcPkg_builtin, /*diverging*/true},
{STR_LIT("raw_data"), 1, false, Expr_Expr, BuiltinProcPkg_builtin},
{STR_LIT(""), 0, true, Expr_Expr, BuiltinProcPkg_builtin}, // DIRECTIVE
+1 -1
View File
@@ -639,7 +639,7 @@ OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
doc_type.polmorphic_params = odin_doc_type(w, type->Union.polymorphic_params);
}
if (type->Union.node) {
if (type->Union.node && type->Union.node->kind == Ast_UnionType) {
ast_node(ut, UnionType, type->Union.node);
if (ut->align) {
doc_type.custom_align = odin_doc_expr_string(w, ut->align);
+7
View File
@@ -499,6 +499,13 @@ i64 exact_value_to_i64(ExactValue v) {
}
return 0;
}
u64 exact_value_to_u64(ExactValue v) {
v = exact_value_to_integer(v);
if (v.kind == ExactValue_Integer) {
return big_int_to_u64(&v.value_integer);
}
return 0;
}
f64 exact_value_to_f64(ExactValue v) {
v = exact_value_to_float(v);
if (v.kind == ExactValue_Float) {
+44 -19
View File
@@ -537,6 +537,22 @@ namespace lbAbiAmd64SysV {
return false;
}
bool is_llvm_type_slice_like(LLVMTypeRef type) {
if (!lb_is_type_kind(type, LLVMStructTypeKind)) {
return false;
}
if (LLVMCountStructElementTypes(type) != 2) {
return false;
}
LLVMTypeRef fields[2] = {};
LLVMGetStructElementTypes(type, fields);
if (!lb_is_type_kind(fields[0], LLVMPointerTypeKind)) {
return false;
}
return lb_is_type_kind(fields[1], LLVMIntegerTypeKind) && lb_sizeof(fields[1]) == 8;
}
lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention) {
if (is_register(type)) {
LLVMAttributeRef attribute = nullptr;
@@ -550,16 +566,25 @@ namespace lbAbiAmd64SysV {
if (is_mem_cls(cls, attribute_kind)) {
LLVMAttributeRef attribute = nullptr;
if (attribute_kind == Amd64TypeAttribute_ByVal) {
if (!is_calling_convention_odin(calling_convention)) {
// if (!is_calling_convention_odin(calling_convention)) {
return lb_arg_type_indirect_byval(c, type);
}
attribute = nullptr;
// }
// attribute = nullptr;
} else if (attribute_kind == Amd64TypeAttribute_StructRect) {
attribute = lb_create_enum_attribute_with_type(c, "sret", type);
}
return lb_arg_type_indirect(type, attribute);
} else {
return lb_arg_type_direct(type, llreg(c, cls), nullptr, nullptr);
LLVMTypeRef reg_type = nullptr;
if (is_llvm_type_slice_like(type)) {
// NOTE(bill): This is to make the ABI look closer to what the
// original code is just for slices/strings whilst still adhering
// the ABI rules for SysV
reg_type = type;
} else {
reg_type = llreg(c, cls);
}
return lb_arg_type_direct(type, reg_type, nullptr, nullptr);
}
}
@@ -982,13 +1007,13 @@ namespace lbAbiArm64 {
}
return false;
}
unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef *base_type_, unsigned member_count_) {
return (member_count_ <= 4);
}
unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef base_type, unsigned member_count) {
return (member_count <= 4);
}
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef type, bool return_is_defined) {
LLVMTypeRef homo_base_type = {};
LLVMTypeRef homo_base_type = nullptr;
unsigned homo_member_count = 0;
if (!return_is_defined) {
@@ -996,16 +1021,16 @@ namespace lbAbiArm64 {
} else if (is_register(type)) {
return non_struct(c, type);
} else if (is_homogenous_aggregate(c, type, &homo_base_type, &homo_member_count)) {
if(is_homogenous_aggregate_small_enough(&homo_base_type, homo_member_count)) {
return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr);
} else {
//TODO(Platin): do i need to create stuff that can handle the diffrent return type?
// else this needs a fix in llvm_backend_proc as we would need to cast it to the correct array type
//LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count);
LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type);
return lb_arg_type_indirect(type, attr);
}
if (is_homogenous_aggregate_small_enough(homo_base_type, homo_member_count)) {
return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr);
} else {
//TODO(Platin): do i need to create stuff that can handle the diffrent return type?
// else this needs a fix in llvm_backend_proc as we would need to cast it to the correct array type
//LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count);
LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type);
return lb_arg_type_indirect(type, attr);
}
} else {
i64 size = lb_sizeof(type);
if (size <= 16) {
+29 -2
View File
@@ -646,7 +646,7 @@ void lb_insert_dynamic_map_key_and_value(lbProcedure *p, lbValue const &map_ptr,
args[2] = key_hash;
args[3] = key_ptr;
args[4] = lb_emit_conv(p, value_addr.addr, t_rawptr);
args[5] = lb_emit_source_code_location(p, node);
args[5] = lb_emit_source_code_location_as_global(p, node);
lb_emit_runtime_call(p, "__dynamic_map_set", args);
}
@@ -662,7 +662,7 @@ void lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_ptr, isize const
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = lb_gen_map_header_table_internal(p, type_deref(map_ptr.type));
args[2] = lb_const_int(p->module, t_int, capacity);
args[3] = lb_emit_source_code_location(p, proc_name, pos);
args[3] = lb_emit_source_code_location_as_global(p, proc_name, pos);
lb_emit_runtime_call(p, "__dynamic_map_reserve", args);
}
@@ -1736,6 +1736,13 @@ void lb_generate_code(lbGenerator *gen) {
lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, objc_names, global_variables);
gb_unused(startup_runtime);
if (build_context.ODIN_DEBUG) {
for_array(i, builtin_pkg->scope->elements.entries) {
Entity *e = builtin_pkg->scope->elements.entries[i].value;
add_debug_info_for_global_constant_from_entity(gen, e);
}
}
TIME_SECTION("LLVM Global Procedures and Types");
for_array(i, info->entities) {
Entity *e = info->entities[i];
@@ -1759,6 +1766,11 @@ void lb_generate_code(lbGenerator *gen) {
case Entity_TypeName:
case Entity_Procedure:
break;
case Entity_Constant:
if (build_context.ODIN_DEBUG) {
add_debug_info_for_global_constant_from_entity(gen, e);
}
break;
}
bool polymorphic_struct = false;
@@ -1820,6 +1832,21 @@ void lb_generate_code(lbGenerator *gen) {
lb_finalize_objc_names(objc_names);
if (build_context.ODIN_DEBUG) {
TIME_SECTION("LLVM Debug Info for global constant value declarations");
{
// lbModule *m = default_module;
}
// if (gen->modules.entries.count == 1) {
// } else {
// for_array(j, gen->modules.entries) {
// lbModule *m = gen->modules.entries[j].value;
// if (m->debug_builder != nullptr) {
// }
// }
// }
TIME_SECTION("LLVM Debug Info Complete Types and Finalize");
for_array(j, gen->modules.entries) {
lbModule *m = gen->modules.entries[j].value;
+2 -1
View File
@@ -298,6 +298,7 @@ struct lbProcedure {
lbBlock * entry_block;
lbBlock * curr_block;
lbTargetList * target_list;
PtrMap<Entity *, lbValue> direct_parameters;
Ast *curr_stmt;
@@ -456,7 +457,7 @@ lbValue lb_find_value_from_entity(lbModule *m, Entity *e);
void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value);
lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValue value);
lbValue lb_emit_source_code_location(lbProcedure *p, String const &procedure, TokenPos const &pos);
lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedure, TokenPos const &pos);
lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterValue const &param_value, TokenPos const &pos);
+20 -3
View File
@@ -256,7 +256,7 @@ lbValue lb_expr_untyped_const_to_typed(lbModule *m, Ast *expr, Type *t) {
return lb_const_value(m, t, tv.value);
}
lbValue lb_emit_source_code_location(lbProcedure *p, String const &procedure, TokenPos const &pos) {
lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedure, TokenPos const &pos) {
lbModule *m = p->module;
LLVMValueRef fields[4] = {};
@@ -271,7 +271,7 @@ lbValue lb_emit_source_code_location(lbProcedure *p, String const &procedure, To
return res;
}
lbValue lb_emit_source_code_location(lbProcedure *p, Ast *node) {
lbValue lb_emit_source_code_location_const(lbProcedure *p, Ast *node) {
String proc_name = {};
if (p->entity) {
proc_name = p->entity->token.string;
@@ -280,9 +280,26 @@ lbValue lb_emit_source_code_location(lbProcedure *p, Ast *node) {
if (node) {
pos = ast_token(node).pos;
}
return lb_emit_source_code_location(p, proc_name, pos);
return lb_emit_source_code_location_const(p, proc_name, pos);
}
lbValue lb_emit_source_code_location_as_global(lbProcedure *p, String const &procedure, TokenPos const &pos) {
lbValue loc = lb_emit_source_code_location_const(p, procedure, pos);
lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr);
lb_make_global_private_const(addr);
return lb_addr_load(p, addr);
}
lbValue lb_emit_source_code_location_as_global(lbProcedure *p, Ast *node) {
lbValue loc = lb_emit_source_code_location_const(p, node);
lbAddr addr = lb_add_global_generated(p->module, loc.type, loc, nullptr);
lb_make_global_private_const(addr);
return lb_addr_load(p, addr);
}
LLVMValueRef lb_build_constant_array_values(lbModule *m, Type *type, Type *elem_type, isize count, LLVMValueRef *values, bool allow_local) {
bool is_local = allow_local && m->curr_procedure != nullptr;
bool is_const = true;
+114
View File
@@ -293,6 +293,7 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
case Type_Named:
GB_PANIC("Type_Named should be handled in lb_debug_type separately");
case Type_SoaPointer:
case Type_Pointer:
return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), word_bits, word_bits, 0, nullptr, 0);
case Type_MultiPointer:
@@ -1079,3 +1080,116 @@ void lb_add_debug_context_variable(lbProcedure *p, lbAddr const &ctx) {
lb_add_debug_local_variable(p, ptr, t_context, token);
}
String debug_info_mangle_constant_name(Entity *e, bool *did_allocate_) {
String name = e->token.string;
if (e->pkg && e->pkg->name.len > 0) {
// NOTE(bill): C++ NONSENSE FOR DEBUG SHITE!
name = concatenate3_strings(heap_allocator(), e->pkg->name, str_lit("::"), name);
if (did_allocate_) *did_allocate_ = true;
}
return name;
}
void add_debug_info_global_variable_expr(lbModule *m, String const &name, LLVMMetadataRef dtype, LLVMMetadataRef expr) {
LLVMMetadataRef scope = nullptr;
LLVMMetadataRef file = nullptr;
unsigned line = 0;
LLVMMetadataRef decl = nullptr;
LLVMDIBuilderCreateGlobalVariableExpression(
m->debug_builder, scope,
cast(char const *)name.text, cast(size_t)name.len,
"", 0, // Linkage
file, line, dtype,
false, // local to unit
expr, decl, 8/*AlignInBits*/);
}
void add_debug_info_for_global_constant_internal_i64(lbModule *m, Entity *e, LLVMMetadataRef dtype, i64 v) {
LLVMMetadataRef expr = LLVMDIBuilderCreateConstantValueExpression(m->debug_builder, v);
bool did_allocate = false;
String name = debug_info_mangle_constant_name(e, &did_allocate);
defer (if (did_allocate) {
gb_free(heap_allocator(), name.text);
});
add_debug_info_global_variable_expr(m, name, dtype, expr);
if ((e->pkg && e->pkg->kind == Package_Init) ||
(e->scope && (e->scope->flags & ScopeFlag_Global))) {
add_debug_info_global_variable_expr(m, e->token.string, dtype, expr);
}
}
void add_debug_info_for_global_constant_from_entity(lbGenerator *gen, Entity *e) {
if (e == nullptr || e->kind != Entity_Constant) {
return;
}
if (is_blank_ident(e->token)) {
return;
}
lbModule *m = &gen->default_module;
if (USE_SEPARATE_MODULES) {
m = lb_pkg_module(gen, e->pkg);
}
if (is_type_integer(e->type)) {
ExactValue const &value = e->Constant.value;
if (value.kind == ExactValue_Integer) {
LLVMMetadataRef dtype = nullptr;
i64 v = 0;
bool is_signed = false;
if (big_int_is_neg(&value.value_integer)) {
v = exact_value_to_i64(value);
is_signed = true;
} else {
v = cast(i64)exact_value_to_u64(value);
}
if (is_type_untyped(e->type)) {
dtype = lb_debug_type(m, is_signed ? t_i64 : t_u64);
} else {
dtype = lb_debug_type(m, e->type);
}
add_debug_info_for_global_constant_internal_i64(m, e, dtype, v);
}
} else if (is_type_rune(e->type)) {
ExactValue const &value = e->Constant.value;
if (value.kind == ExactValue_Integer) {
LLVMMetadataRef dtype = lb_debug_type(m, t_rune);
i64 v = exact_value_to_i64(value);
add_debug_info_for_global_constant_internal_i64(m, e, dtype, v);
}
} else if (is_type_boolean(e->type)) {
ExactValue const &value = e->Constant.value;
if (value.kind == ExactValue_Bool) {
LLVMMetadataRef dtype = lb_debug_type(m, default_type(e->type));
i64 v = cast(i64)value.value_bool;
add_debug_info_for_global_constant_internal_i64(m, e, dtype, v);
}
} else if (is_type_enum(e->type)) {
ExactValue const &value = e->Constant.value;
if (value.kind == ExactValue_Integer) {
LLVMMetadataRef dtype = lb_debug_type(m, default_type(e->type));
i64 v = 0;
if (big_int_is_neg(&value.value_integer)) {
v = exact_value_to_i64(value);
} else {
v = cast(i64)exact_value_to_u64(value);
}
add_debug_info_for_global_constant_internal_i64(m, e, dtype, v);
}
} else if (is_type_pointer(e->type)) {
ExactValue const &value = e->Constant.value;
if (value.kind == ExactValue_Integer) {
LLVMMetadataRef dtype = lb_debug_type(m, default_type(e->type));
i64 v = cast(i64)exact_value_to_u64(value);
add_debug_info_for_global_constant_internal_i64(m, e, dtype, v);
}
}
}
+27 -28
View File
@@ -1952,34 +1952,33 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
Type *dt = t;
GB_ASSERT(is_type_struct(st) || is_type_raw_union(st));
String field_name = lookup_subtype_polymorphic_field(t, src_type);
if (field_name.len > 0) {
// NOTE(bill): It can be casted
Selection sel = lookup_field(st, field_name, false, true);
if (sel.entity != nullptr) {
if (st_is_ptr) {
lbValue res = lb_emit_deep_field_gep(p, value, sel);
Type *rt = res.type;
if (!are_types_identical(rt, dt) && are_types_identical(type_deref(rt), dt)) {
res = lb_emit_load(p, res);
}
return res;
} else {
if (is_type_pointer(value.type)) {
Type *rt = value.type;
if (!are_types_identical(rt, dt) && are_types_identical(type_deref(rt), dt)) {
value = lb_emit_load(p, value);
} else {
value = lb_emit_deep_field_gep(p, value, sel);
return lb_emit_load(p, value);
}
}
return lb_emit_deep_field_ev(p, value, sel);
Selection sel = {};
sel.index.allocator = heap_allocator();
defer (array_free(&sel.index));
if (lookup_subtype_polymorphic_selection(t, src_type, &sel)) {
if (sel.entity == nullptr) {
GB_PANIC("invalid subtype cast %s -> ", type_to_string(src_type), type_to_string(t));
}
if (st_is_ptr) {
lbValue res = lb_emit_deep_field_gep(p, value, sel);
Type *rt = res.type;
if (!are_types_identical(rt, dt) && are_types_identical(type_deref(rt), dt)) {
res = lb_emit_load(p, res);
}
return res;
} else {
GB_PANIC("invalid subtype cast %s.%.*s", type_to_string(src_type), LIT(field_name));
if (is_type_pointer(value.type)) {
Type *rt = value.type;
if (!are_types_identical(rt, dt) && are_types_identical(type_deref(rt), dt)) {
value = lb_emit_load(p, value);
} else {
value = lb_emit_deep_field_gep(p, value, sel);
return lb_emit_load(p, value);
}
}
return lb_emit_deep_field_ev(p, value, sel);
}
}
}
@@ -4232,7 +4231,7 @@ lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
args[1] = size;
args[2] = align;
args[3] = lb_const_int(p->module, t_int, item_count);
args[4] = lb_emit_source_code_location(p, proc_name, pos);
args[4] = lb_emit_source_code_location_as_global(p, proc_name, pos);
lb_emit_runtime_call(p, "__dynamic_array_reserve", args);
}
@@ -4253,7 +4252,7 @@ lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
args[2] = align;
args[3] = lb_emit_conv(p, items, t_rawptr);
args[4] = lb_const_int(p->module, t_int, item_count);
args[5] = lb_emit_source_code_location(p, proc_name, pos);
args[5] = lb_emit_source_code_location_as_global(p, proc_name, pos);
lb_emit_runtime_call(p, "__dynamic_array_append", args);
}
break;
+40 -9
View File
@@ -383,16 +383,27 @@ Type *lb_addr_type(lbAddr const &addr) {
if (addr.addr.value == nullptr) {
return nullptr;
}
if (addr.kind == lbAddr_Map) {
Type *t = base_type(addr.map.type);
GB_ASSERT(is_type_map(t));
return t->Map.value;
}
if (addr.kind == lbAddr_Swizzle) {
switch (addr.kind) {
case lbAddr_Map:
{
Type *t = base_type(addr.map.type);
GB_ASSERT(is_type_map(t));
return t->Map.value;
}
case lbAddr_Swizzle:
return addr.swizzle.type;
}
if (addr.kind == lbAddr_SwizzleLarge) {
case lbAddr_SwizzleLarge:
return addr.swizzle_large.type;
case lbAddr_Context:
if (addr.ctx.sel.index.count > 0) {
Type *t = t_context;
for_array(i, addr.ctx.sel.index) {
GB_ASSERT(is_type_struct(t));
t = base_type(t)->Struct.fields[addr.ctx.sel.index[i]]->type;
}
return t;
}
break;
}
return type_deref(addr.addr.type);
}
@@ -1507,6 +1518,7 @@ LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *type) {
LLVMTypeRef ret = nullptr;
LLVMTypeRef *params = gb_alloc_array(permanent_allocator(), LLVMTypeRef, param_count);
bool *params_by_ptr = gb_alloc_array(permanent_allocator(), bool, param_count);
if (type->Proc.result_count != 0) {
Type *single_ret = reduce_tuple_to_single_type(type->Proc.results);
ret = lb_type(m, single_ret);
@@ -1532,9 +1544,12 @@ LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *type) {
}
Type *e_type = reduce_tuple_to_single_type(e->type);
bool param_is_by_ptr = false;
LLVMTypeRef param_type = nullptr;
if (e->flags & EntityFlag_ByPtr) {
param_type = lb_type(m, alloc_type_pointer(e_type));
// it will become a pointer afterwards by making it indirect
param_type = lb_type(m, e_type);
param_is_by_ptr = true;
} else if (is_type_boolean(e_type) &&
type_size_of(e_type) <= 1) {
param_type = LLVMInt1TypeInContext(m->ctx);
@@ -1546,6 +1561,7 @@ LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *type) {
}
}
params_by_ptr[param_index] = param_is_by_ptr;
params[param_index++] = param_type;
}
}
@@ -1571,6 +1587,12 @@ LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *type) {
LLVMPrintTypeToString(ft->ret.type),
LLVMGetTypeContext(ft->ret.type), ft->ctx, LLVMGetGlobalContext());
}
for_array(j, ft->args) {
if (params_by_ptr[j]) {
// NOTE(bill): The parameter needs to be passed "indirectly", override it
ft->args[j].kind = lbArg_Indirect;
}
}
map_set(&m->function_type_map, type, ft);
LLVMTypeRef new_abi_fn_type = lb_function_type_to_llvm_raw(ft, type->Proc.c_vararg);
@@ -2579,6 +2601,15 @@ lbValue lb_find_or_add_entity_string_byte_slice_with_type(lbModule *m, String co
lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) {
if (e->flags & EntityFlag_Param) {
// NOTE(bill): Bypass the stack copied variable for
// direct parameters as there is no need for the direct load
auto *found = map_get(&p->direct_parameters, e);
if (found) {
return *found;
}
}
auto *found = map_get(&m->values, e);
if (found) {
auto v = *found;
+60 -4
View File
@@ -486,6 +486,8 @@ void lb_begin_procedure_body(lbProcedure *p) {
p->entry_block = lb_create_block(p, "entry", true);
lb_start_block(p, p->entry_block);
map_init(&p->direct_parameters, heap_allocator());
GB_ASSERT(p->type != nullptr);
lb_ensure_abi_function_type(p->module, p);
@@ -539,6 +541,8 @@ void lb_begin_procedure_body(lbProcedure *p) {
param.value = value;
param.type = e->type;
map_set(&p->direct_parameters, e, param);
lbValue ptr = lb_address_from_load_or_generate_local(p, param);
GB_ASSERT(LLVMIsAAllocaInst(ptr.value));
lb_add_entity(p->module, e, ptr);
@@ -753,12 +757,16 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
}
GB_ASSERT_MSG(lb_is_type_kind(fnp, LLVMFunctionTypeKind), "%s", LLVMPrintTypeToString(fnp));
lbFunctionType *ft = map_must_get(&p->module->function_type_map, base_type(value.type));
{
unsigned param_count = LLVMCountParamTypes(fnp);
GB_ASSERT(arg_count >= param_count);
LLVMTypeRef *param_types = gb_alloc_array(temporary_allocator(), LLVMTypeRef, param_count);
LLVMGetParamTypes(fnp, param_types);
for (unsigned i = 0; i < param_count; i++) {
LLVMTypeRef param_type = param_types[i];
LLVMTypeRef arg_type = LLVMTypeOf(args[i]);
@@ -776,10 +784,20 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr,
LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex;
if (return_ptr.value != nullptr) {
param_offset += 1;
LLVMAddCallSiteAttribute(ret, 1, lb_create_enum_attribute_with_type(p->module->ctx, "sret", LLVMTypeOf(args[0])));
}
for_array(i, ft->args) {
LLVMAttributeRef attribute = ft->args[i].attribute;
if (attribute != nullptr) {
LLVMAddCallSiteAttribute(ret, param_offset + cast(LLVMAttributeIndex)i, attribute);
}
}
switch (inlining) {
case ProcInlining_none:
break;
@@ -893,6 +911,9 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
auto processed_args = array_make<lbValue>(permanent_allocator(), 0, args.count);
{
bool is_odin_cc = is_calling_convention_odin(pt->Proc.calling_convention);
lbFunctionType *ft = lb_get_function_type(m, p, pt);
bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
@@ -928,8 +949,12 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
} else if (arg->kind == lbArg_Indirect) {
lbValue ptr = {};
if (arg->is_byval) {
ptr = lb_copy_value_to_ptr(p, x, original_type, arg->byval_alignment);
} else if (is_calling_convention_odin(pt->Proc.calling_convention)) {
if (is_odin_cc && are_types_identical(original_type, t_source_code_location)) {
ptr = lb_address_from_load_or_generate_local(p, x);
} else {
ptr = lb_copy_value_to_ptr(p, x, original_type, arg->byval_alignment);
}
} else if (is_odin_cc) {
// NOTE(bill): Odin parameters are immutable so the original value can be passed if possible
// i.e. `T const &` in C++
ptr = lb_address_from_load_or_generate_local(p, x);
@@ -1485,7 +1510,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
pos = e->token.pos;
}
return lb_emit_source_code_location(p, procedure, pos);
return lb_emit_source_code_location_as_global(p, procedure, pos);
}
case BuiltinProc_type_info_of: {
@@ -1836,6 +1861,37 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
lb_emit_unreachable(p);
return {};
case BuiltinProc_raw_data:
{
lbValue x = lb_build_expr(p, ce->args[0]);
Type *t = base_type(x.type);
lbValue res = {};
switch (t->kind) {
case Type_Slice:
res = lb_slice_elem(p, x);
res = lb_emit_conv(p, res, tv.type);
break;
case Type_DynamicArray:
res = lb_dynamic_array_elem(p, x);
res = lb_emit_conv(p, res, tv.type);
break;
case Type_Basic:
if (t->Basic.kind == Basic_string) {
res = lb_string_elem(p, x);
res = lb_emit_conv(p, res, tv.type);
} else if (t->Basic.kind == Basic_cstring) {
res = lb_emit_conv(p, x, tv.type);
}
break;
case Type_Pointer:
case Type_MultiPointer:
res = lb_emit_conv(p, x, tv.type);
break;
}
GB_ASSERT(res.value != nullptr);
return res;
}
// "Intrinsics"
@@ -2825,7 +2881,7 @@ lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterVal
if (p->entity != nullptr) {
proc_name = p->entity->token.string;
}
return lb_emit_source_code_location(p, proc_name, pos);
return lb_emit_source_code_location_as_global(p, proc_name, pos);
}
case ParameterValue_Value:
return lb_build_expr(p, param_value.ast_value);
+1 -1
View File
@@ -235,7 +235,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
}
TokenPos pos = t->Named.type_name->token.pos;
lbValue loc = lb_emit_source_code_location(p, proc_name, pos);
lbValue loc = lb_emit_source_code_location_const(p, proc_name, pos);
LLVMValueRef vals[4] = {
lb_const_string(p->module, t->Named.type_name->token.string).value,
+37 -48
View File
@@ -53,6 +53,9 @@ gb_global Timings global_timings = {0};
#if LLVM_VERSION_MAJOR < 11
#error LLVM Version 11+ is required => "brew install llvm@11"
#endif
#if LLVM_VERSION_MAJOR > 14
#error LLVM Version 11..=14 is required => "brew install llvm@14"
#endif
#endif
#include "query_data.cpp"
@@ -478,9 +481,9 @@ i32 linker_stage(lbGenerator *gen) {
if (build_context.metrics.os == TargetOs_darwin) {
// This sets a requirement of Mountain Lion and up, but the compiler doesn't work without this limit.
// NOTE: If you change this (although this minimum is as low as you can go with Odin working)
// make sure to also change the 'mtriple' param passed to 'opt'
if (build_context.metrics.arch == TargetArch_arm64) {
if (build_context.minimum_os_version_string.len) {
link_settings = gb_string_append_fmt(link_settings, " -mmacosx-version-min=%.*s ", LIT(build_context.minimum_os_version_string));
} else if (build_context.metrics.arch == TargetArch_arm64) {
link_settings = gb_string_appendc(link_settings, " -mmacosx-version-min=12.0.0 ");
} else {
link_settings = gb_string_appendc(link_settings, " -mmacosx-version-min=10.12.0 ");
@@ -588,7 +591,6 @@ enum BuildFlagKind {
BuildFlag_SingleFile,
BuildFlag_OutFile,
BuildFlag_OptimizationLevel,
BuildFlag_OptimizationMode,
BuildFlag_ShowTimings,
BuildFlag_ShowUnused,
@@ -622,6 +624,7 @@ enum BuildFlagKind {
BuildFlag_ExtraAssemblerFlags,
BuildFlag_Microarch,
BuildFlag_TargetFeatures,
BuildFlag_MinimumOSVersion,
BuildFlag_RelocMode,
BuildFlag_DisableRedZone,
@@ -742,13 +745,25 @@ ExactValue build_param_to_exact_value(String name, String param) {
return value;
}
// Writes a did-you-mean message for formerly deprecated flags.
void did_you_mean_flag(String flag) {
gbAllocator a = heap_allocator();
String name = copy_string(a, flag);
defer (gb_free(a, name.text));
string_to_lower(&name);
if (name == "opt") {
gb_printf_err("`-opt` is an unrecognized option. Did you mean `-o`?\n");
return;
}
gb_printf_err("Unknown flag: '%.*s'\n", LIT(flag));
}
bool parse_build_flags(Array<String> args) {
auto build_flags = array_make<BuildFlag>(heap_allocator(), 0, BuildFlag_COUNT);
add_flag(&build_flags, BuildFlag_Help, str_lit("help"), BuildFlagParam_None, Command_all);
add_flag(&build_flags, BuildFlag_SingleFile, str_lit("file"), BuildFlagParam_None, Command__does_build | Command__does_check);
add_flag(&build_flags, BuildFlag_OutFile, str_lit("out"), BuildFlagParam_String, Command__does_build &~ Command_test);
add_flag(&build_flags, BuildFlag_OptimizationLevel, str_lit("opt"), BuildFlagParam_Integer, Command__does_build);
add_flag(&build_flags, BuildFlag_OptimizationMode, str_lit("o"), BuildFlagParam_String, Command__does_build);
add_flag(&build_flags, BuildFlag_OptimizationMode, str_lit("O"), BuildFlagParam_String, Command__does_build);
add_flag(&build_flags, BuildFlag_ShowTimings, str_lit("show-timings"), BuildFlagParam_None, Command__does_check);
@@ -783,6 +798,7 @@ bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_ExtraAssemblerFlags, str_lit("extra-assembler-flags"), BuildFlagParam_String, Command__does_build);
add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build);
add_flag(&build_flags, BuildFlag_TargetFeatures, str_lit("target-features"), BuildFlagParam_String, Command__does_build);
add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build);
add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build);
add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build);
@@ -850,16 +866,14 @@ bool parse_build_flags(Array<String> args) {
break;
}
}
name = substring(name, 0, end);
if (have_equals && name != "opt") {
gb_printf_err("`flag=value` has been deprecated and will be removed next release. Use `%.*s:` instead.\n", LIT(name));
}
name = substring(name, 0, end);
String param = {};
if (end < flag.len-1) param = substring(flag, 2+end, flag.len);
bool is_supported = true;
bool found = false;
BuildFlag found_bf = {};
for_array(build_flag_index, build_flags) {
BuildFlag bf = build_flags[build_flag_index];
@@ -979,37 +993,8 @@ bool parse_build_flags(Array<String> args) {
}
break;
}
case BuildFlag_OptimizationLevel: {
GB_ASSERT(value.kind == ExactValue_Integer);
if (set_flags[BuildFlag_OptimizationMode]) {
gb_printf_err("Mixture of -opt and -o is not allowed\n");
bad_flags = true;
break;
}
build_context.optimization_level = cast(i32)big_int_to_i64(&value.value_integer);
if (build_context.optimization_level < 0 || build_context.optimization_level > 3) {
gb_printf_err("Invalid optimization level for -o:<integer>, got %d\n", build_context.optimization_level);
gb_printf_err("Valid optimization levels:\n");
gb_printf_err("\t0\n");
gb_printf_err("\t1\n");
gb_printf_err("\t2\n");
gb_printf_err("\t3\n");
bad_flags = true;
}
// Deprecation warning.
gb_printf_err("`-opt` has been deprecated and will be removed next release. Use `-o:minimal`, etc.\n");
break;
}
case BuildFlag_OptimizationMode: {
GB_ASSERT(value.kind == ExactValue_String);
if (set_flags[BuildFlag_OptimizationLevel]) {
gb_printf_err("Mixture of -opt and -o is not allowed\n");
bad_flags = true;
break;
}
if (value.value_string == "minimal") {
build_context.optimization_level = 0;
} else if (value.value_string == "size") {
@@ -1378,6 +1363,11 @@ bool parse_build_flags(Array<String> args) {
string_to_lower(&build_context.target_features_string);
break;
}
case BuildFlag_MinimumOSVersion: {
GB_ASSERT(value.kind == ExactValue_String);
build_context.minimum_os_version_string = value.value_string;
break;
}
case BuildFlag_RelocMode: {
GB_ASSERT(value.kind == ExactValue_String);
String v = value.value_string;
@@ -1625,7 +1615,7 @@ bool parse_build_flags(Array<String> args) {
gb_printf_err("\n");
bad_flags = true;
} else if (!found) {
gb_printf_err("Unknown flag: '%.*s'\n", LIT(name));
did_you_mean_flag(name);
bad_flags = true;
}
}
@@ -1989,12 +1979,6 @@ void print_show_help(String const arg0, String const &command) {
print_usage_line(2, "Example: -out:foo.exe");
print_usage_line(0, "");
print_usage_line(1, "-opt:<integer>");
print_usage_line(2, "Set the optimization level for compilation");
print_usage_line(2, "Accepted values: 0, 1, 2, 3");
print_usage_line(2, "Example: -opt:2");
print_usage_line(0, "");
print_usage_line(1, "-o:<string>");
print_usage_line(2, "Set the optimization mode for compilation");
print_usage_line(2, "Accepted values: minimal, size, speed");
@@ -2056,8 +2040,8 @@ void print_show_help(String const arg0, String const &command) {
print_usage_line(3, "import \"shared:foo\"");
print_usage_line(0, "");
print_usage_line(1, "-define:<name>=<expression>");
print_usage_line(2, "Defines a global constant with a value");
print_usage_line(1, "-define:<name>=<value>");
print_usage_line(2, "Defines a scalar boolean, integer or string as global constant");
print_usage_line(2, "Example: -define:SPAM=123");
print_usage_line(2, "To use: #config(SPAM, default_value)");
print_usage_line(0, "");
@@ -2158,6 +2142,12 @@ void print_show_help(String const arg0, String const &command) {
}
if (run_or_build) {
print_usage_line(1, "-minimum-os-version:<string>");
print_usage_line(2, "Sets the minimum OS version targeted by the application");
print_usage_line(2, "e.g. -minimum-os-version:12.0.0");
print_usage_line(2, "(Only used when target is Darwin)");
print_usage_line(0, "");
print_usage_line(1, "-extra-linker-flags:<string>");
print_usage_line(2, "Adds extra linker specific flags in a string");
print_usage_line(0, "");
@@ -2166,7 +2156,6 @@ void print_show_help(String const arg0, String const &command) {
print_usage_line(2, "Adds extra assembler specific flags in a string");
print_usage_line(0, "");
print_usage_line(1, "-microarch:<string>");
print_usage_line(2, "Specifies the specific micro-architecture for the build in a string");
print_usage_line(2, "Examples:");
+38
View File
@@ -2526,6 +2526,44 @@ String lookup_subtype_polymorphic_field(Type *dst, Type *src) {
return str_lit("");
}
bool lookup_subtype_polymorphic_selection(Type *dst, Type *src, Selection *sel) {
Type *prev_src = src;
// Type *prev_dst = dst;
src = base_type(type_deref(src));
// dst = base_type(type_deref(dst));
bool src_is_ptr = src != prev_src;
// bool dst_is_ptr = dst != prev_dst;
GB_ASSERT(is_type_struct(src) || is_type_union(src));
for_array(i, src->Struct.fields) {
Entity *f = src->Struct.fields[i];
if (f->kind == Entity_Variable && f->flags & EntityFlags_IsSubtype) {
if (are_types_identical(dst, f->type)) {
array_add(&sel->index, cast(i32)i);
sel->entity = f;
return true;
}
if (src_is_ptr && is_type_pointer(dst)) {
if (are_types_identical(type_deref(dst), f->type)) {
array_add(&sel->index, cast(i32)i);
sel->indirect = true;
sel->entity = f;
return true;
}
}
if ((f->flags & EntityFlag_Using) != 0 && is_type_struct(f->type)) {
String name = lookup_subtype_polymorphic_field(dst, f->type);
if (name.len > 0) {
array_add(&sel->index, cast(i32)i);
return lookup_subtype_polymorphic_selection(dst, f->type, sel);
}
}
}
}
return false;
}
Type *strip_type_aliasing(Type *x) {
+12 -6
View File
@@ -1,17 +1,23 @@
@echo off
if not exist "build\" mkdir build
pushd build
set COMMON=-collection:tests=.. -out:build\test_issue.exe
set COMMON=-collection:tests=..\..
set ERROR_DID_OCCUR=0
@echo on
..\..\odin build test_issue_829.odin %COMMON% -file
build\test_issue
..\..\odin build test_issue_1592.odin %COMMON% -file
build\test_issue
..\..\..\odin test ..\test_issue_829.odin %COMMON% -file
..\..\..\odin test ..\test_issue_1592.odin %COMMON% -file
..\..\..\odin test ..\test_issue_2087.odin %COMMON% -file
..\..\..\odin build ..\test_issue_2113.odin %COMMON% -file -debug
@echo off
if %ERRORLEVEL% NEQ 0 set ERROR_DID_OCCUR=1
popd
rmdir /S /Q build
if %ERROR_DID_OCCUR% NEQ 0 EXIT /B 1
+8 -7
View File
@@ -2,17 +2,18 @@
set -eu
mkdir -p build
ODIN=../../odin
COMMON="-collection:tests=.. -out:build/test_issue"
pushd build
ODIN=../../../odin
COMMON="-collection:tests=../.."
set -x
$ODIN build test_issue_829.odin $COMMON -file
./build/test_issue
$ODIN build test_issue_1592.odin $COMMON -file
./build/test_issue
$ODIN test ../test_issue_829.odin $COMMON -file
$ODIN test ../test_issue_1592.odin $COMMON -file
$ODIN test ../test_issue_2087.odin $COMMON -file
$ODIN build ../test_issue_2113.odin $COMMON -file -debug
set +x
popd
rm -rf build
+146 -177
View File
@@ -3,36 +3,6 @@ package test_issues
import "core:fmt"
import "core:testing"
import tc "tests:common"
main :: proc() {
t := testing.T{}
/* This won't short-circuit */
test_orig()
/* These will short-circuit */
test_simple_const_false(&t)
test_simple_const_true(&t)
/* These won't short-circuit */
test_simple_proc_false(&t)
test_simple_proc_true(&t)
/* These won't short-circuit */
test_const_false_const_false(&t)
test_const_false_const_true(&t)
test_const_true_const_false(&t)
test_const_true_const_true(&t)
/* These won't short-circuit */
test_proc_false_const_false(&t)
test_proc_false_const_true(&t)
test_proc_true_const_false(&t)
test_proc_true_const_true(&t)
tc.report(&t)
}
/* Original issue #1592 example */
@@ -43,7 +13,6 @@ bool_result :: proc() -> bool {
return false
}
@test
test_orig :: proc() {
if bool_result() || CONSTANT_BOOL {
}
@@ -62,428 +31,428 @@ true_result :: proc() -> bool {
@test
test_simple_const_false :: proc(t: ^testing.T) {
if CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if (CONSTANT_FALSE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if (!CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !!CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE == true {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE == false {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_FALSE == true) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_FALSE == false) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
}
@test
test_simple_const_true :: proc(t: ^testing.T) {
if CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if (CONSTANT_TRUE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if (!CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if (!CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !!CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE == true {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE == false {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE == true) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE == false) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_simple_proc_false :: proc(t: ^testing.T) {
if false_result() {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !false_result() {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_simple_proc_true :: proc(t: ^testing.T) {
if true_result() {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !true_result() {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
}
@test
test_const_false_const_false :: proc(t: ^testing.T) {
if CONSTANT_FALSE || CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_FALSE || CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_FALSE && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE || !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_FALSE && !CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_FALSE || CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_FALSE && CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_const_false_const_true :: proc(t: ^testing.T) {
if CONSTANT_FALSE || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_FALSE && CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_FALSE || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_FALSE && CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_FALSE || !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_FALSE && !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_FALSE || CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_FALSE && CONSTANT_TRUE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_const_true_const_false :: proc(t: ^testing.T) {
if CONSTANT_TRUE || CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_TRUE || CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !CONSTANT_TRUE && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_TRUE || !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE && !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(CONSTANT_TRUE || CONSTANT_FALSE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE && CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_const_true_const_true :: proc(t: ^testing.T) {
if CONSTANT_TRUE || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE && CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_TRUE || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !CONSTANT_TRUE && CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if CONSTANT_TRUE || !CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if CONSTANT_TRUE && !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE || CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(CONSTANT_TRUE && CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
}
@test
test_proc_false_const_false :: proc(t: ^testing.T) {
if false_result() || CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if false_result() && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(false_result() || CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(false_result() && CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_proc_false_const_true :: proc(t: ^testing.T) {
if false_result() || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if false_result() && CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(false_result() || CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(false_result() && CONSTANT_TRUE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_proc_true_const_false :: proc(t: ^testing.T) {
if true_result() || CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if true_result() && CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(true_result() || CONSTANT_FALSE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(true_result() && CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
}
@test
test_proc_true_const_true :: proc(t: ^testing.T) {
if true_result() || CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if true_result() && CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
}
if !(true_result() || CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
if !(true_result() && CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
}
}
+62
View File
@@ -0,0 +1,62 @@
// Tests issue #2087 https://github.com/odin-lang/Odin/issues/2087
package test_issues
import "core:math"
import "core:strconv"
import "core:testing"
@(test)
test_parse_float :: proc(t: ^testing.T) {
{
f, ok := strconv.parse_f64("1.2")
testing.expect(t, ok && f == 1.2, "expected f64(1.2), fully consumed")
f, ok = strconv.parse_f64("1.2a")
testing.expect(t, !ok && f == 1.2, "expected f64(1.2), partially consumed")
f, ok = strconv.parse_f64("+")
testing.expect(t, !ok && f == 0.0, "expected f64(0.0), with ok=false")
f, ok = strconv.parse_f64("-")
testing.expect(t, !ok && f == 0.0, "expected f64(0.0), with ok=false")
f, ok = strconv.parse_f64("inf")
testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), fully consumed")
f, ok = strconv.parse_f64("+inf")
testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), fully consumed")
f, ok = strconv.parse_f64("-inf")
testing.expect(t, ok && math.classify(f) == math.Float_Class.Neg_Inf, "expected f64(-inf), fully consumed")
f, ok = strconv.parse_f64("inFinity")
testing.expect(t, !ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), partially consumed")
f, ok = strconv.parse_f64("+InFinity")
testing.expect(t, !ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), partially consumed")
f, ok = strconv.parse_f64("-InfiniTy")
testing.expect(t, !ok && math.classify(f) == math.Float_Class.Neg_Inf, "expected f64(-inf), partially consumed")
f, ok = strconv.parse_f64("nan")
testing.expect(t, ok && math.classify(f) == math.Float_Class.NaN, "expected f64(nan), fully consumed")
f, ok = strconv.parse_f64("nAN")
testing.expect(t, ok && math.classify(f) == math.Float_Class.NaN, "expected f64(nan), fully consumed")
}
{
f, ok := strconv.parse_f32("1.2")
testing.expect(t, ok && f == 1.2, "expected f32(1.2), fully consumed")
f, ok = strconv.parse_f32("1.2a")
testing.expect(t, !ok && f == 1.2, "expected f32(1.2), partially consumed")
f, ok = strconv.parse_f32("inf")
testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f32(+inf), fully consumed")
f, ok = strconv.parse_f32("+inf")
testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f32(+inf), fully consumed")
f, ok = strconv.parse_f32("-inf")
testing.expect(t, ok && math.classify(f) == math.Float_Class.Neg_Inf, "expected f32(-inf), fully consumed")
f, ok = strconv.parse_f32("inFinity")
testing.expect(t, !ok && math.classify(f) == math.Float_Class.Inf, "expected f32(+inf), partially consumed")
f, ok = strconv.parse_f32("+InFinity")
testing.expect(t, !ok && math.classify(f) == math.Float_Class.Inf, "expected f32(+inf), partially consumed")
f, ok = strconv.parse_f32("-InfiniTy")
testing.expect(t, !ok && math.classify(f) == math.Float_Class.Neg_Inf, "expected f32(-inf), partially consumed")
f, ok = strconv.parse_f32("nan")
testing.expect(t, ok && math.classify(f) == math.Float_Class.NaN, "expected f32(nan), fully consumed")
f, ok = strconv.parse_f32("nAN")
testing.expect(t, ok && math.classify(f) == math.Float_Class.NaN, "expected f32(nan), fully consumed")
}
}
+13
View File
@@ -0,0 +1,13 @@
// Tests issue #2113 https://github.com/odin-lang/Odin/issues/2113
// Causes a panic on compilation
package test_issues
T :: struct {
a: int,
}
main :: proc() {
array: #soa[1]T
a := &array[0]
_ = a
}
+2 -17
View File
@@ -3,31 +3,16 @@ package test_issues
import "core:fmt"
import "core:testing"
import tc "tests:common"
/* Original issue #829 example */
env : map[string]proc(a, b : int) -> int = {
"+" = proc(a, b : int) -> int {
return a + b
},
}
test_orig :: proc() {
fmt.println(env["+"](1, 2))
}
main :: proc() {
t := testing.T{}
test_orig()
test_orig_ret(&t)
tc.report(&t)
}
@(test)
test_orig_ret :: proc(t: ^testing.T) {
r := fmt.tprint(env["+"](1, 2))
tc.expect(t, r == "3", fmt.tprintf("%s: \"%s\" != \"3\"\n", #procedure, r))
testing.expect(t, r == "3", fmt.tprintf("%s: \"%s\" != \"3\"\n", #procedure, r))
}
+3 -3
View File
@@ -11,7 +11,7 @@ ActivationPolicy :: enum UInteger {
ApplicationDelegate :: struct {
willFinishLaunching: proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
didFinishLaunching: proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application),
shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application) -> BOOL,
user_data: rawptr,
}
@@ -34,9 +34,9 @@ Application_setDelegate :: proc(self: ^Application, delegate: ^ApplicationDelega
del := (^ApplicationDelegate)(self->pointerValue())
del->didFinishLaunching(notification)
}
shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) {
shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) -> BOOL {
del := (^ApplicationDelegate)(self->pointerValue())
del->shouldTerminateAfterLastWindowClosed(application)
return del->shouldTerminateAfterLastWindowClosed(application)
}
wrapper := Value.valueWithPointer(delegate)
+16
View File
@@ -156,6 +156,22 @@ Window_makeKeyAndOrderFront :: proc(self: ^Window, key: ^NS.Object) {
Window_setTitle :: proc(self: ^Window, title: ^NS.String) {
msgSend(nil, self, "setTitle:", title)
}
@(objc_type=Window, objc_name="setTitlebarAppearsTransparent")
Window_setTitlebarAppearsTransparent :: proc(self: ^Window, ok: NS.BOOL) {
msgSend(nil, self, "setTitlebarAppearsTransparent:", ok)
}
@(objc_type=Window, objc_name="setMovable")
Window_setMovable :: proc(self: ^Window, ok: NS.BOOL) {
msgSend(nil, self, "setMovable:", ok)
}
@(objc_type=Window, objc_name="setMovableByWindowBackground")
Window_setMovableByWindowBackground :: proc(self: ^Window, ok: NS.BOOL) {
msgSend(nil, self, "setMovableByWindowBackground:", ok)
}
@(objc_type=Window, objc_name="setStyleMask")
Window_setStyleMask :: proc(self: ^Window, style_mask: WindowStyleMask) {
msgSend(nil, self, "setStyleMask:", style_mask)
}
@(objc_type=Window, objc_name="close")
Window_close :: proc(self: ^Window) {
msgSend(nil, self, "close")
+5 -1
View File
@@ -10,9 +10,13 @@ IMP :: proc "c" (object: id, sel: SEL, #c_vararg args: ..any) -> id
foreign Foundation {
objc_lookUpClass :: proc "c" (name: cstring) -> Class ---
sel_registerName :: proc "c" (name: cstring) -> SEL ---
objc_allocateClassPair :: proc "c" (superclass: Class, name: cstring, extraBytes: uint) ---
objc_allocateClassPair :: proc "c" (superclass : Class, name : cstring, extraBytes : c.size_t) -> Class ---
objc_registerClassPair :: proc "c" (cls : Class) ---
class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL ---
class_getInstanceMethod :: proc "c" (cls: Class, name: SEL) -> Method ---
method_setImplementation :: proc "c" (method: Method, imp: IMP) ---
}
+184 -143
View File
@@ -30,7 +30,7 @@ foreign d3d11 {
DriverType: DRIVER_TYPE,
Software: HMODULE,
Flags: CREATE_DEVICE_FLAGS,
pFeatureLevels: ^FEATURE_LEVEL,
pFeatureLevels: [^]FEATURE_LEVEL,
FeatureLevels: u32,
SDKVersion: u32,
ppDevice: ^^IDevice,
@@ -41,8 +41,8 @@ foreign d3d11 {
pAdapter: ^dxgi.IAdapter,
DriverType: DRIVER_TYPE,
Software: HMODULE,
Flags: u32,
pFeatureLevels: ^FEATURE_LEVEL,
Flags: CREATE_DEVICE_FLAGS,
pFeatureLevels: [^]FEATURE_LEVEL,
FeatureLevels: u32,
SDKVersion: u32,
pSwapChainDesc: ^dxgi.SWAP_CHAIN_DESC,
@@ -539,25 +539,37 @@ ANISOTROPIC_FILTERING_BIT :: 0x40
SDK_VERSION :: 7
RETURN_PARAMETER_INDEX :: -1
COMPONENT_MASK :: enum u32 { // TODO: make bit_set
COMPONENT_MASK :: distinct bit_set[COMPONENT_MASK_ELEMENT; u32]
COMPONENT_MASK_ELEMENT :: enum u32 {
X = 1,
Y = 2,
Z = 4,
W = 8,
}
SHADER_REQUIRES :: enum u32 { // TODO: make bit_set
DOUBLES = 0x00000001,
EARLY_DEPTH_STENCIL = 0x00000002,
UAVS_AT_EVERY_STAGE = 0x00000004,
_64_UAVS = 0x00000008,
MINIMUM_PRECISION = 0x00000010,
_11_1_DOUBLE_EXTENSIONS = 0x00000020,
_11_1_SHADER_EXTENSIONS = 0x00000040,
LEVEL_9_COMPARISON_FILTERING = 0x00000080,
TILED_RESOURCES = 0x00000100,
SHADER_REQUIRES_FLAGS :: distinct bit_set[SHADER_REQUIRES_FLAG; u64]
SHADER_REQUIRES_FLAG :: enum u64 {
DOUBLES = 0,
EARLY_DEPTH_STENCIL = 1,
UAVS_AT_EVERY_STAGE = 2,
_64_UAVS = 3,
MINIMUM_PRECISION = 4,
_11_1_DOUBLE_EXTENSIONS = 5,
_11_1_SHADER_EXTENSIONS = 6,
LEVEL_9_COMPARISON_FILTERING = 7,
TILED_RESOURCES = 8,
}
SHADER_REQUIRES_DOUBLES :: SHADER_REQUIRES_FLAGS{.DOUBLES}
SHADER_REQUIRES_EARLY_DEPTH_STENCIL :: SHADER_REQUIRES_FLAGS{.EARLY_DEPTH_STENCIL}
SHADER_REQUIRES_UAVS_AT_EVERY_STAGE :: SHADER_REQUIRES_FLAGS{.UAVS_AT_EVERY_STAGE}
SHADER_REQUIRES_64_UAVS :: SHADER_REQUIRES_FLAGS{._64_UAVS}
SHADER_REQUIRES_MINIMUM_PRECISION :: SHADER_REQUIRES_FLAGS{.MINIMUM_PRECISION}
SHADER_REQUIRES_11_1_DOUBLE_EXTENSIONS :: SHADER_REQUIRES_FLAGS{._11_1_DOUBLE_EXTENSIONS}
SHADER_REQUIRES_11_1_SHADER_EXTENSIONS :: SHADER_REQUIRES_FLAGS{._11_1_SHADER_EXTENSIONS}
SHADER_REQUIRES_LEVEL_9_COMPARISON_FILTERING :: SHADER_REQUIRES_FLAGS{.LEVEL_9_COMPARISON_FILTERING}
SHADER_REQUIRES_TILED_RESOURCES :: SHADER_REQUIRES_FLAGS{.TILED_RESOURCES}
DRIVER_TYPE :: enum i32 {
UNKNOWN = 0,
HARDWARE = 1,
@@ -708,11 +720,12 @@ SHADER_VARIABLE_CLASS :: enum i32 {
INTERFACE_POINTER = 7,
}
SHADER_VARIABLE_FLAGS :: enum u32 { // TODO: make bit_set
USERPACKED = 0x1,
USED = 0x2,
INTERFACE_POINTER = 0x4,
INTERFACE_PARAMETER = 0x8,
SHADER_VARIABLE_FLAGS :: distinct bit_set[SHADER_VARIABLE_FLAG; u32]
SHADER_VARIABLE_FLAG :: enum u32 {
USERPACKED = 0,
USED = 1,
INTERFACE_POINTER = 2,
INTERFACE_PARAMETER = 3,
}
SHADER_VARIABLE_TYPE :: enum i32 {
@@ -776,14 +789,21 @@ SHADER_VARIABLE_TYPE :: enum i32 {
MIN16UINT = 57,
}
SHADER_INPUT_FLAGS :: enum u32 { // TODO: make bit_set
USERPACKED = 0x1,
COMPARISON_SAMPLER = 0x2,
TEXTURE_COMPONENT_0 = 0x4,
TEXTURE_COMPONENT_1 = 0x8,
SHADER_INPUT_FLAGS :: distinct bit_set[SHADER_INPUT_FLAG; u32]
SHADER_INPUT_FLAG :: enum u32 {
USERPACKED = 0,
COMPARISON_SAMPLER = 1,
TEXTURE_COMPONENT_0 = 2,
TEXTURE_COMPONENT_1 = 3,
TEXTURE_COMPONENTS = 0xc,
UNUSED = 0x10,
UNUSED = 4,
}
SHADER_INPUT_FLAG_USERPACKED :: SHADER_INPUT_FLAGS{.USERPACKED}
SHADER_INPUT_FLAG_COMPARISON_SAMPLER :: SHADER_INPUT_FLAGS{.COMPARISON_SAMPLER}
SHADER_INPUT_FLAG_TEXTURE_COMPONENT_0 :: SHADER_INPUT_FLAGS{.TEXTURE_COMPONENT_0}
SHADER_INPUT_FLAG_TEXTURE_COMPONENT_1 :: SHADER_INPUT_FLAGS{.TEXTURE_COMPONENT_1}
SHADER_INPUT_FLAG_TEXTURE_COMPONENTS :: SHADER_INPUT_FLAGS{.TEXTURE_COMPONENT_0, .TEXTURE_COMPONENT_1}
SHADER_INPUT_FLAG_UNUSED :: SHADER_INPUT_FLAGS{.UNUSED}
SHADER_INPUT_TYPE :: enum i32 {
CBUFFER = 0,
@@ -802,8 +822,9 @@ SHADER_INPUT_TYPE :: enum i32 {
UAV_FEEDBACKTEXTURE = 13,
}
SHADER_CBUFFER_FLAGS :: enum u32 { // TODO: make bit_set
USERPACKED = 0x1,
SHADER_CBUFFER_FLAGS :: distinct bit_set[SHADER_CBUFFER_FLAG; u32]
SHADER_CBUFFER_FLAG :: enum u32 {
USERPACKED = 0,
}
CBUFFER_TYPE :: enum i32 {
@@ -906,10 +927,10 @@ INTERPOLATION_MODE :: enum i32 {
LINEAR_NOPERSPECTIVE_SAMPLE = 7,
}
PARAMETER_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
IN = 0x1,
OUT = 0x2,
PARAMETER_FLAGS :: distinct bit_set[PARAMETER_FLAG; u32]
PARAMETER_FLAG :: enum u32 {
IN = 0,
OUT = 1,
}
CDEFAULT :: struct {
@@ -1022,43 +1043,46 @@ USAGE :: enum i32 {
STAGING = 3,
}
BIND_FLAG :: enum u32 { // TODO: make bit_set
VERTEX_BUFFER = 0x1,
INDEX_BUFFER = 0x2,
CONSTANT_BUFFER = 0x4,
SHADER_RESOURCE = 0x8,
STREAM_OUTPUT = 0x10,
RENDER_TARGET = 0x20,
DEPTH_STENCIL = 0x40,
UNORDERED_ACCESS = 0x80,
DECODER = 0x200,
VIDEO_ENCODER = 0x400,
BIND_FLAGS :: distinct bit_set[BIND_FLAG; u32]
BIND_FLAG :: enum u32 {
VERTEX_BUFFER = 0,
INDEX_BUFFER = 1,
CONSTANT_BUFFER = 2,
SHADER_RESOURCE = 3,
STREAM_OUTPUT = 4,
RENDER_TARGET = 5,
DEPTH_STENCIL = 6,
UNORDERED_ACCESS = 7,
DECODER = 9,
VIDEO_ENCODER = 10,
}
CPU_ACCESS_FLAG :: enum u32 { // TODO: make bit_set
WRITE = 0x10000,
READ = 0x20000,
CPU_ACCESS_FLAGS :: distinct bit_set[CPU_ACCESS_FLAG; u32]
CPU_ACCESS_FLAG :: enum u32 {
WRITE = 16,
READ = 17,
}
RESOURCE_MISC_FLAG :: enum u32 { // TODO: make bit_set
GENERATE_MIPS = 0x1,
SHARED = 0x2,
TEXTURECUBE = 0x4,
DRAWINDIRECT_ARGS = 0x10,
BUFFER_ALLOW_RAW_VIEWS = 0x20,
BUFFER_STRUCTURED = 0x40,
RESOURCE_CLAMP = 0x80,
SHARED_KEYEDMUTEX = 0x100,
GDI_COMPATIBLE = 0x200,
SHARED_NTHANDLE = 0x800,
RESTRICTED_CONTENT = 0x1000,
RESTRICT_SHARED_RESOURCE = 0x2000,
RESTRICT_SHARED_RESOURCE_DRIVER = 0x4000,
GUARDED = 0x8000,
TILE_POOL = 0x20000,
TILED = 0x40000,
HW_PROTECTED = 0x80000,
RESOURCE_MISC_FLAGS :: distinct bit_set[RESOURCE_MISC_FLAG; u32]
RESOURCE_MISC_FLAG :: enum u32 {
GENERATE_MIPS = 0,
SHARED = 1,
TEXTURECUBE = 2,
DRAWINDIRECT_ARGS = 4,
BUFFER_ALLOW_RAW_VIEWS = 5,
BUFFER_STRUCTURED = 6,
RESOURCE_CLAMP = 7,
SHARED_KEYEDMUTEX = 8,
GDI_COMPATIBLE = 9,
SHARED_NTHANDLE = 11,
RESTRICTED_CONTENT = 12,
RESTRICT_SHARED_RESOURCE = 13,
RESTRICT_SHARED_RESOURCE_DRIVER = 14,
GUARDED = 15,
TILE_POOL = 17,
TILED = 18,
HW_PROTECTED = 19,
}
MAP :: enum i32 {
@@ -1069,17 +1093,20 @@ MAP :: enum i32 {
WRITE_NO_OVERWRITE = 5,
}
MAP_FLAG :: enum u32 { // TODO: make bit_set
DO_NOT_WAIT = 0x100000,
MAP_FLAGS :: distinct bit_set[MAP_FLAG; u32]
MAP_FLAG :: enum u32 {
DO_NOT_WAIT = 20,
}
RAISE_FLAG :: enum u32 { // TODO: make bit_set
DRIVER_INTERNAL_ERROR = 0x1,
RAISE_FLAGS :: distinct bit_set[RAISE_FLAG; u32]
RAISE_FLAG :: enum u32 {
DRIVER_INTERNAL_ERROR = 0,
}
CLEAR_FLAG :: enum u32 { // TODO: make bit_set
DEPTH = 0x1,
STENCIL = 0x2,
CLEAR_FLAGS :: distinct bit_set[CLEAR_FLAG; u32]
CLEAR_FLAG :: enum u32 {
DEPTH = 0,
STENCIL = 1,
}
@@ -1206,12 +1233,19 @@ BLEND_OP :: enum i32 {
MAX = 5,
}
COLOR_WRITE_ENABLE :: enum i32 { // TODO: make bit_set
RED = 1,
GREEN = 2,
BLUE = 4,
ALPHA = 8,
ALL = 15,
COLOR_WRITE_ENABLE_MASK :: distinct bit_set[COLOR_WRITE_ENABLE; u32]
COLOR_WRITE_ENABLE_RED :: COLOR_WRITE_ENABLE_MASK{.RED}
COLOR_WRITE_ENABLE_GREEN :: COLOR_WRITE_ENABLE_MASK{.GREEN}
COLOR_WRITE_ENABLE_BLUE :: COLOR_WRITE_ENABLE_MASK{.BLUE}
COLOR_WRITE_ENABLE_ALPHA :: COLOR_WRITE_ENABLE_MASK{.ALPHA}
COLOR_WRITE_ENABLE_ALL :: COLOR_WRITE_ENABLE_MASK{.RED, .GREEN, .BLUE, .ALPHA}
COLOR_WRITE_ENABLE :: enum i32 {
RED = 0,
GREEN = 1,
BLUE = 2,
ALPHA = 3,
}
RENDER_TARGET_BLEND_DESC :: struct {
@@ -1308,9 +1342,9 @@ IResource_VTable :: struct {
BUFFER_DESC :: struct {
ByteWidth: u32,
Usage: USAGE,
BindFlags: BIND_FLAG,
CPUAccessFlags: CPU_ACCESS_FLAG,
MiscFlags: RESOURCE_MISC_FLAG,
BindFlags: BIND_FLAGS,
CPUAccessFlags: CPU_ACCESS_FLAGS,
MiscFlags: RESOURCE_MISC_FLAGS,
StructureByteStride: u32,
}
@@ -1337,9 +1371,9 @@ TEXTURE1D_DESC :: struct {
ArraySize: u32,
Format: dxgi.FORMAT,
Usage: USAGE,
BindFlags: BIND_FLAG,
CPUAccessFlags: CPU_ACCESS_FLAG,
MiscFlags: RESOURCE_MISC_FLAG,
BindFlags: BIND_FLAGS,
CPUAccessFlags: CPU_ACCESS_FLAGS,
MiscFlags: RESOURCE_MISC_FLAGS,
}
CTEXTURE1D_DESC :: struct {
@@ -1367,9 +1401,9 @@ TEXTURE2D_DESC :: struct {
Format: dxgi.FORMAT,
SampleDesc: dxgi.SAMPLE_DESC,
Usage: USAGE,
BindFlags: BIND_FLAG,
CPUAccessFlags: CPU_ACCESS_FLAG,
MiscFlags: RESOURCE_MISC_FLAG,
BindFlags: BIND_FLAGS,
CPUAccessFlags: CPU_ACCESS_FLAGS,
MiscFlags: RESOURCE_MISC_FLAGS,
}
CTEXTURE2D_DESC :: struct {
@@ -1396,9 +1430,9 @@ TEXTURE3D_DESC :: struct {
MipLevels: u32,
Format: dxgi.FORMAT,
Usage: USAGE,
BindFlags: BIND_FLAG,
CPUAccessFlags: CPU_ACCESS_FLAG,
MiscFlags: RESOURCE_MISC_FLAG,
BindFlags: BIND_FLAGS,
CPUAccessFlags: CPU_ACCESS_FLAGS,
MiscFlags: RESOURCE_MISC_FLAGS,
}
CTEXTURE3D_DESC :: struct {
@@ -1451,14 +1485,15 @@ BUFFER_SRV :: struct {
},
}
BUFFEREX_SRV_FLAG :: enum u32 { // TODO: make bit_set
RAW = 0x1,
BUFFEREX_SRV_FLAGS :: distinct bit_set[BUFFEREX_SRV_FLAG; u32]
BUFFEREX_SRV_FLAG :: enum u32 {
RAW = 0,
}
BUFFEREX_SRV :: struct {
FirstElement: u32,
NumElements: u32,
Flags: u32,
Flags: BUFFEREX_SRV_FLAGS,
}
TEX1D_SRV :: struct {
@@ -1657,15 +1692,16 @@ TEX2DMS_ARRAY_DSV :: struct {
ArraySize: u32,
}
DSV_FLAG :: enum u32 { // TODO: make bit_set
DEPTH = 0x1,
STENCIL = 0x2,
DSV_FLAGS :: distinct bit_set[DSV_FLAG; u32]
DSV_FLAG :: enum u32 {
DEPTH = 0,
STENCIL = 1,
}
DEPTH_STENCIL_VIEW_DESC :: struct {
Format: dxgi.FORMAT,
ViewDimension: DSV_DIMENSION,
Flags: u32,
Flags: DSV_FLAGS,
using _: struct #raw_union {
Texture1D: TEX1D_DSV,
Texture1DArray: TEX1D_ARRAY_DSV,
@@ -1693,16 +1729,17 @@ IDepthStencilView_VTable :: struct {
}
BUFFER_UAV_FLAG :: enum u32 { // TODO: make bit_set
RAW = 0x1,
APPEND = 0x2,
COUNTER = 0x4,
BUFFER_UAV_FLAGS :: distinct bit_set[BUFFER_UAV_FLAG; u32]
BUFFER_UAV_FLAG :: enum u32 {
RAW = 0,
APPEND = 1,
COUNTER = 2,
}
BUFFER_UAV :: struct {
FirstElement: u32,
NumElements: u32,
Flags: u32,
Flags: BUFFER_UAV_FLAGS,
}
TEX1D_UAV :: struct {
@@ -1961,8 +1998,9 @@ IAsynchronous_VTable :: struct {
}
ASYNC_GETDATA_FLAG :: enum u32 { // TODO: make bit_set
DONOTFLUSH = 0x1,
ASYNC_GETDATA_FLAGS :: distinct bit_set[ASYNC_GETDATA_FLAG; u32]
ASYNC_GETDATA_FLAG :: enum u32 {
DONOTFLUSH = 0,
}
QUERY :: enum i32 {
@@ -1984,13 +2022,14 @@ QUERY :: enum i32 {
SO_OVERFLOW_PREDICATE_STREAM3 = 15,
}
QUERY_MISC_FLAG :: enum u32 { // TODO: make bit_set
QUERY_MISC_PREDICATEHINT = 0x1,
QUERY_MISC_FLAGS :: distinct bit_set[QUERY_MISC_FLAG; u32]
QUERY_MISC_FLAG :: enum u32 {
PREDICATEHINT = 0,
}
QUERY_DESC :: struct {
Query: QUERY,
MiscFlags: RESOURCE_MISC_FLAG,
MiscFlags: QUERY_MISC_FLAGS,
}
CQUERY_DESC :: struct {
@@ -2054,7 +2093,7 @@ COUNTER_TYPE :: enum i32 {
COUNTER_DESC :: struct {
Counter: COUNTER,
MiscFlags: RESOURCE_MISC_FLAG,
MiscFlags: RESOURCE_MISC_FLAGS,
}
CCOUNTER_DESC :: struct {
@@ -2150,21 +2189,21 @@ FEATURE :: enum i32 {
FORMAT_SUPPORT = 2,
FORMAT_SUPPORT2 = 3,
D3D10_X_HARDWARE_OPTIONS = 4,
OPTIONS = 5,
OPTIONS = 5,
ARCHITECTURE_INFO = 6,
D3D9_OPTIONS = 7,
SHADER_MIN_PRECISION_SUPPORT = 8,
D3D9_SHADOW_SUPPORT = 9,
OPTIONS1 = 10,
OPTIONS1 = 10,
D3D9_SIMPLE_INSTANCING_SUPPORT = 11,
MARKER_SUPPORT = 12,
D3D9_OPTIONS1 = 13,
OPTIONS2 = 14,
OPTIONS3 = 15,
OPTIONS2 = 14,
OPTIONS3 = 15,
GPU_VIRTUAL_ADDRESS_SUPPORT = 16,
OPTIONS4 = 17,
OPTIONS4 = 17,
SHADER_CACHE = 18,
OPTIONS5 = 19,
OPTIONS5 = 19,
}
FEATURE_DATA_THREADING :: struct {
@@ -2285,14 +2324,14 @@ FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT :: struct {
MaxGPUVirtualAddressBitsPerProcess: u32,
}
SHADER_CACHE_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
AUTOMATIC_INPROC_CACHE = 0x1,
AUTOMATIC_DISK_CACHE = 0x2,
SHADER_CACHE_SUPPORT_FLAGS :: distinct bit_set[SHADER_CACHE_SUPPORT_FLAG; u32]
SHADER_CACHE_SUPPORT_FLAG :: enum u32 {
AUTOMATIC_INPROC_CACHE = 0,
AUTOMATIC_DISK_CACHE = 1,
}
FEATURE_DATA_SHADER_CACHE :: struct {
SupportFlags: u32,
SupportFlags: SHADER_CACHE_SUPPORT_FLAGS,
}
SHARED_RESOURCE_TIER :: enum i32 {
@@ -2322,7 +2361,7 @@ IDeviceContext_VTable :: struct {
VSSetShader: proc "stdcall" (this: ^IDeviceContext, pVertexShader: ^IVertexShader, ppClassInstances: ^^IClassInstance, NumClassInstances: u32),
DrawIndexed: proc "stdcall" (this: ^IDeviceContext, IndexCount: u32, StartIndexLocation: u32, BaseVertexLocation: i32),
Draw: proc "stdcall" (this: ^IDeviceContext, VertexCount: u32, StartVertexLocation: u32),
Map: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, Subresource: u32, MapType: MAP, MapFlags: u32, pMappedResource: ^MAPPED_SUBRESOURCE) -> HRESULT,
Map: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, Subresource: u32, MapType: MAP, MapFlags: MAP_FLAGS, pMappedResource: ^MAPPED_SUBRESOURCE) -> HRESULT,
Unmap: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, Subresource: u32),
PSSetConstantBuffers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumBuffers: u32, ppConstantBuffers: ^^IBuffer),
IASetInputLayout: proc "stdcall" (this: ^IDeviceContext, pInputLayout: ^IInputLayout),
@@ -2343,7 +2382,7 @@ IDeviceContext_VTable :: struct {
GSSetSamplers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumSamplers: u32, ppSamplers: ^^ISamplerState),
OMSetRenderTargets: proc "stdcall" (this: ^IDeviceContext, NumViews: u32, ppRenderTargetViews: ^^IRenderTargetView, pDepthStencilView: ^IDepthStencilView),
OMSetRenderTargetsAndUnorderedAccessViews: proc "stdcall" (this: ^IDeviceContext, NumRTVs: u32, ppRenderTargetViews: ^^IRenderTargetView, pDepthStencilView: ^IDepthStencilView, UAVStartSlot: u32, NumUAVs: u32, ppUnorderedAccessViews: ^^IUnorderedAccessView, pUAVInitialCounts: ^u32),
OMSetBlendState: proc "stdcall" (this: ^IDeviceContext, pBlendState: ^IBlendState, BlendFactor: ^[4]f32, SampleMask: u32),
OMSetBlendState: proc "stdcall" (this: ^IDeviceContext, pBlendState: ^IBlendState, BlendFactor: ^[4]f32, SampleMask: COLOR_WRITE_ENABLE_MASK),
OMSetDepthStencilState: proc "stdcall" (this: ^IDeviceContext, pDepthStencilState: ^IDepthStencilState, StencilRef: u32),
SOSetTargets: proc "stdcall" (this: ^IDeviceContext, NumBuffers: u32, ppSOTargets: ^^IBuffer, pOffsets: ^u32),
DrawAuto: proc "stdcall" (this: ^IDeviceContext),
@@ -2361,7 +2400,7 @@ IDeviceContext_VTable :: struct {
ClearRenderTargetView: proc "stdcall" (this: ^IDeviceContext, pRenderTargetView: ^IRenderTargetView, ColorRGBA: ^[4]f32),
ClearUnorderedAccessViewUint: proc "stdcall" (this: ^IDeviceContext, pUnorderedAccessView: ^IUnorderedAccessView, Values: ^[4]u32),
ClearUnorderedAccessViewFloat: proc "stdcall" (this: ^IDeviceContext, pUnorderedAccessView: ^IUnorderedAccessView, Values: ^[4]f32),
ClearDepthStencilView: proc "stdcall" (this: ^IDeviceContext, pDepthStencilView: ^IDepthStencilView, ClearFlags: CLEAR_FLAG, Depth: f32, Stencil: u8),
ClearDepthStencilView: proc "stdcall" (this: ^IDeviceContext, pDepthStencilView: ^IDepthStencilView, ClearFlags: CLEAR_FLAGS, Depth: f32, Stencil: u8),
GenerateMips: proc "stdcall" (this: ^IDeviceContext, pShaderResourceView: ^IShaderResourceView),
SetResourceMinLOD: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, MinLOD: f32),
GetResourceMinLOD: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource) -> f32,
@@ -2399,7 +2438,7 @@ IDeviceContext_VTable :: struct {
GSGetSamplers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumSamplers: u32, ppSamplers: ^^ISamplerState),
OMGetRenderTargets: proc "stdcall" (this: ^IDeviceContext, NumViews: u32, ppRenderTargetViews: ^^IRenderTargetView, ppDepthStencilView: ^^IDepthStencilView),
OMGetRenderTargetsAndUnorderedAccessViews: proc "stdcall" (this: ^IDeviceContext, NumRTVs: u32, ppRenderTargetViews: ^^IRenderTargetView, ppDepthStencilView: ^^IDepthStencilView, UAVStartSlot: u32, NumUAVs: u32, ppUnorderedAccessViews: ^^IUnorderedAccessView),
OMGetBlendState: proc "stdcall" (this: ^IDeviceContext, ppBlendState: ^^IBlendState, BlendFactor: ^[4]f32, pSampleMask: ^u32),
OMGetBlendState: proc "stdcall" (this: ^IDeviceContext, ppBlendState: ^^IBlendState, BlendFactor: ^[4]f32, pSampleMask: ^COLOR_WRITE_ENABLE_MASK),
OMGetDepthStencilState: proc "stdcall" (this: ^IDeviceContext, ppDepthStencilState: ^^IDepthStencilState, pStencilRef: ^u32),
SOGetTargets: proc "stdcall" (this: ^IDeviceContext, NumBuffers: u32, ppSOTargets: ^^IBuffer),
RSGetState: proc "stdcall" (this: ^IDeviceContext, ppRasterizerState: ^^IRasterizerState),
@@ -3315,13 +3354,13 @@ IDevice_VTable :: struct {
GetCreationFlags: proc "stdcall" (this: ^IDevice) -> u32,
GetDeviceRemovedReason: proc "stdcall" (this: ^IDevice) -> HRESULT,
GetImmediateContext: proc "stdcall" (this: ^IDevice, ppImmediateContext: ^^IDeviceContext),
SetExceptionMode: proc "stdcall" (this: ^IDevice, RaiseFlags: u32) -> HRESULT,
SetExceptionMode: proc "stdcall" (this: ^IDevice, RaiseFlags: RAISE_FLAGS) -> HRESULT,
GetExceptionMode: proc "stdcall" (this: ^IDevice) -> u32,
}
CREATE_DEVICE_FLAGS :: distinct bit_set[CREATE_DEVICE_FLAG; u32]
CREATE_DEVICE_FLAG :: enum u32 { // TODO: make bit_set
CREATE_DEVICE_FLAG :: enum u32 {
SINGLETHREADED = 0,
DEBUG = 1,
SWITCH_TO_REF = 2,
@@ -3367,14 +3406,14 @@ SHADER_BUFFER_DESC :: struct {
Type: CBUFFER_TYPE,
Variables: u32,
Size: u32,
uFlags: u32,
uFlags: SHADER_CBUFFER_FLAGS,
}
SHADER_VARIABLE_DESC :: struct {
Name: cstring,
StartOffset: u32,
Size: u32,
uFlags: u32,
uFlags: SHADER_VARIABLE_FLAGS,
DefaultValue: rawptr,
StartTexture: u32,
TextureSize: u32,
@@ -3443,7 +3482,7 @@ SHADER_INPUT_BIND_DESC :: struct {
BindPoint: u32,
BindCount: u32,
uFlags: u32,
uFlags: SHADER_INPUT_FLAGS,
ReturnType: RESOURCE_RETURN_TYPE,
Dimension: SRV_DIMENSION,
NumSamples: u32,
@@ -3485,7 +3524,7 @@ FUNCTION_DESC :: struct {
ConversionInstructionCount: u32,
BitwiseInstructionCount: u32,
MinFeatureLevel: FEATURE_LEVEL,
RequiredFeatureFlags: u64,
RequiredFeatureFlags: SHADER_REQUIRES_FLAGS,
Name: cstring,
FunctionParameterCount: i32,
@@ -3571,7 +3610,7 @@ IShaderReflection_VTable :: struct {
GetNumInterfaceSlots: proc "stdcall" (this: ^IShaderReflection) -> u32,
GetMinFeatureLevel: proc "stdcall" (this: ^IShaderReflection, pLevel: ^FEATURE_LEVEL) -> HRESULT,
GetThreadGroupSize: proc "stdcall" (this: ^IShaderReflection, pSizeX: ^u32, pSizeY: ^u32, pSizeZ: ^u32) -> u32,
GetRequiresFlags: proc "stdcall" (this: ^IShaderReflection) -> u64,
GetRequiresFlags: proc "stdcall" (this: ^IShaderReflection) -> SHADER_REQUIRES_FLAGS,
}
@@ -3634,22 +3673,24 @@ IDebug :: struct #raw_union {
using id3d11debug_vtable: ^IDebug_VTable,
}
RLDO_FLAGS :: enum u32 { // TODO: make bit_set
SUMMARY = 0x1,
DETAIL = 0x2,
IGNORE_INTERNAL = 0x4,
RLDO_FLAGS :: distinct bit_set[RLDO_FLAG; u32]
RLDO_FLAG :: enum u32 {
SUMMARY = 0,
DETAIL = 1,
IGNORE_INTERNAL = 2,
}
DEBUG_FEATURE :: enum u32 { // TODO: make bit_set
FLUSH_PER_RENDER_OP = 0x1,
FINISH_PER_RENDER_OP = 0x2,
FEATURE_PRESENT_PER_RENDER_OP = 0x4,
DEBUG_FEATURES :: distinct bit_set[DEBUG_FEATURE; u32]
DEBUG_FEATURE :: enum u32 {
FLUSH_PER_RENDER_OP = 0,
FINISH_PER_RENDER_OP = 1,
FEATURE_PRESENT_PER_RENDER_OP = 2,
}
IDebug_VTable :: struct {
using iunkown_vtable: IUnknown_VTable,
SetFeatureMask: proc "stdcall" (this: ^IDebug, mask: DEBUG_FEATURE) -> HRESULT,
GetFeatureMask: proc "stdcall" (this: ^IDebug) -> DEBUG_FEATURE,
SetFeatureMask: proc "stdcall" (this: ^IDebug, mask: DEBUG_FEATURES) -> HRESULT,
GetFeatureMask: proc "stdcall" (this: ^IDebug) -> DEBUG_FEATURES,
SetPresentPerRenderOpDelay: proc "stdcall" (this: ^IDebug, Milliseconds: u32) -> HRESULT,
GetPresentPerRenderOpDelay: proc "stdcall" (this: ^IDebug) -> u32,
SetSwapChain: proc "stdcall" (this: ^IDebug, pSwapChain: ^dxgi.ISwapChain) -> HRESULT,
@@ -3667,7 +3708,7 @@ IInfoQueue :: struct #raw_union {
using id3d11infoqueue_vtable: ^IInfoQueue_VTable,
}
MESSAGE_SEVERITY :: enum u32 { // TODO: make bit_set
MESSAGE_SEVERITY :: enum u32 {
CORRUPTION = 0,
ERROR,
WARNING,
@@ -3675,7 +3716,7 @@ MESSAGE_SEVERITY :: enum u32 { // TODO: make bit_set
MESSAGE, // Not supported until D3D 11.1
}
MESSAGE_CATEGORY :: enum u32 { // TODO: make bit_set
MESSAGE_CATEGORY :: enum u32 {
APPLICATION_DEFINED = 0,
MISCELLANEOUS,
INITIALIZATION,
@@ -3692,10 +3733,10 @@ MESSAGE_CATEGORY :: enum u32 { // TODO: make bit_set
INFO_QUEUE_FILTER_DESC :: struct {
NumCategories: u32,
pCategoryList: ^MESSAGE_CATEGORY,
NumSeverities: u32,
pSeverityList: ^MESSAGE_SEVERITY,
NumIDs: u32,
pIDList: ^MESSAGE_ID,
}
@@ -3750,7 +3791,7 @@ IInfoQueue_VTable :: struct {
SetMuteDebugOutput: proc "stdcall" (this: ^IInfoQueue, bMute: BOOL),
}
MESSAGE_ID :: enum u32 { // TODO: make bit_set
MESSAGE_ID :: enum u32 {
UNKNOWN = 0,
DEVICE_IASETVERTEXBUFFERS_HAZARD,
DEVICE_IASETINDEXBUFFER_HAZARD,
+331 -303
View File
@@ -212,11 +212,12 @@ SHADER_VARIABLE_CLASS :: enum i32 {
INTERFACE_POINTER = 7,
}
SHADER_VARIABLE_FLAGS :: enum u32 { // TODO: make bit_set
USERPACKED = 0x1,
USED = 0x2,
INTERFACE_POINTER = 0x4,
INTERFACE_PARAMETER = 0x8,
SHADER_VARIABLE_FLAGS :: distinct bit_set[SHADER_VARIABLE_FLAG; u32]
SHADER_VARIABLE_FLAG :: enum u32 {
USERPACKED = 0,
USED = 1,
INTERFACE_POINTER = 2,
INTERFACE_PARAMETER = 3,
}
SHADER_VARIABLE_TYPE :: enum i32 {
@@ -280,15 +281,16 @@ SHADER_VARIABLE_TYPE :: enum i32 {
MIN16UINT = 57,
}
SHADER_INPUT_FLAGS :: enum u32 { // TODO: make bit_set
USERPACKED = 0x1,
COMPARISON_SAMPLER = 0x2,
TEXTURE_COMPONENT_0 = 0x4,
TEXTURE_COMPONENT_1 = 0x8,
TEXTURE_COMPONENTS = 0xc,
UNUSED = 0x10,
SHADER_INPUT_FLAGS :: distinct bit_set[SHADER_INPUT_FLAG; u32]
SHADER_INPUT_FLAG :: enum u32 {
USERPACKED = 0,
COMPARISON_SAMPLER = 1,
TEXTURE_COMPONENT_0 = 2,
TEXTURE_COMPONENT_1 = 3,
UNUSED = 4,
}
SHADER_INPUT_TYPE :: enum i32 {
CBUFFER = 0,
TBUFFER = 1,
@@ -306,8 +308,9 @@ SHADER_INPUT_TYPE :: enum i32 {
UAV_FEEDBACKTEXTURE = 13,
}
SHADER_CBUFFER_FLAGS :: enum u32 { // TODO: make bit_set
USERPACKED = 0x1,
SHADER_CBUFFER_FLAGS :: distinct bit_set[SHADER_CBUFFER_FLAG; u32]
SHADER_CBUFFER_FLAG :: enum u32 {
USERPACKED = 0,
}
CBUFFER_TYPE :: enum i32 {
@@ -410,13 +413,12 @@ INTERPOLATION_MODE :: enum i32 {
LINEAR_NOPERSPECTIVE_SAMPLE = 7,
}
PARAMETER_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
IN = 0x1,
OUT = 0x2,
PARAMETER_FLAGS :: distinct bit_set[PARAMETER_FLAG; u32]
PARAMETER_FLAG :: enum u32 {
IN = 0,
OUT = 1,
}
GPU_VIRTUAL_ADDRESS :: u64
COMMAND_LIST_TYPE :: enum i32 {
@@ -429,9 +431,9 @@ COMMAND_LIST_TYPE :: enum i32 {
VIDEO_ENCODE = 6,
}
COMMAND_QUEUE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
DISABLE_GPU_TIMEOUT = 0x1,
COMMAND_QUEUE_FLAGS :: distinct bit_set[COMMAND_QUEUE_FLAG; u32]
COMMAND_QUEUE_FLAG :: enum u32 {
DISABLE_GPU_TIMEOUT = 0,
}
COMMAND_QUEUE_PRIORITY :: enum i32 {
@@ -593,12 +595,19 @@ BLEND_OP :: enum i32 {
MAX = 5,
}
COLOR_WRITE_ENABLE :: enum i32 { // TODO: make bit_set
RED = 1,
GREEN = 2,
BLUE = 4,
ALPHA = 8,
ALL = 15,
COLOR_WRITE_ENABLE_MASK :: distinct bit_set[COLOR_WRITE_ENABLE; u32]
COLOR_WRITE_ENABLE_RED :: COLOR_WRITE_ENABLE_MASK{.RED}
COLOR_WRITE_ENABLE_GREEN :: COLOR_WRITE_ENABLE_MASK{.GREEN}
COLOR_WRITE_ENABLE_BLUE :: COLOR_WRITE_ENABLE_MASK{.BLUE}
COLOR_WRITE_ENABLE_ALPHA :: COLOR_WRITE_ENABLE_MASK{.ALPHA}
COLOR_WRITE_ENABLE_ALL :: COLOR_WRITE_ENABLE_MASK{.RED, .GREEN, .BLUE, .ALPHA}
COLOR_WRITE_ENABLE :: enum i32 {
RED = 0,
GREEN = 1,
BLUE = 2,
ALPHA = 3,
}
LOGIC_OP :: enum i32 {
@@ -721,9 +730,9 @@ CACHED_PIPELINE_STATE :: struct {
CachedBlobSizeInBytes: SIZE_T,
}
PIPELINE_STATE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
TOOL_DEBUG = 0x1,
PIPELINE_STATE_FLAGS :: distinct bit_set[PIPELINE_STATE_FLAG; u32]
PIPELINE_STATE_FLAG :: enum u32 {
TOOL_DEBUG = 0,
}
GRAPHICS_PIPELINE_STATE_DESC :: struct {
@@ -853,58 +862,61 @@ CONSERVATIVE_RASTERIZATION_TIER :: enum i32 {
_3 = 3,
}
FORMAT_SUPPORT1 :: enum i32 { // TODO: make bit_set
NONE = 0,
BUFFER = 1,
IA_VERTEX_BUFFER = 2,
IA_INDEX_BUFFER = 4,
SO_BUFFER = 8,
TEXTURE1D = 16,
TEXTURE2D = 32,
TEXTURE3D = 64,
TEXTURECUBE = 128,
SHADER_LOAD = 256,
SHADER_SAMPLE = 512,
SHADER_SAMPLE_COMPARISON = 1024,
SHADER_SAMPLE_MONO_TEXT = 2048,
MIP = 4096,
RENDER_TARGET = 16384,
BLENDABLE = 32768,
DEPTH_STENCIL = 65536,
MULTISAMPLE_RESOLVE = 262144,
DISPLAY = 524288,
CAST_WITHIN_BIT_LAYOUT = 1048576,
MULTISAMPLE_RENDERTARGET = 2097152,
MULTISAMPLE_LOAD = 4194304,
SHADER_GATHER = 8388608,
BACK_BUFFER_CAST = 16777216,
TYPED_UNORDERED_ACCESS_VIEW = 33554432,
SHADER_GATHER_COMPARISON = 67108864,
DECODER_OUTPUT = 134217728,
VIDEO_PROCESSOR_OUTPUT = 268435456,
VIDEO_PROCESSOR_INPUT = 536870912,
VIDEO_ENCODER = 1073741824,
FORMAT_SUPPORT1 :: distinct bit_set[FORMAT_SUPPORT1_FLAG; u32]
FORMAT_SUPPORT1_FLAG :: enum i32 {
BUFFER = 0,
IA_VERTEX_BUFFER = 1,
IA_INDEX_BUFFER = 2,
SO_BUFFER = 3,
TEXTURE1D = 4,
TEXTURE2D = 5,
TEXTURE3D = 6,
TEXTURECUBE = 7,
SHADER_LOAD = 8,
SHADER_SAMPLE = 9,
SHADER_SAMPLE_COMPARISON = 10,
SHADER_SAMPLE_MONO_TEXT = 11,
MIP = 12,
RENDER_TARGET = 14,
BLENDABLE = 15,
DEPTH_STENCIL = 16,
MULTISAMPLE_RESOLVE = 18,
DISPLAY = 19,
CAST_WITHIN_BIT_LAYOUT = 20,
MULTISAMPLE_RENDERTARGET = 21,
MULTISAMPLE_LOAD = 22,
SHADER_GATHER = 23,
BACK_BUFFER_CAST = 24,
TYPED_UNORDERED_ACCESS_VIEW = 25,
SHADER_GATHER_COMPARISON = 26,
DECODER_OUTPUT = 27,
VIDEO_PROCESSOR_OUTPUT = 28,
VIDEO_PROCESSOR_INPUT = 29,
VIDEO_ENCODER = 30,
}
FORMAT_SUPPORT2 :: enum i32 { // TODO: make bit_set
NONE = 0,
UAV_ATOMIC_ADD = 1,
UAV_ATOMIC_BITWISE_OPS = 2,
UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 4,
UAV_ATOMIC_EXCHANGE = 8,
UAV_ATOMIC_SIGNED_MIN_OR_MAX = 16,
UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 32,
UAV_TYPED_LOAD = 64,
UAV_TYPED_STORE = 128,
OUTPUT_MERGER_LOGIC_OP = 256,
TILED = 512,
MULTIPLANE_OVERLAY = 16384,
SAMPLER_FEEDBACK = 32768,
FORMAT_SUPPORT2 :: distinct bit_set[FORMAT_SUPPORT2_FLAG; u32]
FORMAT_SUPPORT2_FLAG :: enum i32 {
UAV_ATOMIC_ADD = 0,
UAV_ATOMIC_BITWISE_OPS = 1,
UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 2,
UAV_ATOMIC_EXCHANGE = 3,
UAV_ATOMIC_SIGNED_MIN_OR_MAX = 4,
UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 5,
UAV_TYPED_LOAD = 6,
UAV_TYPED_STORE = 7,
OUTPUT_MERGER_LOGIC_OP = 8,
TILED = 9,
MULTIPLANE_OVERLAY = 14,
SAMPLER_FEEDBACK = 15,
}
MULTISAMPLE_QUALITY_LEVEL_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
TILED_RESOURCE = 0x1,
MULTISAMPLE_QUALITY_LEVEL_FLAGS :: distinct bit_set[MULTISAMPLE_QUALITY_LEVEL_FLAG; u32]
MULTISAMPLE_QUALITY_LEVEL_FLAG :: enum u32 {
TILED_RESOURCE = 0,
}
CROSS_NODE_SHARING_TIER :: enum i32 {
@@ -1034,12 +1046,12 @@ FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT :: struct {
MaxGPUVirtualAddressBitsPerProcess: u32,
}
SHADER_CACHE_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
SINGLE_PSO = 0x1,
LIBRARY = 0x2,
AUTOMATIC_INPROC_CACHE = 0x4,
AUTOMATIC_DISK_CACHE = 0x8,
SHADER_CACHE_SUPPORT_FLAGS :: distinct bit_set[SHADER_CACHE_SUPPORT_FLAG; u32]
SHADER_CACHE_SUPPORT_FLAG :: enum u32 {
SINGLE_PSO = 0,
LIBRARY = 1,
AUTOMATIC_INPROC_CACHE = 2,
AUTOMATIC_DISK_CACHE = 3,
}
FEATURE_DATA_SHADER_CACHE :: struct {
@@ -1052,15 +1064,15 @@ FEATURE_DATA_COMMAND_QUEUE_PRIORITY :: struct {
PriorityForTypeIsSupported: BOOL,
}
COMMAND_LIST_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
DIRECT = 0x1,
BUNDLE = 0x2,
COMPUTE = 0x4,
COPY = 0x8,
VIDEO_DECODE = 0x10,
VIDEO_PROCESS = 0x20,
VIDEO_ENCODE = 0x40,
COMMAND_LIST_SUPPORT_FLAGS :: distinct bit_set[COMMAND_LIST_SUPPORT_FLAG; u32]
COMMAND_LIST_SUPPORT_FLAG :: enum u32 {
DIRECT = 0,
BUNDLE = 1,
COMPUTE = 2,
COPY = 3,
VIDEO_DECODE = 4,
VIDEO_PROCESS = 5,
VIDEO_ENCODE = 6,
}
FEATURE_DATA_OPTIONS3 :: struct {
@@ -1198,25 +1210,26 @@ HEAP_PROPERTIES :: struct {
VisibleNodeMask: u32,
}
HEAP_FLAGS :: enum u32 { // TODO: make bit_set ???
NONE = 0x0,
SHARED = 0x1,
DENY_BUFFERS = 0x4,
ALLOW_DISPLAY = 0x8,
SHARED_CROSS_ADAPTER = 0x20,
DENY_RT_DS_TEXTURES = 0x40,
DENY_NON_RT_DS_TEXTURES = 0x80,
HARDWARE_PROTECTED = 0x100,
ALLOW_WRITE_WATCH = 0x200,
ALLOW_SHADER_ATOMICS = 0x400,
CREATE_NOT_RESIDENT = 0x800,
CREATE_NOT_ZEROED = 0x1000,
ALLOW_ALL_BUFFERS_AND_TEXTURES = 0x0,
ALLOW_ONLY_BUFFERS = 0xc0,
ALLOW_ONLY_NON_RT_DS_TEXTURES = 0x44,
ALLOW_ONLY_RT_DS_TEXTURES = 0x84,
HEAP_FLAGS :: distinct bit_set[HEAP_FLAG; u32]
HEAP_FLAG :: enum u32 {
SHARED = 0,
DENY_BUFFERS = 2,
ALLOW_DISPLAY = 3,
SHARED_CROSS_ADAPTER = 5,
DENY_RT_DS_TEXTURES = 6,
DENY_NON_RT_DS_TEXTURES = 7,
HARDWARE_PROTECTED = 8,
ALLOW_WRITE_WATCH = 9,
ALLOW_SHADER_ATOMICS = 10,
CREATE_NOT_RESIDENT = 11,
CREATE_NOT_ZEROED = 12,
}
HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES :: HEAP_FLAGS{}
HEAP_FLAG_ALLOW_ONLY_BUFFERS :: HEAP_FLAGS{.DENY_BUFFERS, .ALLOW_DISPLAY}
HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES :: HEAP_FLAGS{.DENY_BUFFERS, .DENY_RT_DS_TEXTURES}
HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES :: HEAP_FLAGS{.DENY_BUFFERS, .DENY_NON_RT_DS_TEXTURES}
HEAP_DESC :: struct {
SizeInBytes: u64,
Properties: HEAP_PROPERTIES,
@@ -1239,15 +1252,15 @@ TEXTURE_LAYOUT :: enum i32 {
_64KB_STANDARD_SWIZZLE = 3,
}
RESOURCE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
ALLOW_RENDER_TARGET = 0x1,
ALLOW_DEPTH_STENCIL = 0x2,
ALLOW_UNORDERED_ACCESS = 0x4,
DENY_SHADER_RESOURCE = 0x8,
ALLOW_CROSS_ADAPTER = 0x10,
ALLOW_SIMULTANEOUS_ACCESS = 0x20,
VIDEO_DECODE_REFERENCE_ONLY = 0x40,
RESOURCE_FLAGS :: distinct bit_set[RESOURCE_FLAG; u32]
RESOURCE_FLAG :: enum u32 {
ALLOW_RENDER_TARGET = 0,
ALLOW_DEPTH_STENCIL = 1,
ALLOW_UNORDERED_ACCESS = 2,
DENY_SHADER_RESOURCE = 3,
ALLOW_CROSS_ADAPTER = 4,
ALLOW_SIMULTANEOUS_ACCESS = 5,
VIDEO_DECODE_REFERENCE_ONLY = 6,
}
MIP_REGION :: struct {
@@ -1332,11 +1345,11 @@ TILE_REGION_SIZE :: struct {
Depth: u16,
}
TILE_RANGE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
NULL = 0x1,
SKIP = 0x2,
REUSE_SINGLE_TILE = 0x4,
TILE_RANGE_FLAGS :: distinct bit_set[TILE_RANGE_FLAG; u32]
TILE_RANGE_FLAG :: enum u32 {
NULL = 0,
SKIP = 1,
REUSE_SINGLE_TILE = 2,
}
SUBRESOURCE_TILING :: struct {
@@ -1359,45 +1372,52 @@ PACKED_MIP_INFO :: struct {
StartTileIndexInOverallResource: u32,
}
TILE_MAPPING_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
NO_HAZARD = 0x1,
TILE_MAPPING_FLAGS :: distinct bit_set[TILE_MAPPING_FLAG; u32]
TILE_MAPPING_FLAG :: enum u32 {
NO_HAZARD = 0,
}
TILE_COPY_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
NO_HAZARD = 0x1,
LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE = 0x2,
SWIZZLED_TILED_RESOURCE_TO_LINEAR_BUFFER = 0x4,
TILE_COPY_FLAGS :: distinct bit_set[TILE_COPY_FLAG; u32]
TILE_COPY_FLAG :: enum u32 {
NO_HAZARD = 0,
LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE = 1,
SWIZZLED_TILED_RESOURCE_TO_LINEAR_BUFFER = 2,
}
RESOURCE_STATES :: enum i32 { // TODO: make bit_set
COMMON = 0,
VERTEX_AND_CONSTANT_BUFFER = 1,
INDEX_BUFFER = 2,
RENDER_TARGET = 4,
UNORDERED_ACCESS = 8,
DEPTH_WRITE = 16,
DEPTH_READ = 32,
NON_PIXEL_SHADER_RESOURCE = 64,
PIXEL_SHADER_RESOURCE = 128,
STREAM_OUT = 256,
INDIRECT_ARGUMENT = 512,
COPY_DEST = 1024,
COPY_SOURCE = 2048,
RESOLVE_DEST = 4096,
RESOLVE_SOURCE = 8192,
RAYTRACING_ACCELERATION_STRUCTURE = 4194304,
SHADING_RATE_SOURCE = 16777216,
GENERIC_READ = 2755,
PRESENT = 0,
PREDICATION = 512,
VIDEO_DECODE_READ = 65536,
VIDEO_DECODE_WRITE = 131072,
VIDEO_PROCESS_READ = 262144,
VIDEO_PROCESS_WRITE = 524288,
VIDEO_ENCODE_READ = 2097152,
VIDEO_ENCODE_WRITE = 8388608,
RESOURCE_STATES :: distinct bit_set[RESOURCE_STATE; u32]
RESOURCE_STATE :: enum i32 {
VERTEX_AND_CONSTANT_BUFFER = 0,
INDEX_BUFFER = 1,
RENDER_TARGET = 2,
UNORDERED_ACCESS = 3,
DEPTH_WRITE = 4,
DEPTH_READ = 5,
NON_PIXEL_SHADER_RESOURCE = 6,
PIXEL_SHADER_RESOURCE = 7,
STREAM_OUT = 8,
INDIRECT_ARGUMENT = 9,
COPY_DEST = 10,
COPY_SOURCE = 11,
RESOLVE_DEST = 12,
RESOLVE_SOURCE = 13,
RAYTRACING_ACCELERATION_STRUCTURE = 22,
SHADING_RATE_SOURCE = 24,
PREDICATION = 9,
VIDEO_DECODE_READ = 16,
VIDEO_DECODE_WRITE = 17,
VIDEO_PROCESS_READ = 18,
VIDEO_PROCESS_WRITE = 19,
VIDEO_ENCODE_READ = 21,
VIDEO_ENCODE_WRITE = 23,
}
RESOURCE_STATE_COMMON :: RESOURCE_STATES{}
RESOURCE_STATE_PRESENT :: RESOURCE_STATES{}
RESOURCE_STATE_GENERIC_READ :: RESOURCE_STATES{
.VERTEX_AND_CONSTANT_BUFFER, .INDEX_BUFFER, .NON_PIXEL_SHADER_RESOURCE, .PIXEL_SHADER_RESOURCE, .INDIRECT_ARGUMENT, .COPY_SOURCE,
}
RESOURCE_STATE_ALL_SHADER_RESOURCE :: RESOURCE_STATES{
.SHADING_RATE_SOURCE, .INDEX_BUFFER,
}
RESOURCE_BARRIER_TYPE :: enum i32 {
@@ -1422,10 +1442,10 @@ RESOURCE_UAV_BARRIER :: struct {
pResource: ^IResource,
}
RESOURCE_BARRIER_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
BEGIN_ONLY = 0x1,
END_ONLY = 0x2,
RESOURCE_BARRIER_FLAGS :: distinct bit_set[RESOURCE_BARRIER_FLAG; u32]
RESOURCE_BARRIER_FLAG :: enum u32 {
BEGIN_ONLY = 0,
END_ONLY = 1,
}
RESOURCE_BARRIER :: struct {
@@ -1484,9 +1504,9 @@ VIEW_INSTANCE_LOCATION :: struct {
RenderTargetArrayIndex: u32,
}
VIEW_INSTANCING_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
ENABLE_VIEW_INSTANCE_MASKING = 0x1,
VIEW_INSTANCING_FLAGS :: distinct bit_set[VIEW_INSTANCING_FLAG; u32]
VIEW_INSTANCING_FLAG :: enum u32 {
ENABLE_VIEW_INSTANCE_MASKING = 0,
}
VIEW_INSTANCING_DESC :: struct {
@@ -1504,9 +1524,9 @@ SHADER_COMPONENT_MAPPING :: enum i32 {
FORCE_VALUE_1 = 5,
}
BUFFER_SRV_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
RAW = 0x1,
BUFFER_SRV_FLAGS :: distinct bit_set[BUFFER_SRV_FLAG; u32]
BUFFER_SRV_FLAG :: enum u32 {
RAW = 0,
}
BUFFER_SRV :: struct {
@@ -1675,9 +1695,9 @@ SAMPLER_DESC :: struct {
MaxLOD: f32,
}
BUFFER_UAV_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
RAW = 0x1,
BUFFER_UAV_FLAGS :: distinct bit_set[BUFFER_UAV_FLAG; u32]
BUFFER_UAV_FLAG :: enum u32 {
RAW = 0,
}
BUFFER_UAV :: struct {
@@ -1837,10 +1857,10 @@ TEX2DMS_ARRAY_DSV :: struct {
ArraySize: u32,
}
DSV_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
READ_ONLY_DEPTH = 0x1,
READ_ONLY_STENCIL = 0x2,
DSV_FLAGS :: distinct bit_set[DSV_FLAG; u32]
DSV_FLAG :: enum u32 {
READ_ONLY_DEPTH = 0,
READ_ONLY_STENCIL = 1,
}
DSV_DIMENSION :: enum i32 {
@@ -1867,16 +1887,17 @@ DEPTH_STENCIL_VIEW_DESC :: struct {
},
}
CLEAR_FLAGS :: enum u32 { // TODO: make bit_set
DEPTH = 0x1,
STENCIL = 0x2,
CLEAR_FLAGS :: distinct bit_set[CLEAR_FLAG; u32]
CLEAR_FLAG :: enum u32 {
DEPTH = 0,
STENCIL = 1,
}
FENCE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
SHARED = 0x1,
SHARED_CROSS_ADAPTER = 0x2,
NON_MONITORED = 0x4,
FENCE_FLAGS :: distinct bit_set[FENCE_FLAG; u32]
FENCE_FLAG :: enum u32 {
SHARED = 0,
SHARED_CROSS_ADAPTER = 1,
NON_MONITORED = 2,
}
DESCRIPTOR_HEAP_TYPE :: enum i32 {
@@ -1887,9 +1908,9 @@ DESCRIPTOR_HEAP_TYPE :: enum i32 {
NUM_TYPES = 4,
}
DESCRIPTOR_HEAP_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
SHADER_VISIBLE = 0x1,
DESCRIPTOR_HEAP_FLAGS :: distinct bit_set[DESCRIPTOR_HEAP_FLAG; u32]
DESCRIPTOR_HEAP_FLAG :: enum u32 {
SHADER_VISIBLE = 0,
}
DESCRIPTOR_HEAP_DESC :: struct {
@@ -1959,18 +1980,18 @@ ROOT_PARAMETER :: struct {
ShaderVisibility: SHADER_VISIBILITY,
}
ROOT_SIGNATURE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0x1,
DENY_VERTEX_SHADER_ROOT_ACCESS = 0x2,
DENY_HULL_SHADER_ROOT_ACCESS = 0x4,
DENY_DOMAIN_SHADER_ROOT_ACCESS = 0x8,
DENY_GEOMETRY_SHADER_ROOT_ACCESS = 0x10,
DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20,
ALLOW_STREAM_OUTPUT = 0x40,
LOCAL_ROOT_SIGNATURE = 0x80,
DENY_AMPLIFICATION_SHADER_ROOT_ACCESS = 0x100,
DENY_MESH_SHADER_ROOT_ACCESS = 0x200,
ROOT_SIGNATURE_FLAGS :: distinct bit_set[ROOT_SIGNATURE_FLAG; u32]
ROOT_SIGNATURE_FLAG :: enum u32 {
ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0,
DENY_VERTEX_SHADER_ROOT_ACCESS = 1,
DENY_HULL_SHADER_ROOT_ACCESS = 2,
DENY_DOMAIN_SHADER_ROOT_ACCESS = 3,
DENY_GEOMETRY_SHADER_ROOT_ACCESS = 4,
DENY_PIXEL_SHADER_ROOT_ACCESS = 5,
ALLOW_STREAM_OUTPUT = 6,
LOCAL_ROOT_SIGNATURE = 7,
DENY_AMPLIFICATION_SHADER_ROOT_ACCESS = 8,
DENY_MESH_SHADER_ROOT_ACCESS = 9,
}
STATIC_BORDER_COLOR :: enum i32 {
@@ -2003,13 +2024,13 @@ ROOT_SIGNATURE_DESC :: struct {
Flags: ROOT_SIGNATURE_FLAGS,
}
DESCRIPTOR_RANGE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
DESCRIPTORS_VOLATILE = 0x1,
DATA_VOLATILE = 0x2,
DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
DATA_STATIC = 0x8,
DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x10000,
DESCRIPTOR_RANGE_FLAGS :: distinct bit_set[DESCRIPTOR_RANGE_FLAG; u32]
DESCRIPTOR_RANGE_FLAG :: enum u32 {
DESCRIPTORS_VOLATILE = 0,
DATA_VOLATILE = 1,
DATA_STATIC_WHILE_SET_AT_EXECUTE = 2,
DATA_STATIC = 3,
DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 16,
}
DESCRIPTOR_RANGE1 :: struct {
@@ -2026,11 +2047,11 @@ ROOT_DESCRIPTOR_TABLE1 :: struct {
pDescriptorRanges: ^DESCRIPTOR_RANGE1,
}
ROOT_DESCRIPTOR_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
DATA_VOLATILE = 0x2,
DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
DATA_STATIC = 0x8,
ROOT_DESCRIPTOR_FLAGS :: distinct bit_set[ROOT_DESCRIPTOR_FLAG; u32]
ROOT_DESCRIPTOR_FLAG :: enum u32 {
DATA_VOLATILE = 2,
DATA_STATIC_WHILE_SET_AT_EXECUTE = 3,
DATA_STATIC = 4,
}
ROOT_DESCRIPTOR1 :: struct {
@@ -2571,11 +2592,13 @@ IPipelineLibrary1_VTable :: struct {
LoadPipeline: proc "stdcall" (this: ^IPipelineLibrary1, pName: [^]u16, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
}
MULTIPLE_FENCE_WAIT_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
ANY = 0x1,
ALL = 0x0,
MULTIPLE_FENCE_WAIT_FLAGS :: distinct bit_set[MULTIPLE_FENCE_WAIT_FLAG; u32]
MULTIPLE_FENCE_WAIT_FLAG :: enum u32 {
ANY = 0,
}
MULTIPLE_FENCE_WAIT_FLAG_NONE :: MULTIPLE_FENCE_WAIT_FLAGS{}
MULTIPLE_FENCE_WAIT_FLAG_ANY :: MULTIPLE_FENCE_WAIT_FLAGS{.ANY}
MULTIPLE_FENCE_WAIT_FLAG_ALL :: MULTIPLE_FENCE_WAIT_FLAGS{}
RESIDENCY_PRIORITY :: enum i32 {
MINIMUM = 671088640,
@@ -2611,9 +2634,9 @@ IDevice2_VTable :: struct {
CreatePipelineState: proc "stdcall" (this: ^IDevice2, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
}
RESIDENCY_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
DENY_OVERBUDGET = 0x1,
RESIDENCY_FLAGS :: distinct bit_set[RESIDENCY_FLAG; u32]
RESIDENCY_FLAG :: enum u32 {
DENY_OVERBUDGET = 0,
}
@@ -2630,16 +2653,16 @@ IDevice3_VTable :: struct {
EnqueueMakeResident: proc "stdcall" (this: ^IDevice3, Flags: RESIDENCY_FLAGS, NumObjects: u32, ppObjects: ^^IPageable, pFenceToSignal: ^IFence, FenceValueToSignal: u64) -> HRESULT,
}
COMMAND_LIST_FLAGS :: enum u32 { // TODO: make bit_set
COMMAND_LIST_FLAG_NONE = 0x0,
COMMAND_LIST_FLAGS :: distinct bit_set[COMMAND_LIST_FLAG; u32]
COMMAND_LIST_FLAG :: enum u32 {
}
COMMAND_POOL_FLAGS :: enum u32 { // TODO: make bit_set
COMMAND_POOL_FLAG_NONE = 0x0,
COMMAND_POOL_FLAGS :: distinct bit_set[COMMAND_POOL_FLAG; u32]
COMMAND_POOL_FLAG :: enum u32 {
}
COMMAND_RECORDER_FLAGS :: enum u32 { // TODO: make bit_set
COMMAND_RECORDER_FLAG_NONE = 0x0,
COMMAND_RECORDER_FLAGS :: distinct bit_set[COMMAND_RECORDER_FLAG; u32]
COMMAND_RECORDER_FLAG :: enum u32 {
}
PROTECTED_SESSION_STATUS :: enum i32 {
@@ -2660,9 +2683,9 @@ IProtectedSession_VTable :: struct {
GetSessionStatus: proc "stdcall" (this: ^IProtectedSession) -> PROTECTED_SESSION_STATUS,
}
PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
SUPPORTED = 0x1,
PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS :: distinct bit_set[PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG; u32]
PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG :: enum u32 {
SUPPORTED = 0,
}
FEATURE_DATA_PROTECTED_RESOURCE_SESSION_SUPPORT :: struct {
@@ -2670,8 +2693,8 @@ FEATURE_DATA_PROTECTED_RESOURCE_SESSION_SUPPORT :: struct {
Support: PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS,
}
PROTECTED_RESOURCE_SESSION_FLAGS :: enum u32 { // TODO: make bit_set
PROTECTED_RESOURCE_SESSION_FLAG_NONE = 0x0,
PROTECTED_RESOURCE_SESSION_FLAGS :: distinct bit_set[PROTECTED_RESOURCE_SESSION_FLAG; u32]
PROTECTED_RESOURCE_SESSION_FLAG :: enum u32 {
}
PROTECTED_RESOURCE_SESSION_DESC :: struct {
@@ -2760,9 +2783,10 @@ META_COMMAND_PARAMETER_TYPE :: enum i32 {
GPU_DESCRIPTOR_HANDLE_HEAP_TYPE_CBV_SRV_UAV = 4,
}
META_COMMAND_PARAMETER_FLAGS :: enum u32 { // TODO: make bit_set
INPUT = 0x1,
OUTPUT = 0x2,
META_COMMAND_PARAMETER_FLAGS :: distinct bit_set[META_COMMAND_PARAMETER_FLAG; u32]
META_COMMAND_PARAMETER_FLAG :: enum u32 {
INPUT = 0,
OUTPUT = 1,
}
META_COMMAND_PARAMETER_STAGE :: enum i32 {
@@ -2850,11 +2874,11 @@ STATE_SUBOBJECT :: struct {
pDesc: rawptr,
}
STATE_OBJECT_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITIONS = 0x1,
ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS = 0x2,
ALLOW_STATE_OBJECT_ADDITIONS = 0x4,
STATE_OBJECT_FLAGS :: distinct bit_set[STATE_OBJECT_FLAG; u32]
STATE_OBJECT_FLAG :: enum u32 {
ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITIONS = 0,
ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS = 1,
ALLOW_STATE_OBJECT_ADDITIONS = 2,
}
STATE_OBJECT_CONFIG :: struct {
@@ -2873,8 +2897,8 @@ NODE_MASK :: struct {
NodeMask: u32,
}
EXPORT_FLAGS :: enum u32 { // TODO: make bit_set
EXPORT_FLAG_NONE = 0x0,
EXPORT_FLAGS :: distinct bit_set[EXPORT_FLAG; u32]
EXPORT_FLAG :: enum u32 {
}
EXPORT_DESC :: struct {
@@ -2929,10 +2953,10 @@ RAYTRACING_PIPELINE_CONFIG :: struct {
MaxTraceRecursionDepth: u32,
}
RAYTRACING_PIPELINE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
SKIP_TRIANGLES = 0x100,
SKIP_PROCEDURAL_PRIMITIVES = 0x200,
RAYTRACING_PIPELINE_FLAGS :: distinct bit_set[RAYTRACING_PIPELINE_FLAG; u32]
RAYTRACING_PIPELINE_FLAG :: enum u32 {
SKIP_TRIANGLES = 8,
SKIP_PROCEDURAL_PRIMITIVES = 9,
}
RAYTRACING_PIPELINE_CONFIG1 :: struct {
@@ -2951,10 +2975,10 @@ STATE_OBJECT_DESC :: struct {
pSubobjects: ^STATE_SUBOBJECT,
}
RAYTRACING_GEOMETRY_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
OPAQUE = 0x1,
NO_DUPLICATE_ANYHIT_INVOCATION = 0x2,
RAYTRACING_GEOMETRY_FLAGS :: distinct bit_set[RAYTRACING_GEOMETRY_FLAG; u32]
RAYTRACING_GEOMETRY_FLAG :: enum u32 {
OPAQUE = 0,
NO_DUPLICATE_ANYHIT_INVOCATION = 1,
}
RAYTRACING_GEOMETRY_TYPE :: enum i32 {
@@ -2962,12 +2986,12 @@ RAYTRACING_GEOMETRY_TYPE :: enum i32 {
PROCEDURAL_PRIMITIVE_AABBS = 1,
}
RAYTRACING_INSTANCE_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
TRIANGLE_CULL_DISABLE = 0x1,
TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x2,
FORCE_OPAQUE = 0x4,
FORCE_NON_OPAQUE = 0x8,
RAYTRACING_INSTANCE_FLAGS :: distinct bit_set[RAYTRACING_INSTANCE_FLAG; u32]
RAYTRACING_INSTANCE_FLAG :: enum u32 {
TRIANGLE_CULL_DISABLE = 0,
TRIANGLE_FRONT_COUNTERCLOCKWISE = 1,
FORCE_OPAQUE = 2,
FORCE_NON_OPAQUE = 3,
}
GPU_VIRTUAL_ADDRESS_AND_STRIDE :: struct {
@@ -3010,14 +3034,14 @@ RAYTRACING_GEOMETRY_AABBS_DESC :: struct {
AABBs: GPU_VIRTUAL_ADDRESS_AND_STRIDE,
}
RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
ALLOW_UPDATE = 0x1,
ALLOW_COMPACTION = 0x2,
PREFER_FAST_TRACE = 0x4,
PREFER_FAST_BUILD = 0x8,
MINIMIZE_MEMORY = 0x10,
PERFORM_UPDATE = 0x20,
RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS :: distinct bit_set[RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG; u32]
RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG :: enum u32 {
ALLOW_UPDATE = 0,
ALLOW_COMPACTION = 1,
PREFER_FAST_TRACE = 2,
PREFER_FAST_BUILD = 3,
MINIMIZE_MEMORY = 4,
PERFORM_UPDATE = 5,
}
RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE :: enum i32 {
@@ -3137,18 +3161,18 @@ RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO :: struct {
UpdateScratchDataSizeInBytes: u64,
}
RAY_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
FORCE_OPAQUE = 0x1,
FORCE_NON_OPAQUE = 0x2,
ACCEPT_FIRST_HIT_AND_END_SEARCH = 0x4,
SKIP_CLOSEST_HIT_SHADER = 0x8,
CULL_BACK_FACING_TRIANGLES = 0x10,
CULL_FRONT_FACING_TRIANGLES = 0x20,
CULL_OPAQUE = 0x40,
CULL_NON_OPAQUE = 0x80,
SKIP_TRIANGLES = 0x100,
SKIP_PROCEDURAL_PRIMITIVES = 0x200,
RAY_FLAGS :: distinct bit_set[RAY_FLAG; u32]
RAY_FLAG :: enum u32 {
FORCE_OPAQUE = 0,
FORCE_NON_OPAQUE = 1,
ACCEPT_FIRST_HIT_AND_END_SEARCH = 2,
SKIP_CLOSEST_HIT_SHADER = 3,
CULL_BACK_FACING_TRIANGLES = 4,
CULL_FRONT_FACING_TRIANGLES = 5,
CULL_OPAQUE = 6,
CULL_NON_OPAQUE = 7,
SKIP_TRIANGLES = 8,
SKIP_PROCEDURAL_PRIMITIVES = 9,
}
HIT_KIND :: enum i32 {
@@ -3260,10 +3284,10 @@ DRED_VERSION :: enum i32 {
_1_2 = 3,
}
DRED_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
FORCE_ENABLE = 0x1,
DISABLE_AUTOBREADCRUMBS = 0x2,
DRED_FLAGS :: distinct bit_set[DRED_FLAG; u32]
DRED_FLAG :: enum u32 {
FORCE_ENABLE = 0,
DISABLE_AUTOBREADCRUMBS = 1,
}
DRED_ENABLEMENT :: enum i32 {
@@ -3611,11 +3635,11 @@ RENDER_PASS_DEPTH_STENCIL_DESC :: struct {
StencilEndingAccess: RENDER_PASS_ENDING_ACCESS,
}
RENDER_PASS_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
ALLOW_UAV_WRITES = 0x1,
SUSPENDING_PASS = 0x2,
RESUMING_PASS = 0x4,
RENDER_PASS_FLAGS :: distinct bit_set[RENDER_PASS_FLAG; u32]
RENDER_PASS_FLAG :: enum u32 {
ALLOW_UAV_WRITES = 0,
SUSPENDING_PASS = 1,
RESUMING_PASS = 2,
}
@@ -3697,9 +3721,9 @@ IDebug_VTable :: struct {
EnableDebugLayer: proc "stdcall" (this: ^IDebug),
}
GPU_BASED_VALIDATION_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
DISABLE_STATE_TRACKING = 0x1,
GPU_BASED_VALIDATION_FLAGS :: distinct bit_set[GPU_BASED_VALIDATION_FLAG; u32]
GPU_BASED_VALIDATION_FLAG :: enum u32 {
DISABLE_STATE_TRACKING = 0,
}
@@ -3741,11 +3765,11 @@ IDebug3_VTable :: struct {
SetGPUBasedValidationFlags: proc "stdcall" (this: ^IDebug3, Flags: GPU_BASED_VALIDATION_FLAGS),
}
RLDO_FLAGS :: enum u32 { // TODO: make bit_set
NONE = 0x0,
SUMMARY = 0x1,
DETAIL = 0x2,
IGNORE_INTERNAL = 0x4,
RLDO_FLAGS :: distinct bit_set[RLDO_FLAG; u32]
RLDO_FLAG :: enum u32 {
SUMMARY = 0,
DETAIL = 1,
IGNORE_INTERNAL = 2,
}
DEBUG_DEVICE_PARAMETER_TYPE :: enum i32 {
@@ -3754,12 +3778,12 @@ DEBUG_DEVICE_PARAMETER_TYPE :: enum i32 {
GPU_SLOWDOWN_PERFORMANCE_FACTOR = 2,
}
DEBUG_FEATURE :: enum i32 { // TODO: make bit_set
NONE = 0,
ALLOW_BEHAVIOR_CHANGING_DEBUG_AIDS = 1,
CONSERVATIVE_RESOURCE_STATE_TRACKING = 2,
DISABLE_VIRTUALIZED_BUNDLES_VALIDATION = 4,
EMULATE_WINDOWS7 = 8,
DEBUG_FEATURE :: distinct bit_set[DEBUG_FEATURE_FLAG; u32]
DEBUG_FEATURE_FLAG :: enum i32 {
ALLOW_BEHAVIOR_CHANGING_DEBUG_AIDS = 0,
CONSERVATIVE_RESOURCE_STATE_TRACKING = 1,
DISABLE_VIRTUALIZED_BUNDLES_VALIDATION = 2,
EMULATE_WINDOWS7 = 3,
}
GPU_BASED_VALIDATION_SHADER_PATCH_MODE :: enum i32 {
@@ -3770,12 +3794,16 @@ GPU_BASED_VALIDATION_SHADER_PATCH_MODE :: enum i32 {
NUM_GPU_BASED_VALIDATION_SHADER_PATCH_MODES = 4,
}
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS :: enum u32 { // TODO: make bit_set
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_NONE = 0x0,
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_TRACKING_ONLY_SHADERS = 0x1,
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_UNGUARDED_VALIDATION_SHADERS = 0x2,
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_GUARDED_VALIDATION_SHADERS = 0x4,
VALID_MASK = 0x7,
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS :: distinct bit_set[GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG; u32]
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG :: enum u32 {
FRONT_LOAD_CREATE_TRACKING_ONLY_SHADERS = 0,
FRONT_LOAD_CREATE_UNGUARDED_VALIDATION_SHADERS = 1,
FRONT_LOAD_CREATE_GUARDED_VALIDATION_SHADERS = 2,
}
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_VALID_MASK :: GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAGS{
.FRONT_LOAD_CREATE_TRACKING_ONLY_SHADERS,
.FRONT_LOAD_CREATE_UNGUARDED_VALIDATION_SHADERS,
.FRONT_LOAD_CREATE_GUARDED_VALIDATION_SHADERS,
}
DEBUG_DEVICE_GPU_BASED_VALIDATION_SETTINGS :: struct {
+49 -42
View File
@@ -45,50 +45,57 @@ foreign d3dcompiler {
D3DCOMPILE :: enum u32 { // TODO: make bit_field
DEBUG = 1 << 0,
SKIP_VALIDATION = 1 << 1,
SKIP_OPTIMIZATION = 1 << 2,
PACK_MATRIX_ROW_MAJOR = 1 << 3,
PACK_MATRIX_COLUMN_MAJOR = 1 << 4,
PARTIAL_PRECISION = 1 << 5,
FORCE_VS_SOFTWARE_NO_OPT = 1 << 6,
FORCE_PS_SOFTWARE_NO_OPT = 1 << 7,
NO_PRESHADER = 1 << 8,
AVOID_FLOW_CONTROL = 1 << 9,
PREFER_FLOW_CONTROL = 1 << 10,
ENABLE_STRICTNESS = 1 << 11,
ENABLE_BACKWARDS_COMPATIBILITY = 1 << 12,
IEEE_STRICTNESS = 1 << 13,
OPTIMIZATION_LEVEL0 = 1 << 14,
OPTIMIZATION_LEVEL1 = 0,
OPTIMIZATION_LEVEL2 = (1 << 14)|(1 << 15), // Added manually
OPTIMIZATION_LEVEL3 = 1 << 15,
RESERVED16 = 1 << 16,
RESERVED17 = 1 << 17,
WARNINGS_ARE_ERRORS = 1 << 18,
RESOURCES_MAY_ALIAS = 1 << 19,
ENABLE_UNBOUNDED_DESCRIPTOR_TABLES = 1 << 20,
ALL_RESOURCES_BOUND = 1 << 21,
DEBUG_NAME_FOR_SOURCE = 1 << 22,
DEBUG_NAME_FOR_BINARY = 1 << 23,
D3DCOMPILE :: distinct bit_set[D3DCOMPILE_FLAG; u32]
D3DCOMPILE_FLAG :: enum u32 {
DEBUG = 0,
SKIP_VALIDATION = 1,
SKIP_OPTIMIZATION = 2,
PACK_MATRIX_ROW_MAJOR = 3,
PACK_MATRIX_COLUMN_MAJOR = 4,
PARTIAL_PRECISION = 5,
FORCE_VS_SOFTWARE_NO_OPT = 6,
FORCE_PS_SOFTWARE_NO_OPT = 7,
NO_PRESHADER = 8,
AVOID_FLOW_CONTROL = 9,
PREFER_FLOW_CONTROL = 10,
ENABLE_STRICTNESS = 11,
ENABLE_BACKWARDS_COMPATIBILITY = 12,
IEEE_STRICTNESS = 13,
OPTIMIZATION_LEVEL0 = 14,
OPTIMIZATION_LEVEL3 = 15,
RESERVED16 = 16,
RESERVED17 = 17,
WARNINGS_ARE_ERRORS = 18,
RESOURCES_MAY_ALIAS = 19,
ENABLE_UNBOUNDED_DESCRIPTOR_TABLES = 20,
ALL_RESOURCES_BOUND = 21,
DEBUG_NAME_FOR_SOURCE = 22,
DEBUG_NAME_FOR_BINARY = 23,
}
EFFECT :: enum u32 { // TODO: make bit_field
CHILD_EFFECT = 1 << 0,
ALLOW_SLOW_OPS = 1 << 1,
D3DCOMPILE_OPTIMIZATION_LEVEL0 :: D3DCOMPILE{.OPTIMIZATION_LEVEL0}
D3DCOMPILE_OPTIMIZATION_LEVEL1 :: D3DCOMPILE{}
D3DCOMPILE_OPTIMIZATION_LEVEL2 :: D3DCOMPILE{.IEEE_STRICTNESS, .OPTIMIZATION_LEVEL3}
D3DCOMPILE_OPTIMIZATION_LEVEL3 :: D3DCOMPILE{.OPTIMIZATION_LEVEL3}
EFFECT :: distinct bit_set[EFFECT_FLAG; u32]
EFFECT_FLAG :: enum u32 {
CHILD_EFFECT = 0,
ALLOW_SLOW_OPS = 1,
}
FLAGS2 :: enum u32 { // TODO: make bit_field
FLAGS2 :: enum u32 {
FORCE_ROOT_SIGNATURE_LATEST = 0,
FORCE_ROOT_SIGNATURE_1_0 = 1 << 4,
FORCE_ROOT_SIGNATURE_1_1 = 1 << 5,
}
SECDATA :: enum u32 { // TODO: make bit_field
MERGE_UAV_SLOTS = 0x00000001,
PRESERVE_TEMPLATE_SLOTS = 0x00000002,
REQUIRE_TEMPLATE_MATCH = 0x00000004,
SECDATA :: distinct bit_set[SECDATA_FLAG; u32]
SECDATA_FLAG :: enum u32 {
MERGE_UAV_SLOTS = 0,
PRESERVE_TEMPLATE_SLOTS = 1,
REQUIRE_TEMPLATE_MATCH = 2,
}
DISASM_ENABLE_COLOR_CODE :: 0x00000001
@@ -188,13 +195,13 @@ pD3DCompile :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: cstring, a3: ^SHA
pD3DPreprocess :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: cstring, a3: ^SHADER_MACRO, a4: ^ID3DInclude, a5: ^^ID3DBlob, a6: ^^ID3DBlob) -> HRESULT
pD3DDisassemble :: #type proc "c" (a0: rawptr, a1: SIZE_T, a2: u32, a3: cstring, a4: ^^ID3DBlob) -> HRESULT
D3DCOMPILER_STRIP_FLAGS :: enum u32 { // TODO: make bit_field
REFLECTION_DATA = 0x1,
DEBUG_INFO = 0x2,
TEST_BLOBS = 0x4,
PRIVATE_DATA = 0x8,
ROOT_SIGNATURE = 0x10,
FORCE_DWORD = 0x7fffffff,
D3DCOMPILER_STRIP_FLAGS :: distinct bit_set[D3DCOMPILER_STRIP_FLAG; u32]
D3DCOMPILER_STRIP_FLAG :: enum u32 {
REFLECTION_DATA = 0,
DEBUG_INFO = 1,
TEST_BLOBS = 2,
PRIVATE_DATA = 3,
ROOT_SIGNATURE = 4,
}
BLOB_PART :: enum i32 {
+38 -29
View File
@@ -57,14 +57,15 @@ CPU_ACCESS :: enum u32 {
FIELD = 15,
}
USAGE :: enum u32 { // TODO: convert to bit_set
SHADER_INPUT = 0x00000010,
RENDER_TARGET_OUTPUT = 0x00000020,
BACK_BUFFER = 0x00000040,
SHARED = 0x00000080,
READ_ONLY = 0x00000100,
DISCARD_ON_PRESENT = 0x00000200,
UNORDERED_ACCESS = 0x00000400,
USAGE :: distinct bit_set[USAGE_FLAG; u32]
USAGE_FLAG :: enum u32 {
SHADER_INPUT = 4,
RENDER_TARGET_OUTPUT = 5,
BACK_BUFFER = 6,
SHARED = 7,
READ_ONLY = 8,
DISCARD_ON_PRESENT = 9,
UNORDERED_ACCESS = 10,
}
RESOURCE_PRIORITY :: enum u32 {
@@ -75,37 +76,45 @@ RESOURCE_PRIORITY :: enum u32 {
MAXIMUM = 0xc8000000,
}
MAP :: enum u32 { // TODO: convert to bit_set
MAP :: enum u32 {
READ = 1,
WRITE = 2,
DISCARD = 4,
}
ENUM_MODES :: enum u32 { // TODO: convert to bit_set
INTERLACED = 1,
SCALING = 2,
STEREO = 4,
DISABLED_STEREO = 8,
ENUM_MODES :: distinct bit_set[ENUM_MODE; u32]
ENUM_MODE :: enum u32 {
INTERLACED = 0,
SCALING = 1,
STEREO = 2,
DISABLED_STEREO = 3,
}
MAX_SWAP_CHAIN_BUFFERS :: 16
PRESENT :: enum u32 { // TODO: convert to bit_set
TEST = 0x00000001,
DO_NOT_SEQUENCE = 0x00000002,
RESTART = 0x00000004,
DO_NOT_WAIT = 0x00000008,
STEREO_PREFER_RIGHT = 0x00000010,
STEREO_TEMPORARY_MONO = 0x00000020,
RESTRICT_TO_OUTPUT = 0x00000040,
USE_DURATION = 0x00000100,
ALLOW_TEARING = 0x00000200,
PRESENT :: distinct bit_set[PRESENT_FLAG; u32]
PRESENT_FLAG :: enum u32 {
TEST = 0,
DO_NOT_SEQUENCE = 1,
RESTART = 2,
DO_NOT_WAIT = 3,
STEREO_PREFER_RIGHT = 4,
STEREO_TEMPORARY_MONO = 5,
RESTRICT_TO_OUTPUT = 6,
USE_DURATION = 8,
ALLOW_TEARING = 9,
}
MWA :: enum u32 { // TODO: convert to bit_set
NO_WINDOW_CHANGES = 1 << 0,
NO_ALT_ENTER = 1 << 1,
NO_PRINT_SCREEN = 1 << 2,
VALID = 0x7,
MWA :: distinct bit_set[MWA_FLAG; u32]
MWA_FLAG :: enum u32 {
NO_WINDOW_CHANGES = 0,
NO_ALT_ENTER = 1,
NO_PRINT_SCREEN = 2,
}
MWA_VALID :: MWA{
.NO_WINDOW_CHANGES,
.NO_ALT_ENTER,
.NO_PRINT_SCREEN,
}
SHARED_RESOURCE_READ :: 0x80000000
+1
View File
@@ -110,6 +110,7 @@ foreign glfw {
WaitEventsTimeout :: proc(timeout: f64) ---
PostEmptyEvent :: proc() ---
RawMouseMotionSupported :: proc() -> b32 ---
GetInputMode :: proc(window: WindowHandle, mode: c.int) -> c.int ---
SetInputMode :: proc(window: WindowHandle, mode, value: c.int) ---
+3
View File
@@ -339,6 +339,9 @@ CURSOR_NORMAL :: 0x00034001
CURSOR_HIDDEN :: 0x00034002
CURSOR_DISABLED :: 0x00034003
/* Mouse motion */
RAW_MOUSE_MOTION :: 0x00033005
/* Behavior? */
ANY_RELEASE_BEHAVIOR :: 0
RELEASE_BEHAVIOR_FLUSH :: 0x00035001
-33
View File
@@ -1,33 +0,0 @@
package glfw
when ODIN_OS == .Windows {
import win32 "core:sys/windows"
foreign import glfw { "lib/glfw3_mt.lib", "system:user32.lib", "system:gdi32.lib", "system:shell32.lib" }
@(default_calling_convention="c", link_prefix="glfw")
foreign glfw {
GetWin32Adapter :: proc(monitor: MonitorHandle) -> cstring ---
GetWin32Monitor :: proc(monitor: MonitorHandle) -> cstring ---
GetWin32Window :: proc(window: WindowHandle) -> win32.HWND ---
GetWGLContext :: proc(window: WindowHandle) -> rawptr ---
}
} else when ODIN_OS == .Linux {
// TODO: Native Linux
// Display* glfwGetX11Display(void);
// RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
// RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
// Window glfwGetX11Window(GLFWwindow* window);
// void glfwSetX11SelectionString(const char* string);
// const char* glfwGetX11SelectionString(void);
// struct wl_display* glfwGetWaylandDisplay(void);
// struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
// struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
} else when ODIN_OS == .Darwin {
// TODO: Native Darwin
// CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
// id glfwGetCocoaWindow(GLFWwindow* window);
// id glfwGetNSGLContext(GLFWwindow* window);
}
+16
View File
@@ -0,0 +1,16 @@
//+build darwin
package glfw
import NS "vendor:darwin/foundation"
foreign import glfw { "lib/darwin/libglfw3.a" }
@(default_calling_convention="c", link_prefix="glfw")
foreign glfw {
GetCocoaWindow :: proc(window: WindowHandle) -> ^NS.Window ---
}
// TODO:
// CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
// id glfwGetNSGLContext(GLFWwindow* window);
+15
View File
@@ -0,0 +1,15 @@
//+build linux
package glfw
// TODO: Native Linux
// Display* glfwGetX11Display(void);
// RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
// RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
// Window glfwGetX11Window(GLFWwindow* window);
// void glfwSetX11SelectionString(const char* string);
// const char* glfwGetX11SelectionString(void);
// struct wl_display* glfwGetWaylandDisplay(void);
// struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
// struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
+15
View File
@@ -0,0 +1,15 @@
//+build windows
package glfw
import win32 "core:sys/windows"
foreign import glfw { "lib/glfw3_mt.lib", "system:user32.lib", "system:gdi32.lib", "system:shell32.lib" }
@(default_calling_convention="c", link_prefix="glfw")
foreign glfw {
GetWin32Adapter :: proc(monitor: MonitorHandle) -> cstring ---
GetWin32Monitor :: proc(monitor: MonitorHandle) -> cstring ---
GetWin32Window :: proc(window: WindowHandle) -> win32.HWND ---
GetWGLContext :: proc(window: WindowHandle) -> rawptr ---
}
+1 -1
View File
@@ -6,7 +6,7 @@ import c "core:c/libc"
when ODIN_OS == .Windows { foreign import lib "../lib/stb_rect_pack.lib" }
when ODIN_OS == .Linux { foreign import lib "../lib/stb_rect_pack.a" }
when ODIN_OS == .Darwin { foreign import lib "../lib/stb_rect_pack.a" }
when ODIN_OS == .Darwin { foreign import lib "../lib/darwin/stb_rect_pack.a" }
Coord :: distinct c.int
_MAXVAL :: max(Coord)
+1 -1
View File
@@ -5,7 +5,7 @@ import stbrp "vendor:stb/rect_pack"
when ODIN_OS == .Windows { foreign import stbtt "../lib/stb_truetype.lib" }
when ODIN_OS == .Linux { foreign import stbtt "../lib/stb_truetype.a" }
when ODIN_OS == .Darwin { foreign import stbtt "../lib/stb_truetype.a" }
when ODIN_OS == .Darwin { foreign import stbtt "../lib/darwin/stb_truetype.a" }
///////////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -5,7 +5,7 @@ import c "core:c/libc"
when ODIN_OS == .Windows { foreign import lib "../lib/stb_vorbis.lib" }
when ODIN_OS == .Linux { foreign import lib "../lib/stb_vorbis.a" }
when ODIN_OS == .Darwin { foreign import lib "../lib/stb_vorbis.a" }
when ODIN_OS == .Darwin { foreign import lib "../lib/darwin/stb_vorbis.a" }
+7 -7
View File
@@ -84,7 +84,7 @@ def convert_type(t, prev_name, curr_name):
else:
ttype = t[:len(t)-1]
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"):
pointer = "[^]"
@@ -95,10 +95,10 @@ def convert_type(t, prev_name, curr_name):
pointer = "[^]"
elif curr_name.startswith("p"):
pointer = "[^]"
if curr_name and elem.endswith("Flags"):
pointer = "[^]"
return "{}{}".format(pointer, elem)
elif t[0].isupper():
return t
@@ -276,7 +276,7 @@ def parse_enums(f):
f.write("// Enums\n")
data = re.findall(r"typedef enum Vk(\w+) {(.+?)} \w+;", src, re.S)
data.sort(key=lambda x: x[0])
generated_flags = set()
@@ -458,14 +458,14 @@ def parse_procedures(f):
for rt, name, fields in data:
proc_name = no_vk(name)
pf = []
prev_name = ""
for type_, fname in re.findall(r"(?:\s*|)(.+?)\s*(\w+)(?:,|$)", fields):
curr_name = fix_arg(fname)
pf.append((do_type(type_, prev_name, curr_name), curr_name))
prev_name = curr_name
data_fields = ', '.join(["{}: {}".format(n, t) for t, n in pf if t != ""])
ts = "proc \"c\" ({})".format(data_fields)
@@ -510,7 +510,7 @@ def group_functions(f):
if table_name in ('Device', 'Queue', 'CommandBuffer') and name != 'GetDeviceProcAddr':
group_map["Device"].append(nn)
elif table_name in ('Instance', 'PhysicalDevice') or name == 'GetDeviceProcAddr':
elif table_name in ('Instance', 'PhysicalDevice') and name != 'ProcGetInstanceProcAddr' or name == 'GetDeviceProcAddr':
group_map["Instance"].append(nn)
elif table_name in ('rawptr', '', 'DebugReportFlagsEXT') or name == 'GetInstanceProcAddr':
# Skip the allocation function and the dll entry point
+3 -3
View File
@@ -533,6 +533,7 @@ DeviceMemoryReportCallbackEXT: ProcDeviceMemoryReportCallbackEXT
EnumerateInstanceExtensionProperties: ProcEnumerateInstanceExtensionProperties
EnumerateInstanceLayerProperties: ProcEnumerateInstanceLayerProperties
EnumerateInstanceVersion: ProcEnumerateInstanceVersion
GetInstanceProcAddr: ProcGetInstanceProcAddr
// Instance Procedures
AcquireDrmDisplayEXT: ProcAcquireDrmDisplayEXT
@@ -564,7 +565,6 @@ GetDisplayPlaneCapabilities2KHR: ProcGetDisplayP
GetDisplayPlaneCapabilitiesKHR: ProcGetDisplayPlaneCapabilitiesKHR
GetDisplayPlaneSupportedDisplaysKHR: ProcGetDisplayPlaneSupportedDisplaysKHR
GetDrmDisplayEXT: ProcGetDrmDisplayEXT
GetInstanceProcAddr: ProcGetInstanceProcAddr
GetPhysicalDeviceCalibrateableTimeDomainsEXT: ProcGetPhysicalDeviceCalibrateableTimeDomainsEXT
GetPhysicalDeviceCooperativeMatrixPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV
GetPhysicalDeviceDisplayPlaneProperties2KHR: ProcGetPhysicalDeviceDisplayPlaneProperties2KHR
@@ -1045,6 +1045,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) {
set_proc_address(&EnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties")
set_proc_address(&EnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties")
set_proc_address(&EnumerateInstanceVersion, "vkEnumerateInstanceVersion")
set_proc_address(&GetInstanceProcAddr, "vkGetInstanceProcAddr")
// Instance Procedures
set_proc_address(&AcquireDrmDisplayEXT, "vkAcquireDrmDisplayEXT")
@@ -1076,7 +1077,6 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) {
set_proc_address(&GetDisplayPlaneCapabilitiesKHR, "vkGetDisplayPlaneCapabilitiesKHR")
set_proc_address(&GetDisplayPlaneSupportedDisplaysKHR, "vkGetDisplayPlaneSupportedDisplaysKHR")
set_proc_address(&GetDrmDisplayEXT, "vkGetDrmDisplayEXT")
set_proc_address(&GetInstanceProcAddr, "vkGetInstanceProcAddr")
set_proc_address(&GetPhysicalDeviceCalibrateableTimeDomainsEXT, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT")
set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV")
set_proc_address(&GetPhysicalDeviceDisplayPlaneProperties2KHR, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR")
@@ -2839,7 +2839,6 @@ load_proc_addresses_instance :: proc(instance: Instance) {
GetDisplayPlaneCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR")
GetDisplayPlaneSupportedDisplaysKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR")
GetDrmDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkGetDrmDisplayEXT")
GetInstanceProcAddr = auto_cast GetInstanceProcAddr(instance, "vkGetInstanceProcAddr")
GetPhysicalDeviceCalibrateableTimeDomainsEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT")
GetPhysicalDeviceCooperativeMatrixPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV")
GetPhysicalDeviceDisplayPlaneProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR")
@@ -3322,6 +3321,7 @@ load_proc_addresses_global :: proc(vk_get_instance_proc_addr: rawptr) {
EnumerateInstanceExtensionProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceExtensionProperties")
EnumerateInstanceLayerProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceLayerProperties")
EnumerateInstanceVersion = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceVersion")
GetInstanceProcAddr = auto_cast GetInstanceProcAddr(nil, "vkGetInstanceProcAddr")
}
load_proc_addresses :: proc{