mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Merge branch 'master' into new-temp-allocator
This commit is contained in:
@@ -12,7 +12,7 @@ _rand_bytes :: proc (dst: []byte) {
|
|||||||
|
|
||||||
for l > 0 {
|
for l > 0 {
|
||||||
to_read := min(l, _MAX_PER_CALL_BYTES)
|
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 {
|
if ret < 0 {
|
||||||
switch os.Errno(-ret) {
|
switch os.Errno(-ret) {
|
||||||
case os.EINTR:
|
case os.EINTR:
|
||||||
|
|||||||
@@ -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) ---
|
wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
|
||||||
|
|
||||||
// x86 Targets (i386, amd64)
|
// 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) ---
|
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
|
// Internal compiler use only
|
||||||
|
|
||||||
__entry_point :: proc() ---
|
__entry_point :: proc() ---
|
||||||
|
|||||||
+42
-34
@@ -277,8 +277,10 @@ foreign libc {
|
|||||||
|
|
||||||
@(link_name="open") _unix_open :: proc(path: cstring, flags: i32, mode: u16) -> Handle ---
|
@(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="close") _unix_close :: proc(handle: Handle) -> c.int ---
|
||||||
@(link_name="read") _unix_read :: 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: int) -> 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="lseek") _unix_lseek :: proc(fs: Handle, offset: int, whence: int) -> int ---
|
||||||
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---
|
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---
|
||||||
@(link_name="getpagesize") _unix_getpagesize :: proc() -> i32 ---
|
@(link_name="getpagesize") _unix_getpagesize :: proc() -> i32 ---
|
||||||
@@ -386,45 +388,51 @@ close :: proc(fd: Handle) -> bool {
|
|||||||
@(private)
|
@(private)
|
||||||
MAX_RW :: 0x7fffffff // The limit on Darwin is max(i32), trying to read/write more than that fails.
|
MAX_RW :: 0x7fffffff // The limit on Darwin is max(i32), trying to read/write more than that fails.
|
||||||
|
|
||||||
write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||||
assert(fd != -1)
|
if len(data) == 0 {
|
||||||
|
return 0, ERROR_NONE
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||||
assert(fd != -1)
|
if len(data) == 0 {
|
||||||
|
return 0, ERROR_NONE
|
||||||
bytes_total := len(data)
|
|
||||||
bytes_read_total := 0
|
|
||||||
|
|
||||||
for bytes_read_total < bytes_total {
|
|
||||||
bytes_to_read := min(bytes_total - bytes_read_total, MAX_RW)
|
|
||||||
slice := data[bytes_read_total:bytes_read_total + bytes_to_read]
|
|
||||||
bytes_read := _unix_read(fd, raw_data(slice), bytes_to_read)
|
|
||||||
if bytes_read == -1 {
|
|
||||||
return bytes_read_total, 1
|
|
||||||
}
|
|
||||||
if bytes_read == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
bytes_read_total += bytes_read
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes_read_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) {
|
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||||
|
|||||||
+70
-157
@@ -270,136 +270,6 @@ AT_FDCWD :: ~uintptr(99) /* -100 */
|
|||||||
AT_REMOVEDIR :: uintptr(0x200)
|
AT_REMOVEDIR :: uintptr(0x200)
|
||||||
AT_SYMLINK_NOFOLLOW :: uintptr(0x100)
|
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 {
|
foreign libc {
|
||||||
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
|
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
|
||||||
|
|
||||||
@@ -415,6 +285,7 @@ foreign libc {
|
|||||||
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
|
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
|
||||||
@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> 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="getenv") _unix_getenv :: proc(cstring) -> cstring ---
|
||||||
@(link_name="putenv") _unix_putenv :: proc(cstring) -> c.int ---
|
@(link_name="putenv") _unix_putenv :: proc(cstring) -> c.int ---
|
||||||
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
|
@(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) {
|
personality :: proc(persona: u64) -> (Errno) {
|
||||||
res := _unix_personality(persona)
|
res := unix.sys_personality(persona)
|
||||||
if res == -1 {
|
if res == -1 {
|
||||||
return _get_errno(res)
|
return _get_errno(res)
|
||||||
}
|
}
|
||||||
@@ -455,29 +326,47 @@ personality :: proc(persona: u64) -> (Errno) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fork :: proc() -> (Pid, Errno) {
|
fork :: proc() -> (Pid, Errno) {
|
||||||
pid := _unix_fork()
|
pid := unix.sys_fork()
|
||||||
if pid == -1 {
|
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()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
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 {
|
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 {
|
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) {
|
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 {
|
if bytes_read < 0 {
|
||||||
return -1, _get_errno(bytes_read)
|
return -1, _get_errno(bytes_read)
|
||||||
}
|
}
|
||||||
@@ -488,25 +377,49 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return 0, ERROR_NONE
|
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 {
|
if bytes_written < 0 {
|
||||||
return -1, _get_errno(bytes_written)
|
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) {
|
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 {
|
if res < 0 {
|
||||||
return -1, _get_errno(int(res))
|
return -1, _get_errno(int(res))
|
||||||
}
|
}
|
||||||
return res, ERROR_NONE
|
return i64(res), ERROR_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
file_size :: proc(fd: Handle) -> (i64, Errno) {
|
file_size :: proc(fd: Handle) -> (i64, Errno) {
|
||||||
// deliberately uninitialized; the syscall fills this buffer for us
|
// deliberately uninitialized; the syscall fills this buffer for us
|
||||||
s: OS_Stat = ---
|
s: OS_Stat = ---
|
||||||
result := _unix_fstat(fd, &s)
|
result := unix.sys_fstat(int(fd), rawptr(&s))
|
||||||
if result < 0 {
|
if result < 0 {
|
||||||
return 0, _get_errno(result)
|
return 0, _get_errno(result)
|
||||||
}
|
}
|
||||||
@@ -517,25 +430,25 @@ rename :: proc(old_path, new_path: string) -> Errno {
|
|||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
old_path_cstr := strings.clone_to_cstring(old_path, context.temp_allocator)
|
old_path_cstr := strings.clone_to_cstring(old_path, context.temp_allocator)
|
||||||
new_path_cstr := strings.clone_to_cstring(new_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 {
|
remove :: proc(path: string) -> Errno {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
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 {
|
make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
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 {
|
remove_directory :: proc(path: string) -> Errno {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
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 {
|
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 {
|
exists :: proc(path: string) -> bool {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
cpath := strings.clone_to_cstring(path, context.temp_allocator)
|
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
|
return res == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,7 +541,7 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
|
|||||||
|
|
||||||
// deliberately uninitialized; the syscall fills this buffer for us
|
// deliberately uninitialized; the syscall fills this buffer for us
|
||||||
s: OS_Stat = ---
|
s: OS_Stat = ---
|
||||||
result := _unix_stat(cstr, &s)
|
result := unix.sys_stat(cstr, &s)
|
||||||
if result < 0 {
|
if result < 0 {
|
||||||
return s, _get_errno(result)
|
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
|
// deliberately uninitialized; the syscall fills this buffer for us
|
||||||
s: OS_Stat = ---
|
s: OS_Stat = ---
|
||||||
result := _unix_lstat(cstr, &s)
|
result := unix.sys_lstat(cstr, &s)
|
||||||
if result < 0 {
|
if result < 0 {
|
||||||
return s, _get_errno(result)
|
return s, _get_errno(result)
|
||||||
}
|
}
|
||||||
@@ -653,7 +566,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
|
|||||||
_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
|
_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
|
||||||
// deliberately uninitialized; the syscall fills this buffer for us
|
// deliberately uninitialized; the syscall fills this buffer for us
|
||||||
s: OS_Stat = ---
|
s: OS_Stat = ---
|
||||||
result := _unix_fstat(fd, &s)
|
result := unix.sys_fstat(int(fd), rawptr(&s))
|
||||||
if result < 0 {
|
if result < 0 {
|
||||||
return s, _get_errno(result)
|
return s, _get_errno(result)
|
||||||
}
|
}
|
||||||
@@ -711,7 +624,7 @@ _readlink :: proc(path: string) -> (string, Errno) {
|
|||||||
bufsz : uint = 256
|
bufsz : uint = 256
|
||||||
buf := make([]byte, bufsz)
|
buf := make([]byte, bufsz)
|
||||||
for {
|
for {
|
||||||
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
|
rc := unix.sys_readlink(path_cstr, &(buf[0]), bufsz)
|
||||||
if rc < 0 {
|
if rc < 0 {
|
||||||
delete(buf)
|
delete(buf)
|
||||||
return "", _get_errno(rc)
|
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) {
|
access :: proc(path: string, mask: int) -> (bool, Errno) {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||||
result := _unix_access(cstr, mask)
|
result := unix.sys_access(cstr, mask)
|
||||||
if result < 0 {
|
if result < 0 {
|
||||||
return false, _get_errno(result)
|
return false, _get_errno(result)
|
||||||
}
|
}
|
||||||
@@ -831,7 +744,7 @@ get_current_directory :: proc() -> string {
|
|||||||
page_size := get_page_size()
|
page_size := get_page_size()
|
||||||
buf := make([dynamic]u8, page_size)
|
buf := make([dynamic]u8, page_size)
|
||||||
for {
|
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 {
|
if res >= 0 {
|
||||||
return strings.string_from_nul_terminated_ptr(&buf[0], len(buf))
|
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) {
|
set_current_directory :: proc(path: string) -> (err: Errno) {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||||
res := _unix_chdir(cstr)
|
res := unix.sys_chdir(cstr)
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
return _get_errno(res)
|
return _get_errno(res)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -507,11 +507,8 @@ Odin_Endian_Type :: type_of(ODIN_ENDIAN)
|
|||||||
foreign {
|
foreign {
|
||||||
@(link_name="__$startup_runtime")
|
@(link_name="__$startup_runtime")
|
||||||
_startup_runtime :: proc "odin" () ---
|
_startup_runtime :: proc "odin" () ---
|
||||||
}
|
@(link_name="__$cleanup_runtime")
|
||||||
|
_cleanup_runtime :: proc "odin" () ---
|
||||||
@(link_name="__$cleanup_runtime")
|
|
||||||
_cleanup_runtime :: proc() {
|
|
||||||
default_temp_allocator_destroy(&global_default_temp_allocator_data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_cleanup_runtime_contextless :: proc "contextless" () {
|
_cleanup_runtime_contextless :: proc "contextless" () {
|
||||||
|
|||||||
@@ -72,3 +72,8 @@ default_temp_allocator :: proc(allocator: ^Default_Temp_Allocator) -> Allocator
|
|||||||
data = allocator,
|
data = allocator,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(fini, private)
|
||||||
|
_destroy_temp_allocator_fini :: proc() {
|
||||||
|
default_temp_allocator_destroy(&global_default_temp_allocator_data)
|
||||||
|
}
|
||||||
|
|||||||
+11
-10
@@ -184,32 +184,33 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle
|
|||||||
return
|
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 {
|
if allocator.procedure == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if new_size == 0 {
|
if new_size == 0 {
|
||||||
if ptr != nil {
|
if ptr != nil {
|
||||||
_, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
|
_, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
|
||||||
return nil, err
|
return
|
||||||
}
|
}
|
||||||
return nil, nil
|
return
|
||||||
} else if ptr == nil {
|
} else if ptr == nil {
|
||||||
return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
||||||
} else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 {
|
} 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 {
|
if err == .Mode_Not_Implemented {
|
||||||
data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return data, err
|
return
|
||||||
}
|
}
|
||||||
copy(data, ([^]byte)(ptr)[:old_size])
|
copy(data, ([^]byte)(ptr)[:old_size])
|
||||||
_, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc)
|
_, 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 {
|
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 {
|
when size_of(uint) == 8 {
|
||||||
if word_length := length >> 3; word_length != 0 {
|
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)) {
|
if intrinsics.unaligned_load((^u64)(a)) != intrinsics.unaligned_load((^u64)(b)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -254,7 +255,7 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
|
|||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
if word_length := length >> 2; word_length != 0 {
|
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)) {
|
if intrinsics.unaligned_load((^u32)(a)) != intrinsics.unaligned_load((^u32)(b)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-19
@@ -2,6 +2,9 @@ package runtime
|
|||||||
|
|
||||||
_INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz"
|
_INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
@(private="file")
|
||||||
|
_INTEGER_DIGITS_VAR := _INTEGER_DIGITS
|
||||||
|
|
||||||
when !ODIN_DISALLOW_RTTI {
|
when !ODIN_DISALLOW_RTTI {
|
||||||
print_any_single :: proc(arg: any) {
|
print_any_single :: proc(arg: any) {
|
||||||
x := arg
|
x := arg
|
||||||
@@ -105,14 +108,14 @@ encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) {
|
|||||||
return buf, 4
|
return buf, 4
|
||||||
}
|
}
|
||||||
|
|
||||||
print_string :: proc "contextless" (str: string) -> (int, _OS_Errno) {
|
print_string :: proc "contextless" (str: string) -> (n: int) {
|
||||||
return os_write(transmute([]byte)str)
|
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 {
|
for str in args {
|
||||||
m: int
|
m, err := os_write(transmute([]byte)str)
|
||||||
m, err = os_write(transmute([]byte)str)
|
|
||||||
n += m
|
n += m
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
break
|
break
|
||||||
@@ -121,8 +124,9 @@ print_strings :: proc "contextless" (args: ..string) -> (n: int, err: _OS_Errno)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
print_byte :: proc "contextless" (b: byte) -> (int, _OS_Errno) {
|
print_byte :: proc "contextless" (b: byte) -> (n: int) {
|
||||||
return os_write([]byte{b})
|
n, _ = os_write([]byte{b})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
print_encoded_rune :: proc "contextless" (r: rune) {
|
print_encoded_rune :: proc "contextless" (r: rune) {
|
||||||
@@ -141,11 +145,10 @@ print_encoded_rune :: proc "contextless" (r: rune) {
|
|||||||
if r <= 0 {
|
if r <= 0 {
|
||||||
print_string("\\x00")
|
print_string("\\x00")
|
||||||
} else if r < 32 {
|
} else if r < 32 {
|
||||||
digits := _INTEGER_DIGITS
|
|
||||||
n0, n1 := u8(r) >> 4, u8(r) & 0xf
|
n0, n1 := u8(r) >> 4, u8(r) & 0xf
|
||||||
print_string("\\x")
|
print_string("\\x")
|
||||||
print_byte(digits[n0])
|
print_byte(_INTEGER_DIGITS_VAR[n0])
|
||||||
print_byte(digits[n1])
|
print_byte(_INTEGER_DIGITS_VAR[n1])
|
||||||
} else {
|
} else {
|
||||||
print_rune(r)
|
print_rune(r)
|
||||||
}
|
}
|
||||||
@@ -153,7 +156,7 @@ print_encoded_rune :: proc "contextless" (r: rune) {
|
|||||||
print_byte('\'')
|
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
|
RUNE_SELF :: 0x80
|
||||||
|
|
||||||
if r < RUNE_SELF {
|
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)
|
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 {
|
print_u64 :: proc "contextless" (x: u64) #no_bounds_check {
|
||||||
digits := _INTEGER_DIGITS
|
|
||||||
|
|
||||||
a: [129]byte
|
a: [129]byte
|
||||||
i := len(a)
|
i := len(a)
|
||||||
b := u64(10)
|
b := u64(10)
|
||||||
u := x
|
u := x
|
||||||
for u >= b {
|
for u >= b {
|
||||||
i -= 1; a[i] = digits[u % b]
|
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
|
||||||
u /= b
|
u /= b
|
||||||
}
|
}
|
||||||
i -= 1; a[i] = digits[u % b]
|
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
|
||||||
|
|
||||||
os_write(a[i:])
|
os_write(a[i:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
|
print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
|
||||||
digits := _INTEGER_DIGITS
|
|
||||||
b :: i64(10)
|
b :: i64(10)
|
||||||
|
|
||||||
u := x
|
u := x
|
||||||
@@ -193,10 +194,10 @@ print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
|
|||||||
a: [129]byte
|
a: [129]byte
|
||||||
i := len(a)
|
i := len(a)
|
||||||
for u >= b {
|
for u >= b {
|
||||||
i -= 1; a[i] = digits[u % b]
|
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
|
||||||
u /= b
|
u /= b
|
||||||
}
|
}
|
||||||
i -= 1; a[i] = digits[u % b]
|
i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
|
||||||
if neg {
|
if neg {
|
||||||
i -= 1; a[i] = '-'
|
i -= 1; a[i] = '-'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,4 +236,4 @@ _panic :: proc "contextless" (msg: string) -> ! {
|
|||||||
runtime.print_string(msg)
|
runtime.print_string(msg)
|
||||||
runtime.print_byte('\n')
|
runtime.print_byte('\n')
|
||||||
runtime.trap()
|
runtime.trap()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package darwin
|
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)
|
return uintptr(number) + uintptr(0x2000000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)))
|
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)))
|
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))
|
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))
|
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)))
|
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)))
|
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)))
|
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)))
|
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)))
|
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)))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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)
|
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)
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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
|
// 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))
|
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))
|
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))
|
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))
|
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)
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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))
|
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]))
|
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)
|
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)
|
return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(fd), transmute(uintptr)path)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1563,15 +1563,167 @@ MADV_WIPEONFORK :: 18
|
|||||||
MADV_KEEPONFORK :: 19
|
MADV_KEEPONFORK :: 19
|
||||||
MADV_HWPOISON :: 100
|
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 {
|
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 {
|
sys_getrandom :: proc "contextless" (buf: [^]byte, buflen: uint, flags: int) -> int {
|
||||||
return cast(int)intrinsics.syscall(SYS_getrandom, uintptr(buf), uintptr(buflen), uintptr(flags))
|
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 {
|
when ODIN_ARCH != .arm64 {
|
||||||
return int(intrinsics.syscall(SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
|
return int(intrinsics.syscall(SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
|
||||||
} else { // NOTE: arm64 does not have open
|
} 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)))
|
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)))
|
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 {
|
when ODIN_ARCH != .arm64 {
|
||||||
return int(intrinsics.syscall(SYS_chmod, uintptr(rawptr(path)), uintptr(mode)))
|
return int(intrinsics.syscall(SYS_chmod, uintptr(rawptr(path)), uintptr(mode)))
|
||||||
} else { // NOTE: arm64 does not have chmod
|
} 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)))
|
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 {
|
when ODIN_ARCH != .arm64 {
|
||||||
return int(intrinsics.syscall(SYS_mkdir, uintptr(rawptr(path)), uintptr(mode)))
|
return int(intrinsics.syscall(SYS_mkdir, uintptr(rawptr(path)), uintptr(mode)))
|
||||||
} else { // NOTE: arm64 does not have mkdir
|
} 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)))
|
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 {
|
when ODIN_ARCH != .arm64 {
|
||||||
return int(intrinsics.syscall(SYS_mknod, uintptr(rawptr(path)), uintptr(mode), uintptr(dev)))
|
return int(intrinsics.syscall(SYS_mknod, uintptr(rawptr(path)), uintptr(mode), uintptr(dev)))
|
||||||
} else { // NOTE: arm64 does not have mknod
|
} 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)))
|
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))
|
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 {
|
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))
|
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)))
|
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 {
|
get_errno :: proc "contextless" (res: int) -> i32 {
|
||||||
if res < 0 && res > -4096 {
|
if res < 0 && res > -4096 {
|
||||||
return i32(-res)
|
return i32(-res)
|
||||||
|
|||||||
@@ -315,6 +315,13 @@ foreign kernel32 {
|
|||||||
lpOverlapped: LPOVERLAPPED,
|
lpOverlapped: LPOVERLAPPED,
|
||||||
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
|
lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
|
||||||
) -> BOOL ---
|
) -> BOOL ---
|
||||||
|
FindFirstChangeNotificationW :: proc(
|
||||||
|
lpPathName: LPWSTR,
|
||||||
|
bWatchSubtree: BOOL,
|
||||||
|
dwNotifyFilter: DWORD,
|
||||||
|
) -> HANDLE ---
|
||||||
|
FindNextChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL ---
|
||||||
|
FindCloseChangeNotification :: proc(hChangeHandle: HANDLE) -> BOOL ---
|
||||||
|
|
||||||
InitializeSRWLock :: proc(SRWLock: ^SRWLOCK) ---
|
InitializeSRWLock :: proc(SRWLock: ^SRWLOCK) ---
|
||||||
AcquireSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) ---
|
AcquireSRWLockExclusive :: proc(SRWLock: ^SRWLOCK) ---
|
||||||
|
|||||||
+49
-2
@@ -1,11 +1,11 @@
|
|||||||
package time
|
package time
|
||||||
|
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
|
import "core:intrinsics"
|
||||||
|
|
||||||
Tick :: struct {
|
Tick :: struct {
|
||||||
_nsec: i64, // relative amount
|
_nsec: i64, // relative amount
|
||||||
}
|
}
|
||||||
|
|
||||||
tick_now :: proc "contextless" () -> Tick {
|
tick_now :: proc "contextless" () -> Tick {
|
||||||
return _tick_now()
|
return _tick_now()
|
||||||
}
|
}
|
||||||
@@ -40,6 +40,53 @@ _tick_duration_end :: proc "contextless" (d: ^Duration, t: Tick) {
|
|||||||
d^ = tick_since(t)
|
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
|
Benchmark helpers
|
||||||
*/
|
*/
|
||||||
@@ -94,4 +141,4 @@ benchmark :: proc(options: ^Benchmark_Options, allocator := context.allocator) -
|
|||||||
options->teardown(allocator) or_return
|
options->teardown(allocator) or_return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//+private
|
||||||
|
//+build openbsd
|
||||||
|
package time
|
||||||
|
|
||||||
|
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//+private
|
||||||
|
//+build windows
|
||||||
|
package time
|
||||||
|
|
||||||
|
_get_tsc_frequency :: proc "contextless" () -> (u64, bool) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
@@ -288,7 +288,8 @@ struct BuildContext {
|
|||||||
|
|
||||||
bool ignore_warnings;
|
bool ignore_warnings;
|
||||||
bool warnings_as_errors;
|
bool warnings_as_errors;
|
||||||
bool show_error_line;
|
bool hide_error_line;
|
||||||
|
bool has_ansi_terminal_colours;
|
||||||
|
|
||||||
bool ignore_lazy;
|
bool ignore_lazy;
|
||||||
bool ignore_llvm_build;
|
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) {
|
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) {
|
gb_internal bool has_asm_extension(String const &path) {
|
||||||
|
|||||||
+7
-2
@@ -578,7 +578,7 @@ gb_internal void check_const_decl(CheckerContext *ctx, Entity *e, Ast *type_expr
|
|||||||
if (operand.mode == Addressing_Invalid ||
|
if (operand.mode == Addressing_Invalid ||
|
||||||
base_type(operand.type) == t_invalid) {
|
base_type(operand.type) == t_invalid) {
|
||||||
gbString str = expr_to_string(init);
|
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);
|
gb_string_free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -816,9 +816,14 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
if (ac.test) {
|
if (ac.test) {
|
||||||
e->flags |= EntityFlag_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;
|
e->flags |= EntityFlag_Init;
|
||||||
|
} else if (ac.fini) {
|
||||||
|
e->flags |= EntityFlag_Fini;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ac.set_cold) {
|
if (ac.set_cold) {
|
||||||
e->flags |= EntityFlag_Cold;
|
e->flags |= EntityFlag_Cold;
|
||||||
}
|
}
|
||||||
|
|||||||
+265
-126
@@ -1679,9 +1679,13 @@ gb_internal bool check_unary_op(CheckerContext *c, Operand *o, Token op) {
|
|||||||
|
|
||||||
case Token_Not:
|
case Token_Not:
|
||||||
if (!is_type_boolean(type)) {
|
if (!is_type_boolean(type)) {
|
||||||
|
ERROR_BLOCK();
|
||||||
str = expr_to_string(o->expr);
|
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);
|
gb_string_free(str);
|
||||||
|
if (is_type_integer(type)) {
|
||||||
|
error_line("\tSuggestion: Did you mean to use the bitwise not operator '~'?\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
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) {
|
gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o, Type *type) {
|
||||||
gbString a = expr_to_string(o->expr);
|
gbString a = expr_to_string(o->expr);
|
||||||
gbString b = type_to_string(type);
|
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");
|
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) {
|
} 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);
|
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)) {
|
} 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);
|
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) {
|
} else if (check_integer_exceed_suggestion(c, o, type)) {
|
||||||
error_line("\tSuggestion: the expression may be casted to %s\n", b);
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2116,16 +2163,22 @@ gb_internal bool check_is_expressible(CheckerContext *ctx, Operand *o, Type *typ
|
|||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ERROR_BLOCK();
|
||||||
|
|
||||||
|
|
||||||
if (is_type_numeric(o->type) && is_type_numeric(type)) {
|
if (is_type_numeric(o->type) && is_type_numeric(type)) {
|
||||||
if (!is_type_integer(o->type) && is_type_integer(type)) {
|
if (!is_type_integer(o->type) && is_type_integer(type)) {
|
||||||
error(o->expr, "'%s' truncated to '%s', got %s", a, b, s);
|
error(o->expr, "'%s' truncated to '%s', got %s", a, b, s);
|
||||||
} else {
|
} else {
|
||||||
ERROR_BLOCK();
|
if (are_types_identical(o->type, type)) {
|
||||||
error(o->expr, "Cannot convert numeric value '%s' to '%s' from '%s', got %s", a, b, c, s);
|
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);
|
check_assignment_error_suggestion(ctx, o, type);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ERROR_BLOCK();
|
|
||||||
error(o->expr, "Cannot convert '%s' to '%s' from '%s', got %s", a, b, c, s);
|
error(o->expr, "Cannot convert '%s' to '%s' from '%s', got %s", a, b, c, s);
|
||||||
check_assignment_error_suggestion(ctx, o, type);
|
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) {
|
if (x->mode == Addressing_Type && y->mode == Addressing_Type) {
|
||||||
bool comp = are_types_identical(x->type, y->type);
|
bool comp = are_types_identical(x->type, y->type);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@@ -2432,7 +2485,7 @@ gb_internal void check_comparison(CheckerContext *c, Operand *x, Operand *y, Tok
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (err_str != nullptr) {
|
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;
|
x->type = t_untyped_bool;
|
||||||
} else {
|
} else {
|
||||||
if (x->mode == Addressing_Constant &&
|
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->type = t_untyped_integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x->expr = node;
|
||||||
x->value = exact_value_shift(be->op.kind, x_val, y_val);
|
x->value = exact_value_shift(be->op.kind, x_val, y_val);
|
||||||
|
|
||||||
|
|
||||||
if (is_type_typed(x->type)) {
|
if (is_type_typed(x->type)) {
|
||||||
check_is_expressible(c, x, base_type(x->type));
|
check_is_expressible(c, x, x->type);
|
||||||
}
|
}
|
||||||
return;
|
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);
|
bool can_convert = check_cast_internal(c, x, type);
|
||||||
|
|
||||||
if (!can_convert) {
|
if (!can_convert) {
|
||||||
gbString expr_str = expr_to_string(x->expr);
|
TEMPORARY_ALLOCATOR_GUARD();
|
||||||
gbString to_type = type_to_string(type);
|
gbString expr_str = expr_to_string(x->expr, temporary_allocator());
|
||||||
gbString from_type = type_to_string(x->type);
|
gbString to_type = type_to_string(type, temporary_allocator());
|
||||||
error(x->expr, "Cannot cast '%s' as '%s' from '%s'", expr_str, to_type, from_type);
|
gbString from_type = type_to_string(x->type, temporary_allocator());
|
||||||
gb_string_free(from_type);
|
|
||||||
gb_string_free(to_type);
|
|
||||||
gb_string_free(expr_str);
|
|
||||||
|
|
||||||
check_cast_error_suggestion(c, x, type);
|
|
||||||
|
|
||||||
x->mode = Addressing_Invalid;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3422,7 +3498,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ
|
|||||||
|
|
||||||
|
|
||||||
if (token_is_comparison(op.kind)) {
|
if (token_is_comparison(op.kind)) {
|
||||||
check_comparison(c, x, y, op.kind);
|
check_comparison(c, node, x, y, op.kind);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4539,7 +4615,7 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
|
|||||||
entity = scope_lookup_current(import_scope, entity_name);
|
entity = scope_lookup_current(import_scope, entity_name);
|
||||||
bool allow_builtin = false;
|
bool allow_builtin = false;
|
||||||
if (!is_entity_declared_for_selector(entity, import_scope, &allow_builtin)) {
|
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->mode = Addressing_Invalid;
|
||||||
operand->expr = node;
|
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)) {
|
if (!is_entity_exported(entity, allow_builtin)) {
|
||||||
gbString sel_str = expr_to_string(selector);
|
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);
|
gb_string_free(sel_str);
|
||||||
// NOTE(bill): make the state valid still, even if it's "invalid"
|
// NOTE(bill): make the state valid still, even if it's "invalid"
|
||||||
// operand->mode = Addressing_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 op_str = expr_to_string(op_expr);
|
||||||
gbString type_str = type_to_string_shorthand(operand->type);
|
gbString type_str = type_to_string_shorthand(operand->type);
|
||||||
gbString sel_str = expr_to_string(selector);
|
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) {
|
if (operand->mode == Addressing_Type) {
|
||||||
String const &name = selector->Ident.token.string;
|
if (is_type_polymorphic(operand->type, true)) {
|
||||||
Type *bt = base_type(operand->type);
|
error(op_expr, "Type '%s' has no field nor polymorphic parameter '%s'", op_str, sel_str);
|
||||||
if (operand->type->kind == Type_Named &&
|
} else {
|
||||||
operand->type->Named.type_name &&
|
error(op_expr, "Type '%s' has no field '%s'", op_str, sel_str);
|
||||||
operand->type->Named.type_name->kind == Entity_TypeName &&
|
}
|
||||||
operand->type->Named.type_name->TypeName.objc_metadata) {
|
} else {
|
||||||
check_did_you_mean_objc_entity(name, operand->type->Named.type_name, operand->mode == Addressing_Type);
|
error(op_expr, "'%s' of type '%s' has no field '%s'", op_str, type_str, sel_str);
|
||||||
} else if (bt->kind == Type_Struct) {
|
|
||||||
check_did_you_mean_type(name, bt->Struct.fields);
|
if (operand->type != nullptr && selector->kind == Ast_Ident) {
|
||||||
} else if (bt->kind == Type_Enum) {
|
String const &name = selector->Ident.token.string;
|
||||||
check_did_you_mean_type(name, bt->Enum.fields);
|
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->score = score;
|
||||||
data->result_type = final_proc_type->Proc.results;
|
data->result_type = final_proc_type->Proc.results;
|
||||||
data->gen_entity = gen_entity;
|
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;
|
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)) {
|
if (!is_ast_range(node)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -7082,9 +7178,17 @@ gb_internal bool check_range(CheckerContext *c, Ast *node, Operand *x, Operand *
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type *type = x->type;
|
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");
|
if (is_for_loop) {
|
||||||
return false;
|
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 &&
|
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;
|
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) {
|
gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
|
||||||
ExprKind kind = Expr_Expr;
|
ExprKind kind = Expr_Expr;
|
||||||
ast_node(cl, CompoundLit, node);
|
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);
|
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);
|
gb_string_free(type_str);
|
||||||
} else {
|
} else {
|
||||||
Ast *elem = cl->elems[0];
|
check_compound_literal_field_values(c, cl->elems, o, type, is_constant);
|
||||||
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"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
isize field_count = t->Struct.fields.count;
|
isize field_count = t->Struct.fields.count;
|
||||||
isize min_field_count = t->Struct.fields.count;
|
isize min_field_count = t->Struct.fields.count;
|
||||||
for (isize i = min_field_count-1; i >= 0; i--) {
|
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) {
|
if (cl->elems[0]->kind == Ast_FieldValue) {
|
||||||
TEMPORARY_ALLOCATOR_GUARD();
|
check_compound_literal_field_values(c, cl->elems, o, type, is_constant);
|
||||||
|
|
||||||
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"));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
bool seen_field_value = false;
|
bool seen_field_value = false;
|
||||||
|
|
||||||
@@ -8097,7 +8236,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
|||||||
|
|
||||||
Operand x = {};
|
Operand x = {};
|
||||||
Operand y = {};
|
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) {
|
if (!ok) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -8313,7 +8452,7 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
|
|||||||
|
|
||||||
Operand x = {};
|
Operand x = {};
|
||||||
Operand y = {};
|
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) {
|
if (!ok) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-8
@@ -725,7 +725,7 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod
|
|||||||
Operand x = {};
|
Operand x = {};
|
||||||
Operand y = {};
|
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) {
|
if (!ok) {
|
||||||
goto skip_expr;
|
goto skip_expr;
|
||||||
}
|
}
|
||||||
@@ -978,19 +978,19 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags
|
|||||||
|
|
||||||
Operand a = lhs;
|
Operand a = lhs;
|
||||||
Operand b = rhs;
|
Operand b = rhs;
|
||||||
check_comparison(ctx, &a, &x, Token_LtEq);
|
check_comparison(ctx, expr, &a, &x, Token_LtEq);
|
||||||
if (a.mode == Addressing_Invalid) {
|
if (a.mode == Addressing_Invalid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_comparison(ctx, &b, &x, upper_op);
|
check_comparison(ctx, expr, &b, &x, upper_op);
|
||||||
if (b.mode == Addressing_Invalid) {
|
if (b.mode == Addressing_Invalid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand a1 = lhs;
|
Operand a1 = lhs;
|
||||||
Operand b1 = rhs;
|
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);
|
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
|
// NOTE(bill): the ordering here matters
|
||||||
Operand z = y;
|
Operand z = y;
|
||||||
check_comparison(ctx, &z, &x, Token_CmpEq);
|
check_comparison(ctx, expr, &z, &x, Token_CmpEq);
|
||||||
if (z.mode == Addressing_Invalid) {
|
if (z.mode == Addressing_Invalid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1293,7 +1293,6 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_
|
|||||||
for (Type *t : variants) {
|
for (Type *t : variants) {
|
||||||
if (!type_ptr_set_exists(&seen, t)) {
|
if (!type_ptr_set_exists(&seen, t)) {
|
||||||
array_add(&unhandled, 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 x = {};
|
||||||
Operand y = {};
|
Operand y = {};
|
||||||
|
|
||||||
bool ok = check_range(ctx, expr, &x, &y, nullptr);
|
bool ok = check_range(ctx, expr, true, &x, &y, nullptr);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
goto skip_expr_range_stmt;
|
goto skip_expr_range_stmt;
|
||||||
}
|
}
|
||||||
@@ -1921,7 +1920,7 @@ gb_internal void check_expr_stmt(CheckerContext *ctx, Ast *node) {
|
|||||||
case Addressing_Type:
|
case Addressing_Type:
|
||||||
{
|
{
|
||||||
gbString str = type_to_string(operand.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);
|
gb_string_free(str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-4
@@ -1309,6 +1309,8 @@ gb_internal ParameterValue handle_parameter_value(CheckerContext *ctx, Type *in_
|
|||||||
init_core_source_code_location(ctx->checker);
|
init_core_source_code_location(ctx->checker);
|
||||||
param_value.kind = ParameterValue_Location;
|
param_value.kind = ParameterValue_Location;
|
||||||
o.type = t_source_code_location;
|
o.type = t_source_code_location;
|
||||||
|
o.mode = Addressing_Value;
|
||||||
|
o.expr = expr;
|
||||||
|
|
||||||
if (in_type) {
|
if (in_type) {
|
||||||
check_assignment(ctx, &o, in_type, str_lit("parameter value"));
|
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) {
|
if (is_poly_name) {
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
if (is_type_proc(op.type)) {
|
if (is_type_proc(op.type)) {
|
||||||
Entity *proc_entity = entity_from_expr(op.expr);
|
Ast *expr = unparen_expr(op.expr);
|
||||||
valid = (proc_entity != nullptr) && (op.value.kind == ExactValue_Procedure);
|
Entity *proc_entity = entity_from_expr(expr);
|
||||||
if (valid) {
|
if (proc_entity) {
|
||||||
poly_const = exact_value_procedure(proc_entity->identifier.load() ? proc_entity->identifier.load() : op.expr);
|
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 (!valid) {
|
||||||
if (op.mode == Addressing_Constant) {
|
if (op.mode == Addressing_Constant) {
|
||||||
poly_const = op.value;
|
poly_const = op.value;
|
||||||
} else {
|
} 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;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-8
@@ -1155,6 +1155,7 @@ gb_internal void init_checker_info(CheckerInfo *i) {
|
|||||||
array_init(&i->variable_init_order, a);
|
array_init(&i->variable_init_order, a);
|
||||||
array_init(&i->testing_procedures, a, 0, 0);
|
array_init(&i->testing_procedures, a, 0, 0);
|
||||||
array_init(&i->init_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);
|
array_init(&i->required_foreign_imports_through_force, a, 0, 0);
|
||||||
|
|
||||||
map_init(&i->objc_msgSend_types);
|
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) {
|
if (expr == nullptr) {
|
||||||
return;
|
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);
|
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) {
|
if (expr == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1546,7 +1547,7 @@ gb_internal void add_entity_flags_from_file(CheckerContext *c, Entity *e, Scope
|
|||||||
AstPackage *pkg = c->file->pkg;
|
AstPackage *pkg = c->file->pkg;
|
||||||
if (pkg->kind == Package_Init && e->kind == Entity_Procedure && e->token.string == "main") {
|
if (pkg->kind == Package_Init && e->kind == Entity_Procedure && e->token.string == "main") {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
} else if (e->flags & (EntityFlag_Test|EntityFlag_Init)) {
|
} else if (e->flags & (EntityFlag_Test|EntityFlag_Init|EntityFlag_Fini)) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
} else {
|
} else {
|
||||||
e->flags |= EntityFlag_Lazy;
|
e->flags |= EntityFlag_Lazy;
|
||||||
@@ -1614,7 +1615,7 @@ gb_internal bool could_entity_be_lazy(Entity *e, DeclInfo *d) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->flags & (EntityFlag_Test|EntityFlag_Init)) {
|
if (e->flags & (EntityFlag_Test|EntityFlag_Init|EntityFlag_Fini)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (e->kind == Entity_Variable && e->Variable.is_export) {
|
} else if (e->kind == Entity_Variable && e->Variable.is_export) {
|
||||||
return false;
|
return false;
|
||||||
@@ -2423,6 +2424,28 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
|||||||
add_dependency_to_set(c, e);
|
add_dependency_to_set(c, e);
|
||||||
array_add(&c->info.init_procedures, 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;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2974,6 +2997,12 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
|||||||
}
|
}
|
||||||
ac->init = true;
|
ac->init = true;
|
||||||
return 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") {
|
} else if (name == "deferred") {
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
Operand o = {};
|
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;
|
EntityVisiblityKind entity_visibility_kind = c->foreign_context.visibility_kind;
|
||||||
bool is_test = false;
|
bool is_test = false;
|
||||||
bool is_init = false;
|
bool is_init = false;
|
||||||
|
bool is_fini = false;
|
||||||
|
|
||||||
for_array(i, vd->attributes) {
|
for_array(i, vd->attributes) {
|
||||||
Ast *attr = vd->attributes[i];
|
Ast *attr = vd->attributes[i];
|
||||||
@@ -3674,6 +3704,8 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
|||||||
is_test = true;
|
is_test = true;
|
||||||
} else if (name == "init") {
|
} else if (name == "init") {
|
||||||
is_init = true;
|
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) {
|
if (is_test) {
|
||||||
e->flags |= EntityFlag_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;
|
e->flags |= EntityFlag_Init;
|
||||||
|
} else if (is_fini) {
|
||||||
|
e->flags |= EntityFlag_Fini;
|
||||||
}
|
}
|
||||||
} else if (init->kind == Ast_ProcGroup) {
|
} else if (init->kind == Ast_ProcGroup) {
|
||||||
ast_node(pg, ProcGroup, init);
|
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);
|
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.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) {
|
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);
|
add_type_and_value(&c->builtin_ctx, u.expr, u.info->mode, u.info->type, u.info->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
TIME_SECTION("sort init procedures");
|
TIME_SECTION("sort init and fini procedures");
|
||||||
check_sort_init_procedures(c);
|
check_sort_init_and_fini_procedures(c);
|
||||||
|
|
||||||
if (c->info.intrinsics_entry_point_usage.count > 0) {
|
if (c->info.intrinsics_entry_point_usage.count > 0) {
|
||||||
TIME_SECTION("check intrinsics.__entry_point usage");
|
TIME_SECTION("check intrinsics.__entry_point usage");
|
||||||
|
|||||||
+4
-2
@@ -117,6 +117,7 @@ struct AttributeContext {
|
|||||||
bool disabled_proc : 1;
|
bool disabled_proc : 1;
|
||||||
bool test : 1;
|
bool test : 1;
|
||||||
bool init : 1;
|
bool init : 1;
|
||||||
|
bool fini : 1;
|
||||||
bool set_cold : 1;
|
bool set_cold : 1;
|
||||||
u32 optimization_mode; // ProcedureOptimizationMode
|
u32 optimization_mode; // ProcedureOptimizationMode
|
||||||
i64 foreign_import_priority_index;
|
i64 foreign_import_priority_index;
|
||||||
@@ -351,6 +352,7 @@ struct CheckerInfo {
|
|||||||
|
|
||||||
Array<Entity *> testing_procedures;
|
Array<Entity *> testing_procedures;
|
||||||
Array<Entity *> init_procedures;
|
Array<Entity *> init_procedures;
|
||||||
|
Array<Entity *> fini_procedures;
|
||||||
|
|
||||||
Array<Entity *> definitions;
|
Array<Entity *> definitions;
|
||||||
Array<Entity *> entities;
|
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 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 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_entity_use (CheckerContext *c, Ast *identifier, Entity *entity);
|
||||||
gb_internal void add_implicit_entity (CheckerContext *c, Ast *node, Entity *e);
|
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);
|
gb_internal void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, Entity *e, DeclInfo *d, bool is_exported=true);
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ struct TypeIsPointer<T *> {
|
|||||||
enum {value = true};
|
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 "unicode.cpp"
|
||||||
#include "array.cpp"
|
#include "array.cpp"
|
||||||
#include "threading.cpp"
|
#include "threading.cpp"
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ enum EntityFlag : u64 {
|
|||||||
EntityFlag_Test = 1ull<<30,
|
EntityFlag_Test = 1ull<<30,
|
||||||
EntityFlag_Init = 1ull<<31,
|
EntityFlag_Init = 1ull<<31,
|
||||||
EntityFlag_Subtype = 1ull<<32,
|
EntityFlag_Subtype = 1ull<<32,
|
||||||
|
EntityFlag_Fini = 1ull<<33,
|
||||||
|
|
||||||
EntityFlag_CustomLinkName = 1ull<<40,
|
EntityFlag_CustomLinkName = 1ull<<40,
|
||||||
EntityFlag_CustomLinkage_Internal = 1ull<<41,
|
EntityFlag_CustomLinkage_Internal = 1ull<<41,
|
||||||
|
|||||||
+171
-51
@@ -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) {
|
gb_internal void begin_error_block(void) {
|
||||||
mutex_lock(&global_error_collector.block_mutex);
|
mutex_lock(&global_error_collector.block_mutex);
|
||||||
global_error_collector.in_block.store(true);
|
global_error_collector.in_block.store(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal void end_error_block(void) {
|
gb_internal void end_error_block(void) {
|
||||||
if (global_error_collector.error_buffer.count > 0) {
|
isize n = global_error_collector.error_buffer.count;
|
||||||
isize n = global_error_collector.error_buffer.count;
|
if (n > 0) {
|
||||||
u8 *text = gb_alloc_array(permanent_allocator(), u8, n+1);
|
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);
|
gb_memmove(text, global_error_collector.error_buffer.data, n);
|
||||||
text[n] = 0;
|
text[n] = 0;
|
||||||
String s = {text, n};
|
String s = {text, n};
|
||||||
@@ -149,15 +191,8 @@ gb_internal ERROR_OUT_PROC(default_error_out_va) {
|
|||||||
gb_file_write(f, buf, n);
|
gb_file_write(f, buf, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_global ErrorOutProc *error_out_va = default_error_out_va;
|
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, ...) {
|
gb_internal void error_out(char const *fmt, ...) {
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
@@ -165,6 +200,49 @@ gb_internal void error_out(char const *fmt, ...) {
|
|||||||
va_end(va);
|
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) {
|
gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
|
||||||
if (!show_error_line()) {
|
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
|
// TODO(bill): This assumes ASCII
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MAX_LINE_LENGTH = 76,
|
MAX_LINE_LENGTH = 80,
|
||||||
MAX_TAB_WIDTH = 8,
|
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");
|
error_out("\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);
|
|
||||||
|
|
||||||
|
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.text += offset-left;
|
||||||
line.len -= offset+right-left;
|
line.len -= offset-left;
|
||||||
|
offset = left+MAX_TAB_WIDTH/2;
|
||||||
line = string_trim_whitespace(line);
|
if (line.len > MAX_LINE_LENGTH_PADDED) {
|
||||||
|
line.len = MAX_LINE_LENGTH_PADDED;
|
||||||
offset = left + ELLIPSIS_PADDING/2;
|
if (error_length > line.len-left) {
|
||||||
|
error_length = cast(i32)line.len - left;
|
||||||
|
squiggle_extra = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
error_out("... %.*s ...", LIT(line));
|
error_out("... %.*s ...", LIT(line));
|
||||||
} else {
|
} else {
|
||||||
error_out("%.*s", LIT(line));
|
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++) {
|
for (i32 i = 0; i < offset; i++) {
|
||||||
error_out(" ");
|
error_out(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terminal_set_colours(TerminalStyle_Bold, TerminalColour_Green);
|
||||||
|
|
||||||
error_out("^");
|
error_out("^");
|
||||||
if (end.file_id == pos.file_id) {
|
if (end.file_id == pos.file_id) {
|
||||||
if (end.line > pos.line) {
|
if (end.line > pos.line) {
|
||||||
@@ -217,34 +305,54 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
|
|||||||
error_out("~");
|
error_out("~");
|
||||||
}
|
}
|
||||||
} else if (end.line == pos.line && end.column > pos.column) {
|
} 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 < error_length-1+squiggle_extra; i++) {
|
||||||
for (i32 i = 1; i < length-1; i++) {
|
|
||||||
error_out("~");
|
error_out("~");
|
||||||
}
|
}
|
||||||
if (length > 1) {
|
if (error_length > 1 && squiggle_extra == 0) {
|
||||||
error_out("^");
|
error_out("^");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error_out("\n\n");
|
terminal_reset_colours();
|
||||||
|
|
||||||
|
error_out("\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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) {
|
gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) {
|
||||||
global_error_collector.count.fetch_add(1);
|
global_error_collector.count.fetch_add(1);
|
||||||
|
|
||||||
mutex_lock(&global_error_collector.mutex);
|
mutex_lock(&global_error_collector.mutex);
|
||||||
// NOTE(bill): Duplicate error, skip it
|
// NOTE(bill): Duplicate error, skip it
|
||||||
if (pos.line == 0) {
|
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) {
|
} else if (global_error_collector.prev != pos) {
|
||||||
global_error_collector.prev = pos;
|
global_error_collector.prev = pos;
|
||||||
error_out("%s %s\n",
|
error_out_pos(pos);
|
||||||
token_pos_to_string(pos),
|
if (has_ansi_terminal_colours()) {
|
||||||
gb_bprintf_va(fmt, va));
|
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||||
|
}
|
||||||
|
error_out_va(fmt, va);
|
||||||
|
error_out("\n");
|
||||||
show_error_on_line(pos, end);
|
show_error_on_line(pos, end);
|
||||||
}
|
}
|
||||||
mutex_unlock(&global_error_collector.mutex);
|
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()) {
|
if (!global_ignore_warnings()) {
|
||||||
// NOTE(bill): Duplicate error, skip it
|
// NOTE(bill): Duplicate error, skip it
|
||||||
if (pos.line == 0) {
|
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) {
|
} else if (global_error_collector.prev != pos) {
|
||||||
global_error_collector.prev = pos;
|
global_error_collector.prev = pos;
|
||||||
error_out("%s Warning: %s\n",
|
error_out_pos(pos);
|
||||||
token_pos_to_string(pos),
|
error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||||
gb_bprintf_va(fmt, va));
|
error_out_va(fmt, va);
|
||||||
|
error_out("\n");
|
||||||
show_error_on_line(pos, end);
|
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++;
|
global_error_collector.count++;
|
||||||
// NOTE(bill): Duplicate error, skip it
|
// NOTE(bill): Duplicate error, skip it
|
||||||
if (pos.line == 0) {
|
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) {
|
} else if (global_error_collector.prev != pos) {
|
||||||
global_error_collector.prev = pos;
|
global_error_collector.prev = pos;
|
||||||
error_out("%s %s",
|
error_out_pos(pos);
|
||||||
token_pos_to_string(pos),
|
if (has_ansi_terminal_colours()) {
|
||||||
gb_bprintf_va(fmt, va));
|
error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||||
|
}
|
||||||
|
error_out_va(fmt, va);
|
||||||
}
|
}
|
||||||
mutex_unlock(&global_error_collector.mutex);
|
mutex_unlock(&global_error_collector.mutex);
|
||||||
if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT) {
|
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
|
// NOTE(bill): Duplicate error, skip it
|
||||||
if (global_error_collector.prev != pos) {
|
if (global_error_collector.prev != pos) {
|
||||||
global_error_collector.prev = pos;
|
global_error_collector.prev = pos;
|
||||||
error_out("%s Syntax Error: %s\n",
|
error_out_pos(pos);
|
||||||
token_pos_to_string(pos),
|
error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
|
||||||
gb_bprintf_va(fmt, va));
|
error_out_va(fmt, va);
|
||||||
show_error_on_line(pos, end);
|
error_out("\n");
|
||||||
|
// show_error_on_line(pos, end);
|
||||||
} else if (pos.line == 0) {
|
} 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);
|
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
|
// NOTE(bill): Duplicate error, skip it
|
||||||
if (global_error_collector.prev != pos) {
|
if (global_error_collector.prev != pos) {
|
||||||
global_error_collector.prev = pos;
|
global_error_collector.prev = pos;
|
||||||
error_out("%s Syntax Warning: %s\n",
|
error_out_pos(pos);
|
||||||
token_pos_to_string(pos),
|
error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
|
||||||
gb_bprintf_va(fmt, va));
|
error_out_va(fmt, va);
|
||||||
show_error_on_line(pos, end);
|
error_out("\n");
|
||||||
|
// show_error_on_line(pos, end);
|
||||||
} else if (pos.line == 0) {
|
} 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);
|
mutex_unlock(&global_error_collector.mutex);
|
||||||
|
|||||||
+1
-3
@@ -578,9 +578,7 @@ gb_internal ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
failure:
|
failure:;
|
||||||
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op]));
|
|
||||||
|
|
||||||
ExactValue error_value = {};
|
ExactValue error_value = {};
|
||||||
return error_value;
|
return error_value;
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-4
@@ -1161,6 +1161,34 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
|
|||||||
return p;
|
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) {
|
gb_internal WORKER_TASK_PROC(lb_generate_procedures_and_types_per_module) {
|
||||||
lbModule *m = cast(lbModule *)data;
|
lbModule *m = cast(lbModule *)data;
|
||||||
for (Entity *e : m->global_procedures_and_types_to_create) {
|
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) {
|
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_type_info);
|
||||||
lb_llvm_function_pass_per_function_internal(m, m->gen->startup_runtime);
|
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);
|
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);
|
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(m->mod);
|
||||||
lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level);
|
lb_populate_function_pass_manager(m, default_function_pass_manager, false, build_context.optimization_level);
|
||||||
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
|
LLVMFinalizeFunctionPassManager(default_function_pass_manager);
|
||||||
@@ -1793,7 +1822,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
|
|||||||
|
|
||||||
|
|
||||||
if (call_cleanup) {
|
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);
|
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->startup_type_info = lb_create_startup_type_info(default_module);
|
||||||
gen->objc_names = lb_create_objc_names(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);
|
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) {
|
if (build_context.ODIN_DEBUG) {
|
||||||
for (auto const &entry : builtin_pkg->scope->elements) {
|
for (auto const &entry : builtin_pkg->scope->elements) {
|
||||||
Entity *e = entry.value;
|
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) {
|
if (build_context.command_kind == Command_test && !already_has_entry_point) {
|
||||||
TIME_SECTION("LLVM main");
|
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)");
|
TIME_SECTION("LLVM Procedure Generation (missing)");
|
||||||
|
|||||||
@@ -182,6 +182,8 @@ struct lbModule {
|
|||||||
PtrMap<Type *, lbAddr> map_cell_info_map; // address of runtime.Map_Info
|
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<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];
|
LLVMPassManagerRef function_pass_managers[lbFunctionPassManager_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -208,6 +210,7 @@ struct lbGenerator {
|
|||||||
|
|
||||||
lbProcedure *startup_type_info;
|
lbProcedure *startup_type_info;
|
||||||
lbProcedure *startup_runtime;
|
lbProcedure *startup_runtime;
|
||||||
|
lbProcedure *cleanup_runtime;
|
||||||
lbProcedure *objc_names;
|
lbProcedure *objc_names;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -540,6 +543,7 @@ gb_internal LLVMTypeRef OdinLLVMGetArrayElementType(LLVMTypeRef type);
|
|||||||
gb_internal LLVMTypeRef OdinLLVMGetVectorElementType(LLVMTypeRef type);
|
gb_internal LLVMTypeRef OdinLLVMGetVectorElementType(LLVMTypeRef type);
|
||||||
|
|
||||||
#define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
|
#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_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info"
|
||||||
#define LB_TYPE_INFO_DATA_NAME "__$type_info_data"
|
#define LB_TYPE_INFO_DATA_NAME "__$type_info_data"
|
||||||
#define LB_TYPE_INFO_TYPES_NAME "__$type_info_types_data"
|
#define LB_TYPE_INFO_TYPES_NAME "__$type_info_types_data"
|
||||||
|
|||||||
@@ -386,6 +386,31 @@ gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, Bi
|
|||||||
return value;
|
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) {
|
gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_local) {
|
||||||
LLVMContextRef ctx = m->ctx;
|
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);
|
Ast *expr = unparen_expr(value.value_procedure);
|
||||||
if (expr->kind == Ast_ProcLit) {
|
if (expr->kind == Ast_ProcLit) {
|
||||||
res = lb_generate_anonymous_proc_lit(m, str_lit("_proclit"), expr);
|
res = lb_generate_anonymous_proc_lit(m, str_lit("_proclit"), expr);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Entity *e = entity_from_expr(expr);
|
Entity *e = entity_from_expr(expr);
|
||||||
res = lb_find_procedure_value_from_entity(m, e);
|
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 ptr = LLVMBuildInBoundsGEP2(p->builder, llvm_type, array_data, indices, 2, "");
|
||||||
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
|
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true);
|
||||||
lbAddr slice = lb_add_local_generated(p, type, false);
|
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});
|
lb_fill_slice(p, slice, {ptr, alloc_type_pointer(elem)}, {len, t_int});
|
||||||
return lb_addr_load(p, slice);
|
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);
|
GB_ASSERT(tav.mode != Addressing_Invalid);
|
||||||
|
|
||||||
Selection sel = lookup_field(type, name, false);
|
Selection sel = lookup_field(type, name, false);
|
||||||
|
GB_ASSERT(!sel.indirect);
|
||||||
|
|
||||||
Entity *f = type->Struct.fields[sel.index[0]];
|
Entity *f = type->Struct.fields[sel.index[0]];
|
||||||
|
|
||||||
i32 index = field_remapping[f->Variable.field_index];
|
i32 index = field_remapping[f->Variable.field_index];
|
||||||
if (elem_type_can_be_constant(f->type)) {
|
if (elem_type_can_be_constant(f->type)) {
|
||||||
values[index] = lb_const_value(m, f->type, tav.value, allow_local).value;
|
if (sel.index.count == 1) {
|
||||||
visited[index] = true;
|
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 {
|
} else {
|
||||||
@@ -1043,6 +1115,8 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
|
|||||||
GB_ASSERT(is_local);
|
GB_ASSERT(is_local);
|
||||||
lbProcedure *p = m->curr_procedure;
|
lbProcedure *p = m->curr_procedure;
|
||||||
lbAddr v = lb_add_local_generated(p, res.type, true);
|
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);
|
LLVMBuildStore(p->builder, constant_value, v.addr.value);
|
||||||
for (isize i = 0; i < value_count; i++) {
|
for (isize i = 0; i < value_count; i++) {
|
||||||
LLVMValueRef val = old_values[i];
|
LLVMValueRef val = old_values[i];
|
||||||
|
|||||||
@@ -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 left_ptr = lb_address_from_load_or_generate_local(p, left);
|
||||||
lbValue right_ptr = lb_address_from_load_or_generate_local(p, right);
|
lbValue right_ptr = lb_address_from_load_or_generate_local(p, right);
|
||||||
lbValue res = {};
|
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)) {
|
if (is_type_simple_compare(type)) {
|
||||||
// TODO(bill): Test to see if this is actually faster!!!!
|
// TODO(bill): Test to see if this is actually faster!!!!
|
||||||
auto args = array_make<lbValue>(permanent_allocator(), 3);
|
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);
|
Entity *e = entity_from_expr(expr);
|
||||||
e = strip_entity_wrapping(e);
|
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) {
|
if (e->kind == Entity_Builtin) {
|
||||||
Token token = ast_token(expr);
|
Token token = ast_token(expr);
|
||||||
GB_PANIC("TODO(bill): lb_build_expr Entity_Builtin '%.*s'\n"
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
|
gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
|
||||||
ast_node(cl, CompoundLit, 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);
|
ast_node(fv, FieldValue, elem);
|
||||||
String name = fv->field->Ident.token.string;
|
String name = fv->field->Ident.token.string;
|
||||||
Selection sel = lookup_field(bt, name, false);
|
Selection sel = lookup_field(bt, name, false);
|
||||||
index = sel.index[0];
|
GB_ASSERT(!sel.indirect);
|
||||||
|
|
||||||
elem = fv->value;
|
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 {
|
} else {
|
||||||
TypeAndValue tav = type_and_value_of_expr(elem);
|
|
||||||
Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_index);
|
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];
|
index = sel.index[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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_info_map, 0);
|
||||||
map_init(&m->map_cell_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]) {
|
if (params_by_ptr[i]) {
|
||||||
// NOTE(bill): The parameter needs to be passed "indirectly", override it
|
// NOTE(bill): The parameter needs to be passed "indirectly", override it
|
||||||
ft->args[i].kind = lbArg_Indirect;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1045,9 +1045,25 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> c
|
|||||||
} else if (is_odin_cc) {
|
} else if (is_odin_cc) {
|
||||||
// NOTE(bill): Odin parameters are immutable so the original value can be passed if possible
|
// NOTE(bill): Odin parameters are immutable so the original value can be passed if possible
|
||||||
// i.e. `T const &` in C++
|
// i.e. `T const &` in C++
|
||||||
ptr = lb_address_from_load_or_generate_local(p, x);
|
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 {
|
} 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);
|
array_add(&processed_args, ptr);
|
||||||
}
|
}
|
||||||
@@ -2288,7 +2304,15 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
|||||||
break;
|
break;
|
||||||
case BuiltinProc_volatile_store: LLVMSetVolatile(instr, true); break;
|
case BuiltinProc_volatile_store: LLVMSetVolatile(instr, true); break;
|
||||||
case BuiltinProc_atomic_store: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); 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)));
|
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;
|
break;
|
||||||
case BuiltinProc_volatile_load: LLVMSetVolatile(instr, true); break;
|
case BuiltinProc_volatile_load: LLVMSetVolatile(instr, true); break;
|
||||||
case BuiltinProc_atomic_load: LLVMSetOrdering(instr, LLVMAtomicOrderingSequentiallyConsistent); 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)));
|
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 = {};
|
lbValue res = {};
|
||||||
res.value = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false);
|
res.value = LLVMBuildAtomicRMW(p->builder, op, dst.value, val.value, ordering, false);
|
||||||
res.type = tv.type;
|
res.type = tv.type;
|
||||||
|
if (ordering == LLVMAtomicOrderingUnordered) {
|
||||||
|
LLVMSetVolatile(res.value, true);
|
||||||
|
}
|
||||||
return res;
|
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;
|
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;
|
LLVMBool single_threaded = false;
|
||||||
|
|
||||||
LLVMValueRef value = LLVMBuildAtomicCmpXchg(
|
LLVMValueRef value = LLVMBuildAtomicCmpXchg(
|
||||||
@@ -2420,6 +2454,9 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
|||||||
single_threaded
|
single_threaded
|
||||||
);
|
);
|
||||||
LLVMSetWeak(value, weak);
|
LLVMSetWeak(value, weak);
|
||||||
|
if (success_ordering == LLVMAtomicOrderingUnordered || failure_ordering == LLVMAtomicOrderingUnordered) {
|
||||||
|
LLVMSetVolatile(value, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_type_tuple(tv.type)) {
|
if (is_type_tuple(tv.type)) {
|
||||||
Type *fix_typed = alloc_type_tuple();
|
Type *fix_typed = alloc_type_tuple();
|
||||||
|
|||||||
+104
-8
@@ -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);
|
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) {
|
for (Ast *clause : body->stmts) {
|
||||||
ast_node(cc, CaseClause, clause);
|
ast_node(cc, CaseClause, clause);
|
||||||
lb_open_scope(p, cc->scope);
|
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);
|
Entity *case_entity = implicit_entity_of_node(clause);
|
||||||
|
|
||||||
lbValue value = parent_value;
|
|
||||||
|
|
||||||
lb_start_block(p, body);
|
lb_start_block(p, body);
|
||||||
|
|
||||||
bool by_reference = (case_entity->flags & EntityFlag_Value) == 0;
|
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 = case_entity->type;
|
||||||
Type *ct_ptr = alloc_type_pointer(ct);
|
Type *ct_ptr = alloc_type_pointer(ct);
|
||||||
|
|
||||||
value = lb_emit_conv(p, data, ct_ptr);
|
lbValue ptr = {};
|
||||||
if (!by_reference) {
|
|
||||||
value = lb_emit_load(p, value);
|
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);
|
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);
|
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;
|
Type *t = src_value.type;
|
||||||
if (t->kind == Type_Tuple) {
|
if (t->kind == Type_Tuple) {
|
||||||
lbTupleFix *tf = map_get(&p->tuple_fix_map, src_value.value);
|
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 {
|
} else {
|
||||||
array_add(dst_values, src_value);
|
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);
|
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_end;
|
||||||
|
|
||||||
case_ast_node(as, AssignStmt, node);
|
case_ast_node(as, AssignStmt, node);
|
||||||
|
|||||||
@@ -915,7 +915,7 @@ gb_internal lbStructFieldRemapping lb_get_struct_remapping(lbModule *m, Type *t)
|
|||||||
if (field_remapping == nullptr) {
|
if (field_remapping == nullptr) {
|
||||||
field_remapping = map_get(&m->struct_field_remapping, cast(void *)t);
|
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;
|
return *field_remapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+44
-1
@@ -659,6 +659,7 @@ enum BuildFlagKind {
|
|||||||
|
|
||||||
BuildFlag_IgnoreWarnings,
|
BuildFlag_IgnoreWarnings,
|
||||||
BuildFlag_WarningsAsErrors,
|
BuildFlag_WarningsAsErrors,
|
||||||
|
BuildFlag_TerseErrors,
|
||||||
BuildFlag_VerboseErrors,
|
BuildFlag_VerboseErrors,
|
||||||
BuildFlag_ErrorPosStyle,
|
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_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_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_VerboseErrors, str_lit("verbose-errors"), BuildFlagParam_None, Command_all);
|
||||||
add_flag(&build_flags, BuildFlag_ErrorPosStyle, str_lit("error-pos-style"), BuildFlagParam_String, 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BuildFlag_TerseErrors:
|
||||||
|
build_context.hide_error_line = true;
|
||||||
|
break;
|
||||||
case BuildFlag_VerboseErrors:
|
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;
|
break;
|
||||||
|
|
||||||
case BuildFlag_ErrorPosStyle:
|
case BuildFlag_ErrorPosStyle:
|
||||||
@@ -1835,6 +1842,17 @@ gb_internal void show_timings(Checker *c, Timings *t) {
|
|||||||
gb_internal void remove_temp_files(lbGenerator *gen) {
|
gb_internal void remove_temp_files(lbGenerator *gen) {
|
||||||
if (build_context.keep_temp_files) return;
|
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");
|
TIME_SECTION("remove keep temp files");
|
||||||
|
|
||||||
for (String const &path : gen->output_temp_paths) {
|
for (String const &path : gen->output_temp_paths) {
|
||||||
@@ -2476,6 +2494,30 @@ gb_internal int strip_semicolons(Parser *parser) {
|
|||||||
return cast(int)failed;
|
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) {
|
int main(int arg_count, char const **arg_ptr) {
|
||||||
if (arg_count < 2) {
|
if (arg_count < 2) {
|
||||||
usage(make_string_c(arg_ptr[0]));
|
usage(make_string_c(arg_ptr[0]));
|
||||||
@@ -2491,6 +2533,7 @@ int main(int arg_count, char const **arg_ptr) {
|
|||||||
init_string_interner();
|
init_string_interner();
|
||||||
init_global_error_collector();
|
init_global_error_collector();
|
||||||
init_keyword_hash_table();
|
init_keyword_hash_table();
|
||||||
|
init_terminal();
|
||||||
|
|
||||||
if (!check_env()) {
|
if (!check_env()) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ gb_internal Token ast_token(Ast *node) {
|
|||||||
case Ast_ParenExpr: return node->ParenExpr.open;
|
case Ast_ParenExpr: return node->ParenExpr.open;
|
||||||
case Ast_CallExpr: return ast_token(node->CallExpr.proc);
|
case Ast_CallExpr: return ast_token(node->CallExpr.proc);
|
||||||
case Ast_SelectorExpr:
|
case Ast_SelectorExpr:
|
||||||
|
if (node->SelectorExpr.expr != nullptr) {
|
||||||
|
return ast_token(node->SelectorExpr.expr);
|
||||||
|
}
|
||||||
if (node->SelectorExpr.selector != nullptr) {
|
if (node->SelectorExpr.selector != nullptr) {
|
||||||
return ast_token(node->SelectorExpr.selector);
|
return ast_token(node->SelectorExpr.selector);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct PtrSet {
|
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);
|
static constexpr uintptr TOMBSTONE = ~(uintptr)(0ull);
|
||||||
|
|
||||||
T * keys;
|
T * keys;
|
||||||
|
|||||||
@@ -430,7 +430,6 @@ gb_internal Selection sub_selection(Selection const &sel, isize offset) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_global Type basic_types[] = {
|
gb_global Type basic_types[] = {
|
||||||
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
|
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},
|
||||||
|
|
||||||
@@ -2313,9 +2312,6 @@ gb_internal bool is_type_comparable(Type *t) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Type_Struct:
|
case Type_Struct:
|
||||||
if (type_size_of(t) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (t->Struct.soa_kind != StructSoa_None) {
|
if (t->Struct.soa_kind != StructSoa_None) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2331,9 +2327,6 @@ gb_internal bool is_type_comparable(Type *t) {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Type_Union:
|
case Type_Union:
|
||||||
if (type_size_of(t) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for_array(i, t->Union.variants) {
|
for_array(i, t->Union.variants) {
|
||||||
Type *v = t->Union.variants[i];
|
Type *v = t->Union.variants[i];
|
||||||
if (!is_type_comparable(v)) {
|
if (!is_type_comparable(v)) {
|
||||||
|
|||||||
+31
@@ -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
@@ -0,0 +1,9 @@
|
|||||||
|
package objc_Foundation
|
||||||
|
|
||||||
|
ModalResponse :: enum UInteger {
|
||||||
|
Cancel = 0,
|
||||||
|
OK = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
@(objc_class="NSPanel")
|
||||||
|
Panel :: struct{ using _: Window }
|
||||||
+9
@@ -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")
|
||||||
|
}
|
||||||
Vendored
+3
-3
@@ -25,6 +25,6 @@ URL_initFileURLWithPath :: proc(self: ^URL, path: ^String) -> ^URL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(objc_type=URL, objc_name="fileSystemRepresentation")
|
@(objc_type=URL, objc_name="fileSystemRepresentation")
|
||||||
URL_fileSystemRepresentation :: proc(self: ^URL) -> ^String {
|
URL_fileSystemRepresentation :: proc(self: ^URL) -> cstring {
|
||||||
return msgSend(^String, self, "fileSystemRepresentation")
|
return msgSend(cstring, self, "fileSystemRepresentation")
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -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)
|
||||||
|
}
|
||||||
Vendored
+248
@@ -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.
|
||||||
Vendored
+90
-18
@@ -1226,7 +1226,7 @@ HEAP_FLAG :: enum u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES :: HEAP_FLAGS{}
|
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_NON_RT_DS_TEXTURES :: HEAP_FLAGS{.DENY_BUFFERS, .DENY_RT_DS_TEXTURES}
|
||||||
HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES :: HEAP_FLAGS{.DENY_BUFFERS, .DENY_NON_RT_DS_TEXTURES}
|
HEAP_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),
|
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),
|
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),
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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 {
|
LIFETIME_STATE :: enum i32 {
|
||||||
@@ -3516,7 +3516,7 @@ IDevice8 :: struct #raw_union {
|
|||||||
}
|
}
|
||||||
IDevice8_VTable :: struct {
|
IDevice8_VTable :: struct {
|
||||||
using id3d12device7_vtable: IDevice7_VTable,
|
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,
|
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,
|
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),
|
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),
|
DispatchMesh: proc "stdcall" (this: ^IGraphicsCommandList6, ThreadGroupCountX: u32, ThreadGroupCountY: u32, ThreadGroupCountZ: u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
SHADER_VERSION_TYPE :: enum i32 {
|
SHADER_VERSION_TYPE :: enum u32 {
|
||||||
PIXEL_SHADER = 0,
|
PIXEL_SHADER = 0,
|
||||||
VERTEX_SHADER = 1,
|
VERTEX_SHADER = 1,
|
||||||
GEOMETRY_SHADER = 2,
|
GEOMETRY_SHADER = 2,
|
||||||
|
|
||||||
HULL_SHADER = 3,
|
HULL_SHADER = 3,
|
||||||
DOMAIN_SHADER = 4,
|
DOMAIN_SHADER = 4,
|
||||||
COMPUTE_SHADER = 5,
|
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 {
|
SIGNATURE_PARAMETER_DESC :: struct {
|
||||||
@@ -4984,6 +5008,7 @@ SHADER_TYPE_DESC :: struct {
|
|||||||
Offset: u32,
|
Offset: u32,
|
||||||
Name: cstring,
|
Name: cstring,
|
||||||
}
|
}
|
||||||
|
|
||||||
SHADER_DESC :: struct {
|
SHADER_DESC :: struct {
|
||||||
Version: u32,
|
Version: u32,
|
||||||
Creator: cstring,
|
Creator: cstring,
|
||||||
@@ -5042,6 +5067,39 @@ SHADER_INPUT_BIND_DESC :: struct {
|
|||||||
uID: u32,
|
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 {
|
LIBRARY_DESC :: struct {
|
||||||
Creator: cstring,
|
Creator: cstring,
|
||||||
Flags: u32,
|
Flags: u32,
|
||||||
@@ -5103,8 +5161,10 @@ PARAMETER_DESC :: struct {
|
|||||||
FirstOutComponent: u32,
|
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 {
|
IShaderReflectionType :: struct {
|
||||||
vtable: ^IShaderReflectionType_VTable,
|
using id3d12shaderreflectiontype_vtable: ^IShaderReflectionType_VTable,
|
||||||
}
|
}
|
||||||
IShaderReflectionType_VTable :: struct {
|
IShaderReflectionType_VTable :: struct {
|
||||||
GetDesc: proc "stdcall" (this: ^IShaderReflectionType, pDesc: ^SHADER_TYPE_DESC) -> HRESULT,
|
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,
|
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 {
|
IShaderReflectionVariable :: struct {
|
||||||
vtable: ^IShaderReflectionVariable_VTable,
|
using id3d12shaderreflectionvariable_vtable: ^IShaderReflectionVariable_VTable,
|
||||||
}
|
}
|
||||||
IShaderReflectionVariable_VTable :: struct {
|
IShaderReflectionVariable_VTable :: struct {
|
||||||
GetDesc: proc "stdcall" (this: ^IShaderReflectionVariable, pDesc: ^SHADER_VARIABLE_DESC) -> HRESULT,
|
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,
|
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 {
|
IShaderReflectionConstantBuffer :: struct {
|
||||||
vtable: ^IShaderReflectionConstantBuffer_VTable,
|
using id3d12shaderreflectionconstantbuffer_vtable: ^IShaderReflectionConstantBuffer_VTable,
|
||||||
}
|
}
|
||||||
IShaderReflectionConstantBuffer_VTable :: struct {
|
IShaderReflectionConstantBuffer_VTable :: struct {
|
||||||
GetDesc: proc "stdcall" (this: ^IShaderReflectionConstantBuffer, pDesc: ^SHADER_BUFFER_DESC) -> HRESULT,
|
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,
|
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 {
|
IShaderReflection :: struct #raw_union {
|
||||||
#subtype iunknown: IUnknown,
|
#subtype iunknown: IUnknown,
|
||||||
using id3d12shaderreflection_vtable: ^IShaderReflection_VTable,
|
using id3d12shaderreflection_vtable: ^IShaderReflection_VTable,
|
||||||
@@ -5163,9 +5229,11 @@ IShaderReflection_VTable :: struct {
|
|||||||
GetNumInterfaceSlots: proc "stdcall" (this: ^IShaderReflection) -> u32,
|
GetNumInterfaceSlots: proc "stdcall" (this: ^IShaderReflection) -> u32,
|
||||||
GetMinFeatureLevel: proc "stdcall" (this: ^IShaderReflection, pLevel: ^FEATURE_LEVEL) -> HRESULT,
|
GetMinFeatureLevel: proc "stdcall" (this: ^IShaderReflection, pLevel: ^FEATURE_LEVEL) -> HRESULT,
|
||||||
GetThreadGroupSize: proc "stdcall" (this: ^IShaderReflection, pSizeX: ^u32, pSizeY: ^u32, pSizeZ: ^u32) -> u32,
|
GetThreadGroupSize: proc "stdcall" (this: ^IShaderReflection, pSizeX: ^u32, pSizeY: ^u32, pSizeZ: ^u32) -> u32,
|
||||||
GetRequiresFlags: proc "stdcall" (this: ^IShaderReflection) -> u64,
|
GetRequiresFlags: proc "stdcall" (this: ^IShaderReflection) -> SHADER_REQUIRES_FLAGS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
ILibraryReflection :: struct #raw_union {
|
||||||
#subtype iunknown: IUnknown,
|
#subtype iunknown: IUnknown,
|
||||||
using id3d12libraryreflection_vtable: ^ILibraryReflection_VTable,
|
using id3d12libraryreflection_vtable: ^ILibraryReflection_VTable,
|
||||||
@@ -5176,8 +5244,10 @@ ILibraryReflection_VTable :: struct {
|
|||||||
GetFunctionByIndex: proc "stdcall" (this: ^ILibraryReflection, FunctionIndex: i32) -> ^IFunctionReflection,
|
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 {
|
IFunctionReflection :: struct {
|
||||||
vtable: ^IFunctionReflection_VTable,
|
using id3d12functionreflection_vtable: ^IFunctionReflection_VTable,
|
||||||
}
|
}
|
||||||
IFunctionReflection_VTable :: struct {
|
IFunctionReflection_VTable :: struct {
|
||||||
GetDesc: proc "stdcall" (this: ^IFunctionReflection, pDesc: ^FUNCTION_DESC) -> HRESULT,
|
GetDesc: proc "stdcall" (this: ^IFunctionReflection, pDesc: ^FUNCTION_DESC) -> HRESULT,
|
||||||
@@ -5189,8 +5259,10 @@ IFunctionReflection_VTable :: struct {
|
|||||||
GetFunctionParameter: proc "stdcall" (this: ^IFunctionReflection, ParameterIndex: i32) -> ^IFunctionParameterReflection,
|
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 {
|
IFunctionParameterReflection :: struct {
|
||||||
vtable: ^IFunctionParameterReflection_VTable,
|
using id3d12functionparameterreflection_vtable: ^IFunctionParameterReflection_VTable,
|
||||||
}
|
}
|
||||||
IFunctionParameterReflection_VTable :: struct {
|
IFunctionParameterReflection_VTable :: struct {
|
||||||
GetDesc: proc "stdcall" (this: ^IFunctionParameterReflection, pDesc: ^PARAMETER_DESC) -> HRESULT,
|
GetDesc: proc "stdcall" (this: ^IFunctionParameterReflection, pDesc: ^PARAMETER_DESC) -> HRESULT,
|
||||||
|
|||||||
Vendored
+603
@@ -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*"
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
+141
@@ -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,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user