Merge branch 'master' into new-temp-allocator

This commit is contained in:
gingerBill
2023-02-28 12:15:54 +00:00
committed by GitHub
55 changed files with 2758 additions and 554 deletions

View File

@@ -12,7 +12,7 @@ _rand_bytes :: proc (dst: []byte) {
for l > 0 {
to_read := min(l, _MAX_PER_CALL_BYTES)
ret := unix.sys_getrandom(raw_data(dst), to_read, 0)
ret := unix.sys_getrandom(raw_data(dst), uint(to_read), 0)
if ret < 0 {
switch os.Errno(-ret) {
case os.EINTR:

View File

@@ -283,7 +283,7 @@ wasm_memory_atomic_wait32 :: proc(ptr: ^u32, expected: u32, timeout_ns: i64) -
wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
// x86 Targets (i386, amd64)
x86_cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) ---
x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) ---
x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
@@ -305,4 +305,4 @@ valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2,
// Internal compiler use only
__entry_point :: proc() ---
__entry_point :: proc() ---

View File

@@ -277,8 +277,10 @@ foreign libc {
@(link_name="open") _unix_open :: proc(path: cstring, flags: i32, mode: u16) -> Handle ---
@(link_name="close") _unix_close :: proc(handle: Handle) -> c.int ---
@(link_name="read") _unix_read :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---
@(link_name="write") _unix_write :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---
@(link_name="read") _unix_read :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
@(link_name="write") _unix_write :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
@(link_name="pread") _unix_pread :: proc(handle: Handle, buffer: rawptr, count: c.size_t, offset: i64) -> int ---
@(link_name="pwrite") _unix_pwrite :: proc(handle: Handle, buffer: rawptr, count: c.size_t, offset: i64) -> int ---
@(link_name="lseek") _unix_lseek :: proc(fs: Handle, offset: int, whence: int) -> int ---
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---
@(link_name="getpagesize") _unix_getpagesize :: proc() -> i32 ---
@@ -386,45 +388,51 @@ close :: proc(fd: Handle) -> bool {
@(private)
MAX_RW :: 0x7fffffff // The limit on Darwin is max(i32), trying to read/write more than that fails.
write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
assert(fd != -1)
bytes_total := len(data)
bytes_written_total := 0
for bytes_written_total < bytes_total {
bytes_to_write := min(bytes_total - bytes_written_total, MAX_RW)
slice := data[bytes_written_total:bytes_written_total + bytes_to_write]
bytes_written := _unix_write(fd, raw_data(slice), bytes_to_write)
if bytes_written == -1 {
return bytes_written_total, 1
}
bytes_written_total += bytes_written
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
return bytes_written_total, 0
bytes_written := _unix_write(fd, raw_data(data), c.size_t(len(data)))
if bytes_written < 0 {
return -1, Errno(get_last_error())
}
return bytes_written, ERROR_NONE
}
read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
assert(fd != -1)
bytes_total := len(data)
bytes_read_total := 0
for bytes_read_total < bytes_total {
bytes_to_read := min(bytes_total - bytes_read_total, MAX_RW)
slice := data[bytes_read_total:bytes_read_total + bytes_to_read]
bytes_read := _unix_read(fd, raw_data(slice), bytes_to_read)
if bytes_read == -1 {
return bytes_read_total, 1
}
if bytes_read == 0 {
break
}
bytes_read_total += bytes_read
if len(data) == 0 {
return 0, ERROR_NONE
}
return bytes_read_total, 0
bytes_read := _unix_read(fd, raw_data(data), c.size_t(len(data)))
if bytes_read < 0 {
return -1, Errno(get_last_error())
}
return bytes_read, ERROR_NONE
}
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_read := _unix_pread(fd, raw_data(data), c.size_t(len(data)), offset)
if bytes_read < 0 {
return -1, Errno(get_last_error())
}
return bytes_read, ERROR_NONE
}
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_written := _unix_pwrite(fd, raw_data(data), c.size_t(len(data)), offset)
if bytes_written < 0 {
return -1, Errno(get_last_error())
}
return bytes_written, ERROR_NONE
}
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {

View File

@@ -270,136 +270,6 @@ AT_FDCWD :: ~uintptr(99) /* -100 */
AT_REMOVEDIR :: uintptr(0x200)
AT_SYMLINK_NOFOLLOW :: uintptr(0x100)
_unix_personality :: proc(persona: u64) -> int {
return int(intrinsics.syscall(unix.SYS_personality, uintptr(persona)))
}
_unix_fork :: proc() -> Pid {
when ODIN_ARCH != .arm64 {
res := int(intrinsics.syscall(unix.SYS_fork))
} else {
res := int(intrinsics.syscall(unix.SYS_clone, unix.SIGCHLD))
}
return -1 if res < 0 else Pid(res)
}
_unix_open :: proc(path: cstring, flags: int, mode: int = 0o000) -> Handle {
when ODIN_ARCH != .arm64 {
res := int(intrinsics.syscall(unix.SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
} else { // NOTE: arm64 does not have open
res := int(intrinsics.syscall(unix.SYS_openat, AT_FDCWD, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
}
return -1 if res < 0 else Handle(res)
}
_unix_close :: proc(fd: Handle) -> int {
return int(intrinsics.syscall(unix.SYS_close, uintptr(fd)))
}
_unix_read :: proc(fd: Handle, buf: rawptr, size: uint) -> int {
return int(intrinsics.syscall(unix.SYS_read, uintptr(fd), uintptr(buf), uintptr(size)))
}
_unix_write :: proc(fd: Handle, buf: rawptr, size: uint) -> int {
return int(intrinsics.syscall(unix.SYS_write, uintptr(fd), uintptr(buf), uintptr(size)))
}
_unix_seek :: proc(fd: Handle, offset: i64, whence: int) -> i64 {
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
return i64(intrinsics.syscall(unix.SYS_lseek, uintptr(fd), uintptr(offset), uintptr(whence)))
} else {
low := uintptr(offset & 0xFFFFFFFF)
high := uintptr(offset >> 32)
result: i64
res := i64(intrinsics.syscall(unix.SYS__llseek, uintptr(fd), high, low, uintptr(&result), uintptr(whence)))
return -1 if res < 0 else result
}
}
_unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> int {
when ODIN_ARCH == .amd64 {
return int(intrinsics.syscall(unix.SYS_stat, uintptr(rawptr(path)), uintptr(stat)))
} else when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(unix.SYS_stat64, uintptr(rawptr(path)), uintptr(stat)))
} else { // NOTE: arm64 does not have stat
return int(intrinsics.syscall(unix.SYS_fstatat, AT_FDCWD, uintptr(rawptr(path)), uintptr(stat), 0))
}
}
_unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> int {
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
return int(intrinsics.syscall(unix.SYS_fstat, uintptr(fd), uintptr(stat)))
} else {
return int(intrinsics.syscall(unix.SYS_fstat64, uintptr(fd), uintptr(stat)))
}
}
_unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> int {
when ODIN_ARCH == .amd64 {
return int(intrinsics.syscall(unix.SYS_lstat, uintptr(rawptr(path)), uintptr(stat)))
} else when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(unix.SYS_lstat64, uintptr(rawptr(path)), uintptr(stat)))
} else { // NOTE: arm64 does not have any lstat
return int(intrinsics.syscall(unix.SYS_fstatat, AT_FDCWD, uintptr(rawptr(path)), uintptr(stat), AT_SYMLINK_NOFOLLOW))
}
}
_unix_readlink :: proc(path: cstring, buf: rawptr, bufsiz: uint) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(unix.SYS_readlink, uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz)))
} else { // NOTE: arm64 does not have readlink
return int(intrinsics.syscall(unix.SYS_readlinkat, AT_FDCWD, uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz)))
}
}
_unix_access :: proc(path: cstring, mask: int) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(unix.SYS_access, uintptr(rawptr(path)), uintptr(mask)))
} else { // NOTE: arm64 does not have access
return int(intrinsics.syscall(unix.SYS_faccessat, AT_FDCWD, uintptr(rawptr(path)), uintptr(mask)))
}
}
_unix_getcwd :: proc(buf: rawptr, size: uint) -> int {
return int(intrinsics.syscall(unix.SYS_getcwd, uintptr(buf), uintptr(size)))
}
_unix_chdir :: proc(path: cstring) -> int {
return int(intrinsics.syscall(unix.SYS_chdir, uintptr(rawptr(path))))
}
_unix_rename :: proc(old, new: cstring) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(unix.SYS_rename, uintptr(rawptr(old)), uintptr(rawptr(new))))
} else { // NOTE: arm64 does not have rename
return int(intrinsics.syscall(unix.SYS_renameat, AT_FDCWD, uintptr(rawptr(old)), uintptr(rawptr(new))))
}
}
_unix_unlink :: proc(path: cstring) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(unix.SYS_unlink, uintptr(rawptr(path))))
} else { // NOTE: arm64 does not have unlink
return int(intrinsics.syscall(unix.SYS_unlinkat, AT_FDCWD, uintptr(rawptr(path)), 0))
}
}
_unix_rmdir :: proc(path: cstring) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(unix.SYS_rmdir, uintptr(rawptr(path))))
} else { // NOTE: arm64 does not have rmdir
return int(intrinsics.syscall(unix.SYS_unlinkat, AT_FDCWD, uintptr(rawptr(path)), AT_REMOVEDIR))
}
}
_unix_mkdir :: proc(path: cstring, mode: u32) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(unix.SYS_mkdir, uintptr(rawptr(path)), uintptr(mode)))
} else { // NOTE: arm64 does not have mkdir
return int(intrinsics.syscall(unix.SYS_mkdirat, AT_FDCWD, uintptr(rawptr(path)), uintptr(mode)))
}
}
foreign libc {
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
@@ -415,6 +285,7 @@ foreign libc {
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
@(link_name="execvp") _unix_execvp :: proc(path: cstring, argv: [^]cstring) -> int ---
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
@(link_name="putenv") _unix_putenv :: proc(cstring) -> c.int ---
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
@@ -447,7 +318,7 @@ get_last_error :: proc "contextless" () -> int {
}
personality :: proc(persona: u64) -> (Errno) {
res := _unix_personality(persona)
res := unix.sys_personality(persona)
if res == -1 {
return _get_errno(res)
}
@@ -455,29 +326,47 @@ personality :: proc(persona: u64) -> (Errno) {
}
fork :: proc() -> (Pid, Errno) {
pid := _unix_fork()
pid := unix.sys_fork()
if pid == -1 {
return -1, _get_errno(int(pid))
return -1, _get_errno(pid)
}
return pid, ERROR_NONE
return Pid(pid), ERROR_NONE
}
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
execvp :: proc(path: string, args: []string) -> Errno {
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
args_cstrs := make([]cstring, len(args) + 2, context.temp_allocator)
args_cstrs[0] = strings.clone_to_cstring(path, context.temp_allocator)
for i := 0; i < len(args); i += 1 {
args_cstrs[i+1] = strings.clone_to_cstring(args[i], context.temp_allocator)
}
_unix_execvp(path_cstr, raw_data(args_cstrs))
return Errno(get_last_error())
}
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0o000) -> (Handle, Errno) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator)
handle := _unix_open(cstr, flags, mode)
handle := unix.sys_open(cstr, flags, uint(mode))
if handle < 0 {
return INVALID_HANDLE, _get_errno(int(handle))
return INVALID_HANDLE, _get_errno(handle)
}
return handle, ERROR_NONE
return Handle(handle), ERROR_NONE
}
close :: proc(fd: Handle) -> Errno {
return _get_errno(_unix_close(fd))
return _get_errno(unix.sys_close(int(fd)))
}
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)))
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_read := unix.sys_read(int(fd), raw_data(data), len(data))
if bytes_read < 0 {
return -1, _get_errno(bytes_read)
}
@@ -488,25 +377,49 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_written := _unix_write(fd, &data[0], uint(len(data)))
bytes_written := unix.sys_write(int(fd), raw_data(data), len(data))
if bytes_written < 0 {
return -1, _get_errno(bytes_written)
}
return int(bytes_written), ERROR_NONE
return bytes_written, ERROR_NONE
}
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_read := unix.sys_pread(int(fd), raw_data(data), len(data), offset)
if bytes_read < 0 {
return -1, _get_errno(bytes_read)
}
return bytes_read, ERROR_NONE
}
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
if len(data) == 0 {
return 0, ERROR_NONE
}
bytes_written := unix.sys_pwrite(int(fd), raw_data(data), uint(len(data)), offset)
if bytes_written < 0 {
return -1, _get_errno(bytes_written)
}
return bytes_written, ERROR_NONE
}
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
res := _unix_seek(fd, offset, whence)
res := unix.sys_lseek(int(fd), offset, whence)
if res < 0 {
return -1, _get_errno(int(res))
}
return res, ERROR_NONE
return i64(res), ERROR_NONE
}
file_size :: proc(fd: Handle) -> (i64, Errno) {
// deliberately uninitialized; the syscall fills this buffer for us
s: OS_Stat = ---
result := _unix_fstat(fd, &s)
result := unix.sys_fstat(int(fd), rawptr(&s))
if result < 0 {
return 0, _get_errno(result)
}
@@ -517,25 +430,25 @@ rename :: proc(old_path, new_path: string) -> Errno {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
old_path_cstr := strings.clone_to_cstring(old_path, context.temp_allocator)
new_path_cstr := strings.clone_to_cstring(new_path, context.temp_allocator)
return _get_errno(_unix_rename(old_path_cstr, new_path_cstr))
return _get_errno(unix.sys_rename(old_path_cstr, new_path_cstr))
}
remove :: proc(path: string) -> Errno {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
return _get_errno(_unix_unlink(path_cstr))
return _get_errno(unix.sys_unlink(path_cstr))
}
make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
return _get_errno(_unix_mkdir(path_cstr, mode))
return _get_errno(unix.sys_mkdir(path_cstr, uint(mode)))
}
remove_directory :: proc(path: string) -> Errno {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
return _get_errno(_unix_rmdir(path_cstr))
return _get_errno(unix.sys_rmdir(path_cstr))
}
is_file_handle :: proc(fd: Handle) -> bool {
@@ -589,7 +502,7 @@ is_dir :: proc {is_dir_path, is_dir_handle}
exists :: proc(path: string) -> bool {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cpath := strings.clone_to_cstring(path, context.temp_allocator)
res := _unix_access(cpath, O_RDONLY)
res := unix.sys_access(cpath, O_RDONLY)
return res == 0
}
@@ -628,7 +541,7 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
// deliberately uninitialized; the syscall fills this buffer for us
s: OS_Stat = ---
result := _unix_stat(cstr, &s)
result := unix.sys_stat(cstr, &s)
if result < 0 {
return s, _get_errno(result)
}
@@ -642,7 +555,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
// deliberately uninitialized; the syscall fills this buffer for us
s: OS_Stat = ---
result := _unix_lstat(cstr, &s)
result := unix.sys_lstat(cstr, &s)
if result < 0 {
return s, _get_errno(result)
}
@@ -653,7 +566,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
// deliberately uninitialized; the syscall fills this buffer for us
s: OS_Stat = ---
result := _unix_fstat(fd, &s)
result := unix.sys_fstat(int(fd), rawptr(&s))
if result < 0 {
return s, _get_errno(result)
}
@@ -711,7 +624,7 @@ _readlink :: proc(path: string) -> (string, Errno) {
bufsz : uint = 256
buf := make([]byte, bufsz)
for {
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
rc := unix.sys_readlink(path_cstr, &(buf[0]), bufsz)
if rc < 0 {
delete(buf)
return "", _get_errno(rc)
@@ -760,7 +673,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
access :: proc(path: string, mask: int) -> (bool, Errno) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator)
result := _unix_access(cstr, mask)
result := unix.sys_access(cstr, mask)
if result < 0 {
return false, _get_errno(result)
}
@@ -831,7 +744,7 @@ get_current_directory :: proc() -> string {
page_size := get_page_size()
buf := make([dynamic]u8, page_size)
for {
#no_bounds_check res := _unix_getcwd(&buf[0], uint(len(buf)))
#no_bounds_check res := unix.sys_getcwd(&buf[0], uint(len(buf)))
if res >= 0 {
return strings.string_from_nul_terminated_ptr(&buf[0], len(buf))
@@ -848,7 +761,7 @@ get_current_directory :: proc() -> string {
set_current_directory :: proc(path: string) -> (err: Errno) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator)
res := _unix_chdir(cstr)
res := unix.sys_chdir(cstr)
if res < 0 {
return _get_errno(res)
}

208
core/prof/spall/spall.odin Normal file
View File

@@ -0,0 +1,208 @@
package prof_spall
import "core:os"
import "core:time"
import "core:intrinsics"
import "core:mem"
// File Format
MANUAL_MAGIC :: u64le(0x0BADF00D)
Manual_Header :: struct #packed {
magic: u64le,
version: u64le,
timestamp_scale: f64le,
reserved: u64le,
}
Manual_Event_Type :: enum u8 {
Invalid = 0,
Begin = 3,
End = 4,
Instant = 5,
Pad_Skip = 7,
}
Begin_Event :: struct #packed {
type: Manual_Event_Type,
category: u8,
pid: u32le,
tid: u32le,
ts: f64le,
name_len: u8,
args_len: u8,
}
BEGIN_EVENT_MAX :: size_of(Begin_Event) + 255 + 255
End_Event :: struct #packed {
type: Manual_Event_Type,
pid: u32le,
tid: u32le,
ts: f64le,
}
Pad_Skip :: struct #packed {
type: Manual_Event_Type,
size: u32le,
}
// User Interface
Context :: struct {
precise_time: bool,
timestamp_scale: f64,
fd: os.Handle,
}
Buffer :: struct {
data: []u8,
head: int,
tid: u32,
pid: u32,
}
BUFFER_DEFAULT_SIZE :: 0x10_0000
context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_ok {
fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600)
if err != os.ERROR_NONE {
return
}
ctx.fd = fd
freq, freq_ok := time.tsc_frequency()
ctx.precise_time = freq_ok
ctx.timestamp_scale = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1
temp := [size_of(Manual_Header)]u8{}
_build_header(temp[:], ctx.timestamp_scale)
os.write(ctx.fd, temp[:])
ok = true
return
}
context_destroy :: proc(ctx: ^Context) {
if ctx == nil {
return
}
os.close(ctx.fd)
ctx^ = Context{}
}
buffer_create :: proc(data: []byte, tid: u32 = 0, pid: u32 = 0) -> (buffer: Buffer, ok: bool) #optional_ok {
assert(len(data) > 0)
buffer.data = data
buffer.tid = tid
buffer.pid = pid
buffer.head = 0
ok = true
return
}
buffer_flush :: proc(ctx: ^Context, buffer: ^Buffer) {
os.write(ctx.fd, buffer.data[:buffer.head])
buffer.head = 0
}
buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) {
buffer_flush(ctx, buffer)
buffer^ = Buffer{}
}
@(deferred_in=_scoped_buffer_end)
SCOPED_EVENT :: proc(ctx: ^Context, buffer: ^Buffer, name: string, args: string = "", location := #caller_location) -> bool {
_buffer_begin(ctx, buffer, name, args, location)
return true
}
@(private)
_scoped_buffer_end :: proc(ctx: ^Context, buffer: ^Buffer, _, _: string, _ := #caller_location) {
_buffer_end(ctx, buffer)
}
_trace_now :: proc "contextless" (ctx: ^Context) -> f64 {
if !ctx.precise_time {
return f64(time.tick_now()._nsec) / 1_000
}
return f64(intrinsics.read_cycle_counter())
}
_build_header :: proc "contextless" (buffer: []u8, timestamp_scale: f64) -> (header_size: int, ok: bool) #optional_ok {
header_size = size_of(Manual_Header)
if header_size > len(buffer) {
return 0, false
}
hdr := (^Manual_Header)(raw_data(buffer))
hdr.magic = MANUAL_MAGIC
hdr.version = 1
hdr.timestamp_scale = f64le(timestamp_scale)
hdr.reserved = 0
ok = true
return
}
_build_begin :: proc "contextless" (buffer: []u8, name: string, args: string, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok {
ev := (^Begin_Event)(raw_data(buffer))
name_len := min(len(name), 255)
args_len := min(len(args), 255)
event_size = size_of(Begin_Event) + name_len + args_len
if event_size > len(buffer) {
return 0, false
}
ev.type = .Begin
ev.pid = u32le(pid)
ev.tid = u32le(tid)
ev.ts = f64le(ts)
ev.name_len = u8(name_len)
ev.args_len = u8(args_len)
mem.copy(raw_data(buffer[size_of(Begin_Event):]), raw_data(name), name_len)
mem.copy(raw_data(buffer[size_of(Begin_Event)+name_len:]), raw_data(args), args_len)
ok = true
return
}
_build_end :: proc(buffer: []u8, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok {
ev := (^End_Event)(raw_data(buffer))
event_size = size_of(End_Event)
if event_size > len(buffer) {
return 0, false
}
ev.type = .End
ev.pid = u32le(pid)
ev.tid = u32le(tid)
ev.ts = f64le(ts)
ok = true
return
}
_buffer_begin :: proc(ctx: ^Context, buffer: ^Buffer, name: string, args: string = "", location := #caller_location) {
if buffer.head + BEGIN_EVENT_MAX > len(buffer.data) {
buffer_flush(ctx, buffer)
}
name := location.procedure if name == "" else name
buffer.head += _build_begin(buffer.data[buffer.head:], name, args, _trace_now(ctx), buffer.tid, buffer.pid)
}
_buffer_end :: proc(ctx: ^Context, buffer: ^Buffer) {
ts := _trace_now(ctx)
if buffer.head + size_of(End_Event) > len(buffer.data) {
buffer_flush(ctx, buffer)
}
buffer.head += _build_end(buffer.data[buffer.head:], ts, buffer.tid, buffer.pid)
}

View File

@@ -507,11 +507,8 @@ Odin_Endian_Type :: type_of(ODIN_ENDIAN)
foreign {
@(link_name="__$startup_runtime")
_startup_runtime :: proc "odin" () ---
}
@(link_name="__$cleanup_runtime")
_cleanup_runtime :: proc() {
default_temp_allocator_destroy(&global_default_temp_allocator_data)
@(link_name="__$cleanup_runtime")
_cleanup_runtime :: proc "odin" () ---
}
_cleanup_runtime_contextless :: proc "contextless" () {

View File

@@ -72,3 +72,8 @@ default_temp_allocator :: proc(allocator: ^Default_Temp_Allocator) -> Allocator
data = allocator,
}
}
@(fini, private)
_destroy_temp_allocator_fini :: proc() {
default_temp_allocator_destroy(&global_default_temp_allocator_data)
}

View File

@@ -184,32 +184,33 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle
return
}
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
if allocator.procedure == nil {
return nil, nil
}
if new_size == 0 {
if ptr != nil {
_, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
return nil, err
_, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
return
}
return nil, nil
return
} else if ptr == nil {
return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
} else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 {
return ([^]byte)(ptr)[:old_size], nil
data = ([^]byte)(ptr)[:old_size]
return
}
data, err := allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc)
if err == .Mode_Not_Implemented {
data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
if err != nil {
return data, err
return
}
copy(data, ([^]byte)(ptr)[:old_size])
_, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
}
return data, err
return
}
memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
@@ -223,7 +224,7 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
when size_of(uint) == 8 {
if word_length := length >> 3; word_length != 0 {
for i in 0..<word_length {
for _ in 0..<word_length {
if intrinsics.unaligned_load((^u64)(a)) != intrinsics.unaligned_load((^u64)(b)) {
return false
}
@@ -254,7 +255,7 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
return true
} else {
if word_length := length >> 2; word_length != 0 {
for i in 0..<word_length {
for _ in 0..<word_length {
if intrinsics.unaligned_load((^u32)(a)) != intrinsics.unaligned_load((^u32)(b)) {
return false
}

View File

@@ -2,6 +2,9 @@ package runtime
_INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz"
@(private="file")
_INTEGER_DIGITS_VAR := _INTEGER_DIGITS
when !ODIN_DISALLOW_RTTI {
print_any_single :: proc(arg: any) {
x := arg
@@ -105,14 +108,14 @@ encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) {
return buf, 4
}
print_string :: proc "contextless" (str: string) -> (int, _OS_Errno) {
return os_write(transmute([]byte)str)
print_string :: proc "contextless" (str: string) -> (n: int) {
n, _ = os_write(transmute([]byte)str)
return
}
print_strings :: proc "contextless" (args: ..string) -> (n: int, err: _OS_Errno) {
print_strings :: proc "contextless" (args: ..string) -> (n: int) {
for str in args {
m: int
m, err = os_write(transmute([]byte)str)
m, err := os_write(transmute([]byte)str)
n += m
if err != 0 {
break
@@ -121,8 +124,9 @@ print_strings :: proc "contextless" (args: ..string) -> (n: int, err: _OS_Errno)
return
}
print_byte :: proc "contextless" (b: byte) -> (int, _OS_Errno) {
return os_write([]byte{b})
print_byte :: proc "contextless" (b: byte) -> (n: int) {
n, _ = os_write([]byte{b})
return
}
print_encoded_rune :: proc "contextless" (r: rune) {
@@ -141,11 +145,10 @@ print_encoded_rune :: proc "contextless" (r: rune) {
if r <= 0 {
print_string("\\x00")
} else if r < 32 {
digits := _INTEGER_DIGITS
n0, n1 := u8(r) >> 4, u8(r) & 0xf
print_string("\\x")
print_byte(digits[n0])
print_byte(digits[n1])
print_byte(_INTEGER_DIGITS_VAR[n0])
print_byte(_INTEGER_DIGITS_VAR[n1])
} else {
print_rune(r)
}
@@ -153,7 +156,7 @@ print_encoded_rune :: proc "contextless" (r: rune) {
print_byte('\'')
}
print_rune :: proc "contextless" (r: rune) -> (int, _OS_Errno) #no_bounds_check {
print_rune :: proc "contextless" (r: rune) -> int #no_bounds_check {
RUNE_SELF :: 0x80
if r < RUNE_SELF {
@@ -161,29 +164,27 @@ print_rune :: proc "contextless" (r: rune) -> (int, _OS_Errno) #no_bounds_check
}
b, n := encode_rune(r)
return os_write(b[:n])
m, _ := os_write(b[:n])
return m
}
print_u64 :: proc "contextless" (x: u64) #no_bounds_check {
digits := _INTEGER_DIGITS
a: [129]byte
i := len(a)
b := u64(10)
u := x
for u >= b {
i -= 1; a[i] = digits[u % b]
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
u /= b
}
i -= 1; a[i] = digits[u % b]
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
os_write(a[i:])
}
print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
digits := _INTEGER_DIGITS
b :: i64(10)
u := x
@@ -193,10 +194,10 @@ print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
a: [129]byte
i := len(a)
for u >= b {
i -= 1; a[i] = digits[u % b]
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
u /= b
}
i -= 1; a[i] = digits[u % b]
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
if neg {
i -= 1; a[i] = '-'
}

View File

@@ -236,4 +236,4 @@ _panic :: proc "contextless" (msg: string) -> ! {
runtime.print_string(msg)
runtime.print_byte('\n')
runtime.trap()
}
}

View File

@@ -1,6 +1,6 @@
package darwin
unix_offset_syscall :: proc(number: System_Call_Number) -> uintptr {
unix_offset_syscall :: proc "contextless" (number: System_Call_Number) -> uintptr {
return uintptr(number) + uintptr(0x2000000)
}

View File

@@ -229,191 +229,191 @@ _Proc_Bsdinfo :: struct {
/*--==========================================================================--*/
syscall_fsync :: #force_inline proc(fildes: c.int) -> bool {
syscall_fsync :: #force_inline proc "contextless" (fildes: c.int) -> bool {
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.fsync), uintptr(fildes)))
}
syscall_write :: #force_inline proc (fildes: c.int, buf: ^byte, nbyte: u64) -> bool {
syscall_write :: #force_inline proc "contextless" (fildes: c.int, buf: ^byte, nbyte: u64) -> bool {
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.write), uintptr(fildes), uintptr(buf), uintptr(nbyte)))
}
syscall_read :: #force_inline proc(fildes: c.int, buf: ^byte, nbyte: u64) -> i64 {
syscall_read :: #force_inline proc "contextless" (fildes: c.int, buf: ^byte, nbyte: u64) -> i64 {
return cast(i64)intrinsics.syscall(unix_offset_syscall(.read), uintptr(fildes), uintptr(buf), uintptr(nbyte))
}
syscall_open :: #force_inline proc(path: cstring, oflag: u32, mode: u32) -> c.int {
syscall_open :: #force_inline proc "contextless" (path: cstring, oflag: u32, mode: u32) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.open), transmute(uintptr)path, uintptr(oflag), uintptr(mode))
}
syscall_close :: #force_inline proc(fd: c.int) -> bool {
syscall_close :: #force_inline proc "contextless" (fd: c.int) -> bool {
return !(cast(bool)intrinsics.syscall(unix_offset_syscall(.close), uintptr(fd)))
}
syscall_fchmod :: #force_inline proc(fildes: c.int, mode: u32) -> c.int {
syscall_fchmod :: #force_inline proc "contextless" (fildes: c.int, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.fchmod), uintptr(fildes), uintptr(mode)))
}
syscall_chmod :: #force_inline proc(path: cstring, mode: u32) -> c.int {
syscall_chmod :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.chmod), transmute(uintptr)path, uintptr(mode)))
}
syscall_mkdir :: #force_inline proc(path: cstring, mode: u32) -> c.int {
syscall_mkdir :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.mkdir), transmute(uintptr)path, uintptr(mode)))
}
syscall_mkdir_at :: #force_inline proc(fd: c.int, path: cstring, mode: u32) -> c.int {
syscall_mkdir_at :: #force_inline proc "contextless" (fd: c.int, path: cstring, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.mkdir), uintptr(fd), transmute(uintptr)path, uintptr(mode)))
}
syscall_rmdir :: #force_inline proc(path: cstring, mode: u32) -> c.int {
syscall_rmdir :: #force_inline proc "contextless" (path: cstring, mode: u32) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.rmdir), transmute(uintptr)path, uintptr(mode)))
}
syscall_rename :: #force_inline proc(path_old: cstring, path_new: cstring) -> c.int {
syscall_rename :: #force_inline proc "contextless" (path_old: cstring, path_new: cstring) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.rename), transmute(uintptr)path_old, transmute(uintptr)path_new))
}
syscall_rename_at :: #force_inline proc(from_fd: c.int, from: cstring, to_fd: c.int, to: cstring) -> c.int {
syscall_rename_at :: #force_inline proc "contextless" (from_fd: c.int, from: cstring, to_fd: c.int, to: cstring) -> c.int {
return (cast(c.int)intrinsics.syscall(unix_offset_syscall(.renameat), uintptr(from_fd), transmute(uintptr)from, uintptr(to_fd), transmute(uintptr)to))
}
syscall_lseek :: #force_inline proc(fd: c.int, offset: i64, whence: c.int) -> i64 {
syscall_lseek :: #force_inline proc "contextless" (fd: c.int, offset: i64, whence: c.int) -> i64 {
return cast(i64)intrinsics.syscall(unix_offset_syscall(.lseek), uintptr(fd), uintptr(offset), uintptr(whence))
}
syscall_gettid :: #force_inline proc() -> u64 {
syscall_gettid :: #force_inline proc "contextless" () -> u64 {
return cast(u64)intrinsics.syscall(unix_offset_syscall(.gettid))
}
syscall_fstat :: #force_inline proc(fd: c.int, status: ^stat) -> c.int {
syscall_fstat :: #force_inline proc "contextless" (fd: c.int, status: ^stat) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fstat), uintptr(fd), uintptr(status))
}
syscall_lstat :: #force_inline proc(path: cstring, status: ^stat) -> c.int {
syscall_lstat :: #force_inline proc "contextless" (path: cstring, status: ^stat) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.lstat), transmute(uintptr)path, uintptr(status))
}
syscall_stat :: #force_inline proc(path: cstring, status: ^stat) -> c.int {
syscall_stat :: #force_inline proc "contextless" (path: cstring, status: ^stat) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.stat), transmute(uintptr)path, uintptr(status))
}
syscall_fstatat :: #force_inline proc(fd: c.int, path: cstring, status: ^stat) -> c.int {
syscall_fstatat :: #force_inline proc "contextless" (fd: c.int, path: cstring, status: ^stat) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fstatat), uintptr(fd), transmute(uintptr)path, uintptr(status))
}
syscall_link :: #force_inline proc(path: cstring, to_link: cstring) -> c.int {
syscall_link :: #force_inline proc "contextless" (path: cstring, to_link: cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.link), transmute(uintptr)path, transmute(uintptr)to_link)
}
syscall_linkat :: #force_inline proc(fd: c.int, path: cstring, fd2: c.int, to_link: cstring) -> c.int {
syscall_linkat :: #force_inline proc "contextless" (fd: c.int, path: cstring, fd2: c.int, to_link: cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.linkat), uintptr(fd), transmute(uintptr)path, uintptr(fd2), transmute(uintptr)to_link)
}
syscall_readlink :: #force_inline proc(path: cstring, buf: ^u8, buf_size: u64) -> i64 {
syscall_readlink :: #force_inline proc "contextless" (path: cstring, buf: ^u8, buf_size: u64) -> i64 {
return cast(i64)intrinsics.syscall(unix_offset_syscall(.readlink), transmute(uintptr)path, uintptr(buf), uintptr(buf_size))
}
syscall_readlinkat :: #force_inline proc(fd: c.int, path: cstring, buf: ^u8, buf_size: u64) -> i64 {
syscall_readlinkat :: #force_inline proc "contextless" (fd: c.int, path: cstring, buf: ^u8, buf_size: u64) -> i64 {
return cast(i64)intrinsics.syscall(unix_offset_syscall(.readlinkat), uintptr(fd), transmute(uintptr)path, uintptr(buf), uintptr(buf_size))
}
syscall_access :: #force_inline proc(path: cstring, mode: c.int) -> c.int {
syscall_access :: #force_inline proc "contextless" (path: cstring, mode: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.access), transmute(uintptr)path, uintptr(mode))
}
syscall_faccessat :: #force_inline proc(fd: c.int, path: cstring, mode: c.int, flag: c.int) -> c.int {
syscall_faccessat :: #force_inline proc "contextless" (fd: c.int, path: cstring, mode: c.int, flag: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.faccessat), uintptr(fd), transmute(uintptr)path, uintptr(mode), uintptr(flag))
}
syscall_getdirentries :: #force_inline proc(fd: c.int, buf: ^u8, nbytes: c.int, base_pointer: ^u32) -> c.int {
syscall_getdirentries :: #force_inline proc "contextless" (fd: c.int, buf: ^u8, nbytes: c.int, base_pointer: ^u32) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getdirentries), uintptr(fd), uintptr(buf), uintptr(nbytes), uintptr(base_pointer))
}
syscall_truncate :: #force_inline proc (path: cstring, length: off_t) -> c.int {
syscall_truncate :: #force_inline proc "contextless" (path: cstring, length: off_t) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.truncate), transmute(uintptr)path, uintptr(length))
}
syscall_ftruncate :: #force_inline proc (fd: c.int, length: off_t) -> c.int {
syscall_ftruncate :: #force_inline proc "contextless" (fd: c.int, length: off_t) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.ftruncate), uintptr(fd), uintptr(length))
}
syscall_sysctl :: #force_inline proc (name: ^c.int, namelen: c.uint, oldp: rawptr, oldlenp: ^i64, newp: ^i8, newlen: i64) -> c.int {
syscall_sysctl :: #force_inline proc "contextless" (name: ^c.int, namelen: c.uint, oldp: rawptr, oldlenp: ^i64, newp: ^i8, newlen: i64) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.sysctl), uintptr(name), uintptr(namelen), uintptr(oldp), uintptr(oldlenp), uintptr(newp), uintptr(newlen))
}
syscall_copyfile :: #force_inline proc(from: cstring, to: cstring, state: rawptr, flags: u32) -> c.int {
syscall_copyfile :: #force_inline proc "contextless" (from: cstring, to: cstring, state: rawptr, flags: u32) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.copyfile), transmute(uintptr)from, transmute(uintptr)to, uintptr(state), uintptr(flags))
}
// think about this? last arg should be more than one
syscall_fcntl :: #force_inline proc(fd: c.int, cmd: c.int, other: rawptr) -> c.int {
syscall_fcntl :: #force_inline proc "contextless" (fd: c.int, cmd: c.int, other: rawptr) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.fsctl), uintptr(fd), uintptr(cmd), uintptr(other))
}
syscall_exit :: #force_inline proc(code: c.int) {
syscall_exit :: #force_inline proc "contextless" (code: c.int) {
intrinsics.syscall(unix_offset_syscall(.exit), uintptr(code))
}
syscall_kill :: #force_inline proc(pid: pid_t, sig: c.int) -> c.int {
syscall_kill :: #force_inline proc "contextless" (pid: pid_t, sig: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.kill), uintptr(pid), uintptr(sig))
}
syscall_dup :: #force_inline proc(fd: c.int) -> c.int {
syscall_dup :: #force_inline proc "contextless" (fd: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.dup), uintptr(fd))
}
syscall_execve :: #force_inline proc(path: cstring, argv: [^]cstring, env: [^]cstring) -> c.int {
syscall_execve :: #force_inline proc "contextless" (path: cstring, argv: [^]cstring, env: [^]cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.execve), transmute(uintptr)path, transmute(uintptr)argv, transmute(uintptr)env)
}
syscall_munmap :: #force_inline proc(addr: rawptr, len: u64) -> c.int {
syscall_munmap :: #force_inline proc "contextless" (addr: rawptr, len: u64) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.mmap), uintptr(addr), uintptr(len))
}
syscall_mmap :: #force_inline proc(addr: ^u8, len: u64, port: c.int, flags: c.int, fd: int, offset: off_t) -> ^u8 {
syscall_mmap :: #force_inline proc "contextless" (addr: ^u8, len: u64, port: c.int, flags: c.int, fd: int, offset: off_t) -> ^u8 {
return cast(^u8)intrinsics.syscall(unix_offset_syscall(.mmap), uintptr(addr), uintptr(len), uintptr(port), uintptr(flags), uintptr(fd), uintptr(offset))
}
syscall_flock :: #force_inline proc(fd: c.int, operation: c.int) -> c.int {
syscall_flock :: #force_inline proc "contextless" (fd: c.int, operation: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.flock), uintptr(fd), uintptr(operation))
}
syscall_utimes :: #force_inline proc(path: cstring, times: ^timeval) -> c.int {
syscall_utimes :: #force_inline proc "contextless" (path: cstring, times: ^timeval) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.utimes), transmute(uintptr)path, uintptr(times))
}
syscall_futimes :: #force_inline proc(fd: c.int, times: ^timeval) -> c.int {
syscall_futimes :: #force_inline proc "contextless" (fd: c.int, times: ^timeval) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.futimes), uintptr(fd), uintptr(times))
}
syscall_adjtime :: #force_inline proc(delta: ^timeval, old_delta: ^timeval) -> c.int {
syscall_adjtime :: #force_inline proc "contextless" (delta: ^timeval, old_delta: ^timeval) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.adjtime), uintptr(delta), uintptr(old_delta))
}
syscall_sysctlbyname :: #force_inline proc(name: cstring, oldp: rawptr, oldlenp: ^i64, newp: rawptr, newlen: i64) -> c.int {
syscall_sysctlbyname :: #force_inline proc "contextless" (name: cstring, oldp: rawptr, oldlenp: ^i64, newp: rawptr, newlen: i64) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.sysctlbyname), transmute(uintptr)name, uintptr(oldp), uintptr(oldlenp), uintptr(newp), uintptr(newlen))
}
syscall_proc_info :: #force_inline proc(num: c.int, pid: u32, flavor: c.int, arg: u64, buffer: rawptr, buffer_size: c.int) -> c.int {
syscall_proc_info :: #force_inline proc "contextless" (num: c.int, pid: u32, flavor: c.int, arg: u64, buffer: rawptr, buffer_size: c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.proc_info), uintptr(num), uintptr(pid), uintptr(flavor), uintptr(arg), uintptr(buffer), uintptr(buffer_size))
}
syscall_openat :: #force_inline proc(fd: int, path: cstring, oflag: u32, mode: u32) -> c.int {
syscall_openat :: #force_inline proc "contextless" (fd: int, path: cstring, oflag: u32, mode: u32) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.openat), uintptr(fd), transmute(uintptr)path, uintptr(oflag), uintptr(mode))
}
syscall_getentropy :: #force_inline proc(buf: [^]u8, buflen: u64) -> c.int {
syscall_getentropy :: #force_inline proc "contextless" (buf: [^]u8, buflen: u64) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(buf), uintptr(buflen))
}
syscall_pipe :: #force_inline proc(fds: [^]c.int) -> c.int {
syscall_pipe :: #force_inline proc "contextless" (fds: [^]c.int) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(&fds[0]), uintptr(&fds[1]))
}
syscall_chdir :: #force_inline proc(path: cstring) -> c.int {
syscall_chdir :: #force_inline proc "contextless" (path: cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), transmute(uintptr)path)
}
syscall_fchdir :: #force_inline proc(fd: c.int, path: cstring) -> c.int {
syscall_fchdir :: #force_inline proc "contextless" (fd: c.int, path: cstring) -> c.int {
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(fd), transmute(uintptr)path)
}
}

View File

@@ -1563,15 +1563,167 @@ MADV_WIPEONFORK :: 18
MADV_KEEPONFORK :: 19
MADV_HWPOISON :: 100
// pipe2 flags
O_CLOEXEC :: 0o2000000
// perf event data
Perf_Sample :: struct #raw_union {
period: u64,
frequency: u64,
}
Perf_Wakeup :: struct #raw_union {
events: u32,
watermark: u32,
}
Perf_Field1 :: struct #raw_union {
breakpoint_addr: u64,
kprobe_func: u64,
uprobe_path: u64,
config1: u64,
}
Perf_Field2 :: struct #raw_union {
breakpoint_len: u64,
kprobe_addr: u64,
uprobe_offset: u64,
config2: u64,
}
Perf_Event_Attr :: struct #packed {
type: u32,
size: u32,
config: u64,
sample: Perf_Sample,
sample_type: u64,
read_format: u64,
flags: Perf_Flags,
wakeup: Perf_Wakeup,
breakpoint_type: u32,
field1: Perf_Field1,
field2: Perf_Field2,
branch_sample_type: u64,
sample_regs_user: u64,
sample_stack_user: u32,
clock_id: i32,
sample_regs_intr: u64,
aux_watermark: u32,
sample_max_stack: u16,
_padding: u16,
}
Perf_Event_Flags :: distinct bit_set[Perf_Event_Flag; u64]
Perf_Event_Flag :: enum u64 {
Bit0 = 0,
Bit0_Is_Deprecated = 1,
User_Rdpmc = 2,
User_Time = 3,
User_Time_Zero = 4,
User_Time_Short = 5,
}
Perf_Capabilities :: struct #raw_union {
capabilities: u64,
flags: Perf_Event_Flags,
}
Perf_Event_mmap_Page :: struct #packed {
version: u32,
compat_version: u32,
lock: u32,
index: u32,
offset: i64,
time_enabled: u64,
time_running: u64,
cap: Perf_Capabilities,
pmc_width: u16,
time_shift: u16,
time_mult: u32,
time_offset: u64,
time_zero: u64,
size: u32,
reserved1: u32,
time_cycles: u64,
time_mask: u64,
reserved2: [116*8]u8,
data_head: u64,
data_tail: u64,
data_offset: u64,
data_size: u64,
aux_head: u64,
aux_tail: u64,
aux_offset: u64,
aux_size: u64,
}
Perf_Type_Id :: enum u32 {
Hardware = 0,
Software = 1,
Tracepoint = 2,
HW_Cache = 3,
Raw = 4,
Breakpoint = 5,
}
Perf_Hardware_Id :: enum u64 {
CPU_Cycles = 0,
Instructions = 1,
Cache_References = 2,
Cache_Misses = 3,
Branch_Instructions = 4,
Branch_Misses = 5,
Bus_Cycles = 6,
Stalled_Cycles_Frontend = 7,
Stalled_Cycles_Backend = 8,
Ref_CPU_Cycles = 9,
}
Perf_Flags :: distinct bit_set[Perf_Flag; u64]
Perf_Flag :: enum u64 {
Disabled = 0,
Inherit = 1,
Pinned = 2,
Exclusive = 3,
Exclude_User = 4,
Exclude_Kernel = 5,
Exclude_HV = 6,
Exclude_Idle = 7,
mmap = 8,
Comm = 9,
Freq = 10,
Inherit_Stat = 11,
Enable_On_Exec = 12,
Task = 13,
Watermark = 14,
Precise_IP_0 = 15,
Precise_IP_1 = 16,
mmap_Data = 17,
Sample_Id_All = 18,
Exclude_Host = 19,
Exclude_Guest = 20,
Exclude_Callchain_Kernel = 21,
Exclude_Callchain_User = 22,
mmap2 = 23,
Comm_Exec = 24,
Use_Clockid = 25,
Context_Switch = 26,
Write_Backward = 27,
Namespaces = 28,
KSymbol = 29,
BPF_Event = 30,
Aux_Output = 31,
CGroup = 32,
Text_Poke = 33,
Build_Id = 34,
Inherit_Thread = 35,
Remove_On_Exec = 36,
Sigtrap = 37,
}
sys_gettid :: proc "contextless" () -> int {
return cast(int)intrinsics.syscall(SYS_gettid)
return int(intrinsics.syscall(SYS_gettid))
}
sys_getrandom :: proc "contextless" (buf: [^]byte, buflen: int, flags: uint) -> int {
return cast(int)intrinsics.syscall(SYS_getrandom, uintptr(buf), uintptr(buflen), uintptr(flags))
sys_getrandom :: proc "contextless" (buf: [^]byte, buflen: uint, flags: int) -> int {
return int(intrinsics.syscall(SYS_getrandom, uintptr(buf), uintptr(buflen), uintptr(flags)))
}
sys_open :: proc "contextless" (path: cstring, flags: int, mode: int = 0o000) -> int {
sys_open :: proc "contextless" (path: cstring, flags: int, mode: uint = 0o000) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
} else { // NOTE: arm64 does not have open
@@ -1579,7 +1731,7 @@ sys_open :: proc "contextless" (path: cstring, flags: int, mode: int = 0o000) ->
}
}
sys_openat :: proc "contextless" (dfd: int, path: cstring, flags: int, mode: int = 0o000) -> int {
sys_openat :: proc "contextless" (dfd: int, path: cstring, flags: int, mode: uint = 0o000) -> int {
return int(intrinsics.syscall(SYS_openat, uintptr(dfd), uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
}
@@ -1691,7 +1843,7 @@ sys_fchdir :: proc "contextless" (fd: int) -> int {
return int(intrinsics.syscall(SYS_fchdir, uintptr(fd)))
}
sys_chmod :: proc "contextless" (path: cstring, mode: int) -> int {
sys_chmod :: proc "contextless" (path: cstring, mode: uint) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(SYS_chmod, uintptr(rawptr(path)), uintptr(mode)))
} else { // NOTE: arm64 does not have chmod
@@ -1699,7 +1851,7 @@ sys_chmod :: proc "contextless" (path: cstring, mode: int) -> int {
}
}
sys_fchmod :: proc "contextless" (fd: int, mode: int) -> int {
sys_fchmod :: proc "contextless" (fd: int, mode: uint) -> int {
return int(intrinsics.syscall(SYS_fchmod, uintptr(fd), uintptr(mode)))
}
@@ -1759,7 +1911,7 @@ sys_rmdir :: proc "contextless" (path: cstring) -> int {
}
}
sys_mkdir :: proc "contextless" (path: cstring, mode: int) -> int {
sys_mkdir :: proc "contextless" (path: cstring, mode: uint) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(SYS_mkdir, uintptr(rawptr(path)), uintptr(mode)))
} else { // NOTE: arm64 does not have mkdir
@@ -1767,11 +1919,11 @@ sys_mkdir :: proc "contextless" (path: cstring, mode: int) -> int {
}
}
sys_mkdirat :: proc "contextless" (dfd: int, path: cstring, mode: int) -> int {
sys_mkdirat :: proc "contextless" (dfd: int, path: cstring, mode: uint) -> int {
return int(intrinsics.syscall(SYS_mkdirat, uintptr(dfd), uintptr(rawptr(path)), uintptr(mode)))
}
sys_mknod :: proc "contextless" (path: cstring, mode: int, dev: int) -> int {
sys_mknod :: proc "contextless" (path: cstring, mode: uint, dev: int) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(SYS_mknod, uintptr(rawptr(path)), uintptr(mode), uintptr(dev)))
} else { // NOTE: arm64 does not have mknod
@@ -1779,7 +1931,7 @@ sys_mknod :: proc "contextless" (path: cstring, mode: int, dev: int) -> int {
}
}
sys_mknodat :: proc "contextless" (dfd: int, path: cstring, mode: int, dev: int) -> int {
sys_mknodat :: proc "contextless" (dfd: int, path: cstring, mode: uint, dev: int) -> int {
return int(intrinsics.syscall(SYS_mknodat, uintptr(dfd), uintptr(rawptr(path)), uintptr(mode), uintptr(dev)))
}
@@ -1818,6 +1970,16 @@ sys_fork :: proc "contextless" () -> int {
return int(intrinsics.syscall(SYS_clone, SIGCHLD))
}
}
sys_pipe2 :: proc "contextless" (fds: rawptr, flags: int) -> int {
return int(intrinsics.syscall(SYS_pipe2, uintptr(fds), uintptr(flags)))
}
sys_dup2 :: proc "contextless" (oldfd: int, newfd: int) -> int {
when ODIN_ARCH != .arm64 {
return int(intrinsics.syscall(SYS_dup2, uintptr(oldfd), uintptr(newfd)))
} else {
return int(intrinsics.syscall(SYS_dup3, uintptr(oldfd), uintptr(newfd), 0))
}
}
sys_mmap :: proc "contextless" (addr: rawptr, length: uint, prot, flags, fd: int, offset: uintptr) -> int {
return int(intrinsics.syscall(SYS_mmap, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), offset))
@@ -1846,6 +2008,14 @@ sys_utimensat :: proc "contextless" (dfd: int, path: cstring, times: rawptr, fla
return int(intrinsics.syscall(SYS_utimensat, uintptr(dfd), uintptr(rawptr(path)), uintptr(times), uintptr(flags)))
}
sys_perf_event_open :: proc "contextless" (event_attr: rawptr, pid: i32, cpu: i32, group_fd: i32, flags: u32) -> int {
return int(intrinsics.syscall(SYS_perf_event_open, uintptr(event_attr), uintptr(pid), uintptr(cpu), uintptr(group_fd), uintptr(flags)))
}
sys_personality :: proc(persona: u64) -> int {
return int(intrinsics.syscall(SYS_personality, uintptr(persona)))
}
get_errno :: proc "contextless" (res: int) -> i32 {
if res < 0 && res > -4096 {
return i32(-res)

View File

@@ -315,6 +315,13 @@ foreign kernel32 {
lpOverlapped: LPOVERLAPPED,
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
) -> BOOL ---
FindFirstChangeNotificationW :: proc(
lpPathName: LPWSTR,
bWatchSubtree: BOOL,
dwNotifyFilter: DWORD,
) -> HANDLE ---
FindNextChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL ---
FindCloseChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL ---
InitializeSRWLock :: proc(SRWLock: ^SRWLOCK) ---
AcquireSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) ---

View File

@@ -1,11 +1,11 @@
package time
import "core:runtime"
import "core:intrinsics"
Tick :: struct {
_nsec: i64, // relative amount
}
tick_now :: proc "contextless" () -> Tick {
return _tick_now()
}
@@ -40,6 +40,53 @@ _tick_duration_end :: proc "contextless" (d: ^Duration, t: Tick) {
d^ = tick_since(t)
}
when ODIN_ARCH == .amd64 {
@(private)
x86_has_invariant_tsc :: proc "contextless" () -> bool {
eax, _, _, _ := intrinsics.x86_cpuid(0x80_000_000, 0)
// Is this processor *really* ancient?
if eax < 0x80_000_007 {
return false
}
// check if the invariant TSC bit is set
_, _, _, edx := intrinsics.x86_cpuid(0x80_000_007, 0)
return (edx & (1 << 8)) != 0
}
}
has_invariant_tsc :: proc "contextless" () -> bool {
when ODIN_ARCH == .amd64 {
return x86_has_invariant_tsc()
}
return false
}
tsc_frequency :: proc "contextless" () -> (u64, bool) {
if !has_invariant_tsc() {
return 0, false
}
hz, ok := _get_tsc_frequency()
if !ok {
// fallback to approximate TSC
tsc_begin := intrinsics.read_cycle_counter()
tick_begin := tick_now()
sleep(2 * Second)
tsc_end := intrinsics.read_cycle_counter()
tick_end := tick_now()
time_diff := u128(duration_nanoseconds(tick_diff(tick_begin, tick_end)))
hz = u64((u128(tsc_end - tsc_begin) * 1_000_000_000) / time_diff)
}
return hz, true
}
/*
Benchmark helpers
*/
@@ -94,4 +141,4 @@ benchmark :: proc(options: ^Benchmark_Options, allocator := context.allocator) -
options->teardown(allocator) or_return
}
return
}
}

21
core/time/tsc_darwin.odin Normal file
View File

@@ -0,0 +1,21 @@
//+private
//+build darwin
package time
import "core:c"
foreign import libc "System.framework"
foreign libc {
@(link_name="sysctlbyname") _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
}
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
tmp_freq : u64 = 0
tmp_size : i64 = size_of(tmp_freq)
ret := _sysctlbyname("machdep.tsc.frequency", &tmp_freq, &tmp_size, nil, 0)
if ret < 0 {
return 0, false
}
return tmp_freq, true
}

View File

@@ -0,0 +1,21 @@
//+private
//+build freebsd
package time
import "core:c"
foreign import libc "system:c"
foreign libc {
@(link_name="sysctlbyname") _sysctlbyname :: proc(path: cstring, oldp: rawptr, oldlenp: rawptr, newp: rawptr, newlen: int) -> c.int ---
}
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
tmp_freq : u64 = 0
tmp_size : i64 = size_of(tmp_freq)
ret := _sysctlbyname("machdep.tsc_freq", &tmp_freq, &tmp_size, nil, 0)
if ret < 0 {
return 0, false
}
return tmp_freq, true
}

35
core/time/tsc_linux.odin Normal file
View File

@@ -0,0 +1,35 @@
//+private
//+build linux
package time
import "core:intrinsics"
import "core:sys/unix"
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
perf_attr := unix.Perf_Event_Attr{}
perf_attr.type = u32(unix.Perf_Type_Id.Hardware)
perf_attr.config = u64(unix.Perf_Hardware_Id.Instructions)
perf_attr.size = size_of(perf_attr)
perf_attr.flags = {.Disabled, .Exclude_Kernel, .Exclude_HV}
fd := unix.sys_perf_event_open(&perf_attr, 0, -1, -1, 0)
if fd == -1 {
return 0, false
}
defer unix.sys_close(fd)
page_size : uint = 4096
ret := unix.sys_mmap(nil, page_size, unix.PROT_READ, unix.MAP_SHARED, fd, 0)
if ret < 0 && ret > -4096 {
return 0, false
}
addr := rawptr(uintptr(ret))
defer unix.sys_munmap(addr, page_size)
event_page := (^unix.Perf_Event_mmap_Page)(addr)
if .User_Time not_in event_page.cap.flags {
return 0, false
}
frequency := u64((u128(1_000_000_000) << u128(event_page.time_shift)) / u128(event_page.time_mult))
return frequency, true
}

View File

@@ -0,0 +1,7 @@
//+private
//+build openbsd
package time
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
return 0, false
}

View File

@@ -0,0 +1,7 @@
//+private
//+build windows
package time
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
return 0, false
}

View File

@@ -288,7 +288,8 @@ struct BuildContext {
bool ignore_warnings;
bool warnings_as_errors;
bool show_error_line;
bool hide_error_line;
bool has_ansi_terminal_colours;
bool ignore_lazy;
bool ignore_llvm_build;
@@ -1033,7 +1034,10 @@ gb_internal String get_fullpath_core(gbAllocator a, String path) {
}
gb_internal bool show_error_line(void) {
return build_context.show_error_line;
return !build_context.hide_error_line;
}
gb_internal bool has_ansi_terminal_colours(void) {
return build_context.has_ansi_terminal_colours;
}
gb_internal bool has_asm_extension(String const &path) {

View File

@@ -578,7 +578,7 @@ gb_internal void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr
if (operand.mode == Addressing_Invalid ||
base_type(operand.type) == t_invalid) {
gbString str = expr_to_string(init);
error(e->token, "Invalid declaration type '%s'", str);
error(init, "Invalid declaration value '%s'", str);
gb_string_free(str);
}
@@ -816,9 +816,14 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
if (ac.test) {
e->flags |= EntityFlag_Test;
}
if (ac.init) {
if (ac.init && ac.fini) {
error(e->token, "A procedure cannot be both declared as @(init) and @(fini)");
} else if (ac.init) {
e->flags |= EntityFlag_Init;
} else if (ac.fini) {
e->flags |= EntityFlag_Fini;
}
if (ac.set_cold) {
e->flags |= EntityFlag_Cold;
}

View File

@@ -1679,9 +1679,13 @@ gb_internal bool check_unary_op(CheckerContext *c, Operand *o, Token op) {
case Token_Not:
if (!is_type_boolean(type)) {
ERROR_BLOCK();
str = expr_to_string(o->expr);
error(op, "Operator '%.*s' is only allowed on boolean expression", LIT(op.string));
error(op, "Operator '%.*s' is only allowed on boolean expressions", LIT(op.string));
gb_string_free(str);
if (is_type_integer(type)) {
error_line("\tSuggestion: Did you mean to use the bitwise not operator '~'?\n");
}
}
break;
@@ -2019,6 +2023,47 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i
}
gb_internal bool check_integer_exceed_suggestion(CheckerContext *c, Operand *o, Type *type) {
if (is_type_integer(type) && o->value.kind == ExactValue_Integer) {
gbString b = type_to_string(type);
i64 sz = type_size_of(type);
BigInt *bi = &o->value.value_integer;
if (is_type_unsigned(type)) {
if (big_int_is_neg(bi)) {
error_line("\tA negative value cannot be represented by the unsigned integer type '%s'\n", b);
} else {
BigInt one = big_int_make_u64(1);
BigInt max_size = big_int_make_u64(1);
BigInt bits = big_int_make_i64(8*sz);
big_int_shl_eq(&max_size, &bits);
big_int_sub_eq(&max_size, &one);
String max_size_str = big_int_to_string(temporary_allocator(), &max_size);
error_line("\tThe maximum value that can be represented by '%s' is '%.*s'\n", b, LIT(max_size_str));
}
} else {
BigInt zero = big_int_make_u64(0);
BigInt one = big_int_make_u64(1);
BigInt max_size = big_int_make_u64(1);
BigInt bits = big_int_make_i64(8*sz - 1);
big_int_shl_eq(&max_size, &bits);
if (big_int_is_neg(bi)) {
big_int_neg(&max_size, &max_size);
String max_size_str = big_int_to_string(temporary_allocator(), &max_size);
error_line("\tThe minimum value that can be represented by '%s' is '%.*s'\n", b, LIT(max_size_str));
} else {
big_int_sub_eq(&max_size, &one);
String max_size_str = big_int_to_string(temporary_allocator(), &max_size);
error_line("\tThe maximum value that can be represented by '%s' is '%.*s'\n", b, LIT(max_size_str));
}
}
gb_string_free(b);
return true;
}
return false;
}
gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type) {
gbString a = expr_to_string(o->expr);
gbString b = type_to_string(type);
@@ -2050,6 +2095,8 @@ gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o
error_line("\t whereas slices in general are assumed to be mutable.\n");
} else if (is_type_u8_slice(src) && are_types_identical(dst, t_string) && o->mode != Addressing_Constant) {
error_line("\tSuggestion: the expression may be casted to %s\n", b);
} else if (check_integer_exceed_suggestion(c, o, type)) {
return;
}
}
@@ -2089,8 +2136,8 @@ gb_internal void check_cast_error_suggestion(CheckerContext *c, Operand *o, Type
}
} else if (are_types_identical(src, t_string) && is_type_u8_slice(dst)) {
error_line("\tSuggestion: a string may be transmuted to %s\n", b);
} else if (is_type_u8_slice(src) && are_types_identical(dst, t_string) && o->mode != Addressing_Constant) {
error_line("\tSuggestion: the expression may be casted to %s\n", b);
} else if (check_integer_exceed_suggestion(c, o, type)) {
return;
}
}
@@ -2116,16 +2163,22 @@ gb_internal bool check_is_expressible(CheckerContext *ctx, Operand *o, Type *typ
o->mode = Addressing_Invalid;
);
ERROR_BLOCK();
if (is_type_numeric(o->type) && is_type_numeric(type)) {
if (!is_type_integer(o->type) && is_type_integer(type)) {
error(o->expr, "'%s' truncated to '%s', got %s", a, b, s);
} else {
ERROR_BLOCK();
error(o->expr, "Cannot convert numeric value '%s' to '%s' from '%s', got %s", a, b, c, s);
if (are_types_identical(o->type, type)) {
error(o->expr, "Numeric value '%s' from '%s' cannot be represented by '%s'", s, a, b);
} else {
error(o->expr, "Cannot convert numeric value '%s' from '%s' to '%s' from '%s'", s, a, b, c);
}
check_assignment_error_suggestion(ctx, o, type);
}
} else {
ERROR_BLOCK();
error(o->expr, "Cannot convert '%s' to '%s' from '%s', got %s", a, b, c, s);
check_assignment_error_suggestion(ctx, o, type);
}
@@ -2344,7 +2397,7 @@ gb_internal void add_comparison_procedures_for_fields(CheckerContext *c, Type *t
}
gb_internal void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) {
gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Operand *y, TokenKind op) {
if (x->mode == Addressing_Type && y->mode == Addressing_Type) {
bool comp = are_types_identical(x->type, y->type);
switch (op) {
@@ -2432,7 +2485,7 @@ gb_internal void check_comparison(CheckerContext *c, Operand *x, Operand *y, Tok
}
if (err_str != nullptr) {
error(x->expr, "Cannot compare expression, %s", err_str);
error(node, "Cannot compare expression, %s", err_str);
x->type = t_untyped_bool;
} else {
if (x->mode == Addressing_Constant &&
@@ -2597,10 +2650,12 @@ gb_internal void check_shift(CheckerContext *c, Operand *x, Operand *y, Ast *nod
x->type = t_untyped_integer;
}
x->expr = node;
x->value = exact_value_shift(be->op.kind, x_val, y_val);
if (is_type_typed(x->type)) {
check_is_expressible(c, x, base_type(x->type));
check_is_expressible(c, x, x->type);
}
return;
}
@@ -2915,17 +2970,38 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) {
bool can_convert = check_cast_internal(c, x, type);
if (!can_convert) {
gbString expr_str = expr_to_string(x->expr);
gbString to_type = type_to_string(type);
gbString from_type = type_to_string(x->type);
error(x->expr, "Cannot cast '%s' as '%s' from '%s'", expr_str, to_type, from_type);
gb_string_free(from_type);
gb_string_free(to_type);
gb_string_free(expr_str);
check_cast_error_suggestion(c, x, type);
TEMPORARY_ALLOCATOR_GUARD();
gbString expr_str = expr_to_string(x->expr, temporary_allocator());
gbString to_type = type_to_string(type, temporary_allocator());
gbString from_type = type_to_string(x->type, temporary_allocator());
x->mode = Addressing_Invalid;
begin_error_block();
error(x->expr, "Cannot cast '%s' as '%s' from '%s'", expr_str, to_type, from_type);
if (is_const_expr) {
gbString val_str = exact_value_to_string(x->value);
if (is_type_float(x->type) && is_type_integer(type)) {
error_line("\t%s cannot be represented without truncation/rounding as the type '%s'\n", val_str, to_type);
// NOTE(bill): keep the mode and modify the type to minimize errors further on
x->mode = Addressing_Constant;
x->type = type;
} else {
error_line("\t'%s' cannot be represented as the type '%s'\n", val_str, to_type);
if (is_type_numeric(type)) {
// NOTE(bill): keep the mode and modify the type to minimize errors further on
x->mode = Addressing_Constant;
x->type = type;
}
}
gb_string_free(val_str);
}
check_cast_error_suggestion(c, x, type);
end_error_block();
return;
}
@@ -3422,7 +3498,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ
if (token_is_comparison(op.kind)) {
check_comparison(c, x, y, op.kind);
check_comparison(c, node, x, y, op.kind);
return;
}
@@ -4539,7 +4615,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
entity = scope_lookup_current(import_scope, entity_name);
bool allow_builtin = false;
if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) {
error(op_expr, "'%.*s' is not declared by '%.*s'", LIT(entity_name), LIT(import_name));
error(node, "'%.*s' is not declared by '%.*s'", LIT(entity_name), LIT(import_name));
operand->mode = Addressing_Invalid;
operand->expr = node;
@@ -4559,7 +4635,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
if (!is_entity_exported(entity, allow_builtin)) {
gbString sel_str = expr_to_string(selector);
error(op_expr, "'%s' is not exported by '%.*s'", sel_str, LIT(import_name));
error(node, "'%s' is not exported by '%.*s'", sel_str, LIT(import_name));
gb_string_free(sel_str);
// NOTE(bill): make the state valid still, even if it's "invalid"
// operand->mode = Addressing_Invalid;
@@ -4730,20 +4806,29 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
gbString op_str = expr_to_string(op_expr);
gbString type_str = type_to_string_shorthand(operand->type);
gbString sel_str = expr_to_string(selector);
error(op_expr, "'%s' of type '%s' has no field '%s'", op_str, type_str, sel_str);
if (operand->type != nullptr && selector->kind == Ast_Ident) {
String const &name = selector->Ident.token.string;
Type *bt = base_type(operand->type);
if (operand->type->kind == Type_Named &&
operand->type->Named.type_name &&
operand->type->Named.type_name->kind == Entity_TypeName &&
operand->type->Named.type_name->TypeName.objc_metadata) {
check_did_you_mean_objc_entity(name, operand->type->Named.type_name, operand->mode == Addressing_Type);
} else if (bt->kind == Type_Struct) {
check_did_you_mean_type(name, bt->Struct.fields);
} else if (bt->kind == Type_Enum) {
check_did_you_mean_type(name, bt->Enum.fields);
if (operand->mode == Addressing_Type) {
if (is_type_polymorphic(operand->type, true)) {
error(op_expr, "Type '%s' has no field nor polymorphic parameter '%s'", op_str, sel_str);
} else {
error(op_expr, "Type '%s' has no field '%s'", op_str, sel_str);
}
} else {
error(op_expr, "'%s' of type '%s' has no field '%s'", op_str, type_str, sel_str);
if (operand->type != nullptr && selector->kind == Ast_Ident) {
String const &name = selector->Ident.token.string;
Type *bt = base_type(operand->type);
if (operand->type->kind == Type_Named &&
operand->type->Named.type_name &&
operand->type->Named.type_name->kind == Entity_TypeName &&
operand->type->Named.type_name->TypeName.objc_metadata) {
check_did_you_mean_objc_entity(name, operand->type->Named.type_name, operand->mode == Addressing_Type);
} else if (bt->kind == Type_Struct) {
check_did_you_mean_type(name, bt->Struct.fields);
} else if (bt->kind == Type_Enum) {
check_did_you_mean_type(name, bt->Enum.fields);
}
}
}
@@ -5418,7 +5503,18 @@ gb_internal CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
data->score = score;
data->result_type = final_proc_type->Proc.results;
data->gen_entity = gen_entity;
add_type_and_value(c, ce->proc, Addressing_Value, final_proc_type, {});
Ast *proc_lit = nullptr;
if (ce->proc->tav.value.kind == ExactValue_Procedure) {
Ast *vp = unparen_expr(ce->proc->tav.value.value_procedure);
if (vp && vp->kind == Ast_ProcLit) {
proc_lit = vp;
}
}
if (proc_lit == nullptr) {
add_type_and_value(c, ce->proc, Addressing_Value, final_proc_type, {});
}
}
return err;
@@ -7033,7 +7129,7 @@ gb_internal bool ternary_compare_types(Type *x, Type *y) {
}
gb_internal bool check_range(CheckerContext *c, Ast *node, Operand *x, Operand *y, ExactValue *inline_for_depth_, Type *type_hint=nullptr) {
gb_internal bool check_range(CheckerContext *c, Ast *node, bool is_for_loop, Operand *x, Operand *y, ExactValue *inline_for_depth_, Type *type_hint=nullptr) {
if (!is_ast_range(node)) {
return false;
}
@@ -7082,9 +7178,17 @@ gb_internal bool check_range(CheckerContext *c, Ast *node, Operand *x, Operand *
}
Type *type = x->type;
if (!is_type_integer(type) && !is_type_float(type) && !is_type_pointer(type) && !is_type_enum(type)) {
error(ie->op, "Only numerical and pointer types are allowed within interval expressions");
return false;
if (is_for_loop) {
if (!is_type_integer(type) && !is_type_float(type) && !is_type_enum(type)) {
error(ie->op, "Only numerical types are allowed within interval expressions");
return false;
}
} else {
if (!is_type_integer(type) && !is_type_float(type) && !is_type_pointer(type) && !is_type_enum(type)) {
error(ie->op, "Only numerical and pointer types are allowed within interval expressions");
return false;
}
}
if (x->mode == Addressing_Constant &&
@@ -7790,6 +7894,124 @@ gb_internal ExprKind check_or_return_expr(CheckerContext *c, Operand *o, Ast *no
return Expr_Expr;
}
gb_internal void check_compound_literal_field_values(CheckerContext *c, Slice<Ast *> const &elems, Operand *o, Type *type, bool &is_constant) {
Type *bt = base_type(type);
StringSet fields_visited = {};
defer (string_set_destroy(&fields_visited));
StringMap<String> fields_visited_through_raw_union = {};
defer (string_map_destroy(&fields_visited_through_raw_union));
for (Ast *elem : elems) {
if (elem->kind != Ast_FieldValue) {
error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
continue;
}
ast_node(fv, FieldValue, elem);
if (fv->field->kind != Ast_Ident) {
gbString expr_str = expr_to_string(fv->field);
error(elem, "Invalid field name '%s' in structure literal", expr_str);
gb_string_free(expr_str);
continue;
}
String name = fv->field->Ident.token.string;
Selection sel = lookup_field(type, name, o->mode == Addressing_Type);
bool is_unknown = sel.entity == nullptr;
if (is_unknown) {
error(fv->field, "Unknown field '%.*s' in structure literal", LIT(name));
continue;
}
Entity *field = bt->Struct.fields[sel.index[0]];
add_entity_use(c, fv->field, field);
if (string_set_update(&fields_visited, name)) {
if (sel.index.count > 1) {
if (String *found = string_map_get(&fields_visited_through_raw_union, sel.entity->token.string)) {
error(fv->field, "Field '%.*s' is already initialized due to a previously assigned struct #raw_union field '%.*s'", LIT(sel.entity->token.string), LIT(*found));
} else {
error(fv->field, "Duplicate or reused field '%.*s' in structure literal", LIT(sel.entity->token.string));
}
} else {
error(fv->field, "Duplicate field '%.*s' in structure literal", LIT(field->token.string));
}
continue;
} else if (String *found = string_map_get(&fields_visited_through_raw_union, sel.entity->token.string)) {
error(fv->field, "Field '%.*s' is already initialized due to a previously assigned struct #raw_union field '%.*s'", LIT(sel.entity->token.string), LIT(*found));
continue;
}
if (sel.indirect) {
error(fv->field, "Cannot assign to the %d-nested anonymous indirect field '%.*s' in a structure literal", cast(int)sel.index.count-1, LIT(name));
continue;
}
if (sel.index.count > 1) {
if (is_constant) {
Type *ft = type;
for (i32 index : sel.index) {
Type *bt = base_type(ft);
switch (bt->kind) {
case Type_Struct:
if (bt->Struct.is_raw_union) {
is_constant = false;
break;
}
ft = bt->Struct.fields[index]->type;
break;
case Type_Array:
ft = bt->Array.elem;
break;
default:
GB_PANIC("invalid type: %s", type_to_string(ft));
break;
}
}
if (is_constant &&
(is_type_any(ft) || is_type_union(ft) || is_type_raw_union(ft) || is_type_typeid(ft))) {
is_constant = false;
}
}
Type *nested_ft = bt;
for (i32 index : sel.index) {
Type *bt = base_type(nested_ft);
switch (bt->kind) {
case Type_Struct:
if (bt->Struct.is_raw_union) {
for (Entity *re : bt->Struct.fields) {
string_map_set(&fields_visited_through_raw_union, re->token.string, sel.entity->token.string);
}
}
nested_ft = bt->Struct.fields[index]->type;
break;
case Type_Array:
nested_ft = bt->Array.elem;
break;
default:
GB_PANIC("invalid type %s", type_to_string(nested_ft));
break;
}
}
field = sel.entity;
}
Operand o = {};
check_expr_or_type(c, &o, fv->value, field->type);
if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) {
is_constant = false;
}
if (is_constant) {
is_constant = check_is_operand_compound_lit_constant(c, &o);
}
check_assignment(c, &o, field->type, str_lit("structure literal"));
}
}
gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Expr;
ast_node(cl, CompoundLit, node);
@@ -7877,45 +8099,13 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
error(node, "%s ('struct #raw_union') compound literals are only allowed to contain up to 1 'field = value' element, got %td", type_str, cl->elems.count);
gb_string_free(type_str);
} else {
Ast *elem = cl->elems[0];
ast_node(fv, FieldValue, elem);
if (fv->field->kind != Ast_Ident) {
gbString expr_str = expr_to_string(fv->field);
error(elem, "Invalid field name '%s' in structure literal", expr_str);
gb_string_free(expr_str);
break;
}
String name = fv->field->Ident.token.string;
Selection sel = lookup_field(type, name, o->mode == Addressing_Type);
bool is_unknown = sel.entity == nullptr;
if (is_unknown) {
error(elem, "Unknown field '%.*s' in structure literal", LIT(name));
break;
}
if (sel.index.count > 1) {
error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name));
break;
}
Entity *field = t->Struct.fields[sel.index[0]];
add_entity_use(c, fv->field, field);
Operand o = {};
check_expr_or_type(c, &o, fv->value, field->type);
check_assignment(c, &o, field->type, str_lit("structure literal"));
check_compound_literal_field_values(c, cl->elems, o, type, is_constant);
}
}
}
break;
}
isize field_count = t->Struct.fields.count;
isize min_field_count = t->Struct.fields.count;
for (isize i = min_field_count-1; i >= 0; i--) {
@@ -7929,58 +8119,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
}
if (cl->elems[0]->kind == Ast_FieldValue) {
TEMPORARY_ALLOCATOR_GUARD();
bool *fields_visited = gb_alloc_array(temporary_allocator(), bool, field_count);
for (Ast *elem : cl->elems) {
if (elem->kind != Ast_FieldValue) {
error(elem, "Mixture of 'field = value' and value elements in a literal is not allowed");
continue;
}
ast_node(fv, FieldValue, elem);
if (fv->field->kind != Ast_Ident) {
gbString expr_str = expr_to_string(fv->field);
error(elem, "Invalid field name '%s' in structure literal", expr_str);
gb_string_free(expr_str);
continue;
}
String name = fv->field->Ident.token.string;
Selection sel = lookup_field(type, name, o->mode == Addressing_Type);
bool is_unknown = sel.entity == nullptr;
if (is_unknown) {
error(elem, "Unknown field '%.*s' in structure literal", LIT(name));
continue;
}
if (sel.index.count > 1) {
error(elem, "Cannot assign to an anonymous field '%.*s' in a structure literal (at the moment)", LIT(name));
continue;
}
Entity *field = t->Struct.fields[sel.index[0]];
add_entity_use(c, fv->field, field);
if (fields_visited[sel.index[0]]) {
error(elem, "Duplicate field '%.*s' in structure literal", LIT(name));
continue;
}
fields_visited[sel.index[0]] = true;
Operand o = {};
check_expr_or_type(c, &o, fv->value, field->type);
if (is_type_any(field->type) || is_type_union(field->type) || is_type_raw_union(field->type) || is_type_typeid(field->type)) {
is_constant = false;
}
if (is_constant) {
is_constant = check_is_operand_compound_lit_constant(c, &o);
}
check_assignment(c, &o, field->type, str_lit("structure literal"));
}
check_compound_literal_field_values(c, cl->elems, o, type, is_constant);
} else {
bool seen_field_value = false;
@@ -8097,7 +8236,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
Operand x = {};
Operand y = {};
bool ok = check_range(c, fv->field, &x, &y, nullptr);
bool ok = check_range(c, fv->field, false, &x, &y, nullptr);
if (!ok) {
continue;
}
@@ -8313,7 +8452,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
Operand x = {};
Operand y = {};
bool ok = check_range(c, fv->field, &x, &y, nullptr, index_type);
bool ok = check_range(c, fv->field, false, &x, &y, nullptr, index_type);
if (!ok) {
continue;
}

View File

@@ -725,7 +725,7 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod
Operand x = {};
Operand y = {};
bool ok = check_range(ctx, expr, &x, &y, &inline_for_depth);
bool ok = check_range(ctx, expr, true, &x, &y, &inline_for_depth);
if (!ok) {
goto skip_expr;
}
@@ -978,19 +978,19 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
Operand a = lhs;
Operand b = rhs;
check_comparison(ctx, &a, &x, Token_LtEq);
check_comparison(ctx, expr, &a, &x, Token_LtEq);
if (a.mode == Addressing_Invalid) {
continue;
}
check_comparison(ctx, &b, &x, upper_op);
check_comparison(ctx, expr, &b, &x, upper_op);
if (b.mode == Addressing_Invalid) {
continue;
}
Operand a1 = lhs;
Operand b1 = rhs;
check_comparison(ctx, &a1, &b1, Token_LtEq);
check_comparison(ctx, expr, &a1, &b1, Token_LtEq);
add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs);
@@ -1029,7 +1029,7 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
// NOTE(bill): the ordering here matters
Operand z = y;
check_comparison(ctx, &z, &x, Token_CmpEq);
check_comparison(ctx, expr, &z, &x, Token_CmpEq);
if (z.mode == Addressing_Invalid) {
continue;
}
@@ -1293,7 +1293,6 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_
for (Type *t : variants) {
if (!type_ptr_set_exists(&seen, t)) {
array_add(&unhandled, t);
gb_printf_err("HERE: %p %s\n", t, type_to_string(t));
}
}
@@ -1439,7 +1438,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
Operand x = {};
Operand y = {};
bool ok = check_range(ctx, expr, &x, &y, nullptr);
bool ok = check_range(ctx, expr, true, &x, &y, nullptr);
if (!ok) {
goto skip_expr_range_stmt;
}
@@ -1921,7 +1920,7 @@ gb_internal void check_expr_stmt(CheckerContext *ctx, Ast *node) {
case Addressing_Type:
{
gbString str = type_to_string(operand.type);
error(node, "'%s' is not an expression", str);
error(node, "'%s' is not an expression but a type and cannot be used as a statement", str);
gb_string_free(str);
break;
}

View File

@@ -1309,6 +1309,8 @@ gb_internal ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_
init_core_source_code_location(ctx->checker);
param_value.kind = ParameterValue_Location;
o.type = t_source_code_location;
o.mode = Addressing_Value;
o.expr = expr;
if (in_type) {
check_assignment(ctx, &o, in_type, str_lit("parameter value"));
@@ -1666,17 +1668,21 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
if (is_poly_name) {
bool valid = false;
if (is_type_proc(op.type)) {
Entity *proc_entity = entity_from_expr(op.expr);
valid = (proc_entity != nullptr) && (op.value.kind == ExactValue_Procedure);
if (valid) {
Ast *expr = unparen_expr(op.expr);
Entity *proc_entity = entity_from_expr(expr);
if (proc_entity) {
poly_const = exact_value_procedure(proc_entity->identifier.load() ? proc_entity->identifier.load() : op.expr);
valid = true;
} else if (expr->kind == Ast_ProcLit) {
poly_const = exact_value_procedure(expr);
valid = true;
}
}
if (!valid) {
if (op.mode == Addressing_Constant) {
poly_const = op.value;
} else {
error(op.expr, "Expected a constant value for this polymorphic name parameter");
error(op.expr, "Expected a constant value for this polymorphic name parameter, got %s", expr_to_string(op.expr));
success = false;
}
}

View File

@@ -1155,6 +1155,7 @@ gb_internal void init_checker_info(CheckerInfo *i) {
array_init(&i->variable_init_order, a);
array_init(&i->testing_procedures, a, 0, 0);
array_init(&i->init_procedures, a, 0, 0);
array_init(&i->fini_procedures, a, 0, 0);
array_init(&i->required_foreign_imports_through_force, a, 0, 0);
map_init(&i->objc_msgSend_types);
@@ -1422,7 +1423,7 @@ gb_internal isize type_info_index(CheckerInfo *info, Type *type, bool error_on_f
}
gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode, Type *type, ExactValue value) {
gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode, Type *type, ExactValue const &value) {
if (expr == nullptr) {
return;
}
@@ -1439,7 +1440,7 @@ gb_internal void add_untyped(CheckerContext *c, Ast *expr, AddressingMode mode,
check_set_expr_info(c, expr, mode, type, value);
}
gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMode mode, Type *type, ExactValue value) {
gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMode mode, Type *type, ExactValue const &value) {
if (expr == nullptr) {
return;
}
@@ -1546,7 +1547,7 @@ gb_internal void add_entity_flags_from_file(CheckerContext *c, Entity *e, Scope
AstPackage *pkg = c->file->pkg;
if (pkg->kind == Package_Init && e->kind == Entity_Procedure && e->token.string == "main") {
// Do nothing
} else if (e->flags & (EntityFlag_Test|EntityFlag_Init)) {
} else if (e->flags & (EntityFlag_Test|EntityFlag_Init|EntityFlag_Fini)) {
// Do nothing
} else {
e->flags |= EntityFlag_Lazy;
@@ -1614,7 +1615,7 @@ gb_internal bool could_entity_be_lazy(Entity *e, DeclInfo *d) {
return false;
}
if (e->flags & (EntityFlag_Test|EntityFlag_Init)) {
if (e->flags & (EntityFlag_Test|EntityFlag_Init|EntityFlag_Fini)) {
return false;
} else if (e->kind == Entity_Variable && e->Variable.is_export) {
return false;
@@ -2423,6 +2424,28 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) {
add_dependency_to_set(c, e);
array_add(&c->info.init_procedures, e);
}
} else if (e->flags & EntityFlag_Fini) {
Type *t = base_type(e->type);
GB_ASSERT(t->kind == Type_Proc);
bool is_fini = true;
if (t->Proc.param_count != 0 || t->Proc.result_count != 0) {
gbString str = type_to_string(t);
error(e->token, "@(fini) procedures must have a signature type with no parameters nor results, got %s", str);
gb_string_free(str);
is_fini = false;
}
if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) {
error(e->token, "@(fini) procedures must be declared at the file scope");
is_fini = false;
}
if (is_fini) {
add_dependency_to_set(c, e);
array_add(&c->info.fini_procedures, e);
}
}
break;
}
@@ -2974,6 +2997,12 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
}
ac->init = true;
return true;
} else if (name == "fini") {
if (value != nullptr) {
error(value, "'%.*s' expects no parameter, or a string literal containing \"file\" or \"package\"", LIT(name));
}
ac->fini = true;
return true;
} else if (name == "deferred") {
if (value != nullptr) {
Operand o = {};
@@ -3615,6 +3644,7 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) {
EntityVisiblityKind entity_visibility_kind = c->foreign_context.visibility_kind;
bool is_test = false;
bool is_init = false;
bool is_fini = false;
for_array(i, vd->attributes) {
Ast *attr = vd->attributes[i];
@@ -3674,6 +3704,8 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) {
is_test = true;
} else if (name == "init") {
is_init = true;
} else if (name == "fini") {
is_fini = true;
}
}
}
@@ -3807,8 +3839,12 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) {
if (is_test) {
e->flags |= EntityFlag_Test;
}
if (is_init) {
if (is_init && is_fini) {
error(name, "A procedure cannot be both declared as @(init) and @(fini)");
} else if (is_init) {
e->flags |= EntityFlag_Init;
} else if (is_fini) {
e->flags |= EntityFlag_Fini;
}
} else if (init->kind == Ast_ProcGroup) {
ast_node(pg, ProcGroup, init);
@@ -5634,9 +5670,14 @@ gb_internal GB_COMPARE_PROC(init_procedures_cmp) {
return i32_cmp(x->token.pos.offset, y->token.pos.offset);
}
gb_internal GB_COMPARE_PROC(fini_procedures_cmp) {
return init_procedures_cmp(b, a);
}
gb_internal void check_sort_init_procedures(Checker *c) {
gb_internal void check_sort_init_and_fini_procedures(Checker *c) {
gb_sort_array(c->info.init_procedures.data, c->info.init_procedures.count, init_procedures_cmp);
gb_sort_array(c->info.fini_procedures.data, c->info.fini_procedures.count, fini_procedures_cmp);
}
gb_internal void add_type_info_for_type_definitions(Checker *c) {
@@ -5846,8 +5887,8 @@ gb_internal void check_parsed_files(Checker *c) {
add_type_and_value(&c->builtin_ctx, u.expr, u.info->mode, u.info->type, u.info->value);
}
TIME_SECTION("sort init procedures");
check_sort_init_procedures(c);
TIME_SECTION("sort init and fini procedures");
check_sort_init_and_fini_procedures(c);
if (c->info.intrinsics_entry_point_usage.count > 0) {
TIME_SECTION("check intrinsics.__entry_point usage");

View File

@@ -117,6 +117,7 @@ struct AttributeContext {
bool disabled_proc : 1;
bool test : 1;
bool init : 1;
bool fini : 1;
bool set_cold : 1;
u32 optimization_mode; // ProcedureOptimizationMode
i64 foreign_import_priority_index;
@@ -351,6 +352,7 @@ struct CheckerInfo {
Array<Entity *> testing_procedures;
Array<Entity *> init_procedures;
Array<Entity *> fini_procedures;
Array<Entity *> definitions;
Array<Entity *> entities;
@@ -483,9 +485,9 @@ gb_internal void scope_lookup_parent (Scope *s, String const &name, Scope **s
gb_internal Entity *scope_insert (Scope *s, Entity *entity);
gb_internal void add_type_and_value (CheckerContext *c, Ast *expression, AddressingMode mode, Type *type, ExactValue value);
gb_internal void add_type_and_value (CheckerContext *c, Ast *expression, AddressingMode mode, Type *type, ExactValue const &value);
gb_internal ExprInfo *check_get_expr_info (CheckerContext *c, Ast *expr);
gb_internal void add_untyped (CheckerContext *c, Ast *expression, AddressingMode mode, Type *basic_type, ExactValue value);
gb_internal void add_untyped (CheckerContext *c, Ast *expression, AddressingMode mode, Type *basic_type, ExactValue const &value);
gb_internal void add_entity_use (CheckerContext *c, Ast *identifier, Entity *entity);
gb_internal void add_implicit_entity (CheckerContext *c, Ast *node, Entity *e);
gb_internal void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, DeclInfo *d, bool is_exported=true);

View File

@@ -53,6 +53,11 @@ struct TypeIsPointer<T *> {
enum {value = true};
};
template <typename T> struct TypeIsPtrSizedInteger { enum {value = false}; };
template <> struct TypeIsPtrSizedInteger<isize> { enum {value = true}; };
template <> struct TypeIsPtrSizedInteger<usize> { enum {value = true}; };
#include "unicode.cpp"
#include "array.cpp"
#include "threading.cpp"

View File

@@ -75,6 +75,7 @@ enum EntityFlag : u64 {
EntityFlag_Test = 1ull<<30,
EntityFlag_Init = 1ull<<31,
EntityFlag_Subtype = 1ull<<32,
EntityFlag_Fini = 1ull<<33,
EntityFlag_CustomLinkName = 1ull<<40,
EntityFlag_CustomLinkage_Internal = 1ull<<41,

View File

@@ -97,15 +97,57 @@ gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) {
// NOTE: defined in build_settings.cpp
gb_internal bool global_warnings_as_errors(void);
gb_internal bool global_ignore_warnings(void);
gb_internal bool show_error_line(void);
gb_internal bool has_ansi_terminal_colours(void);
gb_internal gbString get_file_line_as_string(TokenPos const &pos, i32 *offset);
gb_internal void warning(Token const &token, char const *fmt, ...);
gb_internal void error(Token const &token, char const *fmt, ...);
gb_internal void error(TokenPos pos, char const *fmt, ...);
gb_internal void error_line(char const *fmt, ...);
gb_internal void syntax_error(Token const &token, char const *fmt, ...);
gb_internal void syntax_error(TokenPos pos, char const *fmt, ...);
gb_internal void syntax_warning(Token const &token, char const *fmt, ...);
gb_internal void compiler_error(char const *fmt, ...);
gb_internal void begin_error_block(void) {
mutex_lock(&global_error_collector.block_mutex);
global_error_collector.in_block.store(true);
}
gb_internal void end_error_block(void) {
if (global_error_collector.error_buffer.count > 0) {
isize n = global_error_collector.error_buffer.count;
u8 *text = gb_alloc_array(permanent_allocator(), u8, n+1);
isize n = global_error_collector.error_buffer.count;
if (n > 0) {
u8 *text = global_error_collector.error_buffer.data;
bool add_extra_newline = false;
if (show_error_line()) {
if (n >= 2 && !(text[n-2] == '\n' && text[n-1] == '\n')) {
add_extra_newline = true;
}
} else {
isize newline_count = 0;
for (isize i = 0; i < n; i++) {
if (text[i] == '\n') {
newline_count += 1;
}
}
if (newline_count > 1) {
add_extra_newline = true;
}
}
if (add_extra_newline) {
// add an extra new line as padding when the error line is being shown
error_line("\n");
}
n = global_error_collector.error_buffer.count;
text = gb_alloc_array(permanent_allocator(), u8, n+1);
gb_memmove(text, global_error_collector.error_buffer.data, n);
text[n] = 0;
String s = {text, n};
@@ -149,15 +191,8 @@ gb_internal ERROR_OUT_PROC(default_error_out_va) {
gb_file_write(f, buf, n);
}
gb_global ErrorOutProc *error_out_va = default_error_out_va;
// NOTE: defined in build_settings.cpp
gb_internal bool global_warnings_as_errors(void);
gb_internal bool global_ignore_warnings(void);
gb_internal bool show_error_line(void);
gb_internal gbString get_file_line_as_string(TokenPos const &pos, i32 *offset);
gb_internal void error_out(char const *fmt, ...) {
va_list va;
va_start(va, fmt);
@@ -165,6 +200,49 @@ gb_internal void error_out(char const *fmt, ...) {
va_end(va);
}
enum TerminalStyle {
TerminalStyle_Normal,
TerminalStyle_Bold,
TerminalStyle_Underline,
};
enum TerminalColour {
TerminalColour_White,
TerminalColour_Red,
TerminalColour_Yellow,
TerminalColour_Green,
TerminalColour_Cyan,
TerminalColour_Blue,
TerminalColour_Purple,
TerminalColour_Black,
};
gb_internal void terminal_set_colours(TerminalStyle style, TerminalColour foreground) {
if (has_ansi_terminal_colours()) {
char const *ss = "0";
switch (style) {
case TerminalStyle_Normal: ss = "0"; break;
case TerminalStyle_Bold: ss = "1"; break;
case TerminalStyle_Underline: ss = "4"; break;
}
switch (foreground) {
case TerminalColour_White: error_out("\x1b[%s;37m", ss); break;
case TerminalColour_Red: error_out("\x1b[%s;31m", ss); break;
case TerminalColour_Yellow: error_out("\x1b[%s;33m", ss); break;
case TerminalColour_Green: error_out("\x1b[%s;32m", ss); break;
case TerminalColour_Cyan: error_out("\x1b[%s;36m", ss); break;
case TerminalColour_Blue: error_out("\x1b[%s;34m", ss); break;
case TerminalColour_Purple: error_out("\x1b[%s;35m", ss); break;
case TerminalColour_Black: error_out("\x1b[%s;30m", ss); break;
}
}
}
gb_internal void terminal_reset_colours(void) {
if (has_ansi_terminal_colours()) {
error_out("\x1b[0m");
}
}
gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
if (!show_error_line()) {
@@ -181,26 +259,33 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
// TODO(bill): This assumes ASCII
enum {
MAX_LINE_LENGTH = 76,
MAX_LINE_LENGTH = 80,
MAX_TAB_WIDTH = 8,
ELLIPSIS_PADDING = 8
ELLIPSIS_PADDING = 8, // `... ...`
MAX_LINE_LENGTH_PADDED = MAX_LINE_LENGTH-MAX_TAB_WIDTH-ELLIPSIS_PADDING,
};
error_out("\n\t");
if (line.len+MAX_TAB_WIDTH+ELLIPSIS_PADDING > MAX_LINE_LENGTH) {
i32 const half_width = MAX_LINE_LENGTH/2;
i32 left = cast(i32)(offset);
i32 right = cast(i32)(line.len - offset);
left = gb_min(left, half_width);
right = gb_min(right, half_width);
error_out("\t");
terminal_set_colours(TerminalStyle_Bold, TerminalColour_White);
i32 error_length = gb_max(end.offset - pos.offset, 1);
isize squiggle_extra = 0;
if (line.len > MAX_LINE_LENGTH_PADDED) {
i32 left = MAX_TAB_WIDTH;
line.text += offset-left;
line.len -= offset+right-left;
line = string_trim_whitespace(line);
offset = left + ELLIPSIS_PADDING/2;
line.len -= offset-left;
offset = left+MAX_TAB_WIDTH/2;
if (line.len > MAX_LINE_LENGTH_PADDED) {
line.len = MAX_LINE_LENGTH_PADDED;
if (error_length > line.len-left) {
error_length = cast(i32)line.len - left;
squiggle_extra = 1;
}
}
error_out("... %.*s ...", LIT(line));
} else {
error_out("%.*s", LIT(line));
@@ -210,6 +295,9 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
for (i32 i = 0; i < offset; i++) {
error_out(" ");
}
terminal_set_colours(TerminalStyle_Bold, TerminalColour_Green);
error_out("^");
if (end.file_id == pos.file_id) {
if (end.line > pos.line) {
@@ -217,34 +305,54 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
error_out("~");
}
} else if (end.line == pos.line && end.column > pos.column) {
i32 length = gb_min(end.offset - pos.offset, cast(i32)(line.len-offset));
for (i32 i = 1; i < length-1; i++) {
for (i32 i = 1; i < error_length-1+squiggle_extra; i++) {
error_out("~");
}
if (length > 1) {
if (error_length > 1 && squiggle_extra == 0) {
error_out("^");
}
}
}
error_out("\n\n");
terminal_reset_colours();
error_out("\n");
return true;
}
return false;
}
gb_internal void error_out_pos(TokenPos pos) {
terminal_set_colours(TerminalStyle_Bold, TerminalColour_White);
error_out("%s ", token_pos_to_string(pos));
terminal_reset_colours();
}
gb_internal void error_out_coloured(char const *str, TerminalStyle style, TerminalColour foreground) {
terminal_set_colours(style, foreground);
error_out(str);
terminal_reset_colours();
}
gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) {
global_error_collector.count.fetch_add(1);
mutex_lock(&global_error_collector.mutex);
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
error_out("Error: %s\n", gb_bprintf_va(fmt, va));
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
error_out_va(fmt, va);
error_out("\n");
} else if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
error_out("%s %s\n",
token_pos_to_string(pos),
gb_bprintf_va(fmt, va));
error_out_pos(pos);
if (has_ansi_terminal_colours()) {
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
}
error_out_va(fmt, va);
error_out("\n");
show_error_on_line(pos, end);
}
mutex_unlock(&global_error_collector.mutex);
@@ -263,12 +371,15 @@ gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt,
if (!global_ignore_warnings()) {
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
error_out("Warning: %s\n", gb_bprintf_va(fmt, va));
error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
error_out_va(fmt, va);
error_out("\n");
} else if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
error_out("%s Warning: %s\n",
token_pos_to_string(pos),
gb_bprintf_va(fmt, va));
error_out_pos(pos);
error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
error_out_va(fmt, va);
error_out("\n");
show_error_on_line(pos, end);
}
}
@@ -285,12 +396,15 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li
global_error_collector.count++;
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
error_out("Error: %s", gb_bprintf_va(fmt, va));
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
error_out_va(fmt, va);
} else if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
error_out("%s %s",
token_pos_to_string(pos),
gb_bprintf_va(fmt, va));
error_out_pos(pos);
if (has_ansi_terminal_colours()) {
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
}
error_out_va(fmt, va);
}
mutex_unlock(&global_error_collector.mutex);
if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT) {
@@ -305,12 +419,15 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const *
// NOTE(bill): Duplicate error, skip it
if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
error_out("%s Syntax Error: %s\n",
token_pos_to_string(pos),
gb_bprintf_va(fmt, va));
show_error_on_line(pos, end);
error_out_pos(pos);
error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
error_out_va(fmt, va);
error_out("\n");
// show_error_on_line(pos, end);
} else if (pos.line == 0) {
error_out("Syntax Error: %s\n", gb_bprintf_va(fmt, va));
error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
error_out_va(fmt, va);
error_out("\n");
}
mutex_unlock(&global_error_collector.mutex);
@@ -330,12 +447,15 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const
// NOTE(bill): Duplicate error, skip it
if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
error_out("%s Syntax Warning: %s\n",
token_pos_to_string(pos),
gb_bprintf_va(fmt, va));
show_error_on_line(pos, end);
error_out_pos(pos);
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
error_out_va(fmt, va);
error_out("\n");
// show_error_on_line(pos, end);
} else if (pos.line == 0) {
error_out("Warning: %s\n", gb_bprintf_va(fmt, va));
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
error_out_va(fmt, va);
error_out("\n");
}
}
mutex_unlock(&global_error_collector.mutex);

View File

@@ -578,9 +578,7 @@ gb_internal ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i3
}
}
failure:
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op]));
failure:;
ExactValue error_value = {};
return error_value;
}

View File

@@ -1161,6 +1161,34 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
return p;
}
gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // Cleanup Runtime
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin);
lbProcedure *p = lb_create_dummy_procedure(main_module, str_lit(LB_CLEANUP_RUNTIME_PROC_NAME), proc_type);
p->is_startup = true;
lb_begin_procedure_body(p);
CheckerInfo *info = main_module->gen->info;
for (Entity *e : info->fini_procedures) {
lbValue value = lb_find_procedure_value_from_entity(main_module, e);
lb_emit_call(p, value, {}, ProcInlining_none);
}
lb_end_procedure_body(p);
if (!main_module->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
LLVMDumpValue(p->value);
gb_printf_err("\n\n\n\n");
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
return p;
}
gb_internal WORKER_TASK_PROC(lb_generate_procedures_and_types_per_module) {
lbModule *m = cast(lbModule *)data;
for (Entity *e : m->global_procedures_and_types_to_create) {
@@ -1328,6 +1356,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) {
if (m == &m->gen->default_module) {
lb_llvm_function_pass_per_function_internal(m, m->gen->startup_type_info);
lb_llvm_function_pass_per_function_internal(m, m->gen->startup_runtime);
lb_llvm_function_pass_per_function_internal(m, m->gen->cleanup_runtime);
lb_llvm_function_pass_per_function_internal(m, m->gen->objc_names);
}
@@ -1674,7 +1703,7 @@ gb_internal bool lb_llvm_object_generation(lbGenerator *gen, bool do_threading)
gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) {
gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime, lbProcedure *cleanup_runtime) {
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level);
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
@@ -1793,7 +1822,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
if (call_cleanup) {
lbValue cleanup_runtime_value = lb_find_runtime_value(m, str_lit("_cleanup_runtime"));
lbValue cleanup_runtime_value = {cleanup_runtime->value, cleanup_runtime->type};
lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none);
}
@@ -2330,9 +2359,13 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
gen->startup_type_info = lb_create_startup_type_info(default_module);
gen->objc_names = lb_create_objc_names(default_module);
TIME_SECTION("LLVM Runtime Startup Creation (Global Variables)");
TIME_SECTION("LLVM Runtime Startup Creation (Global Variables & @(init))");
gen->startup_runtime = lb_create_startup_runtime(default_module, gen->startup_type_info, gen->objc_names, global_variables);
TIME_SECTION("LLVM Runtime Cleanup Creation & @(fini)");
gen->cleanup_runtime = lb_create_cleanup_runtime(default_module);
if (build_context.ODIN_DEBUG) {
for (auto const &entry : builtin_pkg->scope->elements) {
Entity *e = entry.value;
@@ -2352,7 +2385,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
if (build_context.command_kind == Command_test && !already_has_entry_point) {
TIME_SECTION("LLVM main");
lb_create_main_procedure(default_module, gen->startup_runtime);
lb_create_main_procedure(default_module, gen->startup_runtime, gen->cleanup_runtime);
}
TIME_SECTION("LLVM Procedure Generation (missing)");

View File

@@ -182,6 +182,8 @@ struct lbModule {
PtrMap<Type *, lbAddr> map_cell_info_map; // address of runtime.Map_Info
PtrMap<Type *, lbAddr> map_info_map; // address of runtime.Map_Cell_Info
PtrMap<Ast *, lbAddr> exact_value_compound_literal_addr_map; // Key: Ast_CompoundLit
LLVMPassManagerRef function_pass_managers[lbFunctionPassManager_COUNT];
};
@@ -208,6 +210,7 @@ struct lbGenerator {
lbProcedure *startup_type_info;
lbProcedure *startup_runtime;
lbProcedure *cleanup_runtime;
lbProcedure *objc_names;
};
@@ -540,6 +543,7 @@ gb_internal LLVMTypeRef OdinLLVMGetArrayElementType(LLVMTypeRef type);
gb_internal LLVMTypeRef OdinLLVMGetVectorElementType(LLVMTypeRef type);
#define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
#define LB_CLEANUP_RUNTIME_PROC_NAME "__$cleanup_runtime"
#define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info"
#define LB_TYPE_INFO_DATA_NAME "__$type_info_data"
#define LB_TYPE_INFO_TYPES_NAME "__$type_info_types_data"

View File

@@ -386,6 +386,31 @@ gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, Bi
return value;
}
gb_internal bool lb_is_nested_possibly_constant(Type *ft, Selection const &sel, Ast *elem) {
GB_ASSERT(!sel.indirect);
for (i32 index : sel.index) {
Type *bt = base_type(ft);
switch (bt->kind) {
case Type_Struct:
if (bt->Struct.is_raw_union) {
return false;
}
ft = bt->Struct.fields[index]->type;
break;
case Type_Array:
ft = bt->Array.elem;
break;
default:
return false;
}
}
if (is_type_raw_union(ft) || is_type_typeid(ft)) {
return false;
}
return lb_is_elem_const(elem, ft);
}
gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_local) {
LLVMContextRef ctx = m->ctx;
@@ -411,7 +436,6 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
Ast *expr = unparen_expr(value.value_procedure);
if (expr->kind == Ast_ProcLit) {
res = lb_generate_anonymous_proc_lit(m, str_lit("_proclit"), expr);
} else {
Entity *e = entity_from_expr(expr);
res = lb_find_procedure_value_from_entity(m, e);
@@ -461,6 +485,8 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
LLVMValueRef ptr = LLVMBuildInBoundsGEP2(p->builder, llvm_type, array_data, indices, 2, "");
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
lbAddr slice = lb_add_local_generated(p, type, false);
map_set(&m->exact_value_compound_literal_addr_map, value.value_compound, slice);
lb_fill_slice(p, slice, {ptr, alloc_type_pointer(elem)}, {len, t_int});
return lb_addr_load(p, slice);
}
@@ -978,12 +1004,58 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
GB_ASSERT(tav.mode != Addressing_Invalid);
Selection sel = lookup_field(type, name, false);
GB_ASSERT(!sel.indirect);
Entity *f = type->Struct.fields[sel.index[0]];
i32 index = field_remapping[f->Variable.field_index];
if (elem_type_can_be_constant(f->type)) {
values[index] = lb_const_value(m, f->type, tav.value, allow_local).value;
visited[index] = true;
if (sel.index.count == 1) {
values[index] = lb_const_value(m, f->type, tav.value, allow_local).value;
visited[index] = true;
} else {
if (!visited[index]) {
values[index] = lb_const_value(m, f->type, {}, false).value;
visited[index] = true;
}
unsigned idx_list_len = cast(unsigned)sel.index.count-1;
unsigned *idx_list = gb_alloc_array(temporary_allocator(), unsigned, idx_list_len);
if (lb_is_nested_possibly_constant(type, sel, fv->value)) {
bool is_constant = true;
Type *cv_type = f->type;
for (isize j = 1; j < sel.index.count; j++) {
i32 index = sel.index[j];
Type *cvt = base_type(cv_type);
if (cvt->kind == Type_Struct) {
if (cvt->Struct.is_raw_union) {
// sanity check which should have been caught by `lb_is_nested_possibly_constant`
is_constant = false;
break;
}
cv_type = cvt->Struct.fields[index]->type;
if (is_type_struct(cv_type)) {
auto cv_field_remapping = lb_get_struct_remapping(m, cv_type);
idx_list[j-1] = cast(unsigned)cv_field_remapping[index];
} else {
idx_list[j-1] = cast(unsigned)index;
}
} else if (cvt->kind == Type_Array) {
cv_type = cvt->Array.elem;
idx_list[j-1] = cast(unsigned)index;
} else {
GB_PANIC("UNKNOWN TYPE: %s", type_to_string(cv_type));
}
}
if (is_constant) {
LLVMValueRef elem_value = lb_const_value(m, tav.type, tav.value, allow_local).value;
GB_ASSERT(LLVMIsConstant(elem_value));
values[index] = LLVMConstInsertValue(values[index], elem_value, idx_list, idx_list_len);
}
}
}
}
}
} else {
@@ -1043,6 +1115,8 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
GB_ASSERT(is_local);
lbProcedure *p = m->curr_procedure;
lbAddr v = lb_add_local_generated(p, res.type, true);
map_set(&m->exact_value_compound_literal_addr_map, value.value_compound, v);
LLVMBuildStore(p->builder, constant_value, v.addr.value);
for (isize i = 0; i < value_count; i++) {
LLVMValueRef val = old_values[i];

View File

@@ -2210,6 +2210,15 @@ gb_internal lbValue lb_compare_records(lbProcedure *p, TokenKind op_kind, lbValu
lbValue left_ptr = lb_address_from_load_or_generate_local(p, left);
lbValue right_ptr = lb_address_from_load_or_generate_local(p, right);
lbValue res = {};
if (type_size_of(type) == 0) {
switch (op_kind) {
case Token_CmpEq:
return lb_const_bool(p->module, t_bool, true);
case Token_NotEq:
return lb_const_bool(p->module, t_bool, false);
}
GB_PANIC("invalid operator");
}
if (is_type_simple_compare(type)) {
// TODO(bill): Test to see if this is actually faster!!!!
auto args = array_make<lbValue>(permanent_allocator(), 3);
@@ -3138,7 +3147,7 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
Entity *e = entity_from_expr(expr);
e = strip_entity_wrapping(e);
GB_ASSERT_MSG(e != nullptr, "%s", expr_to_string(expr));
GB_ASSERT_MSG(e != nullptr, "%s in %.*s %p", expr_to_string(expr), LIT(p->name), expr);
if (e->kind == Entity_Builtin) {
Token token = ast_token(expr);
GB_PANIC("TODO(bill): lb_build_expr Entity_Builtin '%.*s'\n"
@@ -4035,7 +4044,6 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) {
return {};
}
gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
ast_node(cl, CompoundLit, expr);
@@ -4084,12 +4092,25 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
ast_node(fv, FieldValue, elem);
String name = fv->field->Ident.token.string;
Selection sel = lookup_field(bt, name, false);
index = sel.index[0];
GB_ASSERT(!sel.indirect);
elem = fv->value;
TypeAndValue tav = type_and_value_of_expr(elem);
if (sel.index.count > 1) {
if (lb_is_nested_possibly_constant(type, sel, elem)) {
continue;
}
lbValue dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sel);
field_expr = lb_build_expr(p, elem);
field_expr = lb_emit_conv(p, field_expr, sel.entity->type);
lb_emit_store(p, dst, field_expr);
continue;
}
index = sel.index[0];
} else {
TypeAndValue tav = type_and_value_of_expr(elem);
Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_index);
GB_ASSERT(sel.index.count == 1);
GB_ASSERT(!sel.indirect);
index = sel.index[0];
}

View File

@@ -82,6 +82,7 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) {
map_init(&m->map_info_map, 0);
map_init(&m->map_cell_info_map, 0);
map_init(&m->exact_value_compound_literal_addr_map, 1024);
}
@@ -1586,6 +1587,10 @@ gb_internal LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *t
if (params_by_ptr[i]) {
// NOTE(bill): The parameter needs to be passed "indirectly", override it
ft->args[i].kind = lbArg_Indirect;
ft->args[i].attribute = nullptr;
ft->args[i].align_attribute = nullptr;
ft->args[i].byval_alignment = 0;
ft->args[i].is_byval = false;
}
}

View File

@@ -1045,9 +1045,25 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c
} else if (is_odin_cc) {
// NOTE(bill): Odin parameters are immutable so the original value can be passed if possible
// i.e. `T const &` in C++
ptr = lb_address_from_load_or_generate_local(p, x);
if (LLVMIsConstant(x.value)) {
// NOTE(bill): if the value is already constant, then just it as a global variable
// and pass it by pointer
lbAddr addr = lb_add_global_generated(p->module, original_type, x);
lb_make_global_private_const(addr);
ptr = addr.addr;
} else {
ptr = lb_address_from_load_or_generate_local(p, x);
}
} else {
ptr = lb_copy_value_to_ptr(p, x, original_type, 16);
if (LLVMIsConstant(x.value)) {
// NOTE(bill): if the value is already constant, then just it as a global variable
// and pass it by pointer
lbAddr addr = lb_add_global_generated(p->module, original_type, x);
lb_make_global_private_const(addr);
ptr = addr.addr;
} else {
ptr = lb_copy_value_to_ptr(p, x, original_type, 16);
}
}
array_add(&processed_args, ptr);
}
@@ -2288,7 +2304,15 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
break;
case BuiltinProc_volatile_store: LLVMSetVolatile(instr, true); break;
case BuiltinProc_atomic_store: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break;
case BuiltinProc_atomic_store_explicit: LLVMSetOrdering(instr, llvm_atomic_ordering_from_odin(ce->args[2])); break;
case BuiltinProc_atomic_store_explicit:
{
auto ordering = llvm_atomic_ordering_from_odin(ce->args[2]);
LLVMSetOrdering(instr, ordering);
if (ordering == LLVMAtomicOrderingUnordered) {
LLVMSetVolatile(instr, true);
}
}
break;
}
LLVMSetAlignment(instr, cast(unsigned)type_align_of(type_deref(dst.type)));
@@ -2314,7 +2338,15 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
break;
case BuiltinProc_volatile_load: LLVMSetVolatile(instr, true); break;
case BuiltinProc_atomic_load: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); break;
case BuiltinProc_atomic_load_explicit: LLVMSetOrdering(instr, llvm_atomic_ordering_from_odin(ce->args[1])); break;
case BuiltinProc_atomic_load_explicit:
{
auto ordering = llvm_atomic_ordering_from_odin(ce->args[1]);
LLVMSetOrdering(instr, ordering);
if (ordering == LLVMAtomicOrderingUnordered) {
LLVMSetVolatile(instr, true);
}
}
break;
}
LLVMSetAlignment(instr, cast(unsigned)type_align_of(type_deref(dst.type)));
@@ -2384,6 +2416,9 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
lbValue res = {};
res.value = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false);
res.type = tv.type;
if (ordering == LLVMAtomicOrderingUnordered) {
LLVMSetVolatile(res.value, true);
}
return res;
}
@@ -2409,7 +2444,6 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
case BuiltinProc_atomic_compare_exchange_weak_explicit: success_ordering = llvm_atomic_ordering_from_odin(ce->args[3]); failure_ordering = llvm_atomic_ordering_from_odin(ce->args[4]); weak = true; break;
}
// TODO(bill): Figure out how to make it weak
LLVMBool single_threaded = false;
LLVMValueRef value = LLVMBuildAtomicCmpXchg(
@@ -2420,6 +2454,9 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
single_threaded
);
LLVMSetWeak(value, weak);
if (success_ordering == LLVMAtomicOrderingUnordered || failure_ordering == LLVMAtomicOrderingUnordered) {
LLVMSetVolatile(value, true);
}
if (is_type_tuple(tv.type)) {
Type *fix_typed = alloc_type_tuple();

View File

@@ -1397,6 +1397,52 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
switch_instr = LLVMBuildSwitch(p->builder, tag.value, else_block->block, cast(unsigned)num_cases);
}
bool all_by_reference = false;
for (Ast *clause : body->stmts) {
ast_node(cc, CaseClause, clause);
if (cc->list.count != 1) {
continue;
}
Entity *case_entity = implicit_entity_of_node(clause);
all_by_reference |= (case_entity->flags & EntityFlag_Value) == 0;
break;
}
// NOTE(bill, 2023-02-17): In the case of a pass by value, the value does need to be copied
// to prevent errors such as these:
//
// switch v in some_union {
// case i32:
// fmt.println(v) // 'i32'
// some_union = f32(123)
// fmt.println(v) // if `v` is an implicit reference, then the data is now completely corrupted
// case f32:
// fmt.println(v)
// }
//
lbAddr backing_data = {};
if (!all_by_reference) {
bool variants_found = false;
i64 max_size = 0;
i64 max_align = 1;
for (Ast *clause : body->stmts) {
ast_node(cc, CaseClause, clause);
if (cc->list.count != 1) {
continue;
}
Entity *case_entity = implicit_entity_of_node(clause);
max_size = gb_max(max_size, type_size_of(case_entity->type));
max_align = gb_max(max_align, type_align_of(case_entity->type));
variants_found = true;
}
if (variants_found) {
Type *t = alloc_type_array(t_u8, max_size);
backing_data = lb_add_local(p, t, nullptr, false, true);
GB_ASSERT(lb_try_update_alignment(backing_data.addr, cast(unsigned)max_align));
}
}
lbValue backing_ptr = backing_data.addr;
for (Ast *clause : body->stmts) {
ast_node(cc, CaseClause, clause);
lb_open_scope(p, cc->scope);
@@ -1427,8 +1473,6 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
Entity *case_entity = implicit_entity_of_node(clause);
lbValue value = parent_value;
lb_start_block(p, body);
bool by_reference = (case_entity->flags & EntityFlag_Value) == 0;
@@ -1444,13 +1488,29 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
Type *ct = case_entity->type;
Type *ct_ptr = alloc_type_pointer(ct);
value = lb_emit_conv(p, data, ct_ptr);
if (!by_reference) {
value = lb_emit_load(p, value);
lbValue ptr = {};
if (backing_data.addr.value) { // by value
GB_ASSERT(!by_reference);
// make a copy of the case value
lb_mem_copy_non_overlapping(p,
backing_ptr, // dst
data, // src
lb_const_int(p->module, t_int, type_size_of(case_entity->type)));
ptr = lb_emit_conv(p, backing_ptr, ct_ptr);
} else { // by reference
GB_ASSERT(by_reference);
ptr = lb_emit_conv(p, data, ct_ptr);
}
GB_ASSERT(are_types_identical(case_entity->type, type_deref(ptr.type)));
lb_add_entity(p->module, case_entity, ptr);
lb_add_debug_local_variable(p, ptr.value, case_entity->type, case_entity->token);
} else {
// TODO(bill): is the correct expected behaviour?
lb_store_type_case_implicit(p, clause, parent_value);
}
lb_store_type_case_implicit(p, clause, value);
lb_type_case_body(p, ss->label, clause, body, done);
}
@@ -1523,7 +1583,8 @@ gb_internal void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) {
lb_add_member(p->module, mangled_name, global_val);
}
}
gb_internal void lb_append_tuple_values(lbProcedure *p, Array<lbValue> *dst_values, lbValue src_value) {
gb_internal isize lb_append_tuple_values(lbProcedure *p, Array<lbValue> *dst_values, lbValue src_value) {
isize init_count = dst_values->count;
Type *t = src_value.type;
if (t->kind == Type_Tuple) {
lbTupleFix *tf = map_get(&p->tuple_fix_map, src_value.value);
@@ -1540,6 +1601,7 @@ gb_internal void lb_append_tuple_values(lbProcedure *p, Array<lbValue> *dst_valu
} else {
array_add(dst_values, src_value);
}
return dst_values->count - init_count;
}
@@ -2218,7 +2280,41 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
}
array_add(&lvals, lval);
}
lb_build_assignment(p, lvals, vd->values);
auto const &values = vd->values;
if (values.count > 0) {
auto inits = array_make<lbValue>(permanent_allocator(), 0, lvals.count);
isize lval_index = 0;
for (Ast *rhs : values) {
rhs = unparen_expr(rhs);
lbValue init = lb_build_expr(p, rhs);
#if 1
// NOTE(bill, 2023-02-17): lb_const_value might produce a stack local variable for the
// compound literal, so reusing that variable should minimize the stack wastage
if (rhs->kind == Ast_CompoundLit) {
lbAddr *comp_lit_addr = map_get(&p->module->exact_value_compound_literal_addr_map, rhs);
if (comp_lit_addr) {
Entity *e = entity_of_node(vd->names[lval_index]);
if (e) {
lb_add_entity(p->module, e, comp_lit_addr->addr);
lvals[lval_index] = {}; // do nothing so that nothing will assign to it
}
}
}
#endif
lval_index += lb_append_tuple_values(p, &inits, init);
}
GB_ASSERT(lval_index == lvals.count);
GB_ASSERT(lvals.count == inits.count);
for_array(i, inits) {
lbAddr lval = lvals[i];
lbValue init = inits[i];
lb_addr_store(p, lval, init);
}
}
case_end;
case_ast_node(as, AssignStmt, node);

View File

@@ -915,7 +915,7 @@ gb_internal lbStructFieldRemapping lb_get_struct_remapping(lbModule *m, Type *t)
if (field_remapping == nullptr) {
field_remapping = map_get(&m->struct_field_remapping, cast(void *)t);
}
GB_ASSERT(field_remapping != nullptr);
GB_ASSERT_MSG(field_remapping != nullptr, "%s", type_to_string(t));
return *field_remapping;
}

View File

@@ -659,6 +659,7 @@ enum BuildFlagKind {
BuildFlag_IgnoreWarnings,
BuildFlag_WarningsAsErrors,
BuildFlag_TerseErrors,
BuildFlag_VerboseErrors,
BuildFlag_ErrorPosStyle,
@@ -832,6 +833,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_IgnoreWarnings, str_lit("ignore-warnings"), BuildFlagParam_None, Command_all);
add_flag(&build_flags, BuildFlag_WarningsAsErrors, str_lit("warnings-as-errors"), BuildFlagParam_None, Command_all);
add_flag(&build_flags, BuildFlag_TerseErrors, str_lit("terse-errors"), BuildFlagParam_None, Command_all);
add_flag(&build_flags, BuildFlag_VerboseErrors, str_lit("verbose-errors"), BuildFlagParam_None, Command_all);
add_flag(&build_flags, BuildFlag_ErrorPosStyle, str_lit("error-pos-style"), BuildFlagParam_String, Command_all);
@@ -1462,8 +1464,13 @@ gb_internal bool parse_build_flags(Array<String> args) {
}
break;
}
case BuildFlag_TerseErrors:
build_context.hide_error_line = true;
break;
case BuildFlag_VerboseErrors:
build_context.show_error_line = true;
gb_printf_err("-verbose-errors is not the default, -terse-errors can now disable it\n");
build_context.hide_error_line = false;
break;
case BuildFlag_ErrorPosStyle:
@@ -1835,6 +1842,17 @@ gb_internal void show_timings(Checker *c, Timings *t) {
gb_internal void remove_temp_files(lbGenerator *gen) {
if (build_context.keep_temp_files) return;
switch (build_context.build_mode) {
case BuildMode_Executable:
case BuildMode_DynamicLibrary:
break;
case BuildMode_Object:
case BuildMode_Assembly:
case BuildMode_LLVM_IR:
return;
}
TIME_SECTION("remove keep temp files");
for (String const &path : gen->output_temp_paths) {
@@ -2476,6 +2494,30 @@ gb_internal int strip_semicolons(Parser *parser) {
return cast(int)failed;
}
gb_internal void init_terminal(void) {
build_context.has_ansi_terminal_colours = false;
#if defined(GB_SYSTEM_WINDOWS)
HANDLE hnd = GetStdHandle(STD_ERROR_HANDLE);
DWORD mode = 0;
if (GetConsoleMode(hnd, &mode)) {
enum {FLAG_ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004};
if (SetConsoleMode(hnd, mode|FLAG_ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
build_context.has_ansi_terminal_colours = true;
}
}
#endif
if (!build_context.has_ansi_terminal_colours) {
gbAllocator a = heap_allocator();
char const *odin_terminal_ = gb_get_env("ODIN_TERMINAL", a);
defer (gb_free(a, cast(void *)odin_terminal_));
String odin_terminal = make_string_c(odin_terminal_);
if (str_eq_ignore_case(odin_terminal, str_lit("ansi"))) {
build_context.has_ansi_terminal_colours = true;
}
}
}
int main(int arg_count, char const **arg_ptr) {
if (arg_count < 2) {
usage(make_string_c(arg_ptr[0]));
@@ -2491,6 +2533,7 @@ int main(int arg_count, char const **arg_ptr) {
init_string_interner();
init_global_error_collector();
init_keyword_hash_table();
init_terminal();
if (!check_env()) {
return 1;

View File

@@ -20,6 +20,9 @@ gb_internal Token ast_token(Ast *node) {
case Ast_ParenExpr: return node->ParenExpr.open;
case Ast_CallExpr: return ast_token(node->CallExpr.proc);
case Ast_SelectorExpr:
if (node->SelectorExpr.expr != nullptr) {
return ast_token(node->SelectorExpr.expr);
}
if (node->SelectorExpr.selector != nullptr) {
return ast_token(node->SelectorExpr.selector);
}

View File

@@ -1,6 +1,6 @@
template <typename T>
struct PtrSet {
static_assert(TypeIsPointer<T>::value, "PtrSet::T must be a pointer");
static_assert(TypeIsPointer<T>::value || TypeIsPtrSizedInteger<T>::value, "PtrSet::T must be a pointer");
static constexpr uintptr TOMBSTONE = ~(uintptr)(0ull);
T * keys;

View File

@@ -430,7 +430,6 @@ gb_internal Selection sub_selection(Selection const &sel, isize offset) {
return res;
}
gb_global Type basic_types[] = {
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
@@ -2313,9 +2312,6 @@ gb_internal bool is_type_comparable(Type *t) {
return true;
case Type_Struct:
if (type_size_of(t) == 0) {
return false;
}
if (t->Struct.soa_kind != StructSoa_None) {
return false;
}
@@ -2331,9 +2327,6 @@ gb_internal bool is_type_comparable(Type *t) {
return true;
case Type_Union:
if (type_size_of(t) == 0) {
return false;
}
for_array(i, t->Union.variants) {
Type *v = t->Union.variants[i];
if (!is_type_comparable(v)) {

View File

@@ -0,0 +1,31 @@
package objc_Foundation
@(objc_class="NSOpenPanel")
OpenPanel :: struct{ using _: SavePanel }
@(objc_type=OpenPanel, objc_name="openPanel", objc_is_class_method=true)
OpenPanel_openPanel :: proc() -> ^OpenPanel {
return msgSend(^OpenPanel, OpenPanel, "openPanel")
}
@(objc_type=OpenPanel, objc_name="URLs")
OpenPanel_URLs :: proc(self: ^OpenPanel) -> ^Array {
return msgSend(^Array, self, "URLs")
}
@(objc_type=OpenPanel, objc_name="setCanChooseFiles")
OpenPanel_setCanChooseFiles :: proc(self: ^OpenPanel, setting: BOOL) {
msgSend(nil, self, "setCanChooseFiles:", setting)
}
@(objc_type=OpenPanel, objc_name="setCanChooseDirectories")
OpenPanel_setCanChooseDirectories :: proc(self: ^OpenPanel, setting: BOOL) {
msgSend(nil, self, "setCanChooseDirectories:", setting)
}
@(objc_type=OpenPanel, objc_name="setResolvesAliases")
OpenPanel_setResolvesAliases :: proc(self: ^OpenPanel, setting: BOOL) {
msgSend(nil, self, "setResolvesAliases:", setting)
}
@(objc_type=OpenPanel, objc_name="setAllowsMultipleSelection")
OpenPanel_setAllowsMultipleSelection :: proc(self: ^OpenPanel, setting: BOOL) {
msgSend(nil, self, "setAllowsMultipleSelection:", setting)
}

9
vendor/darwin/Foundation/NSPanel.odin vendored Normal file
View File

@@ -0,0 +1,9 @@
package objc_Foundation
ModalResponse :: enum UInteger {
Cancel = 0,
OK = 1,
}
@(objc_class="NSPanel")
Panel :: struct{ using _: Window }

View File

@@ -0,0 +1,9 @@
package objc_Foundation
@(objc_class="NSSavePanel")
SavePanel :: struct{ using _: Panel }
@(objc_type=SavePanel, objc_name="runModal")
SavePanel_runModal :: proc(self: ^SavePanel) -> ModalResponse {
return msgSend(ModalResponse, self, "runModal")
}

View File

@@ -25,6 +25,6 @@ URL_initFileURLWithPath :: proc(self: ^URL, path: ^String) -> ^URL {
}
@(objc_type=URL, objc_name="fileSystemRepresentation")
URL_fileSystemRepresentation :: proc(self: ^URL) -> ^String {
return msgSend(^String, self, "fileSystemRepresentation")
}
URL_fileSystemRepresentation :: proc(self: ^URL) -> cstring {
return msgSend(cstring, self, "fileSystemRepresentation")
}

View File

@@ -0,0 +1,14 @@
package objc_Foundation
@(objc_class="NSUserDefaults")
UserDefaults :: struct { using _: Object }
@(objc_type=UserDefaults, objc_name="standardUserDefaults", objc_is_class_method=true)
UserDefaults_standardUserDefaults :: proc() -> ^UserDefaults {
return msgSend(^UserDefaults, UserDefaults, "standardUserDefaults")
}
@(objc_type=UserDefaults, objc_name="setBoolForKey")
UserDefaults_setBoolForKey :: proc(self: ^UserDefaults, value: BOOL, name: ^String) {
msgSend(nil, self, "setBool:forKey:", value, name)
}

248
vendor/directx/ThirdPartyNotices.txt vendored Normal file
View File

@@ -0,0 +1,248 @@
Microsoft/DirectXShaderCompiler
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
Do Not Translate or Localize
This project incorporates components from the projects listed below. The
original copyright notices and the licenses under which Microsoft received
such components are set forth below. Microsoft reserves all rights not
expressly granted herein, whether by implication, estoppel or otherwise.
* LLVM
==============================================================================
LLVM Release License
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
Copyrights and Licenses for Third Party Software Distributed with LLVM:
==============================================================================
The LLVM software contains code written by third parties. Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.
The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:
Program Directory
------- ---------
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
* tools\clang
==============================================================================
LLVM Release License
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2007-2015 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
The LLVM software contains code written by third parties. Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.
* test\YAMLParser
Copyright (c) 2006 Kirill Simonov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
* include\llvm\Support
LLVM System Interface Library
-------------------------------------------------------------------------------
The LLVM System Interface Library is licensed under the Illinois Open Source
License and has the following additional copyright:
Copyright (C) 2004 eXtensible Systems, Inc.
* OpenBSD regex
$OpenBSD: COPYRIGHT,v 1.3 2003/06/02 20:18:36 millert Exp $
Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved.
This software is not subject to any license of the American Telephone
and Telegraph Company or of the Regents of the University of California.
Permission is granted to anyone to use this software for any purpose on
any computer system, and to alter it and redistribute it, subject
to the following restrictions:
1. The author is not responsible for the consequences of use of this
software, no matter how awful, even if they arise from flaws in it.
2. The origin of this software must not be misrepresented, either by
explicit claim or by omission. Since few users ever read sources,
credits must appear in the documentation.
3. Altered versions must be plainly marked as such, and must not be
misrepresented as being the original software. Since few users
ever read sources, credits must appear in the documentation.
4. This notice may not be removed or altered.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
/*-
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)COPYRIGHT 8.1 (Berkeley) 3/16/94
*/
* lib\Headers Files
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1226,7 +1226,7 @@ HEAP_FLAG :: enum u32 {
}
HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES :: HEAP_FLAGS{}
HEAP_FLAG_ALLOW_ONLY_BUFFERS :: HEAP_FLAGS{.DENY_BUFFERS, .ALLOW_DISPLAY}
HEAP_FLAG_ALLOW_ONLY_BUFFERS :: HEAP_FLAGS{.DENY_RT_DS_TEXTURES, .DENY_NON_RT_DS_TEXTURES}
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}
@@ -2543,7 +2543,7 @@ IDevice_VTable :: struct {
CreateSampler: proc "stdcall" (this: ^IDevice, pDesc: ^SAMPLER_DESC, DestDescriptor: CPU_DESCRIPTOR_HANDLE),
CopyDescriptors: proc "stdcall" (this: ^IDevice, NumDestDescriptorRanges: u32, pDestDescriptorRangeStarts: ^CPU_DESCRIPTOR_HANDLE, pDestDescriptorRangeSizes: ^u32, NumSrcDescriptorRanges: u32, pSrcDescriptorRangeStarts: ^CPU_DESCRIPTOR_HANDLE, pSrcDescriptorRangeSizes: ^u32, DescriptorHeapsType: DESCRIPTOR_HEAP_TYPE),
CopyDescriptorsSimple: proc "stdcall" (this: ^IDevice, NumDescriptors: u32, DestDescriptorRangeStart: CPU_DESCRIPTOR_HANDLE, SrcDescriptorRangeStart: CPU_DESCRIPTOR_HANDLE, DescriptorHeapsType: DESCRIPTOR_HEAP_TYPE),
GetResourceAllocationInfo: proc "stdcall" (this: ^IDevice, visibleMask: u32, numResourceDescs: u32, pResourceDescs: ^RESOURCE_DESC) -> RESOURCE_ALLOCATION_INFO,
GetResourceAllocationInfo: proc "stdcall" (this: ^IDevice, RetVal: ^RESOURCE_ALLOCATION_INFO, visibleMask: u32, numResourceDescs: u32, pResourceDescs: ^RESOURCE_DESC),
GetCustomHeapProperties: proc "stdcall" (this: ^IDevice, nodeMask: u32, heapType: HEAP_TYPE) -> HEAP_PROPERTIES,
CreateCommittedResource: proc "stdcall" (this: ^IDevice, pHeapProperties: ^HEAP_PROPERTIES, HeapFlags: HEAP_FLAGS, pDesc: ^RESOURCE_DESC, InitialResourceState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, riidResource: ^IID, ppvResource: ^rawptr) -> HRESULT,
CreateHeap: proc "stdcall" (this: ^IDevice, pDesc: ^HEAP_DESC, riid: ^IID, ppvHeap: ^rawptr) -> HRESULT,
@@ -2728,7 +2728,7 @@ IDevice4_VTable :: struct {
CreateCommittedResource1: proc "stdcall" (this: ^IDevice4, pHeapProperties: ^HEAP_PROPERTIES, HeapFlags: HEAP_FLAGS, pDesc: ^RESOURCE_DESC, InitialResourceState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, pProtectedSession: ^IProtectedResourceSession, riidResource: ^IID, ppvResource: ^rawptr) -> HRESULT,
CreateHeap1: proc "stdcall" (this: ^IDevice4, pDesc: ^HEAP_DESC, pProtectedSession: ^IProtectedResourceSession, riid: ^IID, ppvHeap: ^rawptr) -> HRESULT,
CreateReservedResource1: proc "stdcall" (this: ^IDevice4, pDesc: ^RESOURCE_DESC, InitialState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, pProtectedSession: ^IProtectedResourceSession, riid: ^IID, ppvResource: ^rawptr) -> HRESULT,
GetResourceAllocationInfo1: proc "stdcall" (this: ^IDevice4, visibleMask: u32, numResourceDescs: u32, pResourceDescs: ^RESOURCE_DESC, pResourceAllocationInfo1: ^RESOURCE_ALLOCATION_INFO1) -> RESOURCE_ALLOCATION_INFO,
GetResourceAllocationInfo1: proc "stdcall" (this: ^IDevice4, RetVal: ^RESOURCE_ALLOCATION_INFO, visibleMask: u32, numResourceDescs: u32, pResourceDescs: ^RESOURCE_DESC, pResourceAllocationInfo1: ^RESOURCE_ALLOCATION_INFO1),
}
LIFETIME_STATE :: enum i32 {
@@ -3516,7 +3516,7 @@ IDevice8 :: struct #raw_union {
}
IDevice8_VTable :: struct {
using id3d12device7_vtable: IDevice7_VTable,
GetResourceAllocationInfo2: proc "stdcall" (this: ^IDevice8, visibleMask: u32, numResourceDescs: u32, pResourceDescs: ^RESOURCE_DESC1, pResourceAllocationInfo1: ^RESOURCE_ALLOCATION_INFO1) -> RESOURCE_ALLOCATION_INFO,
GetResourceAllocationInfo2: proc "stdcall" (this: ^IDevice8, RetVal: ^RESOURCE_ALLOCATION_INFO, visibleMask: u32, numResourceDescs: u32, pResourceDescs: ^RESOURCE_DESC1, pResourceAllocationInfo1: ^RESOURCE_ALLOCATION_INFO1),
CreateCommittedResource2: proc "stdcall" (this: ^IDevice8, pHeapProperties: ^HEAP_PROPERTIES, HeapFlags: HEAP_FLAGS, pDesc: ^RESOURCE_DESC1, InitialResourceState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, pProtectedSession: ^IProtectedResourceSession, riidResource: ^IID, ppvResource: ^rawptr) -> HRESULT,
CreatePlacedResource1: proc "stdcall" (this: ^IDevice8, pHeap: ^IHeap, HeapOffset: u64, pDesc: ^RESOURCE_DESC1, InitialState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, riid: ^IID, ppvResource: ^rawptr) -> HRESULT,
CreateSamplerFeedbackUnorderedAccessView: proc "stdcall" (this: ^IDevice8, pTargetedResource: ^IResource, pFeedbackResource: ^IResource, DestDescriptor: CPU_DESCRIPTOR_HANDLE),
@@ -4928,16 +4928,40 @@ IGraphicsCommandList6_VTable :: struct {
DispatchMesh: proc "stdcall" (this: ^IGraphicsCommandList6, ThreadGroupCountX: u32, ThreadGroupCountY: u32, ThreadGroupCountZ: u32),
}
SHADER_VERSION_TYPE :: enum i32 {
PIXEL_SHADER = 0,
VERTEX_SHADER = 1,
GEOMETRY_SHADER = 2,
SHADER_VERSION_TYPE :: enum u32 {
PIXEL_SHADER = 0,
VERTEX_SHADER = 1,
GEOMETRY_SHADER = 2,
HULL_SHADER = 3,
DOMAIN_SHADER = 4,
COMPUTE_SHADER = 5,
HULL_SHADER = 3,
DOMAIN_SHADER = 4,
COMPUTE_SHADER = 5,
RESERVED0 = 65520,
LIBRARY = 6,
RAY_GENERATION_SHADER = 7,
INTERSECTION_SHADER = 8,
ANY_HIT_SHADER = 9,
CLOSEST_HIT_SHADER = 10,
MISS_SHADER = 11,
CALLABLE_SHADER = 12,
MESH_SHADER = 13,
AMPLIFICATION_SHADER = 14,
RESERVED0 = 0xFFF0,
}
shver_get_type :: proc "contextless" (version: u32) -> SHADER_VERSION_TYPE {
return SHADER_VERSION_TYPE((version >> 16) & 0xffff)
}
shver_get_major :: proc "contextless" (version: u32) -> u8 {
return u8((version >> 4) & 0xf)
}
shver_get_minor :: proc "contextless" (version: u32) -> u8 {
return u8((version >> 0) & 0xf)
}
SIGNATURE_PARAMETER_DESC :: struct {
@@ -4984,6 +5008,7 @@ SHADER_TYPE_DESC :: struct {
Offset: u32,
Name: cstring,
}
SHADER_DESC :: struct {
Version: u32,
Creator: cstring,
@@ -5042,6 +5067,39 @@ SHADER_INPUT_BIND_DESC :: struct {
uID: u32,
}
SHADER_REQUIRES_FLAGS :: distinct bit_set[SHADER_REQUIRES; u64]
SHADER_REQUIRES :: enum u64 {
DOUBLES = 0,
EARLY_DEPTH_STENCIL = 1,
UAVS_AT_EVERY_STAGE = 2,
_64_UAVS = 3,
MINIMUM_PRECISION = 4,
_11_1_DOUBLE_EXTENSIONS = 5,
_11_1_SHADER_EXTENSIONS = 6,
LEVEL_9_COMPARISON_FILTERING = 7,
TILED_RESOURCES = 8,
STENCIL_REF = 9,
INNER_COVERAGE = 10,
TYPED_UAV_LOAD_ADDITIONAL_FORMATS = 11,
ROVS = 12,
VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER = 13,
WAVE_OPS = 14,
INT64_OPS = 15,
VIEW_ID = 16,
BARYCENTRICS = 17,
NATIVE_16BIT_OPS = 18,
SHADING_RATE = 19,
RAYTRACING_TIER_1_1 = 20,
SAMPLER_FEEDBACK = 21,
ATOMIC_INT64_ON_TYPED_RESOURCE = 22,
ATOMIC_INT64_ON_GROUP_SHARED = 23,
DERIVATIVES_IN_MESH_AND_AMPLIFICATION_SHADERS = 24,
RESOURCE_DESCRIPTOR_HEAP_INDEXING = 25,
SAMPLER_DESCRIPTOR_HEAP_INDEXING = 26,
WAVE_MMA = 27,
ATOMIC_INT64_ON_DESCRIPTOR_HEAP_RESOURCE = 28,
}
LIBRARY_DESC :: struct {
Creator: cstring,
Flags: u32,
@@ -5103,8 +5161,10 @@ PARAMETER_DESC :: struct {
FirstOutComponent: u32,
}
IShaderReflectionType_UUID_STRING :: "E913C351-783D-48CA-A1D1-4F306284AD56"
IShaderReflectionType_UUID := &IID{0xE913C351, 0x783D, 0x48CA, {0xA1, 0xD1, 0x4F, 0x30, 0x62, 0x84, 0xAD, 0x56}}
IShaderReflectionType :: struct {
vtable: ^IShaderReflectionType_VTable,
using id3d12shaderreflectiontype_vtable: ^IShaderReflectionType_VTable,
}
IShaderReflectionType_VTable :: struct {
GetDesc: proc "stdcall" (this: ^IShaderReflectionType, pDesc: ^SHADER_TYPE_DESC) -> HRESULT,
@@ -5120,8 +5180,10 @@ IShaderReflectionType_VTable :: struct {
ImplementsInterface: proc "stdcall" (this: ^IShaderReflectionType, pBase: ^IShaderReflectionType) -> HRESULT,
}
IShaderReflectionVariable_UUID_STRING :: "8337A8A6-A216-444A-B2F4-314733A73AEA"
IShaderReflectionVariable_UUID := &IID{0x8337A8A6, 0xA216, 0x444A, {0xB2, 0xF4, 0x31, 0x47, 0x33, 0xA7, 0x3A, 0xEA}}
IShaderReflectionVariable :: struct {
vtable: ^IShaderReflectionVariable_VTable,
using id3d12shaderreflectionvariable_vtable: ^IShaderReflectionVariable_VTable,
}
IShaderReflectionVariable_VTable :: struct {
GetDesc: proc "stdcall" (this: ^IShaderReflectionVariable, pDesc: ^SHADER_VARIABLE_DESC) -> HRESULT,
@@ -5130,8 +5192,10 @@ IShaderReflectionVariable_VTable :: struct {
GetInterfaceSlot: proc "stdcall" (this: ^IShaderReflectionVariable, uArrayIndex: u32) -> u32,
}
IShaderReflectionConstantBuffer_UUID_STRING :: "C59598B4-48B3-4869-B9B1-B1618B14A8B7"
IShaderReflectionConstantBuffer_UUID := &IID{0xC59598B4, 0x48B3, 0x4869, {0xB9, 0xB1, 0xB1, 0x61, 0x8B, 0x14, 0xA8, 0xB7}}
IShaderReflectionConstantBuffer :: struct {
vtable: ^IShaderReflectionConstantBuffer_VTable,
using id3d12shaderreflectionconstantbuffer_vtable: ^IShaderReflectionConstantBuffer_VTable,
}
IShaderReflectionConstantBuffer_VTable :: struct {
GetDesc: proc "stdcall" (this: ^IShaderReflectionConstantBuffer, pDesc: ^SHADER_BUFFER_DESC) -> HRESULT,
@@ -5139,6 +5203,8 @@ IShaderReflectionConstantBuffer_VTable :: struct {
GetVariableByName: proc "stdcall" (this: ^IShaderReflectionConstantBuffer, Name: cstring) -> ^IShaderReflectionVariable,
}
IShaderReflection_UUID_STRING :: "5A58797D-A72C-478D-8BA2-EFC6B0EFE88E"
IShaderReflection_UUID := &IID{0x5A58797D, 0xA72C, 0x478D, {0x8B, 0xA2, 0xEF, 0xC6, 0xB0, 0xEF, 0xE8, 0x8E}}
IShaderReflection :: struct #raw_union {
#subtype iunknown: IUnknown,
using id3d12shaderreflection_vtable: ^IShaderReflection_VTable,
@@ -5163,9 +5229,11 @@ IShaderReflection_VTable :: struct {
GetNumInterfaceSlots: proc "stdcall" (this: ^IShaderReflection) -> u32,
GetMinFeatureLevel: proc "stdcall" (this: ^IShaderReflection, pLevel: ^FEATURE_LEVEL) -> HRESULT,
GetThreadGroupSize: proc "stdcall" (this: ^IShaderReflection, pSizeX: ^u32, pSizeY: ^u32, pSizeZ: ^u32) -> u32,
GetRequiresFlags: proc "stdcall" (this: ^IShaderReflection) -> u64,
GetRequiresFlags: proc "stdcall" (this: ^IShaderReflection) -> SHADER_REQUIRES_FLAGS,
}
ILibraryReflection_UUID_STRING :: "8E349D19-54DB-4A56-9DC9-119D87BDB804"
ILibraryReflection_UUID := &IID{0x8E349D19, 0x54DB, 0x4A56, {0x9D, 0xC9, 0x11, 0x9D, 0x87, 0xBD, 0xB8, 0x04}}
ILibraryReflection :: struct #raw_union {
#subtype iunknown: IUnknown,
using id3d12libraryreflection_vtable: ^ILibraryReflection_VTable,
@@ -5176,8 +5244,10 @@ ILibraryReflection_VTable :: struct {
GetFunctionByIndex: proc "stdcall" (this: ^ILibraryReflection, FunctionIndex: i32) -> ^IFunctionReflection,
}
IFunctionReflection_UUID_STRING :: "1108795C-2772-4BA9-B2A8-D464DC7E2799"
IFunctionReflection_UUID := &IID{0x1108795C, 0x2772, 0x4BA9, {0xB2, 0xA8, 0xD4, 0x64, 0xDC, 0x7E, 0x27, 0x99}}
IFunctionReflection :: struct {
vtable: ^IFunctionReflection_VTable,
using id3d12functionreflection_vtable: ^IFunctionReflection_VTable,
}
IFunctionReflection_VTable :: struct {
GetDesc: proc "stdcall" (this: ^IFunctionReflection, pDesc: ^FUNCTION_DESC) -> HRESULT,
@@ -5189,8 +5259,10 @@ IFunctionReflection_VTable :: struct {
GetFunctionParameter: proc "stdcall" (this: ^IFunctionReflection, ParameterIndex: i32) -> ^IFunctionParameterReflection,
}
IFunctionParameterReflection_UUID_STRING :: "EC25F42D-7006-4F2B-B33E-02CC3375733F"
IFunctionParameterReflection_UUID := &IID{0xEC25F42D, 0x7006, 0x4F2B, {0xB3, 0x3E, 0x2, 0xCC, 0x33, 0x75, 0x73, 0x3F}}
IFunctionParameterReflection :: struct {
vtable: ^IFunctionParameterReflection_VTable,
using id3d12functionparameterreflection_vtable: ^IFunctionParameterReflection_VTable,
}
IFunctionParameterReflection_VTable :: struct {
GetDesc: proc "stdcall" (this: ^IFunctionParameterReflection, pDesc: ^PARAMETER_DESC) -> HRESULT,

603
vendor/directx/dxc/dxcapi.odin vendored Normal file
View File

@@ -0,0 +1,603 @@
package directx_dxc
import win32 "core:sys/windows"
import dxgi "vendor:directx/dxgi"
foreign import "dxcompiler.lib"
BOOL :: dxgi.BOOL
SIZE_T :: dxgi.SIZE_T
ULONG :: dxgi.ULONG
CLSID :: dxgi.GUID
IID :: dxgi.IID
HRESULT :: dxgi.HRESULT
IUnknown :: dxgi.IUnknown
IUnknown_VTable :: dxgi.IUnknown_VTable
wstring :: win32.wstring
FILETIME :: win32.FILETIME
BSTR :: wstring
@(default_calling_convention="c", link_prefix="Dxc")
foreign dxcompiler {
CreateInstance :: proc (rclsid: ^CLSID, riid: ^IID, ppv: rawptr) -> HRESULT ---
CreateInstance2 :: proc (pMalloc: ^IMalloc, rclsid: ^CLSID, riid: ^IID, ppv: rawptr) -> HRESULT ---
}
pCreateInstanceProc :: #type proc "c" (rclsid: ^CLSID, riid: ^IID, ppv: rawptr) -> HRESULT
pCreateInstance2Proc :: #type proc "c" (pMalloc: ^IMalloc, rclsid: ^CLSID, riid: ^IID, ppv: rawptr) -> HRESULT
CreateInstance_ProcName :: "DxcCreateInstance"
CreateInstance2_ProcName :: "DxcCreateInstance2"
IMalloc :: struct #raw_union {
#subtype iunknown: IUnknown,
using imalloc_vtable: ^IMalloc_VTable,
}
IMalloc_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
Alloc: proc "stdcall" (this: ^IMalloc, cb: SIZE_T) -> rawptr,
Realloc: proc "stdcall" (this: ^IMalloc, pv: rawptr, cb: SIZE_T) -> rawptr,
Free: proc "stdcall" (this: ^IMalloc, pv: rawptr),
GetSize: proc "stdcall" (this: ^IMalloc, pv: rawptr) -> SIZE_T,
DidAlloc: proc "stdcall" (this: ^IMalloc, pv: rawptr) -> i32,
HeapMinimize: proc "stdcall" (this: ^IMalloc),
}
ISequentialStream :: struct #raw_union {
#subtype iunknown: IUnknown,
using isequentialstream_vtable: ^ISequentialStream_VTable,
}
ISequentialStream_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
Read: proc "stdcall" (this: ^ISequentialStream, pv: rawptr, cb: ULONG, pcbRead: ^ULONG) -> HRESULT,
Write: proc "stdcall" (this: ^ISequentialStream, pv: rawptr, cb: ULONG, pcbWritten: ^ULONG) -> HRESULT,
}
STATSTG :: struct {
pwcsName: wstring,
type: u32,
cbSize: u64,
mtime: FILETIME,
ctime: FILETIME,
atime: FILETIME,
grfMode: u32,
grfLocksSupported: u32,
clsid: CLSID,
grfStateBits: u32,
reserved: u32,
}
IStream :: struct #raw_union {
#subtype isequentialstream: ISequentialStream,
using istream_vtable: ^IStream_VTable,
}
IStream_VTable :: struct {
using isequentialstream_vtable: ISequentialStream_VTable,
Seek: proc "stdcall" (this: ^IStream, dlibMove: i64, dwOrigin: u32, plibNewPosition: ^u64) -> HRESULT,
SetSize: proc "stdcall" (this: ^IStream, libNewSize: u64) -> HRESULT,
CopyTo: proc "stdcall" (this: ^IStream, pstm: ^IStream, cb: u64, pcbRead: ^u64, pcbWritten: ^u64) -> HRESULT,
Commit: proc "stdcall" (this: ^IStream, grfCommitFlags: u32) -> HRESULT,
Revert: proc "stdcall" (this: ^IStream) -> HRESULT,
LockRegion: proc "stdcall" (this: ^IStream, libOffset: u64, cb: u64, dwLockType: u32) -> HRESULT,
UnlockRegion: proc "stdcall" (this: ^IStream, libOffset: u64, cb: u64, dwLockType: u32) -> HRESULT,
Stat: proc "stdcall" (this: ^IStream, pstatstg: ^STATSTG, grfStatFlag: u32) -> HRESULT,
Clone: proc "stdcall" (this: ^IStream, ppstm: ^^IStream) -> HRESULT,
}
IBlob_UUID_STRING :: "8BA5FB08-5195-40E2-AC58-0D989C3A0102"
IBlob_UUID := &IID{0x8BA5FB08, 0x5195, 0x40E2, {0xAC, 0x58, 0x0D, 0x98, 0x9C, 0x3A, 0x01, 0x02}}
IBlob :: struct #raw_union {
#subtype iunknown: IUnknown,
using id3d10blob_vtable: ^IBlob_VTable,
}
IBlob_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
GetBufferPointer: proc "stdcall" (this: ^IBlob) -> rawptr,
GetBufferSize: proc "stdcall" (this: ^IBlob) -> SIZE_T,
}
IBlobEncoding_UUID_STRRING :: "7241D424-2646-4191-97C0-98E96E42FC68"
IBlobEncoding_UUID := &IID{0x7241D424, 0x2646, 0x4191, {0x97, 0xC0, 0x98, 0xE9, 0x6E, 0x42, 0xFC, 0x68}}
IBlobEncoding :: struct #raw_union {
#subtype idxcblob: IBlob,
using idxcblobencoding_vtable: ^IBlobEncoding_VTable,
}
IBlobEncoding_VTable :: struct {
using idxcblob_vtable: IBlob_VTable,
GetEncoding: proc "stdcall" (pKnown: ^BOOL, pCodePage: ^u32) -> HRESULT,
}
IBlobUtf16_UUID_STRING :: "A3F84EAB-0FAA-497E-A39C-EE6ED60B2D84"
IBlobUtf16_UUID := &IID{0xA3F84EAB, 0x0FAA, 0x497E, {0xA3, 0x9C, 0xEE, 0x6E, 0xD6, 0x0B, 0x2D, 0x84}}
IBlobUtf16 :: struct #raw_union {
#subtype idxcblobencoding: IBlobEncoding,
using idxcblobutf16_vtable : ^IBlobUtf16_VTable,
}
IBlobUtf16_VTable :: struct {
using idxcblobencoding_vtable: IBlobEncoding_VTable,
GetStringPointer: proc "stdcall" (this: ^IBlobUtf16) -> wstring,
GetStringLength: proc "stdcall" (this: ^IBlobUtf16) -> SIZE_T,
}
IBlobUtf8_UUID_STRING :: "3DA636C9-BA71-4024-A301-30CBF125305B"
IBlobUtf8_UUID := &IID{0x3DA636C9, 0xBA71, 0x4024, {0xA3, 0x01, 0x30, 0xCB, 0xF1, 0x25, 0x30, 0x5B}}
IBlobUtf8 :: struct #raw_union {
#subtype idxcblobencoding: IBlobEncoding,
using idxcblobutf8_vtable : ^IBlobUtf8_VTable,
}
IBlobUtf8_VTable :: struct {
using idxcblobencoding_vtable: IBlobEncoding_VTable,
GetStringPointer: proc "stdcall" (this: ^IBlobUtf8) -> cstring,
GetStringLength: proc "stdcall" (this: ^IBlobUtf8) -> SIZE_T,
}
IIncludeHandler_UUID_STRING :: "7F61FC7D-950D-467F-B3E3-3C02FB49187C"
IIncludeHandler_UUID := &IID{0x7F61FC7D, 0x950D, 0x467F, {0xB3, 0xE3, 0x3C, 0x02, 0xFB, 0x49, 0x18, 0x7C}}
IIncludeHandler :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcincludehandler_vtable: ^IIncludeHandler_VTable,
}
IIncludeHandler_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
LoadSource: proc "stdcall" (this: ^IIncludeHandler, pFilename: wstring, ppIncludeSource: ^^IBlob) -> HRESULT,
}
Define :: struct {
Name: wstring,
Value: wstring,
}
ICompilerArgs_UUID_STRING :: "73EFFE2A-70DC-45F8-9690-EFF64C02429D"
ICompilerArgs_UUID := &IID{0x73EFFE2A, 0x70DC, 0x45F8, {0x96, 0x90, 0xEF, 0xF6, 0x4C, 0x02, 0x42, 0x9D}}
ICompilerArgs :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxccompilerargs_vtable: ^ICompilerArgs_VTable,
}
ICompilerArgs_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
GetArguments: proc "stdcall" (this: ^ICompilerArgs) -> [^]wstring,
GetCount: proc "stdcall" (this: ^ICompilerArgs) -> u32,
AddArguments: proc "stdcall" (this: ^ICompilerArgs, pArguments: [^]wstring, argCount: u32) -> HRESULT,
AddArgumentsUTF8: proc "stdcall" (this: ^ICompilerArgs, pArguments: [^]cstring, argCount: u32) -> HRESULT,
AddDefines: proc "stdcall" (this: ^ICompilerArgs, pDefines: [^]Define, defineCount: u32) -> HRESULT,
}
ILibrary_UUID_STRING :: "E5204DC7-D18C-4C3C-BDFB-851673980FE7"
ILibrary_UUID := &IID{0xE5204DC7, 0xD18C, 0x4C3C, {0xBD, 0xFB, 0x85, 0x16, 0x73, 0x98, 0x0F, 0xE7}}
ILibrary :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxclibrary_vtable: ^ILibrary_VTable,
}
ILibrary_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
SetMalloc: proc "stdcall" (this: ^ILibrary, pMalloc: ^IMalloc) -> HRESULT,
CreateBlobFromBlob: proc "stdcall" (this: ^ILibrary, pBlob: ^IBlob, offset: u32, length: u32, ppResult: ^^IBlob) -> HRESULT,
CreateBlobFromFile: proc "stdcall" (this: ^ILibrary, pFileName: wstring, codePage: ^u32, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
CreateBlobWithEncodingFromPinned: proc "stdcall" (this: ^ILibrary, pText: rawptr, size: u32, codePage: u32, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
CreateBlobWithEncodingOnHeapCopy: proc "stdcall" (this: ^ILibrary, pText: rawptr, size: u32, codePage: u32, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
CreateBlobWithEncodingOnMalloc: proc "stdcall" (this: ^ILibrary, pText: rawptr, pIMalloc: ^IMalloc, size: u32, codePage: u32, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
CreateIncludeHandler: proc "stdcall" (this: ^ILibrary, ppResult: ^^IIncludeHandler) -> HRESULT,
CreateStreamFromBlobReadOnly: proc "stdcall" (this: ^ILibrary, pBlob: ^IBlob, ppStream: ^^IStream) -> HRESULT,
GetBlobAsUtf8: proc "stdcall" (this: ^ILibrary, pBlob: ^IBlob, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
GetBlobAsUtf16: proc "stdcall" (this: ^ILibrary, pBlob: ^IBlob, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
}
IOperationResult_UUID_STRING :: "CEDB484A-D4E9-445A-B991-CA21CA157DC2"
IOperationResult_UUID := &IID{0xCEDB484A, 0xD4E9, 0x445A, {0xB9, 0x91, 0xCA, 0x21, 0xCA, 0x15, 0x7D, 0xC2}}
IOperationResult :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcoperationresult_vtable: ^IOperationResult_VTable,
}
IOperationResult_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
GetStatus: proc "stdcall" (this: ^IOperationResult, pStatus: ^HRESULT) -> HRESULT,
GetResult: proc "stdcall" (this: ^IOperationResult, ppResult: ^^IBlob) -> HRESULT,
GetErrorBuffer: proc "stdcall" (this: ^IOperationResult, ppErrors: ^^IBlobEncoding) -> HRESULT,
}
ICompiler_UUID_STRING :: "8C210BF3-011F-4422-8D70-6F9ACB8DB617"
ICompiler_UUID := &IID{0x8C210BF3, 0x011F, 0x4422, {0x8D, 0x70, 0x6F, 0x9A, 0xCB, 0x8D, 0xB6, 0x17}}
ICompiler :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxccompiler_vtable: ^ICompiler_VTable,
}
ICompiler_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
Compile: proc "stdcall" (
this: ^ICompiler,
pSource: ^Buffer,
pSourceName: wstring,
pEntryPoint: wstring,
pTargetProfile: wstring,
pArguments: [^]wstring,
argCount: u32,
pDefines: [^]Define,
defineCount: u32,
pIncludeHandler: ^IIncludeHandler,
ppResult: ^^IOperationResult) -> HRESULT,
Preprocess: proc "stdcall" (
this: ^ICompiler,
pSource: ^Buffer,
pSourceName: wstring,
pArguments: [^]wstring,
argCount: u32,
pDefines: [^]Define,
defineCount: u32,
pIncludeHandler: ^IIncludeHandler,
ppResult: ^^IOperationResult) -> HRESULT,
Disassemble: proc "stdcall" (this: ^ICompiler, pSource: ^Buffer, ppDisassembly: ^IBlobEncoding) -> HRESULT,
}
ICompiler2_UUID_STRING :: "A005A9D9-B8BB-4594-B5C9-0E633BEC4D37"
ICompiler2_UUID := &IID{0xA005A9D9, 0xB8BB, 0x4594, {0xB5, 0xC9, 0x0E, 0x63, 0x3B, 0xEC, 0x4D, 0x37}}
ICompiler2 :: struct #raw_union {
#subtype icompiler: ICompiler,
using idxccompiler2_vtable: ^ICompiler2_VTable,
}
ICompiler2_VTable :: struct {
using idxccompiler_vtable: ^ICompiler_VTable,
CompileWithDebug: proc "stdcall" (
this: ^ICompiler2,
pSource: ^Buffer,
pSourceName: wstring,
pEntryPoint: wstring,
pTargetProfile: wstring,
pArguments: [^]wstring,
argCount: u32,
pDefines: [^]Define,
defineCount: u32,
pIncludeHandler: ^IIncludeHandler,
ppResult: ^^IOperationResult,
ppDebugBlobName: ^wstring,
ppDebugBlob: ^^IBlob) -> HRESULT,
}
ILinker_UUID_STRING :: "F1B5BE2A-62DD-4327-A1C2-42AC1E1E78E6"
ILinker_UUID := &IID{0xF1B5BE2A, 0x62DD, 0x4327, {0xA1, 0xC2, 0x42, 0xAC, 0x1E, 0x1E, 0x78, 0xE6}}
ILinker :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxclinker_vtable: ^ILinker_VTable,
}
ILinker_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
RegisterLibrary: proc "stdcall" (this: ^ILinker, pLibName: ^IBlob) -> HRESULT,
Link: proc "stdcall" (
this: ^ILinker,
pEntryName: wstring,
pTargetProfile: wstring,
pLibNames: [^]wstring,
libCount: u32,
pArguments: [^]wstring,
argCount: u32,
ppResult: ^^IOperationResult) -> HRESULT,
}
Buffer :: struct {
Ptr: rawptr,
Size: SIZE_T,
Encoding: u32,
}
IUtils_UUID_STRING :: "4605C4CB-2019-492A-ADA4-65F20BB7D67F"
IUtils_UUID := &IID{0x4605C4CB, 0x2019, 0x492A, {0xAD, 0xA4, 0x65, 0xF2, 0x0B, 0xB7, 0xD6, 0x7F}}
IUtils :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcutils_vtable: ^IUtils_VTable,
}
IUtils_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
CreateBlobFromBlob: proc "stdcall" (this: ^IUtils, pBlob: ^IBlob, offset: u32, length: u32, ppResult: ^^IBlob) -> HRESULT,
CreateBlobFromPinned: proc "stdcall" (this: ^IUtils, pData: rawptr, size: u32, codePage: u32, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
MoveToBlob: proc "stdcall" (this: ^IUtils, pData: rawptr, pIMalloc: ^IMalloc, size: u32, codePage: u32, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
CreateBlob: proc "stdcall" (this: ^IUtils, pData: rawptr, size: u32, codePage: u32, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
LoadFile: proc "stdcall" (this: ^IUtils, pFileName: wstring, pCodePage: ^u32, pBlobEncoding: ^^IBlobEncoding) -> HRESULT,
CreateReadOnlyStreamFromBlob: proc "stdcall" (this: ^IUtils, pBlob: ^IBlob, ppStream: ^^IStream) -> HRESULT,
CreateDefaultIncludeHandler: proc "stdcall" (this: ^IUtils, ppResult: ^^IIncludeHandler) -> HRESULT,
GetBlobAsUtf8: proc "stdcall" (this: ^IUtils, pBlob: ^IBlob, pBlobEncoding: ^^IBlobUtf8) -> HRESULT,
GetBlobAsUtf16: proc "stdcall" (this: ^IUtils, pBlob: ^IBlob, pBlobEncoding: ^^IBlobUtf16) -> HRESULT,
GetDxilContainerPart: proc "stdcall" (this: ^IUtils, pShader: ^Buffer, Part: u32, ppPartData: rawptr, pPartSizeInBytes: ^u32) -> HRESULT,
CreateReflection: proc "stdcall" (this: ^IUtils, pData: ^Buffer, iid: ^IID, ppvReflection: rawptr) -> HRESULT,
BuildArguments: proc "stdcall" (this: ^IUtils, pSourceName: wstring, pEntryPoint: wstring, pTargetProfile: wstring, pArguments: [^]wstring, argCount: u32, pDefines: [^]Define, defineCount: u32, ppArgs: ^[^]ICompilerArgs) -> HRESULT,
GetPDBContents: proc "stdcall" (this: ^IUtils, pPDBBlob: ^IBlob, ppHash: ^^IBlob, ppContainer: ^^IBlob) -> HRESULT,
}
DXC_OUT_KIND :: enum u32 {
NONE = 0,
OBJECT = 1,
ERRORS = 2,
PDB = 3,
SHADER_HASH = 4,
DISASSEMBLY = 5,
HLSL = 6,
TEXT = 7,
REFLECTION = 8,
ROOT_SIGNATURE = 9,
EXTRA_OUTPUTS = 10,
FORCE_DWORD = 0xFFFFFFFF,
}
IResult_UUID_STRING :: "58346CDA-DDE7-4497-9461-6F87AF5E0659"
IResult_UUID := &IID{0x58346CDA, 0xDDE7, 0x4497, {0x94, 0x61, 0x6F, 0x87, 0xAF, 0x5E, 0x06, 0x59}}
IResult :: struct #raw_union {
#subtype idxcoperationresult: IOperationResult,
using idxcresult_vtable: ^IResult_VTable,
}
IResult_VTable :: struct {
using idxcoperationresult_vtable: IOperationResult_VTable,
HasOutput: proc "stdcall" (this: ^IResult, dxcOutKind: DXC_OUT_KIND) -> BOOL,
GetOutput: proc "stdcall" (this: ^IResult, dxcOutKind: DXC_OUT_KIND, iid: ^IID, ppvObject: rawptr, ppOutputName: ^^IBlobUtf16) -> HRESULT,
GetNumOutputs: proc "stdcall" (this: ^IResult) -> u32,
GetOutputByIndex: proc "stdcall" (this: ^IResult, Index: u32) -> DXC_OUT_KIND,
PrimaryOutput: proc "stdcall" (this: ^IResult) -> DXC_OUT_KIND,
}
IExtraOutputs_UUID_STRING :: "319B37A2-A5C2-494A-A5DE-4801B2FAF989"
IExtraOutputs_UUID := &IID{0x319B37A2, 0xA5C2, 0x494A, {0xA5, 0xDE, 0x48, 0x01, 0xB2, 0xFA, 0xF9, 0x89}}
IExtraOutputs :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcextraoutputs_vtable: ^IExtraOutputs_VTable,
}
IExtraOutputs_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
GetOutputCount: proc "stdcall" (this: ^IExtraOutputs) -> u32,
GetOutput: proc "stdcall" (this: ^IExtraOutputs, uIndex: u32, iid: ^IID, ppvObject: rawptr, ppOutputType: ^^IBlobUtf16, ppOutputName: ^^IBlobUtf16) -> HRESULT,
}
ICompiler3_UUID_STRING :: "228B4687-5A6A-4730-900C-9702B2203F54"
ICompiler3_UUID := &IID{0x228B4687, 0x5A6A, 0x4730, {0x90, 0x0C, 0x97, 0x02, 0xB2, 0x20, 0x3F, 0x54}}
ICompiler3 :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxccompiler3_vtable: ^ICompiler3_VTable,
}
ICompiler3_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
Compile: proc "stdcall" (this: ^ICompiler3, pSource: ^Buffer, pArguments: [^]wstring, argCount: u32, pIncludeHandler: ^IIncludeHandler, riid: ^IID, ppResult: rawptr) -> HRESULT,
Disassemble: proc "stdcall" (this: ^ICompiler3, pObject: ^Buffer, riid: ^IID, ppResult: rawptr) -> HRESULT,
}
IValidator_UUID_STRING :: "A6E82BD2-1FD7-4826-9811-2857E797F49A"
IValidator_UUID := &IID{0xA6E82BD2, 0x1FD7, 0x4826, {0x98, 0x11, 0x28, 0x57, 0xE7, 0x97, 0xF4, 0x9A}}
IValidator :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcvalidator_vtable: ^IValidator_VTable,
}
IValidator_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
Validate: proc "stdcall" (this: ^IValidator, pShader: ^IBlob, Flags: u32, ppResult: ^^IOperationResult) -> HRESULT,
}
IValidator2_UUID_STRING :: "458E1FD1-B1B2-4750-A6E1-9C10F03BED92"
IValidator2_UUID := &IID{0x458E1FD1, 0xB1B2, 0x4750, {0xA6, 0xE1, 0x9C, 0x10, 0xF0, 0x3B, 0xED, 0x92}}
IValidator2 :: struct #raw_union {
#subtype idxcvalidator: IValidator,
using idxcvalidator2_vtable: ^IValidator2_VTable,
}
IValidator2_VTable :: struct {
using idxcvalidator_vtable: IValidator_VTable,
ValidateWithDebug: proc "stdcall" (this: ^IValidator2, pShader: ^IBlob, Flags: u32, pOptDebugBitcode: ^Buffer, ppResult: ^^IOperationResult) -> HRESULT,
}
IContainerBuilder_UUID_STRING :: "334B1F50-2292-4B35-99A1-25588D8C17FE"
IContainerBuilder_UUID := &IID{0x334B1F50, 0x2292, 0x4B35, {0x99, 0xA1, 0x25, 0x58, 0x8D, 0x8C, 0x17, 0xFE}}
IContainerBuilder :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxccontainerbuilder_vtable: ^IContainerBuilder_VTable,
}
IContainerBuilder_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
Load: proc "stdcall" (this: ^IContainerBuilder, pDxilContainerHeader: ^IBlob) -> HRESULT,
AddPart: proc "stdcall" (this: ^IContainerBuilder, fourCC: u32, pSource: ^IBlob) -> HRESULT,
RemovePart: proc "stdcall" (this: ^IContainerBuilder, fourCC: u32) -> HRESULT,
SerializeContainer: proc "stdcall" (this: ^IContainerBuilder, ppResult: ^^IOperationResult) -> HRESULT,
}
IAssembler_UUID_STRING :: "091F7A26-1C1F-4948-904B-E6E3A8A771D5"
IAssembler_UUID := &IID{0x091F7A26, 0x1C1F, 0x4948, {0x90, 0x4B, 0xE6, 0xE3, 0xA8, 0xA7, 0x71, 0xD5}}
IAssembler :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcassembler_vtable: ^IAssembler_VTable,
}
IAssembler_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
AssembleToContainer: proc "stdcall" (this: ^IAssembler, pShader: ^IBlob, ppResult: ^^IOperationResult) -> HRESULT,
}
IContainerReflection_UUID_STRING :: "D2C21B26-8350-4BDC-976A-331CE6F4C54C"
IContainerReflection_UUID := &IID{0xD2C21B26, 0x8350, 0x4BDC, {0x97, 0x6A, 0x33, 0x1C, 0xE6, 0xF4, 0xC5, 0x4C}}
IContainerReflection :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxccontainerreflection_vtable: ^IContainerReflection_VTable,
}
IContainerReflection_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
Load: proc "stdcall" (this: ^IContainerReflection, pContainer: ^IBlob) -> HRESULT,
GetPartCount: proc "stdcall" (this: ^IContainerReflection, pResult: ^u32) -> HRESULT,
GetPartKind: proc "stdcall" (this: ^IContainerReflection, idx: u32, pResult: ^u32) -> HRESULT,
GetPartContent: proc "stdcall" (this: ^IContainerReflection, idx: u32, ppResult: ^^IBlob) -> HRESULT,
FindFirstPartKind: proc "stdcall" (this: ^IContainerReflection, kind: u32, pResult: ^u32) -> HRESULT,
GetPartReflection: proc "stdcall" (this: ^IContainerReflection, idx: u32, iid: ^IID, ppvObject: rawptr) -> HRESULT,
}
IOptimizerPass_UUID_STRING :: "AE2CD79F-CC22-453F-9B6B-B124E7A5204C"
IOptimizerPass_UUID := &IID{0xAE2CD79F, 0xCC22, 0x453F, {0x9B, 0x6B, 0xB1, 0x24, 0xE7, 0xA5, 0x20, 0x4C}}
IOptimizerPass :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcoptimizerpass_vtable: ^IOptimizerPass_VTable,
}
IOptimizerPass_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
GetOptionName: proc "stdcall" (this: ^IOptimizerPass, ppResult: ^wstring) -> HRESULT,
GetDescription: proc "stdcall" (this: ^IOptimizerPass, ppResult: ^wstring) -> HRESULT,
GetOptionArgCount: proc "stdcall" (this: ^IOptimizerPass, pCount: ^u32) -> HRESULT,
GetOptionArgName: proc "stdcall" (this: ^IOptimizerPass, argIndex: u32, ppResult: ^wstring) -> HRESULT,
GetOptionArgDescription: proc "stdcall" (this: ^IOptimizerPass, argIndex: u32, ppResult: ^wstring) -> HRESULT,
}
IOptimizer_UUID_STRING :: "25740E2E-9CBA-401B-9119-4FB42F39F270"
IOptimizer_UUID := &IID{0x25740E2E, 0x9CBA, 0x401B, {0x91, 0x19, 0x4F, 0xB4, 0x2F, 0x39, 0xF2, 0x70}}
IOptimizer :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcoptimizer_vtable: ^IOptimizer_VTable,
}
IOptimizer_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
GetAvailablePassCount: proc "stdcall" (this: ^IOptimizer, pCount: ^u32) -> HRESULT,
GetAvailablePass: proc "stdcall" (this: ^IOptimizer, index: u32, ppResult: ^^IOptimizerPass) -> HRESULT,
RunOptimizer: proc "stdcall" (this: ^IOptimizer, pBlob: ^IBlob, ppOptions: [^]wstring, optionCount: u32, pOutputModule: ^^IBlob, ppOutputText: ^^IBlobEncoding) -> HRESULT,
}
VersionInfoFlags :: enum u32 {
None = 0,
Debug = 1,
Internal = 2,
}
IVersionInfo_UUID_STRING :: "B04F5B50-2059-4F12-A8FF-A1E0CDE1CC7E"
IVersionInfo_UUID := &IID{0xB04F5B50, 0x2059, 0x4F12, {0xA8, 0xFF, 0xA1, 0xE0, 0xCD, 0xE1, 0xCC, 0x7E}}
IVersionInfo :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcversioninfo_vtable: ^IVersionInfo_VTable,
}
IVersionInfo_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
GetVersion: proc "stdcall" (this: ^IVersionInfo, pMajor: ^u32, pMinor: ^u32) -> HRESULT,
GetFlags: proc "stdcall" (this: ^IVersionInfo, pFlags: ^VersionInfoFlags) -> HRESULT,
}
IVersionInfo2_UUID_STRING :: "FB6904C4-42F0-4B62-9C46-983AF7DA7C83"
IVersionInfo2_UUID := &IID{0xFB6904C4, 0x42F0, 0x4B62, {0x9C, 0x46, 0x98, 0x3A, 0xF7, 0xDA, 0x7C, 0x83}}
IVersionInfo2 :: struct #raw_union {
#subtype idxcversioninfo: IVersionInfo,
using idxcversioninfo2_vtable: ^IVersionInfo2_VTable,
}
IVersionInfo2_VTable :: struct {
using idxcversioninfo_vtable: IVersionInfo_VTable,
GetCommitInfo: proc "stdcall" (this: ^IVersionInfo2, pCommitCount: ^u32, pCommitHash: ^[^]byte) -> HRESULT,
}
IVersionInfo3_UUID_STRING :: "5E13E843-9D25-473C-9AD2-03B2D0B44B1E"
IVersionInfo3_UUID := &IID{0x5E13E843, 0x9D25, 0x473C, {0x9A, 0xD2, 0x03, 0xB2, 0xD0, 0xB4, 0x4B, 0x1E}}
IVersionInfo3 :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcversioninfo3_vtable: ^IVersionInfo3_VTable,
}
IVersionInfo3_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
GetCustomVersionString: proc "stdcall" (this: ^IVersionInfo3, pVersionString: ^cstring) -> HRESULT,
}
ArgPair :: struct {
pName: wstring,
pValue: wstring,
}
IPdbUtils_UUID_STRING :: "E6C9647E-9D6A-4C3B-B94C-524B5A6C343D"
IPdbUtils_UUID := &IID{0xE6C9647E, 0x9D6A, 0x4C3B, {0xB9, 0x4C, 0x52, 0x4B, 0x5A, 0x6C, 0x34, 0x3D}}
IPdbUtils :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxcpdbutils_vtable: ^IPdbUtils_VTable,
}
IPdbUtils_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
Load: proc "stdcall" (this: ^IPdbUtils, pPdbOrDxil: ^IBlob) -> HRESULT,
GetSourceCount: proc "stdcall" (this: ^IPdbUtils, pCount: ^u32) -> HRESULT,
GetSource: proc "stdcall" (this: ^IPdbUtils, uIndex: u32, ppResult: ^^IBlobEncoding) -> HRESULT,
GetSourceName: proc "stdcall" (this: ^IPdbUtils, uIndex: u32, pResult: ^BSTR) -> HRESULT,
GetFlagCount: proc "stdcall" (this: ^IPdbUtils, pCount: ^u32) -> HRESULT,
GetFlag: proc "stdcall" (this: ^IPdbUtils, uIndex: u32, pResult: ^BSTR) -> HRESULT,
GetArgCount: proc "stdcall" (this: ^IPdbUtils, pCount: ^u32) -> HRESULT,
GetArg: proc "stdcall" (this: ^IPdbUtils, uIndex: u32, pResult: ^BSTR) -> HRESULT,
GetArgPairCount: proc "stdcall" (this: ^IPdbUtils, pCount: ^u32) -> HRESULT,
GetArgPair: proc "stdcall" (this: ^IPdbUtils, uIndex: u32, pName: ^BSTR, pValue: ^BSTR) -> HRESULT,
GetDefineCount: proc "stdcall" (this: ^IPdbUtils, pCount: ^u32) -> HRESULT,
GetDefine: proc "stdcall" (this: ^IPdbUtils, uIndex: u32, pResult: ^BSTR) -> HRESULT,
GetTargetProfile: proc "stdcall" (this: ^IPdbUtils, pResult: ^BSTR) -> HRESULT,
GetEntryPoint: proc "stdcall" (this: ^IPdbUtils, pResult: ^BSTR) -> HRESULT,
GetMainFileName: proc "stdcall" (this: ^IPdbUtils, pResult: ^BSTR) -> HRESULT,
GetHash: proc "stdcall" (this: ^IPdbUtils, ppResult: ^^IBlob) -> HRESULT,
GetName: proc "stdcall" (this: ^IPdbUtils, pResult: ^BSTR) -> HRESULT,
IsFullPDB: proc "stdcall" (this: ^IPdbUtils) -> BOOL,
GetFullPDB: proc "stdcall" (this: ^IPdbUtils, ppFullPDB: ^^IBlob) -> HRESULT,
GetVersionInfo: proc "stdcall" (this: ^IPdbUtils, ppVersionInfo: ^^IVersionInfo) -> HRESULT,
SetCompiler: proc "stdcall" (this: ^IPdbUtils, pCompiler: ^ICompiler3) -> HRESULT,
CompileForFullPDB: proc "stdcall" (this: ^IPdbUtils, ppResult: ^^IResult) -> HRESULT,
OverrideArgs: proc "stdcall" (this: ^IPdbUtils, pArgPairs: ^ArgPair, uNumArgPairs: u32) -> HRESULT,
OverrideRootSignature: proc "stdcall" (this: ^IPdbUtils, pRootSignature: wstring) -> HRESULT,
}
Compiler_CLSID_STRING :: "73E22D93-E6CE-47F3-B5BF-F0664F39C1B0"
Compiler_CLSID := &CLSID{0x73E22D93, 0xE6CE, 0x47F3, {0xB5, 0xBF, 0xF0, 0x66, 0x4F, 0x39, 0xC1, 0xB0}}
Linker_CLSID_STRING :: "EF6A8087-B0EA-4D56-9E45-D07E1A8B7806"
Linker_CLSID := &CLSID{0xEF6A8087, 0xB0EA, 0x4D56, {0x9E, 0x45, 0xD0, 0x7E, 0x1A, 0x8B, 0x78, 0x6}}
DiaDataSource_CLSID_STRING :: "CD1F6B73-2AB0-484D-8EDC-EBE7A43CA09F"
DiaDataSource_CLSID := &CLSID{0xCD1F6B73, 0x2AB0, 0x484D, {0x8E, 0xDC, 0xEB, 0xE7, 0xA4, 0x3C, 0xA0, 0x9F}}
CompilerArgs_CLSID_STRING :: "3E56AE82-224D-470F-A1A1-FE3016EE9F9D"
CompilerArgs_CLSID := &CLSID{0x3E56AE82, 0x224D, 0x470F, {0xA1, 0xA1, 0xFE, 0x30, 0x16, 0xEE, 0x9F, 0x9D}}
Library_CLSID_STRING :: "6245D6AF-66E0-48FD-80B4-4D271796748C"
Library_CLSID := &CLSID{0x6245D6AF, 0x66E0, 0x48FD, {0x80, 0xB4, 0x4D, 0x27, 0x17, 0x96, 0x74, 0x8C}}
Utils_CLSID_STRING :: Library_CLSID_STRING
Utils_CLSID := Library_CLSID
Validator_CLSID_STRING :: "8CA3E215-F728-4CF3-8CDD-88AF917587A1"
Validator_CLSID := &CLSID{0x8CA3E215, 0xF728, 0x4CF3, {0x8C, 0xDD, 0x88, 0xAF, 0x91, 0x75, 0x87, 0xA1}}
Assembler_CLSID_STRING :: "D728DB68-F903-4F80-94CD-DCCF76EC7151"
Assembler_CLSID := &CLSID{0xD728DB68, 0xF903, 0x4F80, {0x94, 0xCD, 0xDC, 0xCF, 0x76, 0xEC, 0x71, 0x51}}
ContainerReflection_CLSID_STRING :: "b9f54489-55b8-400c-ba3a-1675e4728b91"
ContainerReflection_CLSID := &CLSID{0xB9F54489, 0x55B8, 0x400C, {0xBA, 0x3A, 0x16, 0x75, 0xE4, 0x72, 0x8B, 0x91}}
Optimizer_CLSID_STRING :: "AE2CD79F-CC22-453F-9B6B-B124E7A5204C"
Optimizer_CLSID := &CLSID{0xAE2CD79F, 0xCC22, 0x453F, {0x9B, 0x6B, 0xB1, 0x24, 0xE7, 0xA5, 0x20, 0x4C}}
ContainerBuilder_CLSID_STRING :: "94134294-411f-4574-b4d0-8741e25240d2"
ContainerBuilder_CLSID := &CLSID{0x94134294, 0x411F, 0x4574, {0xB4, 0xD0, 0x87, 0x41, 0xE2, 0x52, 0x40, 0xD2}}
PdbUtils_CLSID_STRING :: "54621dfb-f2ce-457e-ae8c-ec355faeec7c"
PdbUtils_CLSID := &CLSID{0x54621DFB, 0xF2CE, 0x457E, {0xAE, 0x8C, 0xEC, 0x35, 0x5F, 0xAE, 0xEC, 0x7C}}
CP_UTF8 :: 65001
CP_UTF16 :: 1200
CP_ACP :: 0
make_fourcc :: proc "contextless" (ch0, ch1, ch2, ch3: u32) -> u32 {
return ch0 | (ch1 << 8) | (ch2 << 16) | (ch3 << 24)
}
PART_PDB :: u32('I') | (u32('L')<<8) | (u32('D')<<16) | (u32('B')<<24)
PART_PDB_NAME :: u32('I') | (u32('L')<<8) | (u32('D')<<16) | (u32('N')<<24)
PART_PRIVATE_DATA :: u32('P') | (u32('R')<<8) | (u32('I')<<16) | (u32('V')<<24)
PART_ROOT_SIGNATURE :: u32('R') | (u32('T')<<8) | (u32('S')<<16) | (u32('0')<<24)
PART_DXIL :: u32('D') | (u32('X')<<8) | (u32('I')<<16) | (u32('L')<<24)
PART_REFLECTION_DATA :: u32('S') | (u32('T')<<8) | (u32('A')<<16) | (u32('T')<<24)
PART_SHADER_HASH :: u32('H') | (u32('A')<<8) | (u32('S')<<16) | (u32('H')<<24)
PART_INPUT_SIGNATURE :: u32('I') | (u32('S')<<8) | (u32('G')<<16) | (u32('1')<<24)
PART_OUTPUT_SIGNATURE :: u32('O') | (u32('S')<<8) | (u32('G')<<16) | (u32('1')<<24)
PART_PATCH_CONSTANT_SIGNATURE :: u32('P') | (u32('S')<<8) | (u32('G')<<16) | (u32('1')<<24)
ARG_DEBUG :: "-Zi"
ARG_SKIP_VALIDATION :: "-Vd"
ARG_SKIP_OPTIMIZATIONS :: "-Od"
ARG_PACK_MATRIX_ROW_MAJOR :: "-Zpr"
ARG_PACK_MATRIX_COLUMN_MAJOR :: "-Zpc"
ARG_AVOID_FLOW_CONTROL :: "-Gfa"
ARG_PREFER_FLOW_CONTROL :: "-Gfp"
ARG_ENABLE_STRICTNESS :: "-Ges"
ARG_ENABLE_BACKWARDS_COMPATIBILITY :: "-Gec"
ARG_IEEE_STRICTNESS :: "-Gis"
ARG_OPTIMIZATION_LEVEL0 :: "-O0"
ARG_OPTIMIZATION_LEVEL1 :: "-O1"
ARG_OPTIMIZATION_LEVEL2 :: "-O2"
ARG_OPTIMIZATION_LEVEL3 :: "-O3"
ARG_WARNINGS_ARE_ERRORS :: "-WX"
ARG_RESOURCES_MAY_ALIAS :: "-res_may_alias"
ARG_ALL_RESOURCES_BOUND :: "-all_resources_bound"
ARG_DEBUG_NAME_FOR_SOURCE :: "-Zss"
ARG_DEBUG_NAME_FOR_BINARY :: "-Zsb"
EXTRA_OUTPUT_NAME_STDOUT :: "*stdout*"
EXTRA_OUTPUT_NAME_STDERR :: "*stderr*"

BIN
vendor/directx/dxc/dxcompiler.dll vendored Normal file

Binary file not shown.

BIN
vendor/directx/dxc/dxcompiler.lib vendored Normal file

Binary file not shown.

BIN
vendor/directx/dxc/dxil.dll vendored Normal file

Binary file not shown.

141
vendor/directx/dxgi/dxgidebug.odin vendored Normal file
View File

@@ -0,0 +1,141 @@
package directx_dxgi
import win32 "core:sys/windows"
import "core:c"
DEBUG_RLO_FLAGS :: enum u32 { // TODO: convert to bit_set
SUMMARY = 0x1,
DETAIL = 0x2,
IGNORE_INTERNAL = 0x4,
ALL = 0x7,
}
UINT :: win32.UINT
UINT64 :: win32.UINT64
LPCSTR :: win32.LPCSTR
DEBUG_ID :: win32.GUID
INFO_QUEUE_MESSAGE_ID :: i32
DEBUG_ALL := DEBUG_ID{0xe48ae283, 0xda80, 0x490b, {0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8}}
DEBUG_DX := DEBUG_ID{0x35cdd7fc, 0x13b2, 0x421d, {0xa5, 0xd7, 0x7e, 0x44, 0x51, 0x28, 0x7d, 0x64}}
DEBUG_DXGI := DEBUG_ID{0x25cddaa4, 0xb1c6, 0x47e1, {0xac, 0x3e, 0x98, 0x87, 0x5b, 0x5a, 0x2e, 0x2a}}
DEBUG_APP := DEBUG_ID{0x6cd6e01, 0x4219, 0x4ebd, {0x87, 0x9, 0x27, 0xed, 0x23, 0x36, 0xc, 0x62}}
INFO_QUEUE_MESSAGE_CATEGORY :: enum u32 {
UNKNOWN = 0,
MISCELLANEOUS = UNKNOWN + 1,
INITIALIZATION = MISCELLANEOUS + 1,
CLEANUP = INITIALIZATION + 1,
COMPILATION = CLEANUP + 1,
STATE_CREATION = COMPILATION + 1,
STATE_SETTING = STATE_CREATION + 1,
STATE_GETTING = STATE_SETTING + 1,
RESOURCE_MANIPULATION = STATE_GETTING + 1,
EXECUTION = RESOURCE_MANIPULATION + 1,
SHADER = EXECUTION + 1,
}
INFO_QUEUE_MESSAGE_SEVERITY :: enum u32 {
CORRUPTION = 0,
ERROR = CORRUPTION + 1,
WARNING = ERROR + 1,
INFO = WARNING + 1,
MESSAGE = INFO + 1,
}
INFO_QUEUE_MESSAGE :: struct {
Producer: DEBUG_ID,
Category: INFO_QUEUE_MESSAGE_CATEGORY,
Severity: INFO_QUEUE_MESSAGE_SEVERITY,
ID: INFO_QUEUE_MESSAGE_ID,
pDescription: [^]c.char,
DescriptionByteLength: SIZE_T,
}
INFO_QUEUE_FILTER_DESC :: struct {
NumCategories: UINT,
pCategoryList: [^]INFO_QUEUE_MESSAGE_CATEGORY,
NumSeverities: UINT,
pSeverityList: [^]INFO_QUEUE_MESSAGE_SEVERITY,
NumIDs: UINT,
pIDList: [^]INFO_QUEUE_MESSAGE_ID,
}
INFO_QUEUE_FILTER :: struct {
AllowList: INFO_QUEUE_FILTER_DESC,
DenyList: INFO_QUEUE_FILTER_DESC,
}
INFO_QUEUE_DEFAULT_MESSAGE_COUNT_LIMIT :: 1024
IInfoQueue_UUID_STRING :: "D67441C7-672A-476f-9E82-CD55B44949CE"
IInfoQueue_UUID := &IID{0xD67441C7, 0x672A, 0x476f, {0x9E, 0x82, 0xCD, 0x55, 0xB4, 0x49, 0x49, 0xCE}}
IInfoQueue :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxgiinfoqueue_vtable: ^IInfoQueue_VTable,
}
IInfoQueue_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
SetMessageCountLimit: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, MessageCountLimit: UINT64) -> HRESULT,
ClearStoredMessages: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID),
GetMessage: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, MessageIndex: UINT64, pMessage: ^INFO_QUEUE_MESSAGE, pMessageByteLength: ^SIZE_T) -> HRESULT,
GetNumStoredMessagesAllowedByRetrievalFilters: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> UINT64,
GetNumStoredMessages: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> UINT64,
GetNumMessagesDiscardedByMessageCountLimit: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> UINT64,
GetMessageCountLimit: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> UINT64,
GetNumMessagesAllowedByStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> UINT64,
GetNumMessagesDeniedByStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> UINT64,
AddStorageFilterEntries: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, pFilter: INFO_QUEUE_FILTER) -> HRESULT,
GetStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, pFilter: ^INFO_QUEUE_FILTER, pFilterByteLength: ^SIZE_T) -> HRESULT,
ClearStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID),
PushEmptyStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> HRESULT,
PushDenyAllStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> HRESULT,
PushCopyOfStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> HRESULT,
PushStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, pFilter: ^INFO_QUEUE_FILTER) -> HRESULT,
PopStorageFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID),
GetStorageFilterStackSize: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> UINT,
AddRetrievalFilterEntries: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, pFilter: ^INFO_QUEUE_FILTER) -> HRESULT,
GetRetrievalFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, pFilter: ^INFO_QUEUE_FILTER, pFilterByteLength: ^SIZE_T) -> HRESULT,
ClearRetrievalFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID),
PushEmptyRetrievalFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> HRESULT,
PushDenyAllRetrievalFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> HRESULT,
PushCopyOfRetrievalFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> HRESULT,
PushRetrievalFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, pFilter: ^INFO_QUEUE_FILTER) -> HRESULT,
PopRetrievalFilter: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID),
GetRetrievalFilterStackSize: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> UINT,
AddMessage: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, Category: INFO_QUEUE_MESSAGE_CATEGORY, Severity: INFO_QUEUE_MESSAGE_SEVERITY, ID: INFO_QUEUE_MESSAGE_ID, pDescription: LPCSTR) -> HRESULT,
AddApplicationMessage: proc "stdcall" (this: ^IInfoQueue, Severity: INFO_QUEUE_MESSAGE_SEVERITY, pDescription: LPCSTR) -> HRESULT,
SetBreakOnCategory: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, Category: INFO_QUEUE_MESSAGE_CATEGORY, bEnable: BOOL) -> HRESULT,
SetBreakOnSeverity: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, Severity: INFO_QUEUE_MESSAGE_SEVERITY, bEnable: BOOL) -> HRESULT,
SetBreakOnID: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, ID: INFO_QUEUE_MESSAGE_ID, bEnable: BOOL) -> HRESULT,
GetBreakOnCategory: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, Category: INFO_QUEUE_MESSAGE_CATEGORY) -> BOOL,
GetBreakOnSeverity: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, Severity: INFO_QUEUE_MESSAGE_SEVERITY) -> BOOL,
GetBreakOnID: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, ID: INFO_QUEUE_MESSAGE_ID) -> BOOL,
SetMuteDebugOutput: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID, bMute: BOOL),
GetMuteDebugOutput: proc "stdcall" (this: ^IInfoQueue, Producer: DEBUG_ID) -> BOOL,
}
IDebug_UUID_STRING :: "119E7452-DE9E-40fe-8806-88F90C12B441"
IDebug_UUID := &IID{0x119E7452, 0xDE9E, 0x40fe, {0x88, 0x06, 0x88, 0xF9, 0x0C, 0x12, 0xB4, 0x41}}
IDebug :: struct #raw_union {
#subtype iunknown: IUnknown,
using idxgidebug_vtable: ^IDebug_VTable,
}
IDebug_VTable :: struct {
using iunknown_vtable: IUnknown_VTable,
ReportLiveObjects: proc "stdcall" (this: ^IDebug, apiid: GUID, flags: DEBUG_RLO_FLAGS),
}
IDebug1_UUID_STRING :: "c5a05f0c-16f2-4adf-9f4d-a8c4d58ac550"
IDebug1_UUID := &IID{0xc5a05f0c, 0x16f2, 0x4adf, {0x9f, 0x4d, 0xa8, 0xc4, 0xd5, 0x8a, 0xc5, 0x50}}
IDebug1 :: struct #raw_union {
#subtype idxgidebug: IDebug,
using idxgidebug1_vtable: ^IDebug1_VTable,
}
IDebug1_VTable :: struct {
using idxgidebug_vtable: IDebug_VTable,
EnableLeakTrackingForThread: proc "stdcall" (this: ^IDebug1),
DisableLeakTrackingForThread: proc "stdcall" (this: ^IDebug1),
IsLeakTrackingEnabledForThread: proc "stdcall" (this: ^IDebug1) -> BOOL,
}