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 cd tests/vendor
make make
timeout-minutes: 10 timeout-minutes: 10
- name: Odin issues tests
run: |
cd tests/issues
./run.sh
timeout-minutes: 10
- name: Odin check examples/all for Linux i386 - name: Odin check examples/all for Linux i386
run: ./odin check examples/all -vet -strict-style -target:linux_i386 run: ./odin check examples/all -vet -strict-style -target:linux_i386
timeout-minutes: 10 timeout-minutes: 10
@@ -92,11 +87,6 @@ jobs:
cd tests/vendor cd tests/vendor
make make
timeout-minutes: 10 timeout-minutes: 10
- name: Odin issues tests
run: |
cd tests/issues
./run.sh
timeout-minutes: 10
- name: Odin check examples/all for Darwin arm64 - name: Odin check examples/all for Darwin arm64
run: ./odin check examples/all -vet -strict-style -target:darwin_arm64 run: ./odin check examples/all -vet -strict-style -target:darwin_arm64
timeout-minutes: 10 timeout-minutes: 10
@@ -163,13 +153,6 @@ jobs:
cd tests\core\math\big cd tests\core\math\big
call build.bat call build.bat
timeout-minutes: 10 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 - name: Odin check examples/all for Windows 32bits
shell: cmd shell: cmd
run: | run: |
+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
run: | run: |
mkdir dist mkdir dist
cp odin dist cp odin dist
cp libLLVM*.so dist cp libLLVM* dist
cp -r shared dist cp -r shared dist
cp -r core dist cp -r core dist
cp -r vendor dist cp -r vendor dist
+1 -1
View File
@@ -271,7 +271,7 @@ odin
odin.dSYM odin.dSYM
*.bin *.bin
demo.bin demo.bin
libLLVM*.so libLLVM*.so*
# shared collection # shared collection
shared/ shared/
+1 -1
View File
@@ -82,7 +82,7 @@ A wiki maintained by the Odin community.
#### [Odin Discord](https://discord.gg/sVBPHEv) #### [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 ### Articles
+25 -1
View File
@@ -44,6 +44,12 @@ config_darwin() {
fi fi
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" LDFLAGS="$LDFLAGS -liconv -ldl"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -lLLVM-C" LDFLAGS="$LDFLAGS -lLLVM-C"
@@ -97,10 +103,20 @@ config_linux() {
panic "Requirement: llvm-config must be base version greater than 11" panic "Requirement: llvm-config must be base version greater than 11"
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 -ldl" LDFLAGS="$LDFLAGS -ldl"
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs --libfiles) -Wl,-rpath=\$ORIGIN" 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() { build_odin() {
@@ -130,6 +146,14 @@ run_demo() {
./odin run examples/demo/demo.odin -file ./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 case $OS in
Linux) Linux)
config_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) { buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
b.last_read = .Invalid b.last_read = .Invalid
if offset < 0 || offset >= len(b.buf) { if uint(offset) >= len(b.buf) {
err = .Invalid_Offset err = .Invalid_Offset
return return
} }
n = copy(p, b.buf[offset:])
if 0 <= offset && offset < len(b.buf) {
n = copy(p, b.buf[offset:])
}
if n > 0 { if n > 0 {
b.last_read = .Read 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 { index_rune :: proc(s: []byte, r: rune) -> int {
switch { switch {
case 0 <= r && r < utf8.RUNE_SELF: case u32(r) < utf8.RUNE_SELF:
return index_byte(s, byte(r)) return index_byte(s, byte(r))
case r == utf8.RUNE_ERROR: case r == utf8.RUNE_ERROR:
+15 -2
View File
@@ -14,11 +14,24 @@ when ODIN_OS == .Windows {
// EDOM, // EDOM,
// EILSEQ // EILSEQ
// ERANGE // ERANGE
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD { when ODIN_OS == .Linux {
@(private="file") @(private="file")
@(default_calling_convention="c") @(default_calling_convention="c")
foreign libc { 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 --- _get_errno :: proc() -> ^int ---
} }
+4 -1
View File
@@ -1,7 +1,10 @@
package libc package libc
when ODIN_OS == .Windows { 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 { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System.framework"
} else { } 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} field := any{field_ptr, type.id}
unmarshal_value(p, field) or_return 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) { if parse_comma(p) {
break struct_loop break struct_loop
} }
continue 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: case reflect.Type_Info_Map:
+1 -1
View File
@@ -975,7 +975,7 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) {
} }
} }
else { else {
io.write_string(fi.writer, s[:fi.width], &fi.n) io.write_string(fi.writer, s, &fi.n)
} }
} }
else 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)) w := io.to_writer(os.stream_from_handle(fd))
return wprintln(w=w, args=args, sep=sep) 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 { fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
w := io.to_writer(os.stream_from_handle(fd)) w := io.to_writer(os.stream_from_handle(fd))
return wprintf(w, fmt, ..args) 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) } 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 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) } 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) } 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 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) } 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 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) } 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) } 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 return
} }
// If you have a choice, prefer fnv32a
@(optimization_mode="speed") @(optimization_mode="speed")
fnv32 :: proc(data: []byte, seed := u32(0x811c9dc5)) -> u32 { fnv32_no_a :: proc(data: []byte, seed := u32(0x811c9dc5)) -> u32 {
h: u32 = seed h: u32 = seed
for b in data { for b in data {
h = (h * 0x01000193) ~ u32(b) h = (h * 0x01000193) ~ u32(b)
@@ -81,8 +82,9 @@ fnv32 :: proc(data: []byte, seed := u32(0x811c9dc5)) -> u32 {
return h return h
} }
// If you have a choice, prefer fnv64a
@(optimization_mode="speed") @(optimization_mode="speed")
fnv64 :: proc(data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 { fnv64_no_a :: proc(data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
h: u64 = seed h: u64 = seed
for b in data { for b in data {
h = (h * 0x100000001b3) ~ u64(b) 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] 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 package mem
import "core:builtin"
import "core:runtime" import "core:runtime"
Raw_Any :: runtime.Raw_Any 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} return transmute(any)Raw_Any{data, id}
} }
raw_array_data :: runtime.raw_array_data raw_data :: builtin.raw_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
Poly_Raw_Map_Entry :: struct($Key, $Value: typeid) { 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 package mem_virtual
import "core:mem" import "core:mem"
import "core:intrinsics"
DEFAULT_PAGE_SIZE := uint(4096) 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.committed = committed
pmblock.block.reserved = reserved 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 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 { calc_alignment_offset :: proc "contextless" (block: ^Memory_Block, alignment: uintptr) -> uint {
alignment_offset := uint(0) alignment_offset := uint(0)
ptr := uintptr(block.base[block.used:]) ptr := uintptr(block.base[block.used:])
@@ -134,11 +128,18 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: int)
return nil return nil
} }
if block == nil {
return nil, .Out_Of_Memory
}
alignment_offset := calc_alignment_offset(block, uintptr(alignment)) 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 err = .Out_Of_Memory
return 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) { memory_block_dealloc :: proc(block_to_free: ^Memory_Block) {
if block := (^Platform_Memory_Block)(block_to_free); block != nil { 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) 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 //+private
package mem_virtual package mem_virtual
import "core:sync"
Platform_Memory_Block :: struct { Platform_Memory_Block :: struct {
block: Memory_Block, block: Memory_Block,
committed: uint, committed: uint,
reserved: 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) { 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) { platform_memory_commit :: proc "contextless" (block: ^Platform_Memory_Block, to_commit: uint) -> (err: Allocator_Error) {
if to_commit < block.committed { if to_commit < block.committed {
return nil return nil
@@ -63,7 +38,6 @@ platform_memory_commit :: proc "contextless" (block: ^Platform_Memory_Block, to_
return .Out_Of_Memory return .Out_Of_Memory
} }
commit(block, to_commit) or_return commit(block, to_commit) or_return
block.committed = to_commit block.committed = to_commit
return nil return nil
+1 -4
View File
@@ -2,7 +2,6 @@ package os
import win32 "core:sys/windows" import win32 "core:sys/windows"
import "core:strings" import "core:strings"
import "core:time"
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) { 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) { 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.mode |= file_type_mode(h);
} }
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) windows_set_file_info_times(&fi, d)
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))
fi.is_dir = fi.mode & File_Mode_Dir != 0 fi.is_dir = fi.mode & File_Mode_Dir != 0
return return
+4 -2
View File
@@ -162,7 +162,8 @@ read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
total_read: int total_read: int
length := len(data) 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 e: win32.BOOL
if is_console { if is_console {
@@ -172,7 +173,8 @@ read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
return int(total_read), err return int(total_read), err
} }
} else { } 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 { if single_read_length <= 0 || !e {
err := Errno(win32.GetLastError()) 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 := new(File, _file_allocator())
f.impl.allocator = _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.name = strings.clone(name, f.impl.allocator)
f.impl.wname = win32.utf8_to_wstring(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 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) { write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
assert(fd != -1) assert(fd != -1)
if len(data) == 0 { bytes_total := len(data)
return 0, 0 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 bytes_written_total, 0
return 0, 1
}
return bytes_written, 0
} }
read :: proc(fd: Handle, data: []u8) -> (int, Errno) { read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
assert(fd != -1) assert(fd != -1)
bytes_read := _unix_read(fd, raw_data(data), len(data)) bytes_total := len(data)
if bytes_read == -1 { bytes_read_total := 0
return 0, 1
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) { seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
+32 -3
View File
@@ -24,7 +24,7 @@ O_CLOEXEC :: 0x80000
stdin: Handle = 0 stdin: Handle = 0
stdout: Handle = 1 stdout: Handle = 1
stderr: Handle = 2 stderr: Handle = 2
current_dir: Handle = 3
write :: proc(fd: Handle, data: []byte) -> (int, Errno) { write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
iovs := wasi.ciovec_t(data) 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) return int(n), Errno(err)
} }
open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) { 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 { close :: proc(fd: Handle) -> Errno {
err := wasi.fd_close(wasi.fd_t(fd)) err := wasi.fd_close(wasi.fd_t(fd))
@@ -96,4 +125,4 @@ heap_free :: proc(ptr: rawptr) {
exit :: proc "contextless" (code: int) -> ! { exit :: proc "contextless" (code: int) -> ! {
runtime._cleanup_runtime_contextless() runtime._cleanup_runtime_contextless()
wasi.proc_exit(wasi.exitcode_t(code)) 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 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) @(private)
file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string) -> (fi: File_Info, e: Errno) { 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) 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.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0)
fi.is_dir = fi.mode & File_Mode_Dir != 0 fi.is_dir = fi.mode & File_Mode_Dir != 0
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) windows_set_file_info_times(&fi, d)
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))
fi.fullpath, e = full_path_from_name(name) fi.fullpath, e = full_path_from_name(name)
fi.name = basename(fi.fullpath) 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.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0)
fi.is_dir = fi.mode & File_Mode_Dir != 0 fi.is_dir = fi.mode & File_Mode_Dir != 0
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) windows_set_file_info_times(&fi, d)
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))
fi.fullpath, e = full_path_from_name(name) fi.fullpath, e = full_path_from_name(name)
fi.name = basename(fi.fullpath) 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.mode |= file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag)
fi.is_dir = fi.mode & File_Mode_Dir != 0 fi.is_dir = fi.mode & File_Mode_Dir != 0
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) windows_set_file_info_times(&fi, &d)
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))
return fi, ERROR_NONE 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 @builtin
map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (ptr: ^V) { map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location) -> (ptr: ^V) {
key, value := key, value 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) e := __dynamic_map_set(m, h, __get_map_key_hash(&key), &key, &value, loc)
return (^V)(uintptr(e) + h.value_offset) 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 @builtin
@(disabled=ODIN_DISABLE_ASSERT) @(disabled=ODIN_DISABLE_ASSERT)
assert :: proc(condition: bool, message := "", loc := #caller_location) { 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) { bounds_check_error :: proc "contextless" (file: string, line, column: i32, index, count: int) {
if 0 <= index && index < count { if uint(index) < uint(count) {
return return
} }
@(cold) @(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) { 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 && if uint(row_index) < uint(row_count) &&
0 <= column_index && column_index < column_count { uint(column_index) < uint(column_count) {
return return
} }
@(cold) @(cold)
+1 -1
View File
@@ -12,7 +12,7 @@ objc_SEL :: ^intrinsics.objc_selector
foreign Foundation { foreign Foundation {
objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class --- objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class ---
sel_registerName :: proc "c" (name: cstring) -> objc_SEL --- 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 :: 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 --- 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) { 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] value = array[index]
ok = true ok = true
} }
return return
} }
get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) { 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] value = &array[index]
ok = true 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 { _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 { less :: #force_inline proc(a, b: E, call: P) -> bool {
when KIND == .Ordered { 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") #panic("unhandled Sort_Kind")
} }
} }
// insertion sort
// TODO(bill): use a different algorithm as insertion sort is O(n^2)
n := len(data) n := len(data)
for i in 1..<n { for i in 1..<n {
for j := i; j > 0 && less(data[j], data[j-1], call); j -= 1 { 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) { parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
s := str s := str
defer if n != nil { n^ = len(str)-len(s) } defer if n != nil { n^ = len(str) - len(s) }
if s == "" { if s == "" {
return return
} }
@@ -575,9 +575,11 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) {
i := 0 i := 0
sign: f64 = 1 sign: f64 = 1
seen_sign := true
switch s[i] { switch s[i] {
case '-': i += 1; sign = -1 case '-': i += 1; sign = -1
case '+': i += 1 case '+': i += 1
case: seen_sign = false
} }
for ; i < len(s); i += 1 { 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) v := _digit_value(r)
if v >= 10 { 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 break
} }
value *= 10 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 } 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 { if frac {
value = sign * (value/scale) value = sign * (value/scale)
} else { } 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 { index_rune :: proc(s: string, r: rune) -> int {
switch { switch {
case 0 <= r && r < utf8.RUNE_SELF: case u32(r) < utf8.RUNE_SELF:
return index_byte(s, byte(r)) return index_byte(s, byte(r))
case r == utf8.RUNE_ERROR: 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}}}, "21F2092" = {{21, 5, 0}, "macOS", {"Monterey", {12, 4, 0}}},
"21G72" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 0}}}, "21G72" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 0}}},
"21G83" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 1}}}, "21G83" = {{21, 6, 0}, "macOS", {"Monterey", {12, 5, 1}}},
"21G115" = {{21, 6, 0}, "macOS", {"Monterey", {12, 6, 0}}},
} }
@(private) @(private)
+30
View File
@@ -128,4 +128,34 @@ foreign advapi32 {
lpData: LPCVOID, lpData: LPCVOID,
cbData: DWORD, cbData: DWORD,
) -> LSTATUS --- ) -> 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 --- ) -> HFONT ---
TextOutW :: proc(hdc: HDC, x, y: c_int, lpString: LPCWSTR, c: c_int) -> BOOL --- 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 --- 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 { RGB :: #force_inline proc "contextless" (r, g, b: u8) -> COLORREF {
+173
View File
@@ -248,6 +248,17 @@ foreign kernel32 {
GetModuleHandleW :: proc(lpModuleName: LPCWSTR) -> HMODULE --- GetModuleHandleW :: proc(lpModuleName: LPCWSTR) -> HMODULE ---
GetModuleHandleA :: proc(lpModuleName: LPCSTR) -> HMODULE --- GetModuleHandleA :: proc(lpModuleName: LPCSTR) -> HMODULE ---
GetSystemTimeAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- 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( CreateEventW :: proc(
lpEventAttributes: LPSECURITY_ATTRIBUTES, lpEventAttributes: LPSECURITY_ATTRIBUTES,
bManualReset: BOOL, bManualReset: BOOL,
@@ -346,6 +357,13 @@ foreign kernel32 {
GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL --- GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL ---
FreeConsole :: proc() -> BOOL --- FreeConsole :: proc() -> BOOL ---
GetConsoleWindow :: proc() -> HWND --- 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 HandlerRoutine :: proc "stdcall" (dwCtrlType: DWORD) -> BOOL
PHANDLER_ROUTINE :: HandlerRoutine 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, lpDirectory: LPCWSTR,
nShowCmd: INT, nShowCmd: INT,
) -> HINSTANCE --- ) -> 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 --- PathFileExistsW :: proc(pszPath: wstring) -> BOOL ---
PathFindExtensionW :: proc(pszPath: wstring) -> wstring --- PathFindExtensionW :: proc(pszPath: wstring) -> wstring ---
PathFindFileNameW :: 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 DWORDLONG :: c.ulonglong
QWORD :: c.ulonglong QWORD :: c.ulonglong
HANDLE :: distinct LPVOID HANDLE :: distinct LPVOID
PHANDLE :: ^HANDLE
HINSTANCE :: HANDLE HINSTANCE :: HANDLE
HMODULE :: distinct HINSTANCE HMODULE :: distinct HINSTANCE
HRESULT :: distinct LONG HRESULT :: distinct LONG
@@ -43,6 +44,7 @@ BOOLEAN :: distinct b8
GROUP :: distinct c_uint GROUP :: distinct c_uint
LARGE_INTEGER :: distinct c_longlong LARGE_INTEGER :: distinct c_longlong
ULARGE_INTEGER :: distinct c_ulonglong ULARGE_INTEGER :: distinct c_ulonglong
PULARGE_INTEGER :: ^ULARGE_INTEGER
LONG :: c_long LONG :: c_long
UINT :: c_uint UINT :: c_uint
INT :: c_int INT :: c_int
@@ -133,6 +135,11 @@ LPWSAOVERLAPPED :: distinct rawptr
LPWSAOVERLAPPED_COMPLETION_ROUTINE :: distinct rawptr LPWSAOVERLAPPED_COMPLETION_ROUTINE :: distinct rawptr
LPCVOID :: rawptr LPCVOID :: rawptr
PACCESS_TOKEN :: PVOID
PSECURITY_DESCRIPTOR :: PVOID
PSID :: PVOID
PCLAIMS_BLOB :: PVOID
PCONDITION_VARIABLE :: ^CONDITION_VARIABLE PCONDITION_VARIABLE :: ^CONDITION_VARIABLE
PLARGE_INTEGER :: ^LARGE_INTEGER PLARGE_INTEGER :: ^LARGE_INTEGER
PSRWLOCK :: ^SRWLOCK PSRWLOCK :: ^SRWLOCK
@@ -175,6 +182,7 @@ FILE_SHARE_DELETE: DWORD : 0x00000004
FILE_GENERIC_ALL: DWORD : 0x10000000 FILE_GENERIC_ALL: DWORD : 0x10000000
FILE_GENERIC_EXECUTE: DWORD : 0x20000000 FILE_GENERIC_EXECUTE: DWORD : 0x20000000
FILE_GENERIC_READ: DWORD : 0x80000000 FILE_GENERIC_READ: DWORD : 0x80000000
FILE_ALL_ACCESS :: STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF
FILE_ACTION_ADDED :: 0x00000001 FILE_ACTION_ADDED :: 0x00000001
FILE_ACTION_REMOVED :: 0x00000002 FILE_ACTION_REMOVED :: 0x00000002
@@ -230,6 +238,20 @@ SECURITY_SQOS_PRESENT: DWORD : 0x00100000
FIONBIO: c_ulong : 0x8004667e 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 GET_FILEEX_INFO_LEVELS :: distinct i32
GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0 GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0
@@ -773,6 +795,30 @@ MSG :: struct {
LPMSG :: ^MSG 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 { PAINTSTRUCT :: struct {
hdc: HDC, hdc: HDC,
fErase: BOOL, fErase: BOOL,
@@ -879,6 +925,48 @@ NM_FONTCHANGED :: NM_OUTOFMEMORY-22
NM_CUSTOMTEXT :: NM_OUTOFMEMORY-23 // uses NMCUSTOMTEXT struct NM_CUSTOMTEXT :: NM_OUTOFMEMORY-23 // uses NMCUSTOMTEXT struct
NM_TVSTATEIMAGECHANGING :: NM_OUTOFMEMORY-23 // uses NMTVSTATEIMAGECHANGING struct, defined after HTREEITEM 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 { DEVMODEW :: struct {
dmDeviceName: [32]wchar_t, dmDeviceName: [32]wchar_t,
dmSpecVersion: WORD, dmSpecVersion: WORD,
@@ -1066,8 +1154,14 @@ WS_EX_TOPMOST : UINT : 0x0000_0008
WS_EX_TRANSPARENT : UINT : 0x0000_0020 WS_EX_TRANSPARENT : UINT : 0x0000_0020
WS_EX_WINDOWEDGE : UINT : 0x0000_0100 WS_EX_WINDOWEDGE : UINT : 0x0000_0100
PBS_SMOOTH :: 0x01 PBS_SMOOTH :: 0x01
PBS_VERTICAL :: 0x04 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_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 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_ERROR := IDI_HAND
IDI_INFORMATION := IDI_ASTERISK 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 color table identifiers
DIB_RGB_COLORS :: 0 DIB_RGB_COLORS :: 0
@@ -1662,6 +1774,7 @@ WSAENOTCONN: c_int : 10057
WSAESHUTDOWN: c_int : 10058 WSAESHUTDOWN: c_int : 10058
WSAETIMEDOUT: c_int : 10060 WSAETIMEDOUT: c_int : 10060
WSAECONNREFUSED: c_int : 10061 WSAECONNREFUSED: c_int : 10061
WSATRY_AGAIN: c_int : 11002
MAX_PROTOCOL_CHAIN: DWORD : 7 MAX_PROTOCOL_CHAIN: DWORD : 7
@@ -1773,12 +1886,15 @@ WAIT_FAILED: DWORD : 0xFFFFFFFF
PIPE_ACCESS_INBOUND: DWORD : 0x00000001 PIPE_ACCESS_INBOUND: DWORD : 0x00000001
PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002 PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002
PIPE_ACCESS_DUPLEX: DWORD : 0x00000003
FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000 FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000
FILE_FLAG_OVERLAPPED: DWORD : 0x40000000 FILE_FLAG_OVERLAPPED: DWORD : 0x40000000
PIPE_WAIT: DWORD : 0x00000000 PIPE_WAIT: DWORD : 0x00000000
PIPE_TYPE_BYTE: DWORD : 0x00000000 PIPE_TYPE_BYTE: DWORD : 0x00000000
PIPE_TYPE_MESSAGE: DWORD : 0x00000004
PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008 PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008
PIPE_READMODE_BYTE: DWORD : 0x00000000 PIPE_READMODE_BYTE: DWORD : 0x00000000
PIPE_READMODE_MESSAGE: DWORD : 0x00000002
PIPE_ACCEPT_REMOTE_CLIENTS: DWORD : 0x00000000 PIPE_ACCEPT_REMOTE_CLIENTS: DWORD : 0x00000000
FD_SETSIZE :: 64 FD_SETSIZE :: 64
@@ -1792,7 +1908,58 @@ HEAP_ZERO_MEMORY: DWORD : 0x00000008
HANDLE_FLAG_INHERIT: DWORD : 0x00000001 HANDLE_FLAG_INHERIT: DWORD : 0x00000001
HANDLE_FLAG_PROTECT_FROM_CLOSE :: 0x00000002 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_ACP :: 0 // default to ANSI code page
CP_OEMCP :: 1 // default to OEM 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 { FILETIME_as_unix_nanoseconds :: proc "contextless" (ft: FILETIME) -> i64 {
t := i64(u64(ft.dwLowDateTime) | u64(ft.dwHighDateTime) << 32) t := i64(u64(ft.dwLowDateTime) | u64(ft.dwHighDateTime) << 32)
return (t - 0x019db1ded53e8000) * 100 return (t - 116444736000000000) * 100
} }
OVERLAPPED :: struct { OVERLAPPED :: struct {
Internal: ^c_ulong, Internal: ^c_ulong,
InternalHigh: ^c_ulong, InternalHigh: ^c_ulong,
@@ -2776,6 +2944,16 @@ SYSTEMTIME :: struct {
milliseconds: WORD, milliseconds: WORD,
} }
TIME_ZONE_INFORMATION :: struct {
Bias: LONG,
StandardName: [32]WCHAR,
StandardDate: SYSTEMTIME,
StandardBias: LONG,
DaylightName: [32]WCHAR,
DaylightDate: SYSTEMTIME,
DaylightBias: LONG,
}
@(private="file") @(private="file")
IMAGE_DOS_HEADER :: struct { IMAGE_DOS_HEADER :: struct {
@@ -3047,12 +3225,32 @@ SHCONTF_FLATLIST :: 0x4000
SHCONTF_ENABLE_ASYNC :: 0x8000 SHCONTF_ENABLE_ASYNC :: 0x8000
SHCONTF_INCLUDESUPERHIDDEN :: 0x10000 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_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_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_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_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_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 { IModalWindow :: struct #raw_union {
#subtype IUnknown: IUnknown, #subtype IUnknown: IUnknown,
@@ -3357,6 +3555,84 @@ IFileSaveDialogVtbl :: struct {
ApplyProperties: proc "stdcall" (this: ^IFileSaveDialog, psi: ^IShellItem, pStore: ^IPropertyStore, hwnd: HWND, pSink: ^IFileOperationProgressSink) -> HRESULT, 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 { MEMORYSTATUSEX :: struct {
dwLength: DWORD, dwLength: DWORD,
dwMemoryLoad: DWORD, dwMemoryLoad: DWORD,
+4
View File
@@ -78,6 +78,7 @@ foreign user32 {
LoadIconW :: proc(hInstance: HINSTANCE, lpIconName: LPCWSTR) -> HICON --- LoadIconW :: proc(hInstance: HINSTANCE, lpIconName: LPCWSTR) -> HICON ---
LoadCursorA :: proc(hInstance: HINSTANCE, lpCursorName: LPCSTR) -> HCURSOR --- LoadCursorA :: proc(hInstance: HINSTANCE, lpCursorName: LPCSTR) -> HCURSOR ---
LoadCursorW :: proc(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> 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 --- GetWindowRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL ---
GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL ---
@@ -104,6 +105,9 @@ foreign user32 {
GetDC :: proc(hWnd: HWND) -> HDC --- GetDC :: proc(hWnd: HWND) -> HDC ---
ReleaseDC :: proc(hWnd: HWND, hDC: HDC) -> c_int --- 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 --- GetUpdateRect :: proc(hWnd: HWND, lpRect: LPRECT, bErase: BOOL) -> BOOL ---
ValidateRect :: proc(hWnd: HWND, lpRect: ^RECT) -> BOOL --- ValidateRect :: proc(hWnd: HWND, lpRect: ^RECT) -> BOOL ---
InvalidateRect :: proc(hWnd: HWND, lpRect: ^RECT, bErase: BOOL) -> 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) { wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) {
context.allocator = allocator context.allocator = allocator
if N <= 0 { if N == 0 {
return 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 { if n == 0 {
return 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 // and will scan it to find the first null terminated character. The resulting string will
// also be null terminated. // 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. // will not be null terminated.
text := make([]byte, n) or_return 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 IS_SUPPORTED :: _IS_SUPPORTED
Time :: struct { Time :: struct {
_nsec: i64, // zero is 1970-01-01 00:00:00 _nsec: i64, // Measured in UNIX nanonseconds
} }
Month :: enum int { Month :: enum int {
@@ -59,36 +59,36 @@ sleep :: proc "contextless" (d: Duration) {
_sleep(d) _sleep(d)
} }
stopwatch_start :: proc(using stopwatch: ^Stopwatch) { stopwatch_start :: proc "contextless" (using stopwatch: ^Stopwatch) {
if !running { if !running {
_start_time = tick_now() _start_time = tick_now()
running = true running = true
} }
} }
stopwatch_stop :: proc(using stopwatch: ^Stopwatch) { stopwatch_stop :: proc "contextless" (using stopwatch: ^Stopwatch) {
if running { if running {
_accumulation += tick_diff(_start_time, tick_now()) _accumulation += tick_diff(_start_time, tick_now())
running = false running = false
} }
} }
stopwatch_reset :: proc(using stopwatch: ^Stopwatch) { stopwatch_reset :: proc "contextless" (using stopwatch: ^Stopwatch) {
_accumulation = {} _accumulation = {}
running = false running = false
} }
stopwatch_duration :: proc(using stopwatch: Stopwatch) -> Duration { stopwatch_duration :: proc "contextless" (using stopwatch: Stopwatch) -> Duration {
if !running { return _accumulation } if !running { return _accumulation }
return _accumulation + tick_diff(_start_time, tick_now()) 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 d := end._nsec - start._nsec
return Duration(d) return Duration(d)
} }
since :: proc(start: Time) -> Duration { since :: proc "contextless" (start: Time) -> Duration {
return diff(start, now()) return diff(start, now())
} }
@@ -117,8 +117,8 @@ duration_hours :: proc "contextless" (d: Duration) -> f64 {
return f64(hour) + f64(nsec)/(60*60*1e9) return f64(hour) + f64(nsec)/(60*60*1e9)
} }
duration_round :: proc(d, m: Duration) -> Duration { duration_round :: proc "contextless" (d, m: Duration) -> Duration {
_less_than_half :: #force_inline proc(x, y: Duration) -> bool { _less_than_half :: #force_inline proc "contextless" (x, y: Duration) -> bool {
return u64(x)+u64(x) < u64(y) return u64(x)+u64(x) < u64(y)
} }
@@ -146,45 +146,45 @@ duration_round :: proc(d, m: Duration) -> Duration {
return MAX_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 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) year, month, day, _ = _abs_date(_time_abs(t), true)
return return
} }
year :: proc(t: Time) -> (year: int) { year :: proc "contextless" (t: Time) -> (year: int) {
year, _, _, _ = _date(t, true) year, _, _, _ = _date(t, true)
return return
} }
month :: proc(t: Time) -> (month: Month) { month :: proc "contextless" (t: Time) -> (month: Month) {
_, month, _, _ = _date(t, true) _, month, _, _ = _date(t, true)
return return
} }
day :: proc(t: Time) -> (day: int) { day :: proc "contextless" (t: Time) -> (day: int) {
_, _, day, _ = _date(t, true) _, _, day, _ = _date(t, true)
return return
} }
clock :: proc { clock_from_time, clock_from_duration, clock_from_stopwatch } 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)) 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)) 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)) 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) sec = int(nsec % SECONDS_PER_DAY)
hour = sec / SECONDS_PER_HOUR hour = sec / SECONDS_PER_HOUR
sec -= hour * SECONDS_PER_HOUR sec -= hour * SECONDS_PER_HOUR
@@ -193,11 +193,11 @@ clock_from_seconds :: proc(nsec: u64) -> (hour, min, sec: int) {
return return
} }
read_cycle_counter :: proc() -> u64 { read_cycle_counter :: proc "contextless" () -> u64 {
return u64(intrinsics.read_cycle_counter()) 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 sec, nsec := sec, nsec
if nsec < 0 || nsec >= 1e9 { if nsec < 0 || nsec >= 1e9 {
n := nsec / 1e9 n := nsec / 1e9
@@ -208,20 +208,20 @@ unix :: proc(sec: i64, nsec: i64) -> Time {
sec -= 1 sec -= 1
} }
} }
return Time{(sec*1e9 + nsec) + UNIX_TO_INTERNAL} return Time{(sec*1e9 + nsec)}
} }
to_unix_seconds :: time_to_unix 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 return t._nsec/1e9
} }
to_unix_nanoseconds :: time_to_unix_nano 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 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)} 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. // 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 // 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. // 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, estimate, mean, m2, count: Duration
to_sleep = d to_sleep = d
@@ -279,19 +279,19 @@ ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE
@(private) @(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) year, month, day, yday = _abs_date(_time_abs(t), full)
return return
} }
@(private) @(private)
_time_abs :: proc(t: Time) -> u64 { _time_abs :: proc "contextless" (t: Time) -> u64 {
return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE) return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE)
} }
@(private) @(private)
_abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) { _abs_date :: proc "contextless" (abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) {
_is_leap_year :: proc(year: int) -> bool { _is_leap_year :: proc "contextless" (year: int) -> bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0) 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 return
} }
datetime_to_time :: proc(year, month, day, hour, minute, second: int, nsec := int(0)) -> (t: Time, ok: bool) { datetime_to_time :: proc "contextless" (year, month, day, hour, minute, second: int, nsec := int(0)) -> (t: Time, ok: bool) {
divmod :: proc(year: int, divisor: int) -> (div: int, mod: int) { divmod :: proc "contextless" (year: int, divisor: int) -> (div: int, mod: int) {
assert(divisor > 0) if divisor <= 0 {
intrinsics.debug_trap()
}
div = int(year / divisor) div = int(year / divisor)
mod = year % divisor mod = year % divisor
return return
+2
View File
@@ -22,3 +22,5 @@ _tick_now :: proc "contextless" () -> Tick {
return {} return {}
} }
_yield :: proc "contextless" () {
}
+10 -3
View File
@@ -7,9 +7,16 @@ _IS_SUPPORTED :: true
_now :: proc "contextless" () -> Time { _now :: proc "contextless" () -> Time {
file_time: win32.FILETIME file_time: win32.FILETIME
win32.GetSystemTimeAsFileTime(&file_time)
ns := win32.FILETIME_as_unix_nanoseconds(file_time) ns: i64
return Time{_nsec=ns}
// 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) { _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_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_xor (BigInt *dst, BigInt const *x, BigInt const *y);
void big_int_or (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); 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 ignore_microsoft_magic;
bool linker_map_file; bool linker_map_file;
bool use_separate_modules; bool use_separate_modules;
bool threaded_checker; 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; RelocMode reloc_mode;
bool disable_red_zone; bool disable_red_zone;
u32 cmd_doc_flags; u32 cmd_doc_flags;
@@ -326,7 +326,7 @@ struct BuildContext {
BlockingMutex target_features_mutex; BlockingMutex target_features_mutex;
StringSet target_features_set; StringSet target_features_set;
String target_features_string; String target_features_string;
String minimum_os_version_string;
}; };
gb_global BuildContext build_context = {0}; 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)); defer (mutex_unlock(&bc->target_features_mutex));
auto items = split_by_comma(target_feature_list); auto items = split_by_comma(target_feature_list);
array_free(&items);
for_array(i, items) { for_array(i, items) {
String const &item = items.data[i]; String const &item = items.data[i];
if (!check_target_feature_is_valid(pos, item)) { if (!check_target_feature_is_valid(pos, item)) {
error(pos, "Target feature '%.*s' is not valid", LIT(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++] = '"'; if (with_quotes) features[len++] = '"';
String feature = build_context.target_features_set.entries[i].value; 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; len += feature.len;
if (with_quotes) features[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); bool is_defined = check_identifier_exists(c->scope, arg);
gb_unused(is_defined); // gb_unused(is_defined);
operand->type = t_untyped_bool; operand->type = t_untyped_bool;
operand->mode = Addressing_Constant; operand->mode = Addressing_Constant;
operand->value = exact_value_bool(false); operand->value = exact_value_bool(is_defined);
} else if (name == "config") { } else if (name == "config") {
if (ce->args.count != 2) { if (ce->args.count != 2) {
@@ -3651,6 +3651,59 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
operand->mode = Addressing_NoValue; operand->mode = Addressing_NoValue;
break; 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: case BuiltinProc_read_cycle_counter:
operand->mode = Addressing_Value; operand->mode = Addressing_Value;
operand->type = t_i64; operand->type = t_i64;
@@ -3685,8 +3738,92 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
gb_string_free(xts); gb_string_free(xts);
} }
Type *type = default_type(x.type);
operand->mode = Addressing_Value; 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; break;
@@ -4667,6 +4804,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
new_type->Union.variants = variants; new_type->Union.variants = variants;
// NOTE(bill): Is this even correct? // NOTE(bill): Is this even correct?
new_type->Union.node = operand->expr;
new_type->Union.scope = bt->Union.scope; new_type->Union.scope = bt->Union.scope;
operand->type = new_type; 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)) { if (!(e->flags & EntityFlag_Using)) {
continue; 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); bool is_value = (e->flags & EntityFlag_Value) != 0 && !is_type_pointer(e->type);
String name = e->token.string; String name = e->token.string;
Type *t = base_type(type_deref(e->type)); 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)) { if (are_types_identical(src, dst)) {
return 5; return 5;
} }
if (dst->Matrix.row_count == dst->Matrix.column_count) {
Type *dst_elem = base_array_type(dst); Type *dst_elem = base_array_type(dst);
i64 distance = check_distance_between_types(c, operand, dst_elem); i64 distance = check_distance_between_types(c, operand, dst_elem);
if (distance >= 0) { if (distance >= 0) {
return distance + 7; return distance + 7;
}
} }
} }
@@ -2916,7 +2917,12 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
// return false; // 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); gbString expr_str = expr_to_string(o->expr);
error(o->expr, "Cannot transmute untyped expression: '%s'", expr_str); error(o->expr, "Cannot transmute untyped expression: '%s'", expr_str);
gb_string_free(expr_str); gb_string_free(expr_str);
@@ -2925,7 +2931,6 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
return false; return false;
} }
Type *dst_bt = base_type(t);
if (dst_bt == nullptr || dst_bt == t_invalid) { if (dst_bt == nullptr || dst_bt == t_invalid) {
GB_ASSERT(global_error_collector.count != 0); GB_ASSERT(global_error_collector.count != 0);
@@ -2934,21 +2939,21 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
return false; return false;
} }
Type *src_bt = base_type(o->type);
if (src_bt == nullptr || src_bt == t_invalid) { if (src_bt == nullptr || src_bt == t_invalid) {
// NOTE(bill): this should be an error // NOTE(bill): this should be an error
GB_ASSERT(global_error_collector.count != 0); GB_ASSERT(global_error_collector.count != 0);
o->mode = Addressing_Value; o->mode = Addressing_Value;
o->expr = node; o->expr = node;
o->type = t; o->type = dst_t;
return true; 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) { if (srcz != dstz) {
gbString expr_str = expr_to_string(o->expr); 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); 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(type_str);
gb_string_free(expr_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 (build_context.vet_extra) {
if (are_types_identical(o->type, t)) { if (are_types_identical(o->type, dst_t)) {
gbString str = type_to_string(t); gbString str = type_to_string(dst_t);
warning(o->expr, "Unneeded transmute to the same type '%s'", str); warning(o->expr, "Unneeded transmute to the same type '%s'", str);
gb_string_free(str); gb_string_free(str);
} }
} }
o->expr = node; 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->mode = Addressing_Value;
o->type = t;
o->value = {}; o->value = {};
return true; return true;
} }
@@ -6413,7 +6455,9 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
if (e->kind == Entity_TypeName) { if (e->kind == Entity_TypeName) {
if (o->mode != Addressing_Type) { if (o->mode != Addressing_Type) {
if (show_error) { 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; err = CallArgumentError_WrongTypes;
} }
@@ -6456,6 +6500,10 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
// add_type_info_type(c, o->type); // add_type_info_type(c, o->type);
} }
if (show_error && err) {
return err;
}
{ {
bool failure = false; bool failure = false;
Entity *found_entity = find_polymorphic_record_entity(c, original_type, param_count, ordered_operands, &failure); 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' // Returns 'true' for 'continue', 'false' for 'return'
bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, bool is_selector, Entity *e) { bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, bool is_selector, Entity *e) {
if (e == nullptr) { 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; 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) { 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(e != nullptr && d != nullptr);
GB_ASSERT(identifier->Ident.token.string == e->token.string); GB_ASSERT(identifier->Ident.token.string == e->token.string);
+4
View File
@@ -42,6 +42,8 @@ enum BuiltinProcId {
BuiltinProc_unreachable, BuiltinProc_unreachable,
BuiltinProc_raw_data,
BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
// "Intrinsics" // "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("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 {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); 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); ast_node(ut, UnionType, type->Union.node);
if (ut->align) { if (ut->align) {
doc_type.custom_align = odin_doc_expr_string(w, 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; 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) { f64 exact_value_to_f64(ExactValue v) {
v = exact_value_to_float(v); v = exact_value_to_float(v);
if (v.kind == ExactValue_Float) { if (v.kind == ExactValue_Float) {
+44 -19
View File
@@ -537,6 +537,22 @@ namespace lbAbiAmd64SysV {
return false; 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) { lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention) {
if (is_register(type)) { if (is_register(type)) {
LLVMAttributeRef attribute = nullptr; LLVMAttributeRef attribute = nullptr;
@@ -550,16 +566,25 @@ namespace lbAbiAmd64SysV {
if (is_mem_cls(cls, attribute_kind)) { if (is_mem_cls(cls, attribute_kind)) {
LLVMAttributeRef attribute = nullptr; LLVMAttributeRef attribute = nullptr;
if (attribute_kind == Amd64TypeAttribute_ByVal) { 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); return lb_arg_type_indirect_byval(c, type);
} // }
attribute = nullptr; // attribute = nullptr;
} else if (attribute_kind == Amd64TypeAttribute_StructRect) { } else if (attribute_kind == Amd64TypeAttribute_StructRect) {
attribute = lb_create_enum_attribute_with_type(c, "sret", type); attribute = lb_create_enum_attribute_with_type(c, "sret", type);
} }
return lb_arg_type_indirect(type, attribute); return lb_arg_type_indirect(type, attribute);
} else { } 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; return false;
} }
unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef *base_type_, unsigned member_count_) { unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef base_type, unsigned member_count) {
return (member_count_ <= 4); return (member_count <= 4);
} }
lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef type, bool return_is_defined) { 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; unsigned homo_member_count = 0;
if (!return_is_defined) { if (!return_is_defined) {
@@ -996,16 +1021,16 @@ namespace lbAbiArm64 {
} else if (is_register(type)) { } else if (is_register(type)) {
return non_struct(c, type); return non_struct(c, type);
} else if (is_homogenous_aggregate(c, type, &homo_base_type, &homo_member_count)) { } 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)) { 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); return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr);
} else { } else {
//TODO(Platin): do i need to create stuff that can handle the diffrent return type? //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 // 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); //LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count);
LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type); LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type);
return lb_arg_type_indirect(type, attr); return lb_arg_type_indirect(type, attr);
} }
} else { } else {
i64 size = lb_sizeof(type); i64 size = lb_sizeof(type);
if (size <= 16) { 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[2] = key_hash;
args[3] = key_ptr; args[3] = key_ptr;
args[4] = lb_emit_conv(p, value_addr.addr, t_rawptr); 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); 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[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = lb_gen_map_header_table_internal(p, type_deref(map_ptr.type)); 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[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); 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); lbProcedure *startup_runtime = lb_create_startup_runtime(default_module, startup_type_info, objc_names, global_variables);
gb_unused(startup_runtime); 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"); TIME_SECTION("LLVM Global Procedures and Types");
for_array(i, info->entities) { for_array(i, info->entities) {
Entity *e = info->entities[i]; Entity *e = info->entities[i];
@@ -1759,6 +1766,11 @@ void lb_generate_code(lbGenerator *gen) {
case Entity_TypeName: case Entity_TypeName:
case Entity_Procedure: case Entity_Procedure:
break; break;
case Entity_Constant:
if (build_context.ODIN_DEBUG) {
add_debug_info_for_global_constant_from_entity(gen, e);
}
break;
} }
bool polymorphic_struct = false; bool polymorphic_struct = false;
@@ -1820,6 +1832,21 @@ void lb_generate_code(lbGenerator *gen) {
lb_finalize_objc_names(objc_names); lb_finalize_objc_names(objc_names);
if (build_context.ODIN_DEBUG) { 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"); TIME_SECTION("LLVM Debug Info Complete Types and Finalize");
for_array(j, gen->modules.entries) { for_array(j, gen->modules.entries) {
lbModule *m = gen->modules.entries[j].value; lbModule *m = gen->modules.entries[j].value;
+2 -1
View File
@@ -298,6 +298,7 @@ struct lbProcedure {
lbBlock * entry_block; lbBlock * entry_block;
lbBlock * curr_block; lbBlock * curr_block;
lbTargetList * target_list; lbTargetList * target_list;
PtrMap<Entity *, lbValue> direct_parameters;
Ast *curr_stmt; 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); 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); 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); 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); 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; lbModule *m = p->module;
LLVMValueRef fields[4] = {}; LLVMValueRef fields[4] = {};
@@ -271,7 +271,7 @@ lbValue lb_emit_source_code_location(lbProcedure *p, String const &procedure, To
return res; 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 = {}; String proc_name = {};
if (p->entity) { if (p->entity) {
proc_name = p->entity->token.string; proc_name = p->entity->token.string;
@@ -280,9 +280,26 @@ lbValue lb_emit_source_code_location(lbProcedure *p, Ast *node) {
if (node) { if (node) {
pos = ast_token(node).pos; 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) { 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_local = allow_local && m->curr_procedure != nullptr;
bool is_const = true; bool is_const = true;
+114
View File
@@ -293,6 +293,7 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
case Type_Named: case Type_Named:
GB_PANIC("Type_Named should be handled in lb_debug_type separately"); GB_PANIC("Type_Named should be handled in lb_debug_type separately");
case Type_SoaPointer:
case Type_Pointer: case Type_Pointer:
return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), word_bits, word_bits, 0, nullptr, 0); return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), word_bits, word_bits, 0, nullptr, 0);
case Type_MultiPointer: 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); 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; Type *dt = t;
GB_ASSERT(is_type_struct(st) || is_type_raw_union(st)); GB_ASSERT(is_type_struct(st) || is_type_raw_union(st));
String field_name = lookup_subtype_polymorphic_field(t, src_type); Selection sel = {};
if (field_name.len > 0) { sel.index.allocator = heap_allocator();
// NOTE(bill): It can be casted defer (array_free(&sel.index));
Selection sel = lookup_field(st, field_name, false, true); if (lookup_subtype_polymorphic_selection(t, src_type, &sel)) {
if (sel.entity != nullptr) { if (sel.entity == nullptr) {
if (st_is_ptr) { GB_PANIC("invalid subtype cast %s -> ", type_to_string(src_type), type_to_string(t));
lbValue res = lb_emit_deep_field_gep(p, value, sel); }
Type *rt = res.type; if (st_is_ptr) {
if (!are_types_identical(rt, dt) && are_types_identical(type_deref(rt), dt)) { lbValue res = lb_emit_deep_field_gep(p, value, sel);
res = lb_emit_load(p, res); Type *rt = res.type;
} if (!are_types_identical(rt, dt) && are_types_identical(type_deref(rt), dt)) {
return res; res = lb_emit_load(p, 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);
} }
return res;
} else { } 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[1] = size;
args[2] = align; args[2] = align;
args[3] = lb_const_int(p->module, t_int, item_count); 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); 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[2] = align;
args[3] = lb_emit_conv(p, items, t_rawptr); args[3] = lb_emit_conv(p, items, t_rawptr);
args[4] = lb_const_int(p->module, t_int, item_count); 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); lb_emit_runtime_call(p, "__dynamic_array_append", args);
} }
break; break;
+40 -9
View File
@@ -383,16 +383,27 @@ Type *lb_addr_type(lbAddr const &addr) {
if (addr.addr.value == nullptr) { if (addr.addr.value == nullptr) {
return nullptr; return nullptr;
} }
if (addr.kind == lbAddr_Map) { switch (addr.kind) {
Type *t = base_type(addr.map.type); case lbAddr_Map:
GB_ASSERT(is_type_map(t)); {
return t->Map.value; Type *t = base_type(addr.map.type);
} GB_ASSERT(is_type_map(t));
if (addr.kind == lbAddr_Swizzle) { return t->Map.value;
}
case lbAddr_Swizzle:
return addr.swizzle.type; return addr.swizzle.type;
} case lbAddr_SwizzleLarge:
if (addr.kind == lbAddr_SwizzleLarge) {
return addr.swizzle_large.type; 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); 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 ret = nullptr;
LLVMTypeRef *params = gb_alloc_array(permanent_allocator(), LLVMTypeRef, param_count); 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) { if (type->Proc.result_count != 0) {
Type *single_ret = reduce_tuple_to_single_type(type->Proc.results); Type *single_ret = reduce_tuple_to_single_type(type->Proc.results);
ret = lb_type(m, single_ret); 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); Type *e_type = reduce_tuple_to_single_type(e->type);
bool param_is_by_ptr = false;
LLVMTypeRef param_type = nullptr; LLVMTypeRef param_type = nullptr;
if (e->flags & EntityFlag_ByPtr) { 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) && } else if (is_type_boolean(e_type) &&
type_size_of(e_type) <= 1) { type_size_of(e_type) <= 1) {
param_type = LLVMInt1TypeInContext(m->ctx); 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; params[param_index++] = param_type;
} }
} }
@@ -1571,6 +1587,12 @@ LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *type) {
LLVMPrintTypeToString(ft->ret.type), LLVMPrintTypeToString(ft->ret.type),
LLVMGetTypeContext(ft->ret.type), ft->ctx, LLVMGetGlobalContext()); 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); map_set(&m->function_type_map, type, ft);
LLVMTypeRef new_abi_fn_type = lb_function_type_to_llvm_raw(ft, type->Proc.c_vararg); 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) { 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); auto *found = map_get(&m->values, e);
if (found) { if (found) {
auto v = *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); p->entry_block = lb_create_block(p, "entry", true);
lb_start_block(p, p->entry_block); lb_start_block(p, p->entry_block);
map_init(&p->direct_parameters, heap_allocator());
GB_ASSERT(p->type != nullptr); GB_ASSERT(p->type != nullptr);
lb_ensure_abi_function_type(p->module, p); lb_ensure_abi_function_type(p->module, p);
@@ -539,6 +541,8 @@ void lb_begin_procedure_body(lbProcedure *p) {
param.value = value; param.value = value;
param.type = e->type; param.type = e->type;
map_set(&p->direct_parameters, e, param);
lbValue ptr = lb_address_from_load_or_generate_local(p, param); lbValue ptr = lb_address_from_load_or_generate_local(p, param);
GB_ASSERT(LLVMIsAAllocaInst(ptr.value)); GB_ASSERT(LLVMIsAAllocaInst(ptr.value));
lb_add_entity(p->module, e, ptr); 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)); 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); unsigned param_count = LLVMCountParamTypes(fnp);
GB_ASSERT(arg_count >= param_count); GB_ASSERT(arg_count >= param_count);
LLVMTypeRef *param_types = gb_alloc_array(temporary_allocator(), LLVMTypeRef, param_count); LLVMTypeRef *param_types = gb_alloc_array(temporary_allocator(), LLVMTypeRef, param_count);
LLVMGetParamTypes(fnp, param_types); LLVMGetParamTypes(fnp, param_types);
for (unsigned i = 0; i < param_count; i++) { for (unsigned i = 0; i < param_count; i++) {
LLVMTypeRef param_type = param_types[i]; LLVMTypeRef param_type = param_types[i];
LLVMTypeRef arg_type = LLVMTypeOf(args[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, ""); LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, "");
LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex;
if (return_ptr.value != nullptr) { if (return_ptr.value != nullptr) {
param_offset += 1;
LLVMAddCallSiteAttribute(ret, 1, lb_create_enum_attribute_with_type(p->module->ctx, "sret", LLVMTypeOf(args[0]))); 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) { switch (inlining) {
case ProcInlining_none: case ProcInlining_none:
break; 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); 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); lbFunctionType *ft = lb_get_function_type(m, p, pt);
bool return_by_pointer = ft->ret.kind == lbArg_Indirect; 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) { } else if (arg->kind == lbArg_Indirect) {
lbValue ptr = {}; lbValue ptr = {};
if (arg->is_byval) { if (arg->is_byval) {
ptr = lb_copy_value_to_ptr(p, x, original_type, arg->byval_alignment); if (is_odin_cc && are_types_identical(original_type, t_source_code_location)) {
} else if (is_calling_convention_odin(pt->Proc.calling_convention)) { 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 // NOTE(bill): Odin parameters are immutable so the original value can be passed if possible
// i.e. `T const &` in C++ // i.e. `T const &` in C++
ptr = lb_address_from_load_or_generate_local(p, x); 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; 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: { 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); lb_emit_unreachable(p);
return {}; 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" // "Intrinsics"
@@ -2825,7 +2881,7 @@ lbValue lb_handle_param_value(lbProcedure *p, Type *parameter_type, ParameterVal
if (p->entity != nullptr) { if (p->entity != nullptr) {
proc_name = p->entity->token.string; 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: case ParameterValue_Value:
return lb_build_expr(p, param_value.ast_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; 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] = { LLVMValueRef vals[4] = {
lb_const_string(p->module, t->Named.type_name->token.string).value, 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 #if LLVM_VERSION_MAJOR < 11
#error LLVM Version 11+ is required => "brew install llvm@11" #error LLVM Version 11+ is required => "brew install llvm@11"
#endif #endif
#if LLVM_VERSION_MAJOR > 14
#error LLVM Version 11..=14 is required => "brew install llvm@14"
#endif
#endif #endif
#include "query_data.cpp" #include "query_data.cpp"
@@ -478,9 +481,9 @@ i32 linker_stage(lbGenerator *gen) {
if (build_context.metrics.os == TargetOs_darwin) { 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. // 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) if (build_context.minimum_os_version_string.len) {
// make sure to also change the 'mtriple' param passed to 'opt' link_settings = gb_string_append_fmt(link_settings, " -mmacosx-version-min=%.*s ", LIT(build_context.minimum_os_version_string));
if (build_context.metrics.arch == TargetArch_arm64) { } else if (build_context.metrics.arch == TargetArch_arm64) {
link_settings = gb_string_appendc(link_settings, " -mmacosx-version-min=12.0.0 "); link_settings = gb_string_appendc(link_settings, " -mmacosx-version-min=12.0.0 ");
} else { } else {
link_settings = gb_string_appendc(link_settings, " -mmacosx-version-min=10.12.0 "); link_settings = gb_string_appendc(link_settings, " -mmacosx-version-min=10.12.0 ");
@@ -588,7 +591,6 @@ enum BuildFlagKind {
BuildFlag_SingleFile, BuildFlag_SingleFile,
BuildFlag_OutFile, BuildFlag_OutFile,
BuildFlag_OptimizationLevel,
BuildFlag_OptimizationMode, BuildFlag_OptimizationMode,
BuildFlag_ShowTimings, BuildFlag_ShowTimings,
BuildFlag_ShowUnused, BuildFlag_ShowUnused,
@@ -622,6 +624,7 @@ enum BuildFlagKind {
BuildFlag_ExtraAssemblerFlags, BuildFlag_ExtraAssemblerFlags,
BuildFlag_Microarch, BuildFlag_Microarch,
BuildFlag_TargetFeatures, BuildFlag_TargetFeatures,
BuildFlag_MinimumOSVersion,
BuildFlag_RelocMode, BuildFlag_RelocMode,
BuildFlag_DisableRedZone, BuildFlag_DisableRedZone,
@@ -742,13 +745,25 @@ ExactValue build_param_to_exact_value(String name, String param) {
return value; 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) { bool parse_build_flags(Array<String> args) {
auto build_flags = array_make<BuildFlag>(heap_allocator(), 0, BuildFlag_COUNT); 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_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_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_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_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); 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_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_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_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_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); 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; 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 = {}; String param = {};
if (end < flag.len-1) param = substring(flag, 2+end, flag.len); if (end < flag.len-1) param = substring(flag, 2+end, flag.len);
bool is_supported = true; bool is_supported = true;
bool found = false; bool found = false;
BuildFlag found_bf = {}; BuildFlag found_bf = {};
for_array(build_flag_index, build_flags) { for_array(build_flag_index, build_flags) {
BuildFlag bf = build_flags[build_flag_index]; BuildFlag bf = build_flags[build_flag_index];
@@ -979,37 +993,8 @@ bool parse_build_flags(Array<String> args) {
} }
break; 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: { case BuildFlag_OptimizationMode: {
GB_ASSERT(value.kind == ExactValue_String); 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") { if (value.value_string == "minimal") {
build_context.optimization_level = 0; build_context.optimization_level = 0;
} else if (value.value_string == "size") { } 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); string_to_lower(&build_context.target_features_string);
break; break;
} }
case BuildFlag_MinimumOSVersion: {
GB_ASSERT(value.kind == ExactValue_String);
build_context.minimum_os_version_string = value.value_string;
break;
}
case BuildFlag_RelocMode: { case BuildFlag_RelocMode: {
GB_ASSERT(value.kind == ExactValue_String); GB_ASSERT(value.kind == ExactValue_String);
String v = value.value_string; String v = value.value_string;
@@ -1625,7 +1615,7 @@ bool parse_build_flags(Array<String> args) {
gb_printf_err("\n"); gb_printf_err("\n");
bad_flags = true; bad_flags = true;
} else if (!found) { } else if (!found) {
gb_printf_err("Unknown flag: '%.*s'\n", LIT(name)); did_you_mean_flag(name);
bad_flags = true; 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(2, "Example: -out:foo.exe");
print_usage_line(0, ""); 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(1, "-o:<string>");
print_usage_line(2, "Set the optimization mode for compilation"); print_usage_line(2, "Set the optimization mode for compilation");
print_usage_line(2, "Accepted values: minimal, size, speed"); 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(3, "import \"shared:foo\"");
print_usage_line(0, ""); print_usage_line(0, "");
print_usage_line(1, "-define:<name>=<expression>"); print_usage_line(1, "-define:<name>=<value>");
print_usage_line(2, "Defines a global constant with a 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, "Example: -define:SPAM=123");
print_usage_line(2, "To use: #config(SPAM, default_value)"); print_usage_line(2, "To use: #config(SPAM, default_value)");
print_usage_line(0, ""); print_usage_line(0, "");
@@ -2158,6 +2142,12 @@ void print_show_help(String const arg0, String const &command) {
} }
if (run_or_build) { 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(1, "-extra-linker-flags:<string>");
print_usage_line(2, "Adds extra linker specific flags in a string"); print_usage_line(2, "Adds extra linker specific flags in a string");
print_usage_line(0, ""); 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(2, "Adds extra assembler specific flags in a string");
print_usage_line(0, ""); print_usage_line(0, "");
print_usage_line(1, "-microarch:<string>"); 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, "Specifies the specific micro-architecture for the build in a string");
print_usage_line(2, "Examples:"); print_usage_line(2, "Examples:");
+38
View File
@@ -2526,6 +2526,44 @@ String lookup_subtype_polymorphic_field(Type *dst, Type *src) {
return str_lit(""); 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) { Type *strip_type_aliasing(Type *x) {
+12 -6
View File
@@ -1,17 +1,23 @@
@echo off @echo off
if not exist "build\" mkdir build 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 @echo on
..\..\odin build test_issue_829.odin %COMMON% -file ..\..\..\odin test ..\test_issue_829.odin %COMMON% -file
build\test_issue ..\..\..\odin test ..\test_issue_1592.odin %COMMON% -file
..\..\..\odin test ..\test_issue_2087.odin %COMMON% -file
..\..\odin build test_issue_1592.odin %COMMON% -file ..\..\..\odin build ..\test_issue_2113.odin %COMMON% -file -debug
build\test_issue
@echo off @echo off
if %ERRORLEVEL% NEQ 0 set ERROR_DID_OCCUR=1
popd
rmdir /S /Q build rmdir /S /Q build
if %ERROR_DID_OCCUR% NEQ 0 EXIT /B 1
+8 -7
View File
@@ -2,17 +2,18 @@
set -eu set -eu
mkdir -p build mkdir -p build
ODIN=../../odin pushd build
COMMON="-collection:tests=.. -out:build/test_issue" ODIN=../../../odin
COMMON="-collection:tests=../.."
set -x set -x
$ODIN build test_issue_829.odin $COMMON -file $ODIN test ../test_issue_829.odin $COMMON -file
./build/test_issue $ODIN test ../test_issue_1592.odin $COMMON -file
$ODIN test ../test_issue_2087.odin $COMMON -file
$ODIN build test_issue_1592.odin $COMMON -file $ODIN build ../test_issue_2113.odin $COMMON -file -debug
./build/test_issue
set +x set +x
popd
rm -rf build rm -rf build
+146 -177
View File
@@ -3,36 +3,6 @@ package test_issues
import "core:fmt" import "core:fmt"
import "core:testing" 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 */ /* Original issue #1592 example */
@@ -43,7 +13,6 @@ bool_result :: proc() -> bool {
return false return false
} }
@test
test_orig :: proc() { test_orig :: proc() {
if bool_result() || CONSTANT_BOOL { if bool_result() || CONSTANT_BOOL {
} }
@@ -62,428 +31,428 @@ true_result :: proc() -> bool {
@test @test
test_simple_const_false :: proc(t: ^testing.T) { test_simple_const_false :: proc(t: ^testing.T) {
if CONSTANT_FALSE { if CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
if (CONSTANT_FALSE) { if (CONSTANT_FALSE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
if !CONSTANT_FALSE { if !CONSTANT_FALSE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
if (!CONSTANT_FALSE) { if (!CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
if !(CONSTANT_FALSE) { if !(CONSTANT_FALSE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
if !!CONSTANT_FALSE { if !!CONSTANT_FALSE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } 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 { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
} }
@test @test
test_simple_const_true :: proc(t: ^testing.T) { test_simple_const_true :: proc(t: ^testing.T) {
if CONSTANT_TRUE { if CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
if (CONSTANT_TRUE) { if (CONSTANT_TRUE) {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
if !CONSTANT_TRUE { if !CONSTANT_TRUE {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
if (!CONSTANT_TRUE) { if (!CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
if (!CONSTANT_TRUE) { if (!CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
if !(CONSTANT_TRUE) { if !(CONSTANT_TRUE) {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
if !!CONSTANT_TRUE { if !!CONSTANT_TRUE {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else { } 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 { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
} }
@test @test
test_simple_proc_false :: proc(t: ^testing.T) { test_simple_proc_false :: proc(t: ^testing.T) {
if false_result() { if false_result() {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
if !false_result() { if !false_result() {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
} }
@test @test
test_simple_proc_true :: proc(t: ^testing.T) { test_simple_proc_true :: proc(t: ^testing.T) {
if true_result() { if true_result() {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} else { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
if !true_result() { if !true_result() {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} else { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
} }
@test @test
test_const_false_const_false :: proc(t: ^testing.T) { test_const_false_const_false :: proc(t: ^testing.T) {
if CONSTANT_FALSE || CONSTANT_FALSE { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
} }
@test @test
test_const_false_const_true :: proc(t: ^testing.T) { test_const_false_const_true :: proc(t: ^testing.T) {
if CONSTANT_FALSE || CONSTANT_TRUE { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
} }
@test @test
test_const_true_const_false :: proc(t: ^testing.T) { test_const_true_const_false :: proc(t: ^testing.T) {
if CONSTANT_TRUE || CONSTANT_FALSE { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
} }
@test @test
test_const_true_const_true :: proc(t: ^testing.T) { test_const_true_const_true :: proc(t: ^testing.T) {
if CONSTANT_TRUE || CONSTANT_TRUE { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, true, fmt.tprintf("%s: !true\n", #procedure)) testing.expect(t, true, fmt.tprintf("%s: !true\n", #procedure))
} }
} }
@test @test
test_proc_false_const_false :: proc(t: ^testing.T) { test_proc_false_const_false :: proc(t: ^testing.T) {
if false_result() || CONSTANT_FALSE { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
} }
@test @test
test_proc_false_const_true :: proc(t: ^testing.T) { test_proc_false_const_true :: proc(t: ^testing.T) {
if false_result() || CONSTANT_TRUE { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
} }
@test @test
test_proc_true_const_false :: proc(t: ^testing.T) { test_proc_true_const_false :: proc(t: ^testing.T) {
if true_result() || CONSTANT_FALSE { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } else {
tc.expect(t, false, fmt.tprintf("%s: !false\n", #procedure)) testing.expect(t, false, fmt.tprintf("%s: !false\n", #procedure))
} }
} }
@test @test
test_proc_true_const_true :: proc(t: ^testing.T) { test_proc_true_const_true :: proc(t: ^testing.T) {
if true_result() || CONSTANT_TRUE { 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 { } 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 { 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 { } 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) { 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 { } 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) { 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 { } 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:fmt"
import "core:testing" import "core:testing"
import tc "tests:common"
/* Original issue #829 example */ /* Original issue #829 example */
env : map[string]proc(a, b : int) -> int = { env : map[string]proc(a, b : int) -> int = {
"+" = proc(a, b : int) -> int { "+" = proc(a, b : int) -> int {
return a + b return a + b
}, },
} }
test_orig :: proc() { @(test)
fmt.println(env["+"](1, 2))
}
main :: proc() {
t := testing.T{}
test_orig()
test_orig_ret(&t)
tc.report(&t)
}
test_orig_ret :: proc(t: ^testing.T) { test_orig_ret :: proc(t: ^testing.T) {
r := fmt.tprint(env["+"](1, 2)) 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 { ApplicationDelegate :: struct {
willFinishLaunching: proc "c" (self: ^ApplicationDelegate, notification: ^Notification), willFinishLaunching: proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
didFinishLaunching: 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, user_data: rawptr,
} }
@@ -34,9 +34,9 @@ Application_setDelegate :: proc(self: ^Application, delegate: ^ApplicationDelega
del := (^ApplicationDelegate)(self->pointerValue()) del := (^ApplicationDelegate)(self->pointerValue())
del->didFinishLaunching(notification) 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 := (^ApplicationDelegate)(self->pointerValue())
del->shouldTerminateAfterLastWindowClosed(application) return del->shouldTerminateAfterLastWindowClosed(application)
} }
wrapper := Value.valueWithPointer(delegate) 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) { Window_setTitle :: proc(self: ^Window, title: ^NS.String) {
msgSend(nil, self, "setTitle:", title) 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") @(objc_type=Window, objc_name="close")
Window_close :: proc(self: ^Window) { Window_close :: proc(self: ^Window) {
msgSend(nil, self, "close") 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 { foreign Foundation {
objc_lookUpClass :: proc "c" (name: cstring) -> Class --- objc_lookUpClass :: proc "c" (name: cstring) -> Class ---
sel_registerName :: proc "c" (name: cstring) -> SEL --- 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_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, DriverType: DRIVER_TYPE,
Software: HMODULE, Software: HMODULE,
Flags: CREATE_DEVICE_FLAGS, Flags: CREATE_DEVICE_FLAGS,
pFeatureLevels: ^FEATURE_LEVEL, pFeatureLevels: [^]FEATURE_LEVEL,
FeatureLevels: u32, FeatureLevels: u32,
SDKVersion: u32, SDKVersion: u32,
ppDevice: ^^IDevice, ppDevice: ^^IDevice,
@@ -41,8 +41,8 @@ foreign d3d11 {
pAdapter: ^dxgi.IAdapter, pAdapter: ^dxgi.IAdapter,
DriverType: DRIVER_TYPE, DriverType: DRIVER_TYPE,
Software: HMODULE, Software: HMODULE,
Flags: u32, Flags: CREATE_DEVICE_FLAGS,
pFeatureLevels: ^FEATURE_LEVEL, pFeatureLevels: [^]FEATURE_LEVEL,
FeatureLevels: u32, FeatureLevels: u32,
SDKVersion: u32, SDKVersion: u32,
pSwapChainDesc: ^dxgi.SWAP_CHAIN_DESC, pSwapChainDesc: ^dxgi.SWAP_CHAIN_DESC,
@@ -539,25 +539,37 @@ ANISOTROPIC_FILTERING_BIT :: 0x40
SDK_VERSION :: 7 SDK_VERSION :: 7
RETURN_PARAMETER_INDEX :: -1 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, X = 1,
Y = 2, Y = 2,
Z = 4, Z = 4,
W = 8, W = 8,
} }
SHADER_REQUIRES :: enum u32 { // TODO: make bit_set SHADER_REQUIRES_FLAGS :: distinct bit_set[SHADER_REQUIRES_FLAG; u64]
DOUBLES = 0x00000001, SHADER_REQUIRES_FLAG :: enum u64 {
EARLY_DEPTH_STENCIL = 0x00000002, DOUBLES = 0,
UAVS_AT_EVERY_STAGE = 0x00000004, EARLY_DEPTH_STENCIL = 1,
_64_UAVS = 0x00000008, UAVS_AT_EVERY_STAGE = 2,
MINIMUM_PRECISION = 0x00000010, _64_UAVS = 3,
_11_1_DOUBLE_EXTENSIONS = 0x00000020, MINIMUM_PRECISION = 4,
_11_1_SHADER_EXTENSIONS = 0x00000040, _11_1_DOUBLE_EXTENSIONS = 5,
LEVEL_9_COMPARISON_FILTERING = 0x00000080, _11_1_SHADER_EXTENSIONS = 6,
TILED_RESOURCES = 0x00000100, 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 { DRIVER_TYPE :: enum i32 {
UNKNOWN = 0, UNKNOWN = 0,
HARDWARE = 1, HARDWARE = 1,
@@ -708,11 +720,12 @@ SHADER_VARIABLE_CLASS :: enum i32 {
INTERFACE_POINTER = 7, INTERFACE_POINTER = 7,
} }
SHADER_VARIABLE_FLAGS :: enum u32 { // TODO: make bit_set SHADER_VARIABLE_FLAGS :: distinct bit_set[SHADER_VARIABLE_FLAG; u32]
USERPACKED = 0x1, SHADER_VARIABLE_FLAG :: enum u32 {
USED = 0x2, USERPACKED = 0,
INTERFACE_POINTER = 0x4, USED = 1,
INTERFACE_PARAMETER = 0x8, INTERFACE_POINTER = 2,
INTERFACE_PARAMETER = 3,
} }
SHADER_VARIABLE_TYPE :: enum i32 { SHADER_VARIABLE_TYPE :: enum i32 {
@@ -776,14 +789,21 @@ SHADER_VARIABLE_TYPE :: enum i32 {
MIN16UINT = 57, MIN16UINT = 57,
} }
SHADER_INPUT_FLAGS :: enum u32 { // TODO: make bit_set SHADER_INPUT_FLAGS :: distinct bit_set[SHADER_INPUT_FLAG; u32]
USERPACKED = 0x1, SHADER_INPUT_FLAG :: enum u32 {
COMPARISON_SAMPLER = 0x2, USERPACKED = 0,
TEXTURE_COMPONENT_0 = 0x4, COMPARISON_SAMPLER = 1,
TEXTURE_COMPONENT_1 = 0x8, TEXTURE_COMPONENT_0 = 2,
TEXTURE_COMPONENT_1 = 3,
TEXTURE_COMPONENTS = 0xc, 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 { SHADER_INPUT_TYPE :: enum i32 {
CBUFFER = 0, CBUFFER = 0,
@@ -802,8 +822,9 @@ SHADER_INPUT_TYPE :: enum i32 {
UAV_FEEDBACKTEXTURE = 13, UAV_FEEDBACKTEXTURE = 13,
} }
SHADER_CBUFFER_FLAGS :: enum u32 { // TODO: make bit_set SHADER_CBUFFER_FLAGS :: distinct bit_set[SHADER_CBUFFER_FLAG; u32]
USERPACKED = 0x1, SHADER_CBUFFER_FLAG :: enum u32 {
USERPACKED = 0,
} }
CBUFFER_TYPE :: enum i32 { CBUFFER_TYPE :: enum i32 {
@@ -906,10 +927,10 @@ INTERPOLATION_MODE :: enum i32 {
LINEAR_NOPERSPECTIVE_SAMPLE = 7, LINEAR_NOPERSPECTIVE_SAMPLE = 7,
} }
PARAMETER_FLAGS :: enum u32 { // TODO: make bit_set PARAMETER_FLAGS :: distinct bit_set[PARAMETER_FLAG; u32]
NONE = 0x0, PARAMETER_FLAG :: enum u32 {
IN = 0x1, IN = 0,
OUT = 0x2, OUT = 1,
} }
CDEFAULT :: struct { CDEFAULT :: struct {
@@ -1022,43 +1043,46 @@ USAGE :: enum i32 {
STAGING = 3, STAGING = 3,
} }
BIND_FLAG :: enum u32 { // TODO: make bit_set BIND_FLAGS :: distinct bit_set[BIND_FLAG; u32]
VERTEX_BUFFER = 0x1, BIND_FLAG :: enum u32 {
INDEX_BUFFER = 0x2, VERTEX_BUFFER = 0,
CONSTANT_BUFFER = 0x4, INDEX_BUFFER = 1,
SHADER_RESOURCE = 0x8, CONSTANT_BUFFER = 2,
STREAM_OUTPUT = 0x10, SHADER_RESOURCE = 3,
RENDER_TARGET = 0x20, STREAM_OUTPUT = 4,
DEPTH_STENCIL = 0x40, RENDER_TARGET = 5,
UNORDERED_ACCESS = 0x80, DEPTH_STENCIL = 6,
DECODER = 0x200, UNORDERED_ACCESS = 7,
VIDEO_ENCODER = 0x400, DECODER = 9,
VIDEO_ENCODER = 10,
} }
CPU_ACCESS_FLAG :: enum u32 { // TODO: make bit_set CPU_ACCESS_FLAGS :: distinct bit_set[CPU_ACCESS_FLAG; u32]
WRITE = 0x10000, CPU_ACCESS_FLAG :: enum u32 {
READ = 0x20000, WRITE = 16,
READ = 17,
} }
RESOURCE_MISC_FLAG :: enum u32 { // TODO: make bit_set RESOURCE_MISC_FLAGS :: distinct bit_set[RESOURCE_MISC_FLAG; u32]
GENERATE_MIPS = 0x1, RESOURCE_MISC_FLAG :: enum u32 {
SHARED = 0x2, GENERATE_MIPS = 0,
TEXTURECUBE = 0x4, SHARED = 1,
DRAWINDIRECT_ARGS = 0x10, TEXTURECUBE = 2,
BUFFER_ALLOW_RAW_VIEWS = 0x20, DRAWINDIRECT_ARGS = 4,
BUFFER_STRUCTURED = 0x40, BUFFER_ALLOW_RAW_VIEWS = 5,
RESOURCE_CLAMP = 0x80, BUFFER_STRUCTURED = 6,
SHARED_KEYEDMUTEX = 0x100, RESOURCE_CLAMP = 7,
GDI_COMPATIBLE = 0x200, SHARED_KEYEDMUTEX = 8,
SHARED_NTHANDLE = 0x800, GDI_COMPATIBLE = 9,
RESTRICTED_CONTENT = 0x1000, SHARED_NTHANDLE = 11,
RESTRICT_SHARED_RESOURCE = 0x2000, RESTRICTED_CONTENT = 12,
RESTRICT_SHARED_RESOURCE_DRIVER = 0x4000, RESTRICT_SHARED_RESOURCE = 13,
GUARDED = 0x8000, RESTRICT_SHARED_RESOURCE_DRIVER = 14,
TILE_POOL = 0x20000, GUARDED = 15,
TILED = 0x40000, TILE_POOL = 17,
HW_PROTECTED = 0x80000, TILED = 18,
HW_PROTECTED = 19,
} }
MAP :: enum i32 { MAP :: enum i32 {
@@ -1069,17 +1093,20 @@ MAP :: enum i32 {
WRITE_NO_OVERWRITE = 5, WRITE_NO_OVERWRITE = 5,
} }
MAP_FLAG :: enum u32 { // TODO: make bit_set MAP_FLAGS :: distinct bit_set[MAP_FLAG; u32]
DO_NOT_WAIT = 0x100000, MAP_FLAG :: enum u32 {
DO_NOT_WAIT = 20,
} }
RAISE_FLAG :: enum u32 { // TODO: make bit_set RAISE_FLAGS :: distinct bit_set[RAISE_FLAG; u32]
DRIVER_INTERNAL_ERROR = 0x1, RAISE_FLAG :: enum u32 {
DRIVER_INTERNAL_ERROR = 0,
} }
CLEAR_FLAG :: enum u32 { // TODO: make bit_set CLEAR_FLAGS :: distinct bit_set[CLEAR_FLAG; u32]
DEPTH = 0x1, CLEAR_FLAG :: enum u32 {
STENCIL = 0x2, DEPTH = 0,
STENCIL = 1,
} }
@@ -1206,12 +1233,19 @@ BLEND_OP :: enum i32 {
MAX = 5, MAX = 5,
} }
COLOR_WRITE_ENABLE :: enum i32 { // TODO: make bit_set COLOR_WRITE_ENABLE_MASK :: distinct bit_set[COLOR_WRITE_ENABLE; u32]
RED = 1,
GREEN = 2, COLOR_WRITE_ENABLE_RED :: COLOR_WRITE_ENABLE_MASK{.RED}
BLUE = 4, COLOR_WRITE_ENABLE_GREEN :: COLOR_WRITE_ENABLE_MASK{.GREEN}
ALPHA = 8, COLOR_WRITE_ENABLE_BLUE :: COLOR_WRITE_ENABLE_MASK{.BLUE}
ALL = 15, 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 { RENDER_TARGET_BLEND_DESC :: struct {
@@ -1308,9 +1342,9 @@ IResource_VTable :: struct {
BUFFER_DESC :: struct { BUFFER_DESC :: struct {
ByteWidth: u32, ByteWidth: u32,
Usage: USAGE, Usage: USAGE,
BindFlags: BIND_FLAG, BindFlags: BIND_FLAGS,
CPUAccessFlags: CPU_ACCESS_FLAG, CPUAccessFlags: CPU_ACCESS_FLAGS,
MiscFlags: RESOURCE_MISC_FLAG, MiscFlags: RESOURCE_MISC_FLAGS,
StructureByteStride: u32, StructureByteStride: u32,
} }
@@ -1337,9 +1371,9 @@ TEXTURE1D_DESC :: struct {
ArraySize: u32, ArraySize: u32,
Format: dxgi.FORMAT, Format: dxgi.FORMAT,
Usage: USAGE, Usage: USAGE,
BindFlags: BIND_FLAG, BindFlags: BIND_FLAGS,
CPUAccessFlags: CPU_ACCESS_FLAG, CPUAccessFlags: CPU_ACCESS_FLAGS,
MiscFlags: RESOURCE_MISC_FLAG, MiscFlags: RESOURCE_MISC_FLAGS,
} }
CTEXTURE1D_DESC :: struct { CTEXTURE1D_DESC :: struct {
@@ -1367,9 +1401,9 @@ TEXTURE2D_DESC :: struct {
Format: dxgi.FORMAT, Format: dxgi.FORMAT,
SampleDesc: dxgi.SAMPLE_DESC, SampleDesc: dxgi.SAMPLE_DESC,
Usage: USAGE, Usage: USAGE,
BindFlags: BIND_FLAG, BindFlags: BIND_FLAGS,
CPUAccessFlags: CPU_ACCESS_FLAG, CPUAccessFlags: CPU_ACCESS_FLAGS,
MiscFlags: RESOURCE_MISC_FLAG, MiscFlags: RESOURCE_MISC_FLAGS,
} }
CTEXTURE2D_DESC :: struct { CTEXTURE2D_DESC :: struct {
@@ -1396,9 +1430,9 @@ TEXTURE3D_DESC :: struct {
MipLevels: u32, MipLevels: u32,
Format: dxgi.FORMAT, Format: dxgi.FORMAT,
Usage: USAGE, Usage: USAGE,
BindFlags: BIND_FLAG, BindFlags: BIND_FLAGS,
CPUAccessFlags: CPU_ACCESS_FLAG, CPUAccessFlags: CPU_ACCESS_FLAGS,
MiscFlags: RESOURCE_MISC_FLAG, MiscFlags: RESOURCE_MISC_FLAGS,
} }
CTEXTURE3D_DESC :: struct { CTEXTURE3D_DESC :: struct {
@@ -1451,14 +1485,15 @@ BUFFER_SRV :: struct {
}, },
} }
BUFFEREX_SRV_FLAG :: enum u32 { // TODO: make bit_set BUFFEREX_SRV_FLAGS :: distinct bit_set[BUFFEREX_SRV_FLAG; u32]
RAW = 0x1, BUFFEREX_SRV_FLAG :: enum u32 {
RAW = 0,
} }
BUFFEREX_SRV :: struct { BUFFEREX_SRV :: struct {
FirstElement: u32, FirstElement: u32,
NumElements: u32, NumElements: u32,
Flags: u32, Flags: BUFFEREX_SRV_FLAGS,
} }
TEX1D_SRV :: struct { TEX1D_SRV :: struct {
@@ -1657,15 +1692,16 @@ TEX2DMS_ARRAY_DSV :: struct {
ArraySize: u32, ArraySize: u32,
} }
DSV_FLAG :: enum u32 { // TODO: make bit_set DSV_FLAGS :: distinct bit_set[DSV_FLAG; u32]
DEPTH = 0x1, DSV_FLAG :: enum u32 {
STENCIL = 0x2, DEPTH = 0,
STENCIL = 1,
} }
DEPTH_STENCIL_VIEW_DESC :: struct { DEPTH_STENCIL_VIEW_DESC :: struct {
Format: dxgi.FORMAT, Format: dxgi.FORMAT,
ViewDimension: DSV_DIMENSION, ViewDimension: DSV_DIMENSION,
Flags: u32, Flags: DSV_FLAGS,
using _: struct #raw_union { using _: struct #raw_union {
Texture1D: TEX1D_DSV, Texture1D: TEX1D_DSV,
Texture1DArray: TEX1D_ARRAY_DSV, Texture1DArray: TEX1D_ARRAY_DSV,
@@ -1693,16 +1729,17 @@ IDepthStencilView_VTable :: struct {
} }
BUFFER_UAV_FLAG :: enum u32 { // TODO: make bit_set BUFFER_UAV_FLAGS :: distinct bit_set[BUFFER_UAV_FLAG; u32]
RAW = 0x1, BUFFER_UAV_FLAG :: enum u32 {
APPEND = 0x2, RAW = 0,
COUNTER = 0x4, APPEND = 1,
COUNTER = 2,
} }
BUFFER_UAV :: struct { BUFFER_UAV :: struct {
FirstElement: u32, FirstElement: u32,
NumElements: u32, NumElements: u32,
Flags: u32, Flags: BUFFER_UAV_FLAGS,
} }
TEX1D_UAV :: struct { TEX1D_UAV :: struct {
@@ -1961,8 +1998,9 @@ IAsynchronous_VTable :: struct {
} }
ASYNC_GETDATA_FLAG :: enum u32 { // TODO: make bit_set ASYNC_GETDATA_FLAGS :: distinct bit_set[ASYNC_GETDATA_FLAG; u32]
DONOTFLUSH = 0x1, ASYNC_GETDATA_FLAG :: enum u32 {
DONOTFLUSH = 0,
} }
QUERY :: enum i32 { QUERY :: enum i32 {
@@ -1984,13 +2022,14 @@ QUERY :: enum i32 {
SO_OVERFLOW_PREDICATE_STREAM3 = 15, SO_OVERFLOW_PREDICATE_STREAM3 = 15,
} }
QUERY_MISC_FLAG :: enum u32 { // TODO: make bit_set QUERY_MISC_FLAGS :: distinct bit_set[QUERY_MISC_FLAG; u32]
QUERY_MISC_PREDICATEHINT = 0x1, QUERY_MISC_FLAG :: enum u32 {
PREDICATEHINT = 0,
} }
QUERY_DESC :: struct { QUERY_DESC :: struct {
Query: QUERY, Query: QUERY,
MiscFlags: RESOURCE_MISC_FLAG, MiscFlags: QUERY_MISC_FLAGS,
} }
CQUERY_DESC :: struct { CQUERY_DESC :: struct {
@@ -2054,7 +2093,7 @@ COUNTER_TYPE :: enum i32 {
COUNTER_DESC :: struct { COUNTER_DESC :: struct {
Counter: COUNTER, Counter: COUNTER,
MiscFlags: RESOURCE_MISC_FLAG, MiscFlags: RESOURCE_MISC_FLAGS,
} }
CCOUNTER_DESC :: struct { CCOUNTER_DESC :: struct {
@@ -2150,21 +2189,21 @@ FEATURE :: enum i32 {
FORMAT_SUPPORT = 2, FORMAT_SUPPORT = 2,
FORMAT_SUPPORT2 = 3, FORMAT_SUPPORT2 = 3,
D3D10_X_HARDWARE_OPTIONS = 4, D3D10_X_HARDWARE_OPTIONS = 4,
OPTIONS = 5, OPTIONS = 5,
ARCHITECTURE_INFO = 6, ARCHITECTURE_INFO = 6,
D3D9_OPTIONS = 7, D3D9_OPTIONS = 7,
SHADER_MIN_PRECISION_SUPPORT = 8, SHADER_MIN_PRECISION_SUPPORT = 8,
D3D9_SHADOW_SUPPORT = 9, D3D9_SHADOW_SUPPORT = 9,
OPTIONS1 = 10, OPTIONS1 = 10,
D3D9_SIMPLE_INSTANCING_SUPPORT = 11, D3D9_SIMPLE_INSTANCING_SUPPORT = 11,
MARKER_SUPPORT = 12, MARKER_SUPPORT = 12,
D3D9_OPTIONS1 = 13, D3D9_OPTIONS1 = 13,
OPTIONS2 = 14, OPTIONS2 = 14,
OPTIONS3 = 15, OPTIONS3 = 15,
GPU_VIRTUAL_ADDRESS_SUPPORT = 16, GPU_VIRTUAL_ADDRESS_SUPPORT = 16,
OPTIONS4 = 17, OPTIONS4 = 17,
SHADER_CACHE = 18, SHADER_CACHE = 18,
OPTIONS5 = 19, OPTIONS5 = 19,
} }
FEATURE_DATA_THREADING :: struct { FEATURE_DATA_THREADING :: struct {
@@ -2285,14 +2324,14 @@ FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT :: struct {
MaxGPUVirtualAddressBitsPerProcess: u32, MaxGPUVirtualAddressBitsPerProcess: u32,
} }
SHADER_CACHE_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set SHADER_CACHE_SUPPORT_FLAGS :: distinct bit_set[SHADER_CACHE_SUPPORT_FLAG; u32]
NONE = 0x0, SHADER_CACHE_SUPPORT_FLAG :: enum u32 {
AUTOMATIC_INPROC_CACHE = 0x1, AUTOMATIC_INPROC_CACHE = 0,
AUTOMATIC_DISK_CACHE = 0x2, AUTOMATIC_DISK_CACHE = 1,
} }
FEATURE_DATA_SHADER_CACHE :: struct { FEATURE_DATA_SHADER_CACHE :: struct {
SupportFlags: u32, SupportFlags: SHADER_CACHE_SUPPORT_FLAGS,
} }
SHARED_RESOURCE_TIER :: enum i32 { SHARED_RESOURCE_TIER :: enum i32 {
@@ -2322,7 +2361,7 @@ IDeviceContext_VTable :: struct {
VSSetShader: proc "stdcall" (this: ^IDeviceContext, pVertexShader: ^IVertexShader, ppClassInstances: ^^IClassInstance, NumClassInstances: u32), VSSetShader: proc "stdcall" (this: ^IDeviceContext, pVertexShader: ^IVertexShader, ppClassInstances: ^^IClassInstance, NumClassInstances: u32),
DrawIndexed: proc "stdcall" (this: ^IDeviceContext, IndexCount: u32, StartIndexLocation: u32, BaseVertexLocation: i32), DrawIndexed: proc "stdcall" (this: ^IDeviceContext, IndexCount: u32, StartIndexLocation: u32, BaseVertexLocation: i32),
Draw: proc "stdcall" (this: ^IDeviceContext, VertexCount: u32, StartVertexLocation: u32), 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), Unmap: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, Subresource: u32),
PSSetConstantBuffers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumBuffers: u32, ppConstantBuffers: ^^IBuffer), PSSetConstantBuffers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumBuffers: u32, ppConstantBuffers: ^^IBuffer),
IASetInputLayout: proc "stdcall" (this: ^IDeviceContext, pInputLayout: ^IInputLayout), 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), GSSetSamplers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumSamplers: u32, ppSamplers: ^^ISamplerState),
OMSetRenderTargets: proc "stdcall" (this: ^IDeviceContext, NumViews: u32, ppRenderTargetViews: ^^IRenderTargetView, pDepthStencilView: ^IDepthStencilView), 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), 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), OMSetDepthStencilState: proc "stdcall" (this: ^IDeviceContext, pDepthStencilState: ^IDepthStencilState, StencilRef: u32),
SOSetTargets: proc "stdcall" (this: ^IDeviceContext, NumBuffers: u32, ppSOTargets: ^^IBuffer, pOffsets: ^u32), SOSetTargets: proc "stdcall" (this: ^IDeviceContext, NumBuffers: u32, ppSOTargets: ^^IBuffer, pOffsets: ^u32),
DrawAuto: proc "stdcall" (this: ^IDeviceContext), DrawAuto: proc "stdcall" (this: ^IDeviceContext),
@@ -2361,7 +2400,7 @@ IDeviceContext_VTable :: struct {
ClearRenderTargetView: proc "stdcall" (this: ^IDeviceContext, pRenderTargetView: ^IRenderTargetView, ColorRGBA: ^[4]f32), ClearRenderTargetView: proc "stdcall" (this: ^IDeviceContext, pRenderTargetView: ^IRenderTargetView, ColorRGBA: ^[4]f32),
ClearUnorderedAccessViewUint: proc "stdcall" (this: ^IDeviceContext, pUnorderedAccessView: ^IUnorderedAccessView, Values: ^[4]u32), ClearUnorderedAccessViewUint: proc "stdcall" (this: ^IDeviceContext, pUnorderedAccessView: ^IUnorderedAccessView, Values: ^[4]u32),
ClearUnorderedAccessViewFloat: proc "stdcall" (this: ^IDeviceContext, pUnorderedAccessView: ^IUnorderedAccessView, Values: ^[4]f32), 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), GenerateMips: proc "stdcall" (this: ^IDeviceContext, pShaderResourceView: ^IShaderResourceView),
SetResourceMinLOD: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, MinLOD: f32), SetResourceMinLOD: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, MinLOD: f32),
GetResourceMinLOD: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource) -> 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), GSGetSamplers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumSamplers: u32, ppSamplers: ^^ISamplerState),
OMGetRenderTargets: proc "stdcall" (this: ^IDeviceContext, NumViews: u32, ppRenderTargetViews: ^^IRenderTargetView, ppDepthStencilView: ^^IDepthStencilView), 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), 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), OMGetDepthStencilState: proc "stdcall" (this: ^IDeviceContext, ppDepthStencilState: ^^IDepthStencilState, pStencilRef: ^u32),
SOGetTargets: proc "stdcall" (this: ^IDeviceContext, NumBuffers: u32, ppSOTargets: ^^IBuffer), SOGetTargets: proc "stdcall" (this: ^IDeviceContext, NumBuffers: u32, ppSOTargets: ^^IBuffer),
RSGetState: proc "stdcall" (this: ^IDeviceContext, ppRasterizerState: ^^IRasterizerState), RSGetState: proc "stdcall" (this: ^IDeviceContext, ppRasterizerState: ^^IRasterizerState),
@@ -3315,13 +3354,13 @@ IDevice_VTable :: struct {
GetCreationFlags: proc "stdcall" (this: ^IDevice) -> u32, GetCreationFlags: proc "stdcall" (this: ^IDevice) -> u32,
GetDeviceRemovedReason: proc "stdcall" (this: ^IDevice) -> HRESULT, GetDeviceRemovedReason: proc "stdcall" (this: ^IDevice) -> HRESULT,
GetImmediateContext: proc "stdcall" (this: ^IDevice, ppImmediateContext: ^^IDeviceContext), 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, GetExceptionMode: proc "stdcall" (this: ^IDevice) -> u32,
} }
CREATE_DEVICE_FLAGS :: distinct bit_set[CREATE_DEVICE_FLAG; 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, SINGLETHREADED = 0,
DEBUG = 1, DEBUG = 1,
SWITCH_TO_REF = 2, SWITCH_TO_REF = 2,
@@ -3367,14 +3406,14 @@ SHADER_BUFFER_DESC :: struct {
Type: CBUFFER_TYPE, Type: CBUFFER_TYPE,
Variables: u32, Variables: u32,
Size: u32, Size: u32,
uFlags: u32, uFlags: SHADER_CBUFFER_FLAGS,
} }
SHADER_VARIABLE_DESC :: struct { SHADER_VARIABLE_DESC :: struct {
Name: cstring, Name: cstring,
StartOffset: u32, StartOffset: u32,
Size: u32, Size: u32,
uFlags: u32, uFlags: SHADER_VARIABLE_FLAGS,
DefaultValue: rawptr, DefaultValue: rawptr,
StartTexture: u32, StartTexture: u32,
TextureSize: u32, TextureSize: u32,
@@ -3443,7 +3482,7 @@ SHADER_INPUT_BIND_DESC :: struct {
BindPoint: u32, BindPoint: u32,
BindCount: u32, BindCount: u32,
uFlags: u32, uFlags: SHADER_INPUT_FLAGS,
ReturnType: RESOURCE_RETURN_TYPE, ReturnType: RESOURCE_RETURN_TYPE,
Dimension: SRV_DIMENSION, Dimension: SRV_DIMENSION,
NumSamples: u32, NumSamples: u32,
@@ -3485,7 +3524,7 @@ FUNCTION_DESC :: struct {
ConversionInstructionCount: u32, ConversionInstructionCount: u32,
BitwiseInstructionCount: u32, BitwiseInstructionCount: u32,
MinFeatureLevel: FEATURE_LEVEL, MinFeatureLevel: FEATURE_LEVEL,
RequiredFeatureFlags: u64, RequiredFeatureFlags: SHADER_REQUIRES_FLAGS,
Name: cstring, Name: cstring,
FunctionParameterCount: i32, FunctionParameterCount: i32,
@@ -3571,7 +3610,7 @@ IShaderReflection_VTable :: struct {
GetNumInterfaceSlots: proc "stdcall" (this: ^IShaderReflection) -> u32, GetNumInterfaceSlots: proc "stdcall" (this: ^IShaderReflection) -> u32,
GetMinFeatureLevel: proc "stdcall" (this: ^IShaderReflection, pLevel: ^FEATURE_LEVEL) -> HRESULT, GetMinFeatureLevel: proc "stdcall" (this: ^IShaderReflection, pLevel: ^FEATURE_LEVEL) -> HRESULT,
GetThreadGroupSize: proc "stdcall" (this: ^IShaderReflection, pSizeX: ^u32, pSizeY: ^u32, pSizeZ: ^u32) -> u32, 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, using id3d11debug_vtable: ^IDebug_VTable,
} }
RLDO_FLAGS :: enum u32 { // TODO: make bit_set RLDO_FLAGS :: distinct bit_set[RLDO_FLAG; u32]
SUMMARY = 0x1, RLDO_FLAG :: enum u32 {
DETAIL = 0x2, SUMMARY = 0,
IGNORE_INTERNAL = 0x4, DETAIL = 1,
IGNORE_INTERNAL = 2,
} }
DEBUG_FEATURE :: enum u32 { // TODO: make bit_set DEBUG_FEATURES :: distinct bit_set[DEBUG_FEATURE; u32]
FLUSH_PER_RENDER_OP = 0x1, DEBUG_FEATURE :: enum u32 {
FINISH_PER_RENDER_OP = 0x2, FLUSH_PER_RENDER_OP = 0,
FEATURE_PRESENT_PER_RENDER_OP = 0x4, FINISH_PER_RENDER_OP = 1,
FEATURE_PRESENT_PER_RENDER_OP = 2,
} }
IDebug_VTable :: struct { IDebug_VTable :: struct {
using iunkown_vtable: IUnknown_VTable, using iunkown_vtable: IUnknown_VTable,
SetFeatureMask: proc "stdcall" (this: ^IDebug, mask: DEBUG_FEATURE) -> HRESULT, SetFeatureMask: proc "stdcall" (this: ^IDebug, mask: DEBUG_FEATURES) -> HRESULT,
GetFeatureMask: proc "stdcall" (this: ^IDebug) -> DEBUG_FEATURE, GetFeatureMask: proc "stdcall" (this: ^IDebug) -> DEBUG_FEATURES,
SetPresentPerRenderOpDelay: proc "stdcall" (this: ^IDebug, Milliseconds: u32) -> HRESULT, SetPresentPerRenderOpDelay: proc "stdcall" (this: ^IDebug, Milliseconds: u32) -> HRESULT,
GetPresentPerRenderOpDelay: proc "stdcall" (this: ^IDebug) -> u32, GetPresentPerRenderOpDelay: proc "stdcall" (this: ^IDebug) -> u32,
SetSwapChain: proc "stdcall" (this: ^IDebug, pSwapChain: ^dxgi.ISwapChain) -> HRESULT, SetSwapChain: proc "stdcall" (this: ^IDebug, pSwapChain: ^dxgi.ISwapChain) -> HRESULT,
@@ -3667,7 +3708,7 @@ IInfoQueue :: struct #raw_union {
using id3d11infoqueue_vtable: ^IInfoQueue_VTable, using id3d11infoqueue_vtable: ^IInfoQueue_VTable,
} }
MESSAGE_SEVERITY :: enum u32 { // TODO: make bit_set MESSAGE_SEVERITY :: enum u32 {
CORRUPTION = 0, CORRUPTION = 0,
ERROR, ERROR,
WARNING, WARNING,
@@ -3675,7 +3716,7 @@ MESSAGE_SEVERITY :: enum u32 { // TODO: make bit_set
MESSAGE, // Not supported until D3D 11.1 MESSAGE, // Not supported until D3D 11.1
} }
MESSAGE_CATEGORY :: enum u32 { // TODO: make bit_set MESSAGE_CATEGORY :: enum u32 {
APPLICATION_DEFINED = 0, APPLICATION_DEFINED = 0,
MISCELLANEOUS, MISCELLANEOUS,
INITIALIZATION, INITIALIZATION,
@@ -3692,10 +3733,10 @@ MESSAGE_CATEGORY :: enum u32 { // TODO: make bit_set
INFO_QUEUE_FILTER_DESC :: struct { INFO_QUEUE_FILTER_DESC :: struct {
NumCategories: u32, NumCategories: u32,
pCategoryList: ^MESSAGE_CATEGORY, pCategoryList: ^MESSAGE_CATEGORY,
NumSeverities: u32, NumSeverities: u32,
pSeverityList: ^MESSAGE_SEVERITY, pSeverityList: ^MESSAGE_SEVERITY,
NumIDs: u32, NumIDs: u32,
pIDList: ^MESSAGE_ID, pIDList: ^MESSAGE_ID,
} }
@@ -3750,7 +3791,7 @@ IInfoQueue_VTable :: struct {
SetMuteDebugOutput: proc "stdcall" (this: ^IInfoQueue, bMute: BOOL), SetMuteDebugOutput: proc "stdcall" (this: ^IInfoQueue, bMute: BOOL),
} }
MESSAGE_ID :: enum u32 { // TODO: make bit_set MESSAGE_ID :: enum u32 {
UNKNOWN = 0, UNKNOWN = 0,
DEVICE_IASETVERTEXBUFFERS_HAZARD, DEVICE_IASETVERTEXBUFFERS_HAZARD,
DEVICE_IASETINDEXBUFFER_HAZARD, DEVICE_IASETINDEXBUFFER_HAZARD,
+331 -303
View File
@@ -212,11 +212,12 @@ SHADER_VARIABLE_CLASS :: enum i32 {
INTERFACE_POINTER = 7, INTERFACE_POINTER = 7,
} }
SHADER_VARIABLE_FLAGS :: enum u32 { // TODO: make bit_set SHADER_VARIABLE_FLAGS :: distinct bit_set[SHADER_VARIABLE_FLAG; u32]
USERPACKED = 0x1, SHADER_VARIABLE_FLAG :: enum u32 {
USED = 0x2, USERPACKED = 0,
INTERFACE_POINTER = 0x4, USED = 1,
INTERFACE_PARAMETER = 0x8, INTERFACE_POINTER = 2,
INTERFACE_PARAMETER = 3,
} }
SHADER_VARIABLE_TYPE :: enum i32 { SHADER_VARIABLE_TYPE :: enum i32 {
@@ -280,15 +281,16 @@ SHADER_VARIABLE_TYPE :: enum i32 {
MIN16UINT = 57, MIN16UINT = 57,
} }
SHADER_INPUT_FLAGS :: enum u32 { // TODO: make bit_set SHADER_INPUT_FLAGS :: distinct bit_set[SHADER_INPUT_FLAG; u32]
USERPACKED = 0x1, SHADER_INPUT_FLAG :: enum u32 {
COMPARISON_SAMPLER = 0x2, USERPACKED = 0,
TEXTURE_COMPONENT_0 = 0x4, COMPARISON_SAMPLER = 1,
TEXTURE_COMPONENT_1 = 0x8, TEXTURE_COMPONENT_0 = 2,
TEXTURE_COMPONENTS = 0xc, TEXTURE_COMPONENT_1 = 3,
UNUSED = 0x10, UNUSED = 4,
} }
SHADER_INPUT_TYPE :: enum i32 { SHADER_INPUT_TYPE :: enum i32 {
CBUFFER = 0, CBUFFER = 0,
TBUFFER = 1, TBUFFER = 1,
@@ -306,8 +308,9 @@ SHADER_INPUT_TYPE :: enum i32 {
UAV_FEEDBACKTEXTURE = 13, UAV_FEEDBACKTEXTURE = 13,
} }
SHADER_CBUFFER_FLAGS :: enum u32 { // TODO: make bit_set SHADER_CBUFFER_FLAGS :: distinct bit_set[SHADER_CBUFFER_FLAG; u32]
USERPACKED = 0x1, SHADER_CBUFFER_FLAG :: enum u32 {
USERPACKED = 0,
} }
CBUFFER_TYPE :: enum i32 { CBUFFER_TYPE :: enum i32 {
@@ -410,13 +413,12 @@ INTERPOLATION_MODE :: enum i32 {
LINEAR_NOPERSPECTIVE_SAMPLE = 7, LINEAR_NOPERSPECTIVE_SAMPLE = 7,
} }
PARAMETER_FLAGS :: enum u32 { // TODO: make bit_set PARAMETER_FLAGS :: distinct bit_set[PARAMETER_FLAG; u32]
NONE = 0x0, PARAMETER_FLAG :: enum u32 {
IN = 0x1, IN = 0,
OUT = 0x2, OUT = 1,
} }
GPU_VIRTUAL_ADDRESS :: u64 GPU_VIRTUAL_ADDRESS :: u64
COMMAND_LIST_TYPE :: enum i32 { COMMAND_LIST_TYPE :: enum i32 {
@@ -429,9 +431,9 @@ COMMAND_LIST_TYPE :: enum i32 {
VIDEO_ENCODE = 6, VIDEO_ENCODE = 6,
} }
COMMAND_QUEUE_FLAGS :: enum u32 { // TODO: make bit_set COMMAND_QUEUE_FLAGS :: distinct bit_set[COMMAND_QUEUE_FLAG; u32]
NONE = 0x0, COMMAND_QUEUE_FLAG :: enum u32 {
DISABLE_GPU_TIMEOUT = 0x1, DISABLE_GPU_TIMEOUT = 0,
} }
COMMAND_QUEUE_PRIORITY :: enum i32 { COMMAND_QUEUE_PRIORITY :: enum i32 {
@@ -593,12 +595,19 @@ BLEND_OP :: enum i32 {
MAX = 5, MAX = 5,
} }
COLOR_WRITE_ENABLE :: enum i32 { // TODO: make bit_set COLOR_WRITE_ENABLE_MASK :: distinct bit_set[COLOR_WRITE_ENABLE; u32]
RED = 1,
GREEN = 2, COLOR_WRITE_ENABLE_RED :: COLOR_WRITE_ENABLE_MASK{.RED}
BLUE = 4, COLOR_WRITE_ENABLE_GREEN :: COLOR_WRITE_ENABLE_MASK{.GREEN}
ALPHA = 8, COLOR_WRITE_ENABLE_BLUE :: COLOR_WRITE_ENABLE_MASK{.BLUE}
ALL = 15, 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 { LOGIC_OP :: enum i32 {
@@ -721,9 +730,9 @@ CACHED_PIPELINE_STATE :: struct {
CachedBlobSizeInBytes: SIZE_T, CachedBlobSizeInBytes: SIZE_T,
} }
PIPELINE_STATE_FLAGS :: enum u32 { // TODO: make bit_set PIPELINE_STATE_FLAGS :: distinct bit_set[PIPELINE_STATE_FLAG; u32]
NONE = 0x0, PIPELINE_STATE_FLAG :: enum u32 {
TOOL_DEBUG = 0x1, TOOL_DEBUG = 0,
} }
GRAPHICS_PIPELINE_STATE_DESC :: struct { GRAPHICS_PIPELINE_STATE_DESC :: struct {
@@ -853,58 +862,61 @@ CONSERVATIVE_RASTERIZATION_TIER :: enum i32 {
_3 = 3, _3 = 3,
} }
FORMAT_SUPPORT1 :: enum i32 { // TODO: make bit_set FORMAT_SUPPORT1 :: distinct bit_set[FORMAT_SUPPORT1_FLAG; u32]
NONE = 0, FORMAT_SUPPORT1_FLAG :: enum i32 {
BUFFER = 1, BUFFER = 0,
IA_VERTEX_BUFFER = 2, IA_VERTEX_BUFFER = 1,
IA_INDEX_BUFFER = 4, IA_INDEX_BUFFER = 2,
SO_BUFFER = 8, SO_BUFFER = 3,
TEXTURE1D = 16, TEXTURE1D = 4,
TEXTURE2D = 32, TEXTURE2D = 5,
TEXTURE3D = 64, TEXTURE3D = 6,
TEXTURECUBE = 128, TEXTURECUBE = 7,
SHADER_LOAD = 256, SHADER_LOAD = 8,
SHADER_SAMPLE = 512, SHADER_SAMPLE = 9,
SHADER_SAMPLE_COMPARISON = 1024, SHADER_SAMPLE_COMPARISON = 10,
SHADER_SAMPLE_MONO_TEXT = 2048, SHADER_SAMPLE_MONO_TEXT = 11,
MIP = 4096, MIP = 12,
RENDER_TARGET = 16384,
BLENDABLE = 32768, RENDER_TARGET = 14,
DEPTH_STENCIL = 65536, BLENDABLE = 15,
MULTISAMPLE_RESOLVE = 262144, DEPTH_STENCIL = 16,
DISPLAY = 524288,
CAST_WITHIN_BIT_LAYOUT = 1048576, MULTISAMPLE_RESOLVE = 18,
MULTISAMPLE_RENDERTARGET = 2097152, DISPLAY = 19,
MULTISAMPLE_LOAD = 4194304, CAST_WITHIN_BIT_LAYOUT = 20,
SHADER_GATHER = 8388608, MULTISAMPLE_RENDERTARGET = 21,
BACK_BUFFER_CAST = 16777216, MULTISAMPLE_LOAD = 22,
TYPED_UNORDERED_ACCESS_VIEW = 33554432, SHADER_GATHER = 23,
SHADER_GATHER_COMPARISON = 67108864, BACK_BUFFER_CAST = 24,
DECODER_OUTPUT = 134217728, TYPED_UNORDERED_ACCESS_VIEW = 25,
VIDEO_PROCESSOR_OUTPUT = 268435456, SHADER_GATHER_COMPARISON = 26,
VIDEO_PROCESSOR_INPUT = 536870912, DECODER_OUTPUT = 27,
VIDEO_ENCODER = 1073741824, VIDEO_PROCESSOR_OUTPUT = 28,
VIDEO_PROCESSOR_INPUT = 29,
VIDEO_ENCODER = 30,
} }
FORMAT_SUPPORT2 :: enum i32 { // TODO: make bit_set FORMAT_SUPPORT2 :: distinct bit_set[FORMAT_SUPPORT2_FLAG; u32]
NONE = 0, FORMAT_SUPPORT2_FLAG :: enum i32 {
UAV_ATOMIC_ADD = 1, UAV_ATOMIC_ADD = 0,
UAV_ATOMIC_BITWISE_OPS = 2, UAV_ATOMIC_BITWISE_OPS = 1,
UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 4, UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE = 2,
UAV_ATOMIC_EXCHANGE = 8, UAV_ATOMIC_EXCHANGE = 3,
UAV_ATOMIC_SIGNED_MIN_OR_MAX = 16, UAV_ATOMIC_SIGNED_MIN_OR_MAX = 4,
UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 32, UAV_ATOMIC_UNSIGNED_MIN_OR_MAX = 5,
UAV_TYPED_LOAD = 64, UAV_TYPED_LOAD = 6,
UAV_TYPED_STORE = 128, UAV_TYPED_STORE = 7,
OUTPUT_MERGER_LOGIC_OP = 256, OUTPUT_MERGER_LOGIC_OP = 8,
TILED = 512, TILED = 9,
MULTIPLANE_OVERLAY = 16384,
SAMPLER_FEEDBACK = 32768, MULTIPLANE_OVERLAY = 14,
SAMPLER_FEEDBACK = 15,
} }
MULTISAMPLE_QUALITY_LEVEL_FLAGS :: enum u32 { // TODO: make bit_set MULTISAMPLE_QUALITY_LEVEL_FLAGS :: distinct bit_set[MULTISAMPLE_QUALITY_LEVEL_FLAG; u32]
NONE = 0x0, MULTISAMPLE_QUALITY_LEVEL_FLAG :: enum u32 {
TILED_RESOURCE = 0x1, TILED_RESOURCE = 0,
} }
CROSS_NODE_SHARING_TIER :: enum i32 { CROSS_NODE_SHARING_TIER :: enum i32 {
@@ -1034,12 +1046,12 @@ FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT :: struct {
MaxGPUVirtualAddressBitsPerProcess: u32, MaxGPUVirtualAddressBitsPerProcess: u32,
} }
SHADER_CACHE_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set SHADER_CACHE_SUPPORT_FLAGS :: distinct bit_set[SHADER_CACHE_SUPPORT_FLAG; u32]
NONE = 0x0, SHADER_CACHE_SUPPORT_FLAG :: enum u32 {
SINGLE_PSO = 0x1, SINGLE_PSO = 0,
LIBRARY = 0x2, LIBRARY = 1,
AUTOMATIC_INPROC_CACHE = 0x4, AUTOMATIC_INPROC_CACHE = 2,
AUTOMATIC_DISK_CACHE = 0x8, AUTOMATIC_DISK_CACHE = 3,
} }
FEATURE_DATA_SHADER_CACHE :: struct { FEATURE_DATA_SHADER_CACHE :: struct {
@@ -1052,15 +1064,15 @@ FEATURE_DATA_COMMAND_QUEUE_PRIORITY :: struct {
PriorityForTypeIsSupported: BOOL, PriorityForTypeIsSupported: BOOL,
} }
COMMAND_LIST_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set COMMAND_LIST_SUPPORT_FLAGS :: distinct bit_set[COMMAND_LIST_SUPPORT_FLAG; u32]
NONE = 0x0, COMMAND_LIST_SUPPORT_FLAG :: enum u32 {
DIRECT = 0x1, DIRECT = 0,
BUNDLE = 0x2, BUNDLE = 1,
COMPUTE = 0x4, COMPUTE = 2,
COPY = 0x8, COPY = 3,
VIDEO_DECODE = 0x10, VIDEO_DECODE = 4,
VIDEO_PROCESS = 0x20, VIDEO_PROCESS = 5,
VIDEO_ENCODE = 0x40, VIDEO_ENCODE = 6,
} }
FEATURE_DATA_OPTIONS3 :: struct { FEATURE_DATA_OPTIONS3 :: struct {
@@ -1198,25 +1210,26 @@ HEAP_PROPERTIES :: struct {
VisibleNodeMask: u32, VisibleNodeMask: u32,
} }
HEAP_FLAGS :: enum u32 { // TODO: make bit_set ??? HEAP_FLAGS :: distinct bit_set[HEAP_FLAG; u32]
NONE = 0x0, HEAP_FLAG :: enum u32 {
SHARED = 0x1, SHARED = 0,
DENY_BUFFERS = 0x4, DENY_BUFFERS = 2,
ALLOW_DISPLAY = 0x8, ALLOW_DISPLAY = 3,
SHARED_CROSS_ADAPTER = 0x20, SHARED_CROSS_ADAPTER = 5,
DENY_RT_DS_TEXTURES = 0x40, DENY_RT_DS_TEXTURES = 6,
DENY_NON_RT_DS_TEXTURES = 0x80, DENY_NON_RT_DS_TEXTURES = 7,
HARDWARE_PROTECTED = 0x100, HARDWARE_PROTECTED = 8,
ALLOW_WRITE_WATCH = 0x200, ALLOW_WRITE_WATCH = 9,
ALLOW_SHADER_ATOMICS = 0x400, ALLOW_SHADER_ATOMICS = 10,
CREATE_NOT_RESIDENT = 0x800, CREATE_NOT_RESIDENT = 11,
CREATE_NOT_ZEROED = 0x1000, CREATE_NOT_ZEROED = 12,
ALLOW_ALL_BUFFERS_AND_TEXTURES = 0x0,
ALLOW_ONLY_BUFFERS = 0xc0,
ALLOW_ONLY_NON_RT_DS_TEXTURES = 0x44,
ALLOW_ONLY_RT_DS_TEXTURES = 0x84,
} }
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 { HEAP_DESC :: struct {
SizeInBytes: u64, SizeInBytes: u64,
Properties: HEAP_PROPERTIES, Properties: HEAP_PROPERTIES,
@@ -1239,15 +1252,15 @@ TEXTURE_LAYOUT :: enum i32 {
_64KB_STANDARD_SWIZZLE = 3, _64KB_STANDARD_SWIZZLE = 3,
} }
RESOURCE_FLAGS :: enum u32 { // TODO: make bit_set RESOURCE_FLAGS :: distinct bit_set[RESOURCE_FLAG; u32]
NONE = 0x0, RESOURCE_FLAG :: enum u32 {
ALLOW_RENDER_TARGET = 0x1, ALLOW_RENDER_TARGET = 0,
ALLOW_DEPTH_STENCIL = 0x2, ALLOW_DEPTH_STENCIL = 1,
ALLOW_UNORDERED_ACCESS = 0x4, ALLOW_UNORDERED_ACCESS = 2,
DENY_SHADER_RESOURCE = 0x8, DENY_SHADER_RESOURCE = 3,
ALLOW_CROSS_ADAPTER = 0x10, ALLOW_CROSS_ADAPTER = 4,
ALLOW_SIMULTANEOUS_ACCESS = 0x20, ALLOW_SIMULTANEOUS_ACCESS = 5,
VIDEO_DECODE_REFERENCE_ONLY = 0x40, VIDEO_DECODE_REFERENCE_ONLY = 6,
} }
MIP_REGION :: struct { MIP_REGION :: struct {
@@ -1332,11 +1345,11 @@ TILE_REGION_SIZE :: struct {
Depth: u16, Depth: u16,
} }
TILE_RANGE_FLAGS :: enum u32 { // TODO: make bit_set TILE_RANGE_FLAGS :: distinct bit_set[TILE_RANGE_FLAG; u32]
NONE = 0x0, TILE_RANGE_FLAG :: enum u32 {
NULL = 0x1, NULL = 0,
SKIP = 0x2, SKIP = 1,
REUSE_SINGLE_TILE = 0x4, REUSE_SINGLE_TILE = 2,
} }
SUBRESOURCE_TILING :: struct { SUBRESOURCE_TILING :: struct {
@@ -1359,45 +1372,52 @@ PACKED_MIP_INFO :: struct {
StartTileIndexInOverallResource: u32, StartTileIndexInOverallResource: u32,
} }
TILE_MAPPING_FLAGS :: enum u32 { // TODO: make bit_set TILE_MAPPING_FLAGS :: distinct bit_set[TILE_MAPPING_FLAG; u32]
NONE = 0x0, TILE_MAPPING_FLAG :: enum u32 {
NO_HAZARD = 0x1, NO_HAZARD = 0,
} }
TILE_COPY_FLAGS :: enum u32 { // TODO: make bit_set TILE_COPY_FLAGS :: distinct bit_set[TILE_COPY_FLAG; u32]
NONE = 0x0, TILE_COPY_FLAG :: enum u32 {
NO_HAZARD = 0x1, NO_HAZARD = 0,
LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE = 0x2, LINEAR_BUFFER_TO_SWIZZLED_TILED_RESOURCE = 1,
SWIZZLED_TILED_RESOURCE_TO_LINEAR_BUFFER = 0x4, SWIZZLED_TILED_RESOURCE_TO_LINEAR_BUFFER = 2,
} }
RESOURCE_STATES :: enum i32 { // TODO: make bit_set RESOURCE_STATES :: distinct bit_set[RESOURCE_STATE; u32]
COMMON = 0, RESOURCE_STATE :: enum i32 {
VERTEX_AND_CONSTANT_BUFFER = 1, VERTEX_AND_CONSTANT_BUFFER = 0,
INDEX_BUFFER = 2, INDEX_BUFFER = 1,
RENDER_TARGET = 4, RENDER_TARGET = 2,
UNORDERED_ACCESS = 8, UNORDERED_ACCESS = 3,
DEPTH_WRITE = 16, DEPTH_WRITE = 4,
DEPTH_READ = 32, DEPTH_READ = 5,
NON_PIXEL_SHADER_RESOURCE = 64, NON_PIXEL_SHADER_RESOURCE = 6,
PIXEL_SHADER_RESOURCE = 128, PIXEL_SHADER_RESOURCE = 7,
STREAM_OUT = 256, STREAM_OUT = 8,
INDIRECT_ARGUMENT = 512, INDIRECT_ARGUMENT = 9,
COPY_DEST = 1024, COPY_DEST = 10,
COPY_SOURCE = 2048, COPY_SOURCE = 11,
RESOLVE_DEST = 4096, RESOLVE_DEST = 12,
RESOLVE_SOURCE = 8192, RESOLVE_SOURCE = 13,
RAYTRACING_ACCELERATION_STRUCTURE = 4194304, RAYTRACING_ACCELERATION_STRUCTURE = 22,
SHADING_RATE_SOURCE = 16777216, SHADING_RATE_SOURCE = 24,
GENERIC_READ = 2755, PREDICATION = 9,
PRESENT = 0, VIDEO_DECODE_READ = 16,
PREDICATION = 512, VIDEO_DECODE_WRITE = 17,
VIDEO_DECODE_READ = 65536, VIDEO_PROCESS_READ = 18,
VIDEO_DECODE_WRITE = 131072, VIDEO_PROCESS_WRITE = 19,
VIDEO_PROCESS_READ = 262144, VIDEO_ENCODE_READ = 21,
VIDEO_PROCESS_WRITE = 524288, VIDEO_ENCODE_WRITE = 23,
VIDEO_ENCODE_READ = 2097152, }
VIDEO_ENCODE_WRITE = 8388608,
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 { RESOURCE_BARRIER_TYPE :: enum i32 {
@@ -1422,10 +1442,10 @@ RESOURCE_UAV_BARRIER :: struct {
pResource: ^IResource, pResource: ^IResource,
} }
RESOURCE_BARRIER_FLAGS :: enum u32 { // TODO: make bit_set RESOURCE_BARRIER_FLAGS :: distinct bit_set[RESOURCE_BARRIER_FLAG; u32]
NONE = 0x0, RESOURCE_BARRIER_FLAG :: enum u32 {
BEGIN_ONLY = 0x1, BEGIN_ONLY = 0,
END_ONLY = 0x2, END_ONLY = 1,
} }
RESOURCE_BARRIER :: struct { RESOURCE_BARRIER :: struct {
@@ -1484,9 +1504,9 @@ VIEW_INSTANCE_LOCATION :: struct {
RenderTargetArrayIndex: u32, RenderTargetArrayIndex: u32,
} }
VIEW_INSTANCING_FLAGS :: enum u32 { // TODO: make bit_set VIEW_INSTANCING_FLAGS :: distinct bit_set[VIEW_INSTANCING_FLAG; u32]
NONE = 0x0, VIEW_INSTANCING_FLAG :: enum u32 {
ENABLE_VIEW_INSTANCE_MASKING = 0x1, ENABLE_VIEW_INSTANCE_MASKING = 0,
} }
VIEW_INSTANCING_DESC :: struct { VIEW_INSTANCING_DESC :: struct {
@@ -1504,9 +1524,9 @@ SHADER_COMPONENT_MAPPING :: enum i32 {
FORCE_VALUE_1 = 5, FORCE_VALUE_1 = 5,
} }
BUFFER_SRV_FLAGS :: enum u32 { // TODO: make bit_set BUFFER_SRV_FLAGS :: distinct bit_set[BUFFER_SRV_FLAG; u32]
NONE = 0x0, BUFFER_SRV_FLAG :: enum u32 {
RAW = 0x1, RAW = 0,
} }
BUFFER_SRV :: struct { BUFFER_SRV :: struct {
@@ -1675,9 +1695,9 @@ SAMPLER_DESC :: struct {
MaxLOD: f32, MaxLOD: f32,
} }
BUFFER_UAV_FLAGS :: enum u32 { // TODO: make bit_set BUFFER_UAV_FLAGS :: distinct bit_set[BUFFER_UAV_FLAG; u32]
NONE = 0x0, BUFFER_UAV_FLAG :: enum u32 {
RAW = 0x1, RAW = 0,
} }
BUFFER_UAV :: struct { BUFFER_UAV :: struct {
@@ -1837,10 +1857,10 @@ TEX2DMS_ARRAY_DSV :: struct {
ArraySize: u32, ArraySize: u32,
} }
DSV_FLAGS :: enum u32 { // TODO: make bit_set DSV_FLAGS :: distinct bit_set[DSV_FLAG; u32]
NONE = 0x0, DSV_FLAG :: enum u32 {
READ_ONLY_DEPTH = 0x1, READ_ONLY_DEPTH = 0,
READ_ONLY_STENCIL = 0x2, READ_ONLY_STENCIL = 1,
} }
DSV_DIMENSION :: enum i32 { DSV_DIMENSION :: enum i32 {
@@ -1867,16 +1887,17 @@ DEPTH_STENCIL_VIEW_DESC :: struct {
}, },
} }
CLEAR_FLAGS :: enum u32 { // TODO: make bit_set CLEAR_FLAGS :: distinct bit_set[CLEAR_FLAG; u32]
DEPTH = 0x1, CLEAR_FLAG :: enum u32 {
STENCIL = 0x2, DEPTH = 0,
STENCIL = 1,
} }
FENCE_FLAGS :: enum u32 { // TODO: make bit_set FENCE_FLAGS :: distinct bit_set[FENCE_FLAG; u32]
NONE = 0x0, FENCE_FLAG :: enum u32 {
SHARED = 0x1, SHARED = 0,
SHARED_CROSS_ADAPTER = 0x2, SHARED_CROSS_ADAPTER = 1,
NON_MONITORED = 0x4, NON_MONITORED = 2,
} }
DESCRIPTOR_HEAP_TYPE :: enum i32 { DESCRIPTOR_HEAP_TYPE :: enum i32 {
@@ -1887,9 +1908,9 @@ DESCRIPTOR_HEAP_TYPE :: enum i32 {
NUM_TYPES = 4, NUM_TYPES = 4,
} }
DESCRIPTOR_HEAP_FLAGS :: enum u32 { // TODO: make bit_set DESCRIPTOR_HEAP_FLAGS :: distinct bit_set[DESCRIPTOR_HEAP_FLAG; u32]
NONE = 0x0, DESCRIPTOR_HEAP_FLAG :: enum u32 {
SHADER_VISIBLE = 0x1, SHADER_VISIBLE = 0,
} }
DESCRIPTOR_HEAP_DESC :: struct { DESCRIPTOR_HEAP_DESC :: struct {
@@ -1959,18 +1980,18 @@ ROOT_PARAMETER :: struct {
ShaderVisibility: SHADER_VISIBILITY, ShaderVisibility: SHADER_VISIBILITY,
} }
ROOT_SIGNATURE_FLAGS :: enum u32 { // TODO: make bit_set ROOT_SIGNATURE_FLAGS :: distinct bit_set[ROOT_SIGNATURE_FLAG; u32]
NONE = 0x0, ROOT_SIGNATURE_FLAG :: enum u32 {
ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0x1, ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0,
DENY_VERTEX_SHADER_ROOT_ACCESS = 0x2, DENY_VERTEX_SHADER_ROOT_ACCESS = 1,
DENY_HULL_SHADER_ROOT_ACCESS = 0x4, DENY_HULL_SHADER_ROOT_ACCESS = 2,
DENY_DOMAIN_SHADER_ROOT_ACCESS = 0x8, DENY_DOMAIN_SHADER_ROOT_ACCESS = 3,
DENY_GEOMETRY_SHADER_ROOT_ACCESS = 0x10, DENY_GEOMETRY_SHADER_ROOT_ACCESS = 4,
DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20, DENY_PIXEL_SHADER_ROOT_ACCESS = 5,
ALLOW_STREAM_OUTPUT = 0x40, ALLOW_STREAM_OUTPUT = 6,
LOCAL_ROOT_SIGNATURE = 0x80, LOCAL_ROOT_SIGNATURE = 7,
DENY_AMPLIFICATION_SHADER_ROOT_ACCESS = 0x100, DENY_AMPLIFICATION_SHADER_ROOT_ACCESS = 8,
DENY_MESH_SHADER_ROOT_ACCESS = 0x200, DENY_MESH_SHADER_ROOT_ACCESS = 9,
} }
STATIC_BORDER_COLOR :: enum i32 { STATIC_BORDER_COLOR :: enum i32 {
@@ -2003,13 +2024,13 @@ ROOT_SIGNATURE_DESC :: struct {
Flags: ROOT_SIGNATURE_FLAGS, Flags: ROOT_SIGNATURE_FLAGS,
} }
DESCRIPTOR_RANGE_FLAGS :: enum u32 { // TODO: make bit_set DESCRIPTOR_RANGE_FLAGS :: distinct bit_set[DESCRIPTOR_RANGE_FLAG; u32]
NONE = 0x0, DESCRIPTOR_RANGE_FLAG :: enum u32 {
DESCRIPTORS_VOLATILE = 0x1, DESCRIPTORS_VOLATILE = 0,
DATA_VOLATILE = 0x2, DATA_VOLATILE = 1,
DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4, DATA_STATIC_WHILE_SET_AT_EXECUTE = 2,
DATA_STATIC = 0x8, DATA_STATIC = 3,
DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x10000, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 16,
} }
DESCRIPTOR_RANGE1 :: struct { DESCRIPTOR_RANGE1 :: struct {
@@ -2026,11 +2047,11 @@ ROOT_DESCRIPTOR_TABLE1 :: struct {
pDescriptorRanges: ^DESCRIPTOR_RANGE1, pDescriptorRanges: ^DESCRIPTOR_RANGE1,
} }
ROOT_DESCRIPTOR_FLAGS :: enum u32 { // TODO: make bit_set ROOT_DESCRIPTOR_FLAGS :: distinct bit_set[ROOT_DESCRIPTOR_FLAG; u32]
NONE = 0x0, ROOT_DESCRIPTOR_FLAG :: enum u32 {
DATA_VOLATILE = 0x2, DATA_VOLATILE = 2,
DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4, DATA_STATIC_WHILE_SET_AT_EXECUTE = 3,
DATA_STATIC = 0x8, DATA_STATIC = 4,
} }
ROOT_DESCRIPTOR1 :: struct { 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, 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 MULTIPLE_FENCE_WAIT_FLAGS :: distinct bit_set[MULTIPLE_FENCE_WAIT_FLAG; u32]
NONE = 0x0, MULTIPLE_FENCE_WAIT_FLAG :: enum u32 {
ANY = 0x1, ANY = 0,
ALL = 0x0,
} }
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 { RESIDENCY_PRIORITY :: enum i32 {
MINIMUM = 671088640, MINIMUM = 671088640,
@@ -2611,9 +2634,9 @@ IDevice2_VTable :: struct {
CreatePipelineState: proc "stdcall" (this: ^IDevice2, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, CreatePipelineState: proc "stdcall" (this: ^IDevice2, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT,
} }
RESIDENCY_FLAGS :: enum u32 { // TODO: make bit_set RESIDENCY_FLAGS :: distinct bit_set[RESIDENCY_FLAG; u32]
NONE = 0x0, RESIDENCY_FLAG :: enum u32 {
DENY_OVERBUDGET = 0x1, 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, 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_FLAGS :: distinct bit_set[COMMAND_LIST_FLAG; u32]
COMMAND_LIST_FLAG_NONE = 0x0, COMMAND_LIST_FLAG :: enum u32 {
} }
COMMAND_POOL_FLAGS :: enum u32 { // TODO: make bit_set COMMAND_POOL_FLAGS :: distinct bit_set[COMMAND_POOL_FLAG; u32]
COMMAND_POOL_FLAG_NONE = 0x0, COMMAND_POOL_FLAG :: enum u32 {
} }
COMMAND_RECORDER_FLAGS :: enum u32 { // TODO: make bit_set COMMAND_RECORDER_FLAGS :: distinct bit_set[COMMAND_RECORDER_FLAG; u32]
COMMAND_RECORDER_FLAG_NONE = 0x0, COMMAND_RECORDER_FLAG :: enum u32 {
} }
PROTECTED_SESSION_STATUS :: enum i32 { PROTECTED_SESSION_STATUS :: enum i32 {
@@ -2660,9 +2683,9 @@ IProtectedSession_VTable :: struct {
GetSessionStatus: proc "stdcall" (this: ^IProtectedSession) -> PROTECTED_SESSION_STATUS, GetSessionStatus: proc "stdcall" (this: ^IProtectedSession) -> PROTECTED_SESSION_STATUS,
} }
PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS :: distinct bit_set[PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG; u32]
NONE = 0x0, PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG :: enum u32 {
SUPPORTED = 0x1, SUPPORTED = 0,
} }
FEATURE_DATA_PROTECTED_RESOURCE_SESSION_SUPPORT :: struct { FEATURE_DATA_PROTECTED_RESOURCE_SESSION_SUPPORT :: struct {
@@ -2670,8 +2693,8 @@ FEATURE_DATA_PROTECTED_RESOURCE_SESSION_SUPPORT :: struct {
Support: PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS, Support: PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS,
} }
PROTECTED_RESOURCE_SESSION_FLAGS :: enum u32 { // TODO: make bit_set PROTECTED_RESOURCE_SESSION_FLAGS :: distinct bit_set[PROTECTED_RESOURCE_SESSION_FLAG; u32]
PROTECTED_RESOURCE_SESSION_FLAG_NONE = 0x0, PROTECTED_RESOURCE_SESSION_FLAG :: enum u32 {
} }
PROTECTED_RESOURCE_SESSION_DESC :: struct { PROTECTED_RESOURCE_SESSION_DESC :: struct {
@@ -2760,9 +2783,10 @@ META_COMMAND_PARAMETER_TYPE :: enum i32 {
GPU_DESCRIPTOR_HANDLE_HEAP_TYPE_CBV_SRV_UAV = 4, GPU_DESCRIPTOR_HANDLE_HEAP_TYPE_CBV_SRV_UAV = 4,
} }
META_COMMAND_PARAMETER_FLAGS :: enum u32 { // TODO: make bit_set META_COMMAND_PARAMETER_FLAGS :: distinct bit_set[META_COMMAND_PARAMETER_FLAG; u32]
INPUT = 0x1, META_COMMAND_PARAMETER_FLAG :: enum u32 {
OUTPUT = 0x2, INPUT = 0,
OUTPUT = 1,
} }
META_COMMAND_PARAMETER_STAGE :: enum i32 { META_COMMAND_PARAMETER_STAGE :: enum i32 {
@@ -2850,11 +2874,11 @@ STATE_SUBOBJECT :: struct {
pDesc: rawptr, pDesc: rawptr,
} }
STATE_OBJECT_FLAGS :: enum u32 { // TODO: make bit_set STATE_OBJECT_FLAGS :: distinct bit_set[STATE_OBJECT_FLAG; u32]
NONE = 0x0, STATE_OBJECT_FLAG :: enum u32 {
ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITIONS = 0x1, ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITIONS = 0,
ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS = 0x2, ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS = 1,
ALLOW_STATE_OBJECT_ADDITIONS = 0x4, ALLOW_STATE_OBJECT_ADDITIONS = 2,
} }
STATE_OBJECT_CONFIG :: struct { STATE_OBJECT_CONFIG :: struct {
@@ -2873,8 +2897,8 @@ NODE_MASK :: struct {
NodeMask: u32, NodeMask: u32,
} }
EXPORT_FLAGS :: enum u32 { // TODO: make bit_set EXPORT_FLAGS :: distinct bit_set[EXPORT_FLAG; u32]
EXPORT_FLAG_NONE = 0x0, EXPORT_FLAG :: enum u32 {
} }
EXPORT_DESC :: struct { EXPORT_DESC :: struct {
@@ -2929,10 +2953,10 @@ RAYTRACING_PIPELINE_CONFIG :: struct {
MaxTraceRecursionDepth: u32, MaxTraceRecursionDepth: u32,
} }
RAYTRACING_PIPELINE_FLAGS :: enum u32 { // TODO: make bit_set RAYTRACING_PIPELINE_FLAGS :: distinct bit_set[RAYTRACING_PIPELINE_FLAG; u32]
NONE = 0x0, RAYTRACING_PIPELINE_FLAG :: enum u32 {
SKIP_TRIANGLES = 0x100, SKIP_TRIANGLES = 8,
SKIP_PROCEDURAL_PRIMITIVES = 0x200, SKIP_PROCEDURAL_PRIMITIVES = 9,
} }
RAYTRACING_PIPELINE_CONFIG1 :: struct { RAYTRACING_PIPELINE_CONFIG1 :: struct {
@@ -2951,10 +2975,10 @@ STATE_OBJECT_DESC :: struct {
pSubobjects: ^STATE_SUBOBJECT, pSubobjects: ^STATE_SUBOBJECT,
} }
RAYTRACING_GEOMETRY_FLAGS :: enum u32 { // TODO: make bit_set RAYTRACING_GEOMETRY_FLAGS :: distinct bit_set[RAYTRACING_GEOMETRY_FLAG; u32]
NONE = 0x0, RAYTRACING_GEOMETRY_FLAG :: enum u32 {
OPAQUE = 0x1, OPAQUE = 0,
NO_DUPLICATE_ANYHIT_INVOCATION = 0x2, NO_DUPLICATE_ANYHIT_INVOCATION = 1,
} }
RAYTRACING_GEOMETRY_TYPE :: enum i32 { RAYTRACING_GEOMETRY_TYPE :: enum i32 {
@@ -2962,12 +2986,12 @@ RAYTRACING_GEOMETRY_TYPE :: enum i32 {
PROCEDURAL_PRIMITIVE_AABBS = 1, PROCEDURAL_PRIMITIVE_AABBS = 1,
} }
RAYTRACING_INSTANCE_FLAGS :: enum u32 { // TODO: make bit_set RAYTRACING_INSTANCE_FLAGS :: distinct bit_set[RAYTRACING_INSTANCE_FLAG; u32]
NONE = 0x0, RAYTRACING_INSTANCE_FLAG :: enum u32 {
TRIANGLE_CULL_DISABLE = 0x1, TRIANGLE_CULL_DISABLE = 0,
TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x2, TRIANGLE_FRONT_COUNTERCLOCKWISE = 1,
FORCE_OPAQUE = 0x4, FORCE_OPAQUE = 2,
FORCE_NON_OPAQUE = 0x8, FORCE_NON_OPAQUE = 3,
} }
GPU_VIRTUAL_ADDRESS_AND_STRIDE :: struct { GPU_VIRTUAL_ADDRESS_AND_STRIDE :: struct {
@@ -3010,14 +3034,14 @@ RAYTRACING_GEOMETRY_AABBS_DESC :: struct {
AABBs: GPU_VIRTUAL_ADDRESS_AND_STRIDE, AABBs: GPU_VIRTUAL_ADDRESS_AND_STRIDE,
} }
RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS :: enum u32 { // TODO: make bit_set RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS :: distinct bit_set[RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG; u32]
NONE = 0x0, RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG :: enum u32 {
ALLOW_UPDATE = 0x1, ALLOW_UPDATE = 0,
ALLOW_COMPACTION = 0x2, ALLOW_COMPACTION = 1,
PREFER_FAST_TRACE = 0x4, PREFER_FAST_TRACE = 2,
PREFER_FAST_BUILD = 0x8, PREFER_FAST_BUILD = 3,
MINIMIZE_MEMORY = 0x10, MINIMIZE_MEMORY = 4,
PERFORM_UPDATE = 0x20, PERFORM_UPDATE = 5,
} }
RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE :: enum i32 { RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE :: enum i32 {
@@ -3137,18 +3161,18 @@ RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO :: struct {
UpdateScratchDataSizeInBytes: u64, UpdateScratchDataSizeInBytes: u64,
} }
RAY_FLAGS :: enum u32 { // TODO: make bit_set RAY_FLAGS :: distinct bit_set[RAY_FLAG; u32]
NONE = 0x0, RAY_FLAG :: enum u32 {
FORCE_OPAQUE = 0x1, FORCE_OPAQUE = 0,
FORCE_NON_OPAQUE = 0x2, FORCE_NON_OPAQUE = 1,
ACCEPT_FIRST_HIT_AND_END_SEARCH = 0x4, ACCEPT_FIRST_HIT_AND_END_SEARCH = 2,
SKIP_CLOSEST_HIT_SHADER = 0x8, SKIP_CLOSEST_HIT_SHADER = 3,
CULL_BACK_FACING_TRIANGLES = 0x10, CULL_BACK_FACING_TRIANGLES = 4,
CULL_FRONT_FACING_TRIANGLES = 0x20, CULL_FRONT_FACING_TRIANGLES = 5,
CULL_OPAQUE = 0x40, CULL_OPAQUE = 6,
CULL_NON_OPAQUE = 0x80, CULL_NON_OPAQUE = 7,
SKIP_TRIANGLES = 0x100, SKIP_TRIANGLES = 8,
SKIP_PROCEDURAL_PRIMITIVES = 0x200, SKIP_PROCEDURAL_PRIMITIVES = 9,
} }
HIT_KIND :: enum i32 { HIT_KIND :: enum i32 {
@@ -3260,10 +3284,10 @@ DRED_VERSION :: enum i32 {
_1_2 = 3, _1_2 = 3,
} }
DRED_FLAGS :: enum u32 { // TODO: make bit_set DRED_FLAGS :: distinct bit_set[DRED_FLAG; u32]
NONE = 0x0, DRED_FLAG :: enum u32 {
FORCE_ENABLE = 0x1, FORCE_ENABLE = 0,
DISABLE_AUTOBREADCRUMBS = 0x2, DISABLE_AUTOBREADCRUMBS = 1,
} }
DRED_ENABLEMENT :: enum i32 { DRED_ENABLEMENT :: enum i32 {
@@ -3611,11 +3635,11 @@ RENDER_PASS_DEPTH_STENCIL_DESC :: struct {
StencilEndingAccess: RENDER_PASS_ENDING_ACCESS, StencilEndingAccess: RENDER_PASS_ENDING_ACCESS,
} }
RENDER_PASS_FLAGS :: enum u32 { // TODO: make bit_set RENDER_PASS_FLAGS :: distinct bit_set[RENDER_PASS_FLAG; u32]
NONE = 0x0, RENDER_PASS_FLAG :: enum u32 {
ALLOW_UAV_WRITES = 0x1, ALLOW_UAV_WRITES = 0,
SUSPENDING_PASS = 0x2, SUSPENDING_PASS = 1,
RESUMING_PASS = 0x4, RESUMING_PASS = 2,
} }
@@ -3697,9 +3721,9 @@ IDebug_VTable :: struct {
EnableDebugLayer: proc "stdcall" (this: ^IDebug), EnableDebugLayer: proc "stdcall" (this: ^IDebug),
} }
GPU_BASED_VALIDATION_FLAGS :: enum u32 { // TODO: make bit_set GPU_BASED_VALIDATION_FLAGS :: distinct bit_set[GPU_BASED_VALIDATION_FLAG; u32]
NONE = 0x0, GPU_BASED_VALIDATION_FLAG :: enum u32 {
DISABLE_STATE_TRACKING = 0x1, DISABLE_STATE_TRACKING = 0,
} }
@@ -3741,11 +3765,11 @@ IDebug3_VTable :: struct {
SetGPUBasedValidationFlags: proc "stdcall" (this: ^IDebug3, Flags: GPU_BASED_VALIDATION_FLAGS), SetGPUBasedValidationFlags: proc "stdcall" (this: ^IDebug3, Flags: GPU_BASED_VALIDATION_FLAGS),
} }
RLDO_FLAGS :: enum u32 { // TODO: make bit_set RLDO_FLAGS :: distinct bit_set[RLDO_FLAG; u32]
NONE = 0x0, RLDO_FLAG :: enum u32 {
SUMMARY = 0x1, SUMMARY = 0,
DETAIL = 0x2, DETAIL = 1,
IGNORE_INTERNAL = 0x4, IGNORE_INTERNAL = 2,
} }
DEBUG_DEVICE_PARAMETER_TYPE :: enum i32 { DEBUG_DEVICE_PARAMETER_TYPE :: enum i32 {
@@ -3754,12 +3778,12 @@ DEBUG_DEVICE_PARAMETER_TYPE :: enum i32 {
GPU_SLOWDOWN_PERFORMANCE_FACTOR = 2, GPU_SLOWDOWN_PERFORMANCE_FACTOR = 2,
} }
DEBUG_FEATURE :: enum i32 { // TODO: make bit_set DEBUG_FEATURE :: distinct bit_set[DEBUG_FEATURE_FLAG; u32]
NONE = 0, DEBUG_FEATURE_FLAG :: enum i32 {
ALLOW_BEHAVIOR_CHANGING_DEBUG_AIDS = 1, ALLOW_BEHAVIOR_CHANGING_DEBUG_AIDS = 0,
CONSERVATIVE_RESOURCE_STATE_TRACKING = 2, CONSERVATIVE_RESOURCE_STATE_TRACKING = 1,
DISABLE_VIRTUALIZED_BUNDLES_VALIDATION = 4, DISABLE_VIRTUALIZED_BUNDLES_VALIDATION = 2,
EMULATE_WINDOWS7 = 8, EMULATE_WINDOWS7 = 3,
} }
GPU_BASED_VALIDATION_SHADER_PATCH_MODE :: enum i32 { 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, 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_FLAGS :: distinct bit_set[GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG; u32]
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_NONE = 0x0, GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG :: enum u32 {
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_TRACKING_ONLY_SHADERS = 0x1, FRONT_LOAD_CREATE_TRACKING_ONLY_SHADERS = 0,
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_UNGUARDED_VALIDATION_SHADERS = 0x2, FRONT_LOAD_CREATE_UNGUARDED_VALIDATION_SHADERS = 1,
GPU_BASED_VALIDATION_PIPELINE_STATE_CREATE_FLAG_FRONT_LOAD_CREATE_GUARDED_VALIDATION_SHADERS = 0x4, FRONT_LOAD_CREATE_GUARDED_VALIDATION_SHADERS = 2,
VALID_MASK = 0x7, }
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 { DEBUG_DEVICE_GPU_BASED_VALIDATION_SETTINGS :: struct {
+49 -42
View File
@@ -45,50 +45,57 @@ foreign d3dcompiler {
D3DCOMPILE :: enum u32 { // TODO: make bit_field D3DCOMPILE :: distinct bit_set[D3DCOMPILE_FLAG; u32]
DEBUG = 1 << 0, D3DCOMPILE_FLAG :: enum u32 {
SKIP_VALIDATION = 1 << 1, DEBUG = 0,
SKIP_OPTIMIZATION = 1 << 2, SKIP_VALIDATION = 1,
PACK_MATRIX_ROW_MAJOR = 1 << 3, SKIP_OPTIMIZATION = 2,
PACK_MATRIX_COLUMN_MAJOR = 1 << 4, PACK_MATRIX_ROW_MAJOR = 3,
PARTIAL_PRECISION = 1 << 5, PACK_MATRIX_COLUMN_MAJOR = 4,
FORCE_VS_SOFTWARE_NO_OPT = 1 << 6, PARTIAL_PRECISION = 5,
FORCE_PS_SOFTWARE_NO_OPT = 1 << 7, FORCE_VS_SOFTWARE_NO_OPT = 6,
NO_PRESHADER = 1 << 8, FORCE_PS_SOFTWARE_NO_OPT = 7,
AVOID_FLOW_CONTROL = 1 << 9, NO_PRESHADER = 8,
PREFER_FLOW_CONTROL = 1 << 10, AVOID_FLOW_CONTROL = 9,
ENABLE_STRICTNESS = 1 << 11, PREFER_FLOW_CONTROL = 10,
ENABLE_BACKWARDS_COMPATIBILITY = 1 << 12, ENABLE_STRICTNESS = 11,
IEEE_STRICTNESS = 1 << 13, ENABLE_BACKWARDS_COMPATIBILITY = 12,
OPTIMIZATION_LEVEL0 = 1 << 14, IEEE_STRICTNESS = 13,
OPTIMIZATION_LEVEL1 = 0, OPTIMIZATION_LEVEL0 = 14,
OPTIMIZATION_LEVEL2 = (1 << 14)|(1 << 15), // Added manually OPTIMIZATION_LEVEL3 = 15,
OPTIMIZATION_LEVEL3 = 1 << 15, RESERVED16 = 16,
RESERVED16 = 1 << 16, RESERVED17 = 17,
RESERVED17 = 1 << 17, WARNINGS_ARE_ERRORS = 18,
WARNINGS_ARE_ERRORS = 1 << 18, RESOURCES_MAY_ALIAS = 19,
RESOURCES_MAY_ALIAS = 1 << 19, ENABLE_UNBOUNDED_DESCRIPTOR_TABLES = 20,
ENABLE_UNBOUNDED_DESCRIPTOR_TABLES = 1 << 20, ALL_RESOURCES_BOUND = 21,
ALL_RESOURCES_BOUND = 1 << 21, DEBUG_NAME_FOR_SOURCE = 22,
DEBUG_NAME_FOR_SOURCE = 1 << 22, DEBUG_NAME_FOR_BINARY = 23,
DEBUG_NAME_FOR_BINARY = 1 << 23,
} }
EFFECT :: enum u32 { // TODO: make bit_field D3DCOMPILE_OPTIMIZATION_LEVEL0 :: D3DCOMPILE{.OPTIMIZATION_LEVEL0}
CHILD_EFFECT = 1 << 0, D3DCOMPILE_OPTIMIZATION_LEVEL1 :: D3DCOMPILE{}
ALLOW_SLOW_OPS = 1 << 1, 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_LATEST = 0,
FORCE_ROOT_SIGNATURE_1_0 = 1 << 4, FORCE_ROOT_SIGNATURE_1_0 = 1 << 4,
FORCE_ROOT_SIGNATURE_1_1 = 1 << 5, FORCE_ROOT_SIGNATURE_1_1 = 1 << 5,
} }
SECDATA :: enum u32 { // TODO: make bit_field SECDATA :: distinct bit_set[SECDATA_FLAG; u32]
MERGE_UAV_SLOTS = 0x00000001, SECDATA_FLAG :: enum u32 {
PRESERVE_TEMPLATE_SLOTS = 0x00000002, MERGE_UAV_SLOTS = 0,
REQUIRE_TEMPLATE_MATCH = 0x00000004, PRESERVE_TEMPLATE_SLOTS = 1,
REQUIRE_TEMPLATE_MATCH = 2,
} }
DISASM_ENABLE_COLOR_CODE :: 0x00000001 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 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 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 D3DCOMPILER_STRIP_FLAGS :: distinct bit_set[D3DCOMPILER_STRIP_FLAG; u32]
REFLECTION_DATA = 0x1, D3DCOMPILER_STRIP_FLAG :: enum u32 {
DEBUG_INFO = 0x2, REFLECTION_DATA = 0,
TEST_BLOBS = 0x4, DEBUG_INFO = 1,
PRIVATE_DATA = 0x8, TEST_BLOBS = 2,
ROOT_SIGNATURE = 0x10, PRIVATE_DATA = 3,
FORCE_DWORD = 0x7fffffff, ROOT_SIGNATURE = 4,
} }
BLOB_PART :: enum i32 { BLOB_PART :: enum i32 {
+38 -29
View File
@@ -57,14 +57,15 @@ CPU_ACCESS :: enum u32 {
FIELD = 15, FIELD = 15,
} }
USAGE :: enum u32 { // TODO: convert to bit_set USAGE :: distinct bit_set[USAGE_FLAG; u32]
SHADER_INPUT = 0x00000010, USAGE_FLAG :: enum u32 {
RENDER_TARGET_OUTPUT = 0x00000020, SHADER_INPUT = 4,
BACK_BUFFER = 0x00000040, RENDER_TARGET_OUTPUT = 5,
SHARED = 0x00000080, BACK_BUFFER = 6,
READ_ONLY = 0x00000100, SHARED = 7,
DISCARD_ON_PRESENT = 0x00000200, READ_ONLY = 8,
UNORDERED_ACCESS = 0x00000400, DISCARD_ON_PRESENT = 9,
UNORDERED_ACCESS = 10,
} }
RESOURCE_PRIORITY :: enum u32 { RESOURCE_PRIORITY :: enum u32 {
@@ -75,37 +76,45 @@ RESOURCE_PRIORITY :: enum u32 {
MAXIMUM = 0xc8000000, MAXIMUM = 0xc8000000,
} }
MAP :: enum u32 { // TODO: convert to bit_set MAP :: enum u32 {
READ = 1, READ = 1,
WRITE = 2, WRITE = 2,
DISCARD = 4, DISCARD = 4,
} }
ENUM_MODES :: enum u32 { // TODO: convert to bit_set ENUM_MODES :: distinct bit_set[ENUM_MODE; u32]
INTERLACED = 1, ENUM_MODE :: enum u32 {
SCALING = 2, INTERLACED = 0,
STEREO = 4, SCALING = 1,
DISABLED_STEREO = 8, STEREO = 2,
DISABLED_STEREO = 3,
} }
MAX_SWAP_CHAIN_BUFFERS :: 16 MAX_SWAP_CHAIN_BUFFERS :: 16
PRESENT :: enum u32 { // TODO: convert to bit_set PRESENT :: distinct bit_set[PRESENT_FLAG; u32]
TEST = 0x00000001, PRESENT_FLAG :: enum u32 {
DO_NOT_SEQUENCE = 0x00000002, TEST = 0,
RESTART = 0x00000004, DO_NOT_SEQUENCE = 1,
DO_NOT_WAIT = 0x00000008, RESTART = 2,
STEREO_PREFER_RIGHT = 0x00000010, DO_NOT_WAIT = 3,
STEREO_TEMPORARY_MONO = 0x00000020, STEREO_PREFER_RIGHT = 4,
RESTRICT_TO_OUTPUT = 0x00000040, STEREO_TEMPORARY_MONO = 5,
USE_DURATION = 0x00000100, RESTRICT_TO_OUTPUT = 6,
ALLOW_TEARING = 0x00000200,
USE_DURATION = 8,
ALLOW_TEARING = 9,
} }
MWA :: enum u32 { // TODO: convert to bit_set MWA :: distinct bit_set[MWA_FLAG; u32]
NO_WINDOW_CHANGES = 1 << 0, MWA_FLAG :: enum u32 {
NO_ALT_ENTER = 1 << 1, NO_WINDOW_CHANGES = 0,
NO_PRINT_SCREEN = 1 << 2, NO_ALT_ENTER = 1,
VALID = 0x7, NO_PRINT_SCREEN = 2,
}
MWA_VALID :: MWA{
.NO_WINDOW_CHANGES,
.NO_ALT_ENTER,
.NO_PRINT_SCREEN,
} }
SHARED_RESOURCE_READ :: 0x80000000 SHARED_RESOURCE_READ :: 0x80000000
+1
View File
@@ -110,6 +110,7 @@ foreign glfw {
WaitEventsTimeout :: proc(timeout: f64) --- WaitEventsTimeout :: proc(timeout: f64) ---
PostEmptyEvent :: proc() --- PostEmptyEvent :: proc() ---
RawMouseMotionSupported :: proc() -> b32 ---
GetInputMode :: proc(window: WindowHandle, mode: c.int) -> c.int --- GetInputMode :: proc(window: WindowHandle, mode: c.int) -> c.int ---
SetInputMode :: proc(window: WindowHandle, mode, value: c.int) --- SetInputMode :: proc(window: WindowHandle, mode, value: c.int) ---
+3
View File
@@ -339,6 +339,9 @@ CURSOR_NORMAL :: 0x00034001
CURSOR_HIDDEN :: 0x00034002 CURSOR_HIDDEN :: 0x00034002
CURSOR_DISABLED :: 0x00034003 CURSOR_DISABLED :: 0x00034003
/* Mouse motion */
RAW_MOUSE_MOTION :: 0x00033005
/* Behavior? */ /* Behavior? */
ANY_RELEASE_BEHAVIOR :: 0 ANY_RELEASE_BEHAVIOR :: 0
RELEASE_BEHAVIOR_FLUSH :: 0x00035001 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 == .Windows { foreign import lib "../lib/stb_rect_pack.lib" }
when ODIN_OS == .Linux { foreign import lib "../lib/stb_rect_pack.a" } 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 Coord :: distinct c.int
_MAXVAL :: max(Coord) _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 == .Windows { foreign import stbtt "../lib/stb_truetype.lib" }
when ODIN_OS == .Linux { foreign import stbtt "../lib/stb_truetype.a" } 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 == .Windows { foreign import lib "../lib/stb_vorbis.lib" }
when ODIN_OS == .Linux { foreign import lib "../lib/stb_vorbis.a" } 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: else:
ttype = t[:len(t)-1] ttype = t[:len(t)-1]
elem = convert_type(ttype, prev_name, curr_name) elem = convert_type(ttype, prev_name, curr_name)
if curr_name.endswith("s") or curr_name.endswith("Table"): if curr_name.endswith("s") or curr_name.endswith("Table"):
if prev_name.endswith("Count") or prev_name.endswith("Counts"): if prev_name.endswith("Count") or prev_name.endswith("Counts"):
pointer = "[^]" pointer = "[^]"
@@ -95,10 +95,10 @@ def convert_type(t, prev_name, curr_name):
pointer = "[^]" pointer = "[^]"
elif curr_name.startswith("p"): elif curr_name.startswith("p"):
pointer = "[^]" pointer = "[^]"
if curr_name and elem.endswith("Flags"): if curr_name and elem.endswith("Flags"):
pointer = "[^]" pointer = "[^]"
return "{}{}".format(pointer, elem) return "{}{}".format(pointer, elem)
elif t[0].isupper(): elif t[0].isupper():
return t return t
@@ -276,7 +276,7 @@ def parse_enums(f):
f.write("// Enums\n") f.write("// Enums\n")
data = re.findall(r"typedef enum Vk(\w+) {(.+?)} \w+;", src, re.S) data = re.findall(r"typedef enum Vk(\w+) {(.+?)} \w+;", src, re.S)
data.sort(key=lambda x: x[0]) data.sort(key=lambda x: x[0])
generated_flags = set() generated_flags = set()
@@ -458,14 +458,14 @@ def parse_procedures(f):
for rt, name, fields in data: for rt, name, fields in data:
proc_name = no_vk(name) proc_name = no_vk(name)
pf = [] pf = []
prev_name = "" prev_name = ""
for type_, fname in re.findall(r"(?:\s*|)(.+?)\s*(\w+)(?:,|$)", fields): for type_, fname in re.findall(r"(?:\s*|)(.+?)\s*(\w+)(?:,|$)", fields):
curr_name = fix_arg(fname) curr_name = fix_arg(fname)
pf.append((do_type(type_, prev_name, curr_name), curr_name)) pf.append((do_type(type_, prev_name, curr_name), curr_name))
prev_name = curr_name prev_name = curr_name
data_fields = ', '.join(["{}: {}".format(n, t) for t, n in pf if t != ""]) data_fields = ', '.join(["{}: {}".format(n, t) for t, n in pf if t != ""])
ts = "proc \"c\" ({})".format(data_fields) ts = "proc \"c\" ({})".format(data_fields)
@@ -510,7 +510,7 @@ def group_functions(f):
if table_name in ('Device', 'Queue', 'CommandBuffer') and name != 'GetDeviceProcAddr': if table_name in ('Device', 'Queue', 'CommandBuffer') and name != 'GetDeviceProcAddr':
group_map["Device"].append(nn) 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) group_map["Instance"].append(nn)
elif table_name in ('rawptr', '', 'DebugReportFlagsEXT') or name == 'GetInstanceProcAddr': elif table_name in ('rawptr', '', 'DebugReportFlagsEXT') or name == 'GetInstanceProcAddr':
# Skip the allocation function and the dll entry point # Skip the allocation function and the dll entry point
+3 -3
View File
@@ -533,6 +533,7 @@ DeviceMemoryReportCallbackEXT: ProcDeviceMemoryReportCallbackEXT
EnumerateInstanceExtensionProperties: ProcEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties: ProcEnumerateInstanceExtensionProperties
EnumerateInstanceLayerProperties: ProcEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties: ProcEnumerateInstanceLayerProperties
EnumerateInstanceVersion: ProcEnumerateInstanceVersion EnumerateInstanceVersion: ProcEnumerateInstanceVersion
GetInstanceProcAddr: ProcGetInstanceProcAddr
// Instance Procedures // Instance Procedures
AcquireDrmDisplayEXT: ProcAcquireDrmDisplayEXT AcquireDrmDisplayEXT: ProcAcquireDrmDisplayEXT
@@ -564,7 +565,6 @@ GetDisplayPlaneCapabilities2KHR: ProcGetDisplayP
GetDisplayPlaneCapabilitiesKHR: ProcGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR: ProcGetDisplayPlaneCapabilitiesKHR
GetDisplayPlaneSupportedDisplaysKHR: ProcGetDisplayPlaneSupportedDisplaysKHR GetDisplayPlaneSupportedDisplaysKHR: ProcGetDisplayPlaneSupportedDisplaysKHR
GetDrmDisplayEXT: ProcGetDrmDisplayEXT GetDrmDisplayEXT: ProcGetDrmDisplayEXT
GetInstanceProcAddr: ProcGetInstanceProcAddr
GetPhysicalDeviceCalibrateableTimeDomainsEXT: ProcGetPhysicalDeviceCalibrateableTimeDomainsEXT GetPhysicalDeviceCalibrateableTimeDomainsEXT: ProcGetPhysicalDeviceCalibrateableTimeDomainsEXT
GetPhysicalDeviceCooperativeMatrixPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV GetPhysicalDeviceCooperativeMatrixPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV
GetPhysicalDeviceDisplayPlaneProperties2KHR: ProcGetPhysicalDeviceDisplayPlaneProperties2KHR GetPhysicalDeviceDisplayPlaneProperties2KHR: ProcGetPhysicalDeviceDisplayPlaneProperties2KHR
@@ -1045,6 +1045,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) {
set_proc_address(&EnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties") set_proc_address(&EnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties")
set_proc_address(&EnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties") set_proc_address(&EnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties")
set_proc_address(&EnumerateInstanceVersion, "vkEnumerateInstanceVersion") set_proc_address(&EnumerateInstanceVersion, "vkEnumerateInstanceVersion")
set_proc_address(&GetInstanceProcAddr, "vkGetInstanceProcAddr")
// Instance Procedures // Instance Procedures
set_proc_address(&AcquireDrmDisplayEXT, "vkAcquireDrmDisplayEXT") 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(&GetDisplayPlaneCapabilitiesKHR, "vkGetDisplayPlaneCapabilitiesKHR")
set_proc_address(&GetDisplayPlaneSupportedDisplaysKHR, "vkGetDisplayPlaneSupportedDisplaysKHR") set_proc_address(&GetDisplayPlaneSupportedDisplaysKHR, "vkGetDisplayPlaneSupportedDisplaysKHR")
set_proc_address(&GetDrmDisplayEXT, "vkGetDrmDisplayEXT") set_proc_address(&GetDrmDisplayEXT, "vkGetDrmDisplayEXT")
set_proc_address(&GetInstanceProcAddr, "vkGetInstanceProcAddr")
set_proc_address(&GetPhysicalDeviceCalibrateableTimeDomainsEXT, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT") set_proc_address(&GetPhysicalDeviceCalibrateableTimeDomainsEXT, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT")
set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV")
set_proc_address(&GetPhysicalDeviceDisplayPlaneProperties2KHR, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") set_proc_address(&GetPhysicalDeviceDisplayPlaneProperties2KHR, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR")
@@ -2839,7 +2839,6 @@ load_proc_addresses_instance :: proc(instance: Instance) {
GetDisplayPlaneCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR") GetDisplayPlaneCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR")
GetDisplayPlaneSupportedDisplaysKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR") GetDisplayPlaneSupportedDisplaysKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR")
GetDrmDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkGetDrmDisplayEXT") GetDrmDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkGetDrmDisplayEXT")
GetInstanceProcAddr = auto_cast GetInstanceProcAddr(instance, "vkGetInstanceProcAddr")
GetPhysicalDeviceCalibrateableTimeDomainsEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT") GetPhysicalDeviceCalibrateableTimeDomainsEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT")
GetPhysicalDeviceCooperativeMatrixPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") GetPhysicalDeviceCooperativeMatrixPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV")
GetPhysicalDeviceDisplayPlaneProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") 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") EnumerateInstanceExtensionProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceExtensionProperties")
EnumerateInstanceLayerProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceLayerProperties") EnumerateInstanceLayerProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceLayerProperties")
EnumerateInstanceVersion = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceVersion") EnumerateInstanceVersion = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceVersion")
GetInstanceProcAddr = auto_cast GetInstanceProcAddr(nil, "vkGetInstanceProcAddr")
} }
load_proc_addresses :: proc{ load_proc_addresses :: proc{