From a7280472812d4a0d82d402e22181c781e0039ebf Mon Sep 17 00:00:00 2001 From: hikari Date: Sat, 1 Oct 2022 17:12:23 +0300 Subject: [PATCH 01/56] sys/windows: add a bunch of stuff --- core/sys/windows/advapi32.odin | 30 ++++++++ core/sys/windows/gdi32.odin | 1 + core/sys/windows/shell32.odin | 5 ++ core/sys/windows/shlwapi.odin | 1 + core/sys/windows/types.odin | 132 ++++++++++++++++++++++++++++++++- core/sys/windows/user32.odin | 1 + 6 files changed, 169 insertions(+), 1 deletion(-) diff --git a/core/sys/windows/advapi32.odin b/core/sys/windows/advapi32.odin index 82031d4f7..c2fbb560a 100644 --- a/core/sys/windows/advapi32.odin +++ b/core/sys/windows/advapi32.odin @@ -128,4 +128,34 @@ foreign advapi32 { lpData: LPCVOID, cbData: DWORD, ) -> LSTATUS --- + + GetFileSecurityA :: proc( + lpFileName: LPCSTR, + RequestedInformation: SECURITY_INFORMATION, + pSecurityDescriptor: PSECURITY_DESCRIPTOR, + nLength: DWORD, + lpnLengthNeeded: LPDWORD, + ) -> BOOL --- + + DuplicateToken :: proc( + ExistingTokenHandle: HANDLE, + ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL, + DuplicateTokenHandle: PHANDLE, + ) -> BOOL --- + + MapGenericMask :: proc( + AccessMask: PDWORD, + GenericMapping: PGENERIC_MAPPING, + ) --- + + AccessCheck :: proc( + pSecurityDescriptor: PSECURITY_DESCRIPTOR, + ClientToken: HANDLE, + DesiredAccess: DWORD, + GenericMapping: PGENERIC_MAPPING, + PrivilegeSet: PPRIVILEGE_SET, + PrivilegeSetLength: LPDWORD, + GrantedAccess: LPDWORD, + AccessStatus: LPBOOL, + ) -> BOOL --- } diff --git a/core/sys/windows/gdi32.odin b/core/sys/windows/gdi32.odin index 4403a5dc3..274cae35b 100644 --- a/core/sys/windows/gdi32.odin +++ b/core/sys/windows/gdi32.odin @@ -77,6 +77,7 @@ foreign gdi32 { ) -> HFONT --- TextOutW :: proc(hdc: HDC, x, y: c_int, lpString: LPCWSTR, c: c_int) -> BOOL --- GetTextExtentPoint32W :: proc(hdc: HDC, lpString: LPCWSTR, c: c_int, psizl: LPSIZE) -> BOOL --- + GetTextMetricsW :: proc(hdc: HDC, lptm: LPTEXTMETRICW) -> BOOL --- } RGB :: #force_inline proc "contextless" (r, g, b: u8) -> COLORREF { diff --git a/core/sys/windows/shell32.odin b/core/sys/windows/shell32.odin index fa7a24906..a3d6c6fb8 100644 --- a/core/sys/windows/shell32.odin +++ b/core/sys/windows/shell32.odin @@ -14,4 +14,9 @@ foreign shell32 { lpDirectory: LPCWSTR, nShowCmd: INT, ) -> HINSTANCE --- + SHCreateDirectoryExW :: proc( + hwnd: HWND, + pszPath: LPCWSTR, + psa: ^SECURITY_ATTRIBUTES, + ) -> c_int --- } diff --git a/core/sys/windows/shlwapi.odin b/core/sys/windows/shlwapi.odin index 1852d536f..241ade8f6 100644 --- a/core/sys/windows/shlwapi.odin +++ b/core/sys/windows/shlwapi.odin @@ -8,4 +8,5 @@ foreign shlwapi { PathFileExistsW :: proc(pszPath: wstring) -> BOOL --- PathFindExtensionW :: proc(pszPath: wstring) -> wstring --- PathFindFileNameW :: proc(pszPath: wstring) -> wstring --- + SHAutoComplete :: proc(hwndEdit: HWND, dwFlags: DWORD) -> LWSTDAPI --- } diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 85c94284c..0b7729767 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -20,6 +20,7 @@ DWORD :: c_ulong DWORDLONG :: c.ulonglong QWORD :: c.ulonglong HANDLE :: distinct LPVOID +PHANDLE :: ^HANDLE HINSTANCE :: HANDLE HMODULE :: distinct HINSTANCE HRESULT :: distinct LONG @@ -133,6 +134,11 @@ LPWSAOVERLAPPED :: distinct rawptr LPWSAOVERLAPPED_COMPLETION_ROUTINE :: distinct rawptr LPCVOID :: rawptr +PACCESS_TOKEN :: PVOID +PSECURITY_DESCRIPTOR :: PVOID +PSID :: PVOID +PCLAIMS_BLOB :: PVOID + PCONDITION_VARIABLE :: ^CONDITION_VARIABLE PLARGE_INTEGER :: ^LARGE_INTEGER PSRWLOCK :: ^SRWLOCK @@ -175,6 +181,7 @@ FILE_SHARE_DELETE: DWORD : 0x00000004 FILE_GENERIC_ALL: DWORD : 0x10000000 FILE_GENERIC_EXECUTE: DWORD : 0x20000000 FILE_GENERIC_READ: DWORD : 0x80000000 +FILE_ALL_ACCESS :: STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF FILE_ACTION_ADDED :: 0x00000001 FILE_ACTION_REMOVED :: 0x00000002 @@ -230,6 +237,20 @@ SECURITY_SQOS_PRESENT: DWORD : 0x00100000 FIONBIO: c_ulong : 0x8004667e +OWNER_SECURITY_INFORMATION :: 0x00000001 +GROUP_SECURITY_INFORMATION :: 0x00000002 +DACL_SECURITY_INFORMATION :: 0x00000004 +SACL_SECURITY_INFORMATION :: 0x00000008 +LABEL_SECURITY_INFORMATION :: 0x00000010 +ATTRIBUTE_SECURITY_INFORMATION :: 0x00000020 +SCOPE_SECURITY_INFORMATION :: 0x00000040 +PROCESS_TRUST_LABEL_SECURITY_INFORMATION :: 0x00000080 +ACCESS_FILTER_SECURITY_INFORMATION :: 0x00000100 +BACKUP_SECURITY_INFORMATION :: 0x00010000 +PROTECTED_DACL_SECURITY_INFORMATION :: 0x80000000 +PROTECTED_SACL_SECURITY_INFORMATION :: 0x40000000 +UNPROTECTED_DACL_SECURITY_INFORMATION :: 0x20000000 +UNPROTECTED_SACL_SECURITY_INFORMATION :: 0x10000000 GET_FILEEX_INFO_LEVELS :: distinct i32 GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0 @@ -773,6 +794,30 @@ MSG :: struct { LPMSG :: ^MSG +TEXTMETRICW :: struct { + tmHeight: LONG, + tmAscent: LONG, + tmDescent: LONG, + tmInternalLeading: LONG, + tmExternalLeading: LONG, + tmAveCharWidth: LONG, + tmMaxCharWidth: LONG, + tmWeight: LONG, + tmOverhang: LONG, + tmDigitizedAspectX: LONG, + tmDigitizedAspectY: LONG, + tmFirstChar: WCHAR, + tmLastChar: WCHAR, + tmDefaultChar: WCHAR, + tmBreakChar: WCHAR, + tmItalic: BYTE, + tmUnderlined: BYTE, + tmStruckOut: BYTE, + tmPitchAndFamily: BYTE, + tmCharSet: BYTE, +} +LPTEXTMETRICW :: ^TEXTMETRICW + PAINTSTRUCT :: struct { hdc: HDC, fErase: BOOL, @@ -1462,6 +1507,24 @@ IDI_WARNING := IDI_EXCLAMATION IDI_ERROR := IDI_HAND IDI_INFORMATION := IDI_ASTERISK +IMAGE_BITMAP :: 0 +IMAGE_ICON :: 1 +IMAGE_CURSOR :: 2 +IMAGE_ENHMETAFILE :: 3 + +LR_DEFAULTCOLOR :: 0x00000000 +LR_MONOCHROME :: 0x00000001 +LR_COLOR :: 0x00000002 +LR_COPYRETURNORG :: 0x00000004 +LR_COPYDELETEORG :: 0x00000008 +LR_LOADFROMFILE :: 0x00000010 +LR_LOADTRANSPARENT :: 0x00000020 +LR_DEFAULTSIZE :: 0x00000040 +LR_VGACOLOR :: 0x00000080 +LR_LOADMAP3DCOLORS :: 0x00001000 +LR_CREATEDIBSECTION :: 0x00002000 +LR_COPYFROMRESOURCE :: 0x00004000 +LR_SHARED :: 0x00008000 // DIB color table identifiers DIB_RGB_COLORS :: 0 @@ -1793,7 +1856,58 @@ HEAP_ZERO_MEMORY: DWORD : 0x00000008 HANDLE_FLAG_INHERIT: DWORD : 0x00000001 HANDLE_FLAG_PROTECT_FROM_CLOSE :: 0x00000002 -TOKEN_READ: DWORD : 0x20008 +GENERIC_MAPPING :: struct { + GenericRead: ACCESS_MASK, + GenericWrite: ACCESS_MASK, + GenericExecute: ACCESS_MASK, + GenericAll: ACCESS_MASK, +} +PGENERIC_MAPPING :: ^GENERIC_MAPPING + +SECURITY_IMPERSONATION_LEVEL :: enum { + SecurityAnonymous, + SecurityIdentification, + SecurityImpersonation, + SecurityDelegation, +} + +SECURITY_INFORMATION :: DWORD +ANYSIZE_ARRAY :: 1 + +LUID_AND_ATTRIBUTES :: struct { + Luid: LUID, + Attributes: DWORD, +} + +PRIVILEGE_SET :: struct { + PrivilegeCount: DWORD, + Control: DWORD, + Privilege: [ANYSIZE_ARRAY]LUID_AND_ATTRIBUTES, +} +PPRIVILEGE_SET :: ^PRIVILEGE_SET + +// Token Specific Access Rights. +TOKEN_ASSIGN_PRIMARY :: 0x0001 +TOKEN_DUPLICATE :: 0x0002 +TOKEN_IMPERSONATE :: 0x0004 +TOKEN_QUERY :: 0x0008 +TOKEN_QUERY_SOURCE :: 0x0010 +TOKEN_ADJUST_PRIVILEGES :: 0x0020 +TOKEN_ADJUST_GROUPS :: 0x0040 +TOKEN_ADJUST_DEFAULT :: 0x0080 +TOKEN_ADJUST_SESSIONID :: 0x0100 + +TOKEN_ALL_ACCESS_P :: STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY |\ + TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT + +TOKEN_ALL_ACCESS :: TOKEN_ALL_ACCESS_P | TOKEN_ADJUST_SESSIONID +TOKEN_READ :: STANDARD_RIGHTS_READ | TOKEN_QUERY +TOKEN_WRITE :: STANDARD_RIGHTS_WRITE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT +TOKEN_EXECUTE :: STANDARD_RIGHTS_EXECUTE +TOKEN_TRUST_CONSTRAINT_MASK :: STANDARD_RIGHTS_READ | TOKEN_QUERY | TOKEN_QUERY_SOURCE +TOKEN_ACCESS_PSEUDO_HANDLE_WIN8 :: TOKEN_QUERY | TOKEN_QUERY_SOURCE +TOKEN_ACCESS_PSEUDO_HANDLE :: TOKEN_ACCESS_PSEUDO_HANDLE_WIN8 + CP_ACP :: 0 // default to ANSI code page CP_OEMCP :: 1 // default to OEM code page @@ -3048,6 +3162,22 @@ SHCONTF_FLATLIST :: 0x4000 SHCONTF_ENABLE_ASYNC :: 0x8000 SHCONTF_INCLUDESUPERHIDDEN :: 0x10000 +SHACF_DEFAULT :: 0x00000000 // Currently (SHACF_FILESYSTEM | SHACF_URLALL) +SHACF_FILESYSTEM :: 0x00000001 // This includes the File System as well as the rest of the shell (Desktop\My Computer\Control Panel\) +SHACF_URLALL :: (SHACF_URLHISTORY | SHACF_URLMRU) +SHACF_URLHISTORY :: 0x00000002 // URLs in the User's History +SHACF_URLMRU :: 0x00000004 // URLs in the User's Recently Used list. +SHACF_USETAB :: 0x00000008 // Use the tab to move thru the autocomplete possibilities instead of to the next dialog/window control. +SHACF_FILESYS_ONLY :: 0x00000010 // This includes the File System +SHACF_FILESYS_DIRS :: 0x00000020 // Same as SHACF_FILESYS_ONLY except it only includes directories, UNC servers, and UNC server shares. +SHACF_VIRTUAL_NAMESPACE :: 0x00000040 // Also include the virtual namespace +SHACF_AUTOSUGGEST_FORCE_ON :: 0x10000000 // Ignore the registry default and force the feature on. +SHACF_AUTOSUGGEST_FORCE_OFF :: 0x20000000 // Ignore the registry default and force the feature off. +SHACF_AUTOAPPEND_FORCE_ON :: 0x40000000 // Ignore the registry default and force the feature on. (Also know as AutoComplete) +SHACF_AUTOAPPEND_FORCE_OFF :: 0x80000000 // Ignore the registry default and force the feature off. (Also know as AutoComplete) + +LWSTDAPI :: HRESULT + CLSID_FileOpenDialog := &GUID{0xDC1C5A9C, 0xE88A, 0x4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}} CLSID_FileSaveDialog := &GUID{0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}} diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin index ffb82ad0e..9a30e6454 100644 --- a/core/sys/windows/user32.odin +++ b/core/sys/windows/user32.odin @@ -78,6 +78,7 @@ foreign user32 { LoadIconW :: proc(hInstance: HINSTANCE, lpIconName: LPCWSTR) -> HICON --- LoadCursorA :: proc(hInstance: HINSTANCE, lpCursorName: LPCSTR) -> HCURSOR --- LoadCursorW :: proc(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> HCURSOR --- + LoadImageW :: proc(hInst: HINSTANCE, name: LPCWSTR, type: UINT, cx: c_int, cy: c_int, fuLoad: UINT) -> HANDLE --- GetWindowRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- From ce09cb0bdb123cca72021117e700b9b404361aeb Mon Sep 17 00:00:00 2001 From: hikari Date: Sat, 1 Oct 2022 17:13:17 +0300 Subject: [PATCH 02/56] sys/windows: add comctl32 --- core/sys/windows/comctl32.odin | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 core/sys/windows/comctl32.odin diff --git a/core/sys/windows/comctl32.odin b/core/sys/windows/comctl32.odin new file mode 100644 index 000000000..983c45d36 --- /dev/null +++ b/core/sys/windows/comctl32.odin @@ -0,0 +1,9 @@ +// +build windows +package sys_windows + +foreign import "system:Comctl32.lib" + +@(default_calling_convention="stdcall") +foreign Comctl32 { + LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT --- +} From bb9b58b8c42eec3d810688939a7dd454b6fa0c32 Mon Sep 17 00:00:00 2001 From: hikari Date: Fri, 7 Oct 2022 03:53:14 +0300 Subject: [PATCH 03/56] sys/windows: add some constants --- core/sys/windows/types.odin | 13 +++++++++++-- core/sys/windows/window_messages.odin | 3 +++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 0b7729767..d4983fd06 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -1111,8 +1111,14 @@ WS_EX_TOPMOST : UINT : 0x0000_0008 WS_EX_TRANSPARENT : UINT : 0x0000_0020 WS_EX_WINDOWEDGE : UINT : 0x0000_0100 -PBS_SMOOTH :: 0x01 -PBS_VERTICAL :: 0x04 +PBS_SMOOTH :: 0x01 +PBS_VERTICAL :: 0x04 +PBS_MARQUEE :: 0x08 +PBS_SMOOTHREVERSE :: 0x10 + +PBST_NORMAL :: 0x0001 +PBST_ERROR :: 0x0002 +PBST_PAUSED :: 0x0003 QS_ALLEVENTS : UINT : QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY QS_ALLINPUT : UINT : QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE @@ -1837,12 +1843,15 @@ WAIT_FAILED: DWORD : 0xFFFFFFFF PIPE_ACCESS_INBOUND: DWORD : 0x00000001 PIPE_ACCESS_OUTBOUND: DWORD : 0x00000002 +PIPE_ACCESS_DUPLEX: DWORD : 0x00000003 FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD : 0x00080000 FILE_FLAG_OVERLAPPED: DWORD : 0x40000000 PIPE_WAIT: DWORD : 0x00000000 PIPE_TYPE_BYTE: DWORD : 0x00000000 +PIPE_TYPE_MESSAGE: DWORD : 0x00000004 PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008 PIPE_READMODE_BYTE: DWORD : 0x00000000 +PIPE_READMODE_MESSAGE: DWORD : 0x00000002 PIPE_ACCEPT_REMOTE_CLIENTS: DWORD : 0x00000000 FD_SETSIZE :: 64 diff --git a/core/sys/windows/window_messages.odin b/core/sys/windows/window_messages.odin index 616247f59..888c5ccf9 100644 --- a/core/sys/windows/window_messages.odin +++ b/core/sys/windows/window_messages.odin @@ -454,6 +454,7 @@ TB_ISBUTTONENABLED :: 0x0409 TBM_CLEARTICS :: 0x0409 TTM_SETTOOLINFOA :: 0x0409 CBEM_HASEDITCHANGED :: 0x040a +PBM_SETMARQUEE :: 0x040a RB_INSERTBANDW :: 0x040a SB_GETRECT :: 0x040a TB_ISBUTTONCHECKED :: 0x040a @@ -488,10 +489,12 @@ TTM_ENUMTOOLSA :: 0x040e SB_SETICON :: 0x040f TBM_GETTICPOS :: 0x040f TTM_GETCURRENTTOOLA :: 0x040f +PBM_SETSTATE :: 0x0410 RB_IDTOINDEX :: 0x0410 SB_SETTIPTEXTA :: 0x0410 TBM_GETNUMTICS :: 0x0410 TTM_WINDOWFROMPOINT :: 0x0410 +PBM_GETSTATE :: 0x0411 RB_GETTOOLTIPS :: 0x0411 SB_SETTIPTEXTW :: 0x0411 TBM_GETSELSTART :: 0x0411 From 8b06fd093518c01c896e4eb2bcb271a5bc593b7e Mon Sep 17 00:00:00 2001 From: Phuk Ng Yu Date: Fri, 7 Oct 2022 00:06:46 -0700 Subject: [PATCH 04/56] os2/file_windows fix --- core/os/os2/file_windows.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 7589ed799..e4ae4856a 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -130,7 +130,7 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File { f := new(File, _file_allocator()) f.impl.allocator = _file_allocator() - f.impl.fd = rawptr(fd) + f.impl.fd = rawptr(handle) f.impl.name = strings.clone(name, f.impl.allocator) f.impl.wname = win32.utf8_to_wstring(name, f.impl.allocator) From 5362e883f43c12ce1340e18752ced120f287f812 Mon Sep 17 00:00:00 2001 From: Jan Ivanecky Date: Sat, 8 Oct 2022 00:47:42 +0200 Subject: [PATCH 05/56] Add additional NSWindow methods --- vendor/darwin/Foundation/NSWindow.odin | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/vendor/darwin/Foundation/NSWindow.odin b/vendor/darwin/Foundation/NSWindow.odin index 330af6012..15a73e63b 100644 --- a/vendor/darwin/Foundation/NSWindow.odin +++ b/vendor/darwin/Foundation/NSWindow.odin @@ -156,6 +156,22 @@ Window_makeKeyAndOrderFront :: proc(self: ^Window, key: ^NS.Object) { Window_setTitle :: proc(self: ^Window, title: ^NS.String) { msgSend(nil, self, "setTitle:", title) } +@(objc_type=Window, objc_name="setTitlebarAppearsTransparent") +Window_setTitlebarAppearsTransparent :: proc(self: ^Window, ok: NS.BOOL) { + msgSend(nil, self, "setTitlebarAppearsTransparent:", ok) +} +@(objc_type=Window, objc_name="setMovable") +Window_setMovable :: proc(self: ^Window, ok: NS.BOOL) { + msgSend(nil, self, "setMovable:", ok) +} +@(objc_type=Window, objc_name="setMovableByWindowBackground") +Window_setMovableByWindowBackground :: proc(self: ^Window, ok: NS.BOOL) { + msgSend(nil, self, "setMovableByWindowBackground:", ok) +} +@(objc_type=Window, objc_name="setStyleMask") +Window_setStyleMask :: proc(self: ^Window, style_mask: WindowStyleMask) { + msgSend(nil, self, "setStyleMask:", style_mask) +} @(objc_type=Window, objc_name="close") Window_close :: proc(self: ^Window) { msgSend(nil, self, "close") From 64f1e8b7a262ebee08900bc2f7e88fe6ad7132e8 Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Sat, 8 Oct 2022 14:55:20 +1100 Subject: [PATCH 06/56] Github CI: Add test case for issue 2113 --- .github/workflows/ci.yml | 8 ++++++++ tests/issues/run.bat | 16 ++++++++++++---- tests/issues/run.sh | 13 ++++++++----- tests/issues/test_issue_2113.odin | 13 +++++++++++++ 4 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 tests/issues/test_issue_2113.odin diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d8e10d59..5da70931f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,10 @@ jobs: cd tests/vendor make timeout-minutes: 10 + - name: Odin issues tests + run: | + cd tests/issues + ./run.sh - name: Odin check examples/all for Linux i386 run: ./odin check examples/all -vet -strict-style -target:linux_i386 timeout-minutes: 10 @@ -151,6 +155,10 @@ jobs: cd tests\vendor call build.bat timeout-minutes: 10 + - name: Odin issues tests + run: | + cd tests/issues + ./run.bat - name: core:math/big tests shell: cmd run: | diff --git a/tests/issues/run.bat b/tests/issues/run.bat index 2ecd14d95..c526fd472 100644 --- a/tests/issues/run.bat +++ b/tests/issues/run.bat @@ -1,15 +1,23 @@ @echo off if not exist "build\" mkdir build +pushd build -set COMMON=-collection:tests=.. +set COMMON=-collection:tests=..\.. + +set ERROR_DID_OCCUR=0 @echo on -..\..\odin test test_issue_829.odin %COMMON% -file -..\..\odin test test_issue_1592.odin %COMMON% -file -..\..\odin test test_issue_2087.odin %COMMON% -file +..\..\..\odin test ..\test_issue_829.odin %COMMON% -file +..\..\..\odin test ..\test_issue_1592.odin %COMMON% -file +..\..\..\odin test ..\test_issue_2087.odin %COMMON% -file +..\..\..\odin build ..\test_issue_2113.odin %COMMON% -file -debug @echo off +if %ERRORLEVEL% NEQ 0 set ERROR_DID_OCCUR=1 + +popd rmdir /S /Q build +if %ERROR_DID_OCCUR% NEQ 0 EXIT /B 1 diff --git a/tests/issues/run.sh b/tests/issues/run.sh index f781c8278..440c953d9 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -2,15 +2,18 @@ set -eu mkdir -p build -ODIN=../../odin -COMMON="-collection:tests=.." +pushd build +ODIN=../../../odin +COMMON="-collection:tests=../.." set -x -$ODIN test test_issue_829.odin $COMMON -file -$ODIN test test_issue_1592.odin $COMMON -file -$ODIN test test_issue_2087.odin $COMMON -file +$ODIN test ../test_issue_829.odin $COMMON -file +$ODIN test ../test_issue_1592.odin $COMMON -file +$ODIN test ../test_issue_2087.odin $COMMON -file +$ODIN build ../test_issue_2113.odin $COMMON -file -debug set +x +popd rm -rf build diff --git a/tests/issues/test_issue_2113.odin b/tests/issues/test_issue_2113.odin new file mode 100644 index 000000000..dab9c7d07 --- /dev/null +++ b/tests/issues/test_issue_2113.odin @@ -0,0 +1,13 @@ +// Tests issue #2113 https://github.com/odin-lang/Odin/issues/2113 +// Causes a panic on compilation +package test_issues + +T :: struct { + a: int, +} + +main :: proc() { + array: #soa[1]T + a := &array[0] + _ = a +} From e188a542dae2268e62f7920f611f466759706347 Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Sat, 8 Oct 2022 16:51:03 +1100 Subject: [PATCH 07/56] llvm_backend_debug: Add debug info for soa pointer This fixes issue #2113 --- src/llvm_backend_debug.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index ee2e03739..29b0ab488 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -293,6 +293,7 @@ LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { case Type_Named: GB_PANIC("Type_Named should be handled in lb_debug_type separately"); + case Type_SoaPointer: case Type_Pointer: return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), word_bits, word_bits, 0, nullptr, 0); case Type_MultiPointer: From 141133e3263b8a8a6004d48c6d8a74ecae9cc3ad Mon Sep 17 00:00:00 2001 From: Jan Ivanecky Date: Sat, 8 Oct 2022 16:29:49 +0200 Subject: [PATCH 08/56] Add class_getInstanceMethod, method_setImplementation bindings --- vendor/darwin/Foundation/objc.odin | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vendor/darwin/Foundation/objc.odin b/vendor/darwin/Foundation/objc.odin index 7db82df73..78f1f7780 100644 --- a/vendor/darwin/Foundation/objc.odin +++ b/vendor/darwin/Foundation/objc.odin @@ -13,6 +13,9 @@ foreign Foundation { objc_allocateClassPair :: proc "c" (superclass: Class, name: cstring, extraBytes: uint) --- class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL --- + class_getInstanceMethod :: proc "c" (cls: Class, name: SEL) -> Method --- + + method_setImplementation :: proc "c" (method: Method, imp: IMP) --- } From 7e5c063d9888cd74a90da73944252e99f6b0adea Mon Sep 17 00:00:00 2001 From: Jan Ivanecky Date: Sat, 8 Oct 2022 16:38:21 +0200 Subject: [PATCH 09/56] Add glfw.GetCocoaWindow --- vendor/glfw/native.odin | 33 --------------------------------- vendor/glfw/native_darwin.odin | 16 ++++++++++++++++ vendor/glfw/native_linux.odin | 15 +++++++++++++++ vendor/glfw/native_windows.odin | 15 +++++++++++++++ 4 files changed, 46 insertions(+), 33 deletions(-) delete mode 100644 vendor/glfw/native.odin create mode 100644 vendor/glfw/native_darwin.odin create mode 100644 vendor/glfw/native_linux.odin create mode 100644 vendor/glfw/native_windows.odin diff --git a/vendor/glfw/native.odin b/vendor/glfw/native.odin deleted file mode 100644 index 8ed439a94..000000000 --- a/vendor/glfw/native.odin +++ /dev/null @@ -1,33 +0,0 @@ -package glfw - -when ODIN_OS == .Windows { - import win32 "core:sys/windows" - - foreign import glfw { "lib/glfw3_mt.lib", "system:user32.lib", "system:gdi32.lib", "system:shell32.lib" } - - @(default_calling_convention="c", link_prefix="glfw") - foreign glfw { - GetWin32Adapter :: proc(monitor: MonitorHandle) -> cstring --- - GetWin32Monitor :: proc(monitor: MonitorHandle) -> cstring --- - GetWin32Window :: proc(window: WindowHandle) -> win32.HWND --- - GetWGLContext :: proc(window: WindowHandle) -> rawptr --- - } -} else when ODIN_OS == .Linux { - // TODO: Native Linux - // Display* glfwGetX11Display(void); - // RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor); - // RROutput glfwGetX11Monitor(GLFWmonitor* monitor); - // Window glfwGetX11Window(GLFWwindow* window); - // void glfwSetX11SelectionString(const char* string); - // const char* glfwGetX11SelectionString(void); - - // struct wl_display* glfwGetWaylandDisplay(void); - // struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); - // struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); -} else when ODIN_OS == .Darwin { - // TODO: Native Darwin - // CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor); - // id glfwGetCocoaWindow(GLFWwindow* window); - // id glfwGetNSGLContext(GLFWwindow* window); -} - diff --git a/vendor/glfw/native_darwin.odin b/vendor/glfw/native_darwin.odin new file mode 100644 index 000000000..696645249 --- /dev/null +++ b/vendor/glfw/native_darwin.odin @@ -0,0 +1,16 @@ +//+build darwin + +package glfw + +import NS "vendor:darwin/foundation" + +foreign import glfw { "lib/darwin/libglfw3.a" } + +@(default_calling_convention="c", link_prefix="glfw") +foreign glfw { + GetCocoaWindow :: proc(window: WindowHandle) -> ^NS.Window --- +} + +// TODO: +// CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor); +// id glfwGetNSGLContext(GLFWwindow* window); diff --git a/vendor/glfw/native_linux.odin b/vendor/glfw/native_linux.odin new file mode 100644 index 000000000..9b9e14790 --- /dev/null +++ b/vendor/glfw/native_linux.odin @@ -0,0 +1,15 @@ +//+build linux + +package glfw + +// TODO: Native Linux +// Display* glfwGetX11Display(void); +// RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor); +// RROutput glfwGetX11Monitor(GLFWmonitor* monitor); +// Window glfwGetX11Window(GLFWwindow* window); +// void glfwSetX11SelectionString(const char* string); +// const char* glfwGetX11SelectionString(void); + +// struct wl_display* glfwGetWaylandDisplay(void); +// struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); +// struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); diff --git a/vendor/glfw/native_windows.odin b/vendor/glfw/native_windows.odin new file mode 100644 index 000000000..1d9c3af86 --- /dev/null +++ b/vendor/glfw/native_windows.odin @@ -0,0 +1,15 @@ +//+build windows + +package glfw + +import win32 "core:sys/windows" + +foreign import glfw { "lib/glfw3_mt.lib", "system:user32.lib", "system:gdi32.lib", "system:shell32.lib" } + +@(default_calling_convention="c", link_prefix="glfw") +foreign glfw { + GetWin32Adapter :: proc(monitor: MonitorHandle) -> cstring --- + GetWin32Monitor :: proc(monitor: MonitorHandle) -> cstring --- + GetWin32Window :: proc(window: WindowHandle) -> win32.HWND --- + GetWGLContext :: proc(window: WindowHandle) -> rawptr --- +} From ab7367ae47ba387c2a7e8ef1401f7cf1e5aca0c8 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 8 Oct 2022 19:00:05 +0200 Subject: [PATCH 10/56] Fix #2112 --- src/build_settings.cpp | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 02de22ec4..237858efa 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1502,44 +1502,24 @@ bool init_build_paths(String init_filename) { } else { Path output_path; - if (str_eq(init_filename, str_lit("."))) { - // We must name the output file after the current directory. - debugf("Output name will be created from current base name %.*s.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename)); - String last_element = last_path_element(bc->build_paths[BuildPath_Main_Package].basename); + // We must name the output file after the current directory. + debugf("Output name will be created from current base name %.*s.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename)); + String last_element = last_path_element(bc->build_paths[BuildPath_Main_Package].basename); - if (last_element.len == 0) { - gb_printf_err("The output name is created from the last path element. `%.*s` has none. Use `-out:output_name.ext` to set it.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename)); - return false; - } - output_path.basename = copy_string(ha, bc->build_paths[BuildPath_Main_Package].basename); - output_path.name = copy_string(ha, last_element); - - } else { - // Init filename was not 'current path'. - // Contruct the output name from the path elements as usual. - String output_name = init_filename; - // If it ends with a trailing (back)slash, strip it before continuing. - while (output_name.len > 0 && (output_name[output_name.len-1] == '/' || output_name[output_name.len-1] == '\\')) { - output_name.len -= 1; - } - output_name = remove_directory_from_path(output_name); - output_name = remove_extension_from_path(output_name); - output_name = copy_string(ha, string_trim_whitespace(output_name)); - output_path = path_from_string(ha, output_name); - - // Replace extension. - if (output_path.ext.len > 0) { - gb_free(ha, output_path.ext.text); - } + if (last_element.len == 0) { + gb_printf_err("The output name is created from the last path element. `%.*s` has none. Use `-out:output_name.ext` to set it.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename)); + return false; } - output_path.ext = copy_string(ha, output_extension); + output_path.basename = copy_string(ha, bc->build_paths[BuildPath_Main_Package].basename); + output_path.name = copy_string(ha, last_element); + output_path.ext = copy_string(ha, output_extension); bc->build_paths[BuildPath_Output] = output_path; } // Do we have an extension? We might not if the output filename was supplied. if (bc->build_paths[BuildPath_Output].ext.len == 0) { - if (build_context.metrics.os == TargetOs_windows || build_context.build_mode != BuildMode_Executable) { + if (bc->metrics.os == TargetOs_windows || bc->build_mode != BuildMode_Executable) { bc->build_paths[BuildPath_Output].ext = copy_string(ha, output_extension); } } From 159c5311c38e815202d300d5852964dbc664ef8d Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 8 Oct 2022 23:01:06 +0200 Subject: [PATCH 11/56] Revert "Fix #2112" --- src/build_settings.cpp | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 237858efa..02de22ec4 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1502,24 +1502,44 @@ bool init_build_paths(String init_filename) { } else { Path output_path; - // We must name the output file after the current directory. - debugf("Output name will be created from current base name %.*s.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename)); - String last_element = last_path_element(bc->build_paths[BuildPath_Main_Package].basename); + if (str_eq(init_filename, str_lit("."))) { + // We must name the output file after the current directory. + debugf("Output name will be created from current base name %.*s.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename)); + String last_element = last_path_element(bc->build_paths[BuildPath_Main_Package].basename); - if (last_element.len == 0) { - gb_printf_err("The output name is created from the last path element. `%.*s` has none. Use `-out:output_name.ext` to set it.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename)); - return false; + if (last_element.len == 0) { + gb_printf_err("The output name is created from the last path element. `%.*s` has none. Use `-out:output_name.ext` to set it.\n", LIT(bc->build_paths[BuildPath_Main_Package].basename)); + return false; + } + output_path.basename = copy_string(ha, bc->build_paths[BuildPath_Main_Package].basename); + output_path.name = copy_string(ha, last_element); + + } else { + // Init filename was not 'current path'. + // Contruct the output name from the path elements as usual. + String output_name = init_filename; + // If it ends with a trailing (back)slash, strip it before continuing. + while (output_name.len > 0 && (output_name[output_name.len-1] == '/' || output_name[output_name.len-1] == '\\')) { + output_name.len -= 1; + } + output_name = remove_directory_from_path(output_name); + output_name = remove_extension_from_path(output_name); + output_name = copy_string(ha, string_trim_whitespace(output_name)); + output_path = path_from_string(ha, output_name); + + // Replace extension. + if (output_path.ext.len > 0) { + gb_free(ha, output_path.ext.text); + } } - output_path.basename = copy_string(ha, bc->build_paths[BuildPath_Main_Package].basename); - output_path.name = copy_string(ha, last_element); - output_path.ext = copy_string(ha, output_extension); + output_path.ext = copy_string(ha, output_extension); bc->build_paths[BuildPath_Output] = output_path; } // Do we have an extension? We might not if the output filename was supplied. if (bc->build_paths[BuildPath_Output].ext.len == 0) { - if (bc->metrics.os == TargetOs_windows || bc->build_mode != BuildMode_Executable) { + if (build_context.metrics.os == TargetOs_windows || build_context.build_mode != BuildMode_Executable) { bc->build_paths[BuildPath_Output].ext = copy_string(ha, output_extension); } } From ef0c6fc4b30a35678cc7190e56745770fbe553cc Mon Sep 17 00:00:00 2001 From: Julian Ceipek Date: Sat, 8 Oct 2022 23:51:50 -0400 Subject: [PATCH 12/56] Fix signature for `shouldTerminateAfterLastWindowClosed` delegate proc --- vendor/darwin/Foundation/NSApplication.odin | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/darwin/Foundation/NSApplication.odin b/vendor/darwin/Foundation/NSApplication.odin index 2fc4e6356..d55a185f2 100644 --- a/vendor/darwin/Foundation/NSApplication.odin +++ b/vendor/darwin/Foundation/NSApplication.odin @@ -11,7 +11,7 @@ ActivationPolicy :: enum UInteger { ApplicationDelegate :: struct { willFinishLaunching: proc "c" (self: ^ApplicationDelegate, notification: ^Notification), didFinishLaunching: proc "c" (self: ^ApplicationDelegate, notification: ^Notification), - shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application), + shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application) -> bool, user_data: rawptr, } @@ -34,9 +34,9 @@ Application_setDelegate :: proc(self: ^Application, delegate: ^ApplicationDelega del := (^ApplicationDelegate)(self->pointerValue()) del->didFinishLaunching(notification) } - shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) { + shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) -> bool { del := (^ApplicationDelegate)(self->pointerValue()) - del->shouldTerminateAfterLastWindowClosed(application) + return del->shouldTerminateAfterLastWindowClosed(application) } wrapper := Value.valueWithPointer(delegate) From 63086c7eaf3c0e97b1e8991fc94e146fb4efac38 Mon Sep 17 00:00:00 2001 From: Julian Ceipek Date: Sun, 9 Oct 2022 14:31:26 -0400 Subject: [PATCH 13/56] Use `NS.BOOL` instead of `bool` --- vendor/darwin/Foundation/NSApplication.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/darwin/Foundation/NSApplication.odin b/vendor/darwin/Foundation/NSApplication.odin index d55a185f2..0b62687b7 100644 --- a/vendor/darwin/Foundation/NSApplication.odin +++ b/vendor/darwin/Foundation/NSApplication.odin @@ -11,7 +11,7 @@ ActivationPolicy :: enum UInteger { ApplicationDelegate :: struct { willFinishLaunching: proc "c" (self: ^ApplicationDelegate, notification: ^Notification), didFinishLaunching: proc "c" (self: ^ApplicationDelegate, notification: ^Notification), - shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application) -> bool, + shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application) -> BOOL, user_data: rawptr, } @@ -34,7 +34,7 @@ Application_setDelegate :: proc(self: ^Application, delegate: ^ApplicationDelega del := (^ApplicationDelegate)(self->pointerValue()) del->didFinishLaunching(notification) } - shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) -> bool { + shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) -> BOOL { del := (^ApplicationDelegate)(self->pointerValue()) return del->shouldTerminateAfterLastWindowClosed(application) } From 4c78ba2152608563ef3e6eade8c6ebaabcec27b5 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 9 Oct 2022 21:34:43 +0200 Subject: [PATCH 14/56] Fix #2122 --- core/strconv/strconv.odin | 9 ++++++++- tests/issues/test_issue_2087.odin | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index ae89722bf..c621ac8e0 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -575,9 +575,11 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { i := 0 sign: f64 = 1 + seen_sign := true switch s[i] { case '-': i += 1; sign = -1 case '+': i += 1 + case: seen_sign = false } for ; i < len(s); i += 1 { @@ -677,8 +679,13 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { for exp > 0 { scale *= 10; exp -= 1 } } } - s = s[i:] + // If we only consumed a sign, return false + if i == 1 && seen_sign { + return 0, false + } + + s = s[i:] if frac { value = sign * (value/scale) } else { diff --git a/tests/issues/test_issue_2087.odin b/tests/issues/test_issue_2087.odin index 19181bfca..26b6d487d 100644 --- a/tests/issues/test_issue_2087.odin +++ b/tests/issues/test_issue_2087.odin @@ -10,9 +10,13 @@ test_parse_float :: proc(t: ^testing.T) { { f, ok := strconv.parse_f64("1.2") testing.expect(t, ok && f == 1.2, "expected f64(1.2), fully consumed") - f, ok = strconv.parse_f64("1.2a") testing.expect(t, !ok && f == 1.2, "expected f64(1.2), partially consumed") + f, ok = strconv.parse_f64("+") + testing.expect(t, !ok && f == 0.0, "expected f64(0.0), with ok=false") + f, ok = strconv.parse_f64("-") + testing.expect(t, !ok && f == 0.0, "expected f64(0.0), with ok=false") + f, ok = strconv.parse_f64("inf") testing.expect(t, ok && math.classify(f) == math.Float_Class.Inf, "expected f64(+inf), fully consumed") From fa6cfde4b0e97e6fffb1a373de37fb9251ac7cfd Mon Sep 17 00:00:00 2001 From: hikari Date: Mon, 10 Oct 2022 07:26:32 +0300 Subject: [PATCH 15/56] sys/windows: add free disk space function binding --- core/sys/windows/kernel32.odin | 7 +++++++ core/sys/windows/types.odin | 1 + 2 files changed, 8 insertions(+) diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 9e5e5448b..05686b7d2 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -346,6 +346,13 @@ foreign kernel32 { GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL --- FreeConsole :: proc() -> BOOL --- GetConsoleWindow :: proc() -> HWND --- + + GetDiskFreeSpaceExW :: proc( + lpDirectoryName: LPCWSTR, + lpFreeBytesAvailableToCaller: PULARGE_INTEGER, + lpTotalNumberOfBytes: PULARGE_INTEGER, + lpTotalNumberOfFreeBytes: PULARGE_INTEGER, + ) -> BOOL --- } diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index d4983fd06..30cc62451 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -44,6 +44,7 @@ BOOLEAN :: distinct b8 GROUP :: distinct c_uint LARGE_INTEGER :: distinct c_longlong ULARGE_INTEGER :: distinct c_ulonglong +PULARGE_INTEGER :: ^ULARGE_INTEGER LONG :: c_long UINT :: c_uint INT :: c_int From a1935bc1f4b4f966e132cb42f4d0f6419a60222b Mon Sep 17 00:00:00 2001 From: hikari Date: Mon, 10 Oct 2022 20:40:41 +0300 Subject: [PATCH 16/56] sys/windows: replace A with W --- core/sys/windows/advapi32.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sys/windows/advapi32.odin b/core/sys/windows/advapi32.odin index c2fbb560a..e98aa6c43 100644 --- a/core/sys/windows/advapi32.odin +++ b/core/sys/windows/advapi32.odin @@ -129,8 +129,8 @@ foreign advapi32 { cbData: DWORD, ) -> LSTATUS --- - GetFileSecurityA :: proc( - lpFileName: LPCSTR, + GetFileSecurityW :: proc( + lpFileName: LPCWSTR, RequestedInformation: SECURITY_INFORMATION, pSecurityDescriptor: PSECURITY_DESCRIPTOR, nLength: DWORD, From 419eab50590ded8777f55f5b29306201a85162c5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 10 Oct 2022 21:48:56 +0100 Subject: [PATCH 17/56] Force call site attributes for procedures (relating to #2121 causing ABI issues for `intrinsics.objc_send`) --- src/llvm_abi.cpp | 36 ++++++++++++++++++------------------ src/llvm_backend_proc.cpp | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 4bdc31077..0654ed82a 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -550,10 +550,10 @@ namespace lbAbiAmd64SysV { if (is_mem_cls(cls, attribute_kind)) { LLVMAttributeRef attribute = nullptr; if (attribute_kind == Amd64TypeAttribute_ByVal) { - if (!is_calling_convention_odin(calling_convention)) { + // if (!is_calling_convention_odin(calling_convention)) { return lb_arg_type_indirect_byval(c, type); - } - attribute = nullptr; + // } + // attribute = nullptr; } else if (attribute_kind == Amd64TypeAttribute_StructRect) { attribute = lb_create_enum_attribute_with_type(c, "sret", type); } @@ -982,13 +982,13 @@ namespace lbAbiArm64 { } return false; } - - unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef *base_type_, unsigned member_count_) { - return (member_count_ <= 4); - } + + unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef base_type, unsigned member_count) { + return (member_count <= 4); + } lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef type, bool return_is_defined) { - LLVMTypeRef homo_base_type = {}; + LLVMTypeRef homo_base_type = nullptr; unsigned homo_member_count = 0; if (!return_is_defined) { @@ -996,16 +996,16 @@ namespace lbAbiArm64 { } else if (is_register(type)) { return non_struct(c, type); } else if (is_homogenous_aggregate(c, type, &homo_base_type, &homo_member_count)) { - if(is_homogenous_aggregate_small_enough(&homo_base_type, homo_member_count)) { - return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr); - } else { - //TODO(Platin): do i need to create stuff that can handle the diffrent return type? - // else this needs a fix in llvm_backend_proc as we would need to cast it to the correct array type - - //LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count); - LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type); - return lb_arg_type_indirect(type, attr); - } + if (is_homogenous_aggregate_small_enough(homo_base_type, homo_member_count)) { + return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr); + } else { + //TODO(Platin): do i need to create stuff that can handle the diffrent return type? + // else this needs a fix in llvm_backend_proc as we would need to cast it to the correct array type + + //LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count); + LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type); + return lb_arg_type_indirect(type, attr); + } } else { i64 size = lb_sizeof(type); if (size <= 16) { diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 56ffe3fe9..4d7896c8a 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -753,12 +753,16 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, } GB_ASSERT_MSG(lb_is_type_kind(fnp, LLVMFunctionTypeKind), "%s", LLVMPrintTypeToString(fnp)); + lbFunctionType *ft = map_must_get(&p->module->function_type_map, base_type(value.type)); + { unsigned param_count = LLVMCountParamTypes(fnp); GB_ASSERT(arg_count >= param_count); LLVMTypeRef *param_types = gb_alloc_array(temporary_allocator(), LLVMTypeRef, param_count); LLVMGetParamTypes(fnp, param_types); + + for (unsigned i = 0; i < param_count; i++) { LLVMTypeRef param_type = param_types[i]; LLVMTypeRef arg_type = LLVMTypeOf(args[i]); @@ -776,10 +780,20 @@ lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue return_ptr, LLVMValueRef ret = LLVMBuildCall2(p->builder, fnp, fn, args, arg_count, ""); + LLVMAttributeIndex param_offset = LLVMAttributeIndex_FirstArgIndex; if (return_ptr.value != nullptr) { + param_offset += 1; + LLVMAddCallSiteAttribute(ret, 1, lb_create_enum_attribute_with_type(p->module->ctx, "sret", LLVMTypeOf(args[0]))); } + for_array(i, ft->args) { + LLVMAttributeRef attribute = ft->args[i].attribute; + if (attribute != nullptr) { + LLVMAddCallSiteAttribute(ret, param_offset + cast(LLVMAttributeIndex)i, attribute); + } + } + switch (inlining) { case ProcInlining_none: break; From 047d45584ec76cf952d040066d00bdd312219a83 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 11 Oct 2022 21:21:56 +0100 Subject: [PATCH 18/56] Fix #2016 when passing an untyped integer to a generic `typeid` parameter --- src/check_expr.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 0686d9cb2..6edd4a93c 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6413,7 +6413,9 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper if (e->kind == Entity_TypeName) { if (o->mode != Addressing_Type) { if (show_error) { - error(o->expr, "Expected a type for the argument '%.*s'", LIT(e->token.string)); + gbString expr = expr_to_string(o->expr); + error(o->expr, "Expected a type for the argument '%.*s', got %s", LIT(e->token.string), expr); + gb_string_free(expr); } err = CallArgumentError_WrongTypes; } @@ -6456,6 +6458,10 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper // add_type_info_type(c, o->type); } + if (show_error && err) { + return err; + } + { bool failure = false; Entity *found_entity = find_polymorphic_record_entity(c, original_type, param_count, ordered_operands, &failure); From c909e8e4b8bf986dd7c57bd527e0c5152da3c3d6 Mon Sep 17 00:00:00 2001 From: hikari Date: Wed, 12 Oct 2022 04:35:41 +0300 Subject: [PATCH 19/56] sys/windows: add SHFileOperationW --- core/sys/windows/shell32.odin | 1 + core/sys/windows/types.odin | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/core/sys/windows/shell32.odin b/core/sys/windows/shell32.odin index a3d6c6fb8..10a7d37d3 100644 --- a/core/sys/windows/shell32.odin +++ b/core/sys/windows/shell32.odin @@ -19,4 +19,5 @@ foreign shell32 { pszPath: LPCWSTR, psa: ^SECURITY_ATTRIBUTES, ) -> c_int --- + SHFileOperationW :: proc(lpFileOp: LPSHFILEOPSTRUCTW) -> c_int --- } diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 30cc62451..b9ff6998a 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -925,6 +925,48 @@ NM_FONTCHANGED :: NM_OUTOFMEMORY-22 NM_CUSTOMTEXT :: NM_OUTOFMEMORY-23 // uses NMCUSTOMTEXT struct NM_TVSTATEIMAGECHANGING :: NM_OUTOFMEMORY-23 // uses NMTVSTATEIMAGECHANGING struct, defined after HTREEITEM +PCZZWSTR :: ^WCHAR + +SHFILEOPSTRUCTW :: struct { + hwnd: HWND, + wFunc: UINT, + pFrom: PCZZWSTR, + pTo: PCZZWSTR, + fFlags: FILEOP_FLAGS, + fAnyOperationsAborted: BOOL, + hNameMappings: LPVOID, + lpszProgressTitle: PCWSTR, // only used if FOF_SIMPLEPROGRESS +} +LPSHFILEOPSTRUCTW :: ^SHFILEOPSTRUCTW + +// Shell File Operations +FO_MOVE :: 0x0001 +FO_COPY :: 0x0002 +FO_DELETE :: 0x0003 +FO_RENAME :: 0x0004 + +// SHFILEOPSTRUCT.fFlags and IFileOperation::SetOperationFlags() flag values +FOF_MULTIDESTFILES :: 0x0001 +FOF_CONFIRMMOUSE :: 0x0002 +FOF_SILENT :: 0x0004 // don't display progress UI (confirm prompts may be displayed still) +FOF_RENAMEONCOLLISION :: 0x0008 // automatically rename the source files to avoid the collisions +FOF_NOCONFIRMATION :: 0x0010 // don't display confirmation UI, assume "yes" for cases that can be bypassed, "no" for those that can not +FOF_WANTMAPPINGHANDLE :: 0x0020 // Fill in SHFILEOPSTRUCT.hNameMappings + // Must be freed using SHFreeNameMappings +FOF_ALLOWUNDO :: 0x0040 // enable undo including Recycle behavior for IFileOperation::Delete() +FOF_FILESONLY :: 0x0080 // only operate on the files (non folders), both files and folders are assumed without this +FOF_SIMPLEPROGRESS :: 0x0100 // means don't show names of files +FOF_NOCONFIRMMKDIR :: 0x0200 // don't dispplay confirmatino UI before making any needed directories, assume "Yes" in these cases +FOF_NOERRORUI :: 0x0400 // don't put up error UI, other UI may be displayed, progress, confirmations +FOF_NOCOPYSECURITYATTRIBS :: 0x0800 // dont copy file security attributes (ACLs) +FOF_NORECURSION :: 0x1000 // don't recurse into directories for operations that would recurse +FOF_NO_CONNECTED_ELEMENTS :: 0x2000 // don't operate on connected elements ("xxx_files" folders that go with .htm files) +FOF_WANTNUKEWARNING :: 0x4000 // during delete operation, warn if object is being permanently destroyed instead of recycling (partially overrides FOF_NOCONFIRMATION) +FOF_NORECURSEREPARSE :: 0x8000 // deprecated; the operations engine always does the right thing on FolderLink objects (symlinks, reparse points, folder shortcuts) +FOF_NO_UI :: (FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR) // don't display any UI at all + +FILEOP_FLAGS :: WORD + DEVMODEW :: struct { dmDeviceName: [32]wchar_t, dmSpecVersion: WORD, From 6642e1fc9df0e7419d067a44fb161994bff8f73c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 19:10:04 +0100 Subject: [PATCH 20/56] Unify `Static_Arena` and `Growing_Arena` into `Arena` --- core/mem/virtual/arena.odin | 270 ++++++++++++++++++++++++++++ core/mem/virtual/arena_util.odin | 64 +++---- core/mem/virtual/growing_arena.odin | 170 ------------------ core/mem/virtual/static_arena.odin | 153 ---------------- 4 files changed, 302 insertions(+), 355 deletions(-) create mode 100644 core/mem/virtual/arena.odin delete mode 100644 core/mem/virtual/growing_arena.odin delete mode 100644 core/mem/virtual/static_arena.odin diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin new file mode 100644 index 000000000..21c3db2ee --- /dev/null +++ b/core/mem/virtual/arena.odin @@ -0,0 +1,270 @@ +package mem_virtual + +import "core:mem" + +Arena_Kind :: enum u8 { + Growing = 0, // chained memory block + Static = 1, // fixed reservation +} + +Arena :: struct { + curr_block: ^Memory_Block, + total_used: uint, + total_reserved: uint, + + kind: Arena_Kind, + minimum_block_size: uint, + temp_count: int, +} + + +STATIC_ARENA_DEFAULT_COMMIT_SIZE :: 1<<20 // 1 MiB should be enough to start with +GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE :: STATIC_ARENA_DEFAULT_COMMIT_SIZE + +// 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default +STATIC_ARENA_DEFAULT_RESERVE_SIZE :: 1<<30 when size_of(uintptr) == 8 else 1<<27 + + + +arena_init_growing :: proc(arena: ^Arena, reserved: uint = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { + arena.kind = .Growing + arena.curr_block = memory_block_alloc(0, reserved, {}) or_return + arena.total_used = 0 + arena.total_reserved = arena.curr_block.reserved + return +} + + +arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = STATIC_ARENA_DEFAULT_COMMIT_SIZE) -> (err: Allocator_Error) { + arena.kind = .Static + arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return + arena.total_used = 0 + arena.total_reserved = arena.curr_block.reserved + return +} + +arena_alloc :: proc(arena: ^Arena, min_size: int, alignment: int, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { + align_forward_offset :: proc "contextless" (arena: ^Arena, alignment: int) -> uint #no_bounds_check { + alignment_offset := uint(0) + ptr := uintptr(arena.curr_block.base[arena.curr_block.used:]) + mask := uintptr(alignment-1) + if ptr & mask != 0 { + alignment_offset = uint(alignment) - uint(ptr & mask) + } + return alignment_offset + } + + assert(mem.is_power_of_two(uintptr(alignment)), "non-power of two alignment", loc) + + switch arena.kind { + case .Growing: + size := uint(0) + if arena.curr_block != nil { + size = uint(min_size) + align_forward_offset(arena, alignment) + } + + if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved { + size = uint(mem.align_forward_int(min_size, alignment)) + arena.minimum_block_size = max(GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE, arena.minimum_block_size) + + block_size := max(size, arena.minimum_block_size) + + new_block := memory_block_alloc(size, block_size, {}) or_return + new_block.prev = arena.curr_block + arena.curr_block = new_block + arena.total_reserved += new_block.reserved + } + + + data, err = alloc_from_memory_block(arena.curr_block, int(size), alignment) + if err == nil { + arena.total_used += size + } + case .Static: + if arena.curr_block == nil { + reserve_size := max(arena.minimum_block_size, STATIC_ARENA_DEFAULT_RESERVE_SIZE) + arena_init_static(arena, reserve_size, STATIC_ARENA_DEFAULT_COMMIT_SIZE) or_return + } + data, err = alloc_from_memory_block(arena.curr_block, min_size, alignment) + arena.total_used = arena.curr_block.used + } + return +} + +arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) -> bool { + if arena.curr_block != nil { + assert(arena.kind == .Static, "expected a .Static arena", loc) + + prev_pos := arena.curr_block.used + arena.curr_block.used = clamp(pos, 0, arena.curr_block.reserved) + + if prev_pos < pos { + mem.zero_slice(arena.curr_block.base[arena.curr_block.used:][:pos-prev_pos]) + } + return true + } else if pos == 0 { + return true + } + return false +} + +arena_growing_free_last_memory_block :: proc(arena: ^Arena, loc := #caller_location) { + if free_block := arena.curr_block; free_block != nil { + assert(arena.kind == .Growing, "expected a .Growing arena", loc) + arena.curr_block = free_block.prev + memory_block_dealloc(free_block) + } +} + +arena_free_all :: proc(arena: ^Arena) { + switch arena.kind { + case .Growing: + for arena.curr_block != nil { + arena_growing_free_last_memory_block(arena) + } + case .Static: + arena_static_reset_to(arena, 0) + } + arena.total_used = 0 + arena.total_reserved = 0 +} + +arena_destroy :: proc(arena: ^Arena) { + arena_free_all(arena) + memory_block_dealloc(arena.curr_block) + arena.curr_block = nil + arena.total_used = 0 + arena.total_reserved = 0 + arena.temp_count = 0 +} + +arena_growing_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size: uint = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { + bootstrap: Arena + bootstrap.kind = .Growing + bootstrap.minimum_block_size = minimum_block_size + + data := arena_alloc(&bootstrap, size_of(T), align_of(T)) or_return + + ptr = (^T)(raw_data(data)) + + (^Arena)(uintptr(ptr) + offset_to_arena)^ = bootstrap + + return +} + +arena_growing_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size: uint = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { + return arena_growing_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size) +} + +arena_growing_bootstrap_new :: proc{ + arena_growing_bootstrap_new_by_offset, + arena_growing_bootstrap_new_by_name, +} + +arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { + bootstrap: Arena + bootstrap.kind = .Static + bootstrap.minimum_block_size = reserved + + data := arena_alloc(&bootstrap, size_of(T), align_of(T)) or_return + + ptr = (^T)(raw_data(data)) + + (^Arena)(uintptr(ptr) + offset_to_arena)^ = bootstrap + + return +} + +arena_static_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { + return arena_static_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), reserved) +} +arena_static_bootstrap_new :: proc{ + arena_static_bootstrap_new_by_offset, + arena_static_bootstrap_new_by_name, +} + + +arena_allocator :: proc(arena: ^Arena) -> mem.Allocator { + return mem.Allocator{arena_allocator_proc, arena} +} + +arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, + location := #caller_location) -> (data: []byte, err: Allocator_Error) { + arena := (^Arena)(allocator_data) + + switch mode { + case .Alloc: + return arena_alloc(arena, size, alignment) + case .Free: + err = .Mode_Not_Implemented + return + case .Free_All: + arena_free_all(arena) + return + case .Resize: + return mem.default_resize_bytes_align(mem.byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena), location) + + case .Query_Features, .Query_Info: + err = .Mode_Not_Implemented + return + } + + err = .Mode_Not_Implemented + return +} + +Arena_Temp :: struct { + arena: ^Arena, + block: ^Memory_Block, + used: uint, +} + +arena_temp_begin :: proc(arena: ^Arena, loc := #caller_location) -> (temp: Arena_Temp) { + assert(arena != nil, "nil arena", loc) + temp.arena = arena + temp.block = arena.curr_block + if arena.curr_block != nil { + temp.used = arena.curr_block.used + } + arena.temp_count += 1 + return +} + +arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) { + assert(temp.arena != nil, "nil arena", loc) + arena := temp.arena + + memory_block_found := false + for block := arena.curr_block; block != nil; block = block.prev { + if block == temp.block { + memory_block_found = true + break + } + } + if !memory_block_found { + assert(arena.curr_block == temp.block, "memory block stored within Arena_Temp not owned by Arena", loc) + } + + for arena.curr_block != temp.block { + arena_growing_free_last_memory_block(arena) + } + + if block := arena.curr_block; block != nil { + assert(block.used >= temp.used, "out of order use of arena_temp_end", loc) + amount_to_zero := min(block.used-temp.used, block.reserved-block.used) + mem.zero_slice(block.base[temp.used:][:amount_to_zero]) + block.used = temp.used + } + + assert(arena.temp_count > 0, "double-use of arena_temp_end", loc) + arena.temp_count -= 1 +} + +arena_check_temp :: proc(arena: ^Arena, loc := #caller_location) { + assert(arena.temp_count == 0, "Arena_Temp not been ended", loc) +} + + + diff --git a/core/mem/virtual/arena_util.odin b/core/mem/virtual/arena_util.odin index 0e152db7a..f721c4ffa 100644 --- a/core/mem/virtual/arena_util.odin +++ b/core/mem/virtual/arena_util.odin @@ -1,41 +1,41 @@ package mem_virtual -arena_init :: proc{ - static_arena_init, - growing_arena_init, -} +// arena_init :: proc{ +// static_arena_init, +// growing_arena_init, +// } -arena_temp_begin :: proc{ - static_arena_temp_begin, - growing_arena_temp_begin, -} +// arena_temp_begin :: proc{ +// static_arena_temp_begin, +// growing_arena_temp_begin, +// } -arena_temp_end :: proc{ - static_arena_temp_end, - growing_arena_temp_end, -} +// arena_temp_end :: proc{ +// static_arena_temp_end, +// growing_arena_temp_end, +// } -arena_check_temp :: proc{ - static_arena_check_temp, - growing_arena_check_temp, -} +// arena_check_temp :: proc{ +// static_arena_check_temp, +// growing_arena_check_temp, +// } -arena_allocator :: proc{ - static_arena_allocator, - growing_arena_allocator, -} +// arena_allocator :: proc{ +// static_arena_allocator, +// growing_arena_allocator, +// } -arena_alloc :: proc{ - static_arena_alloc, - growing_arena_alloc, -} +// arena_alloc :: proc{ +// static_arena_alloc, +// growing_arena_alloc, +// } -arena_free_all :: proc{ - static_arena_free_all, - growing_arena_free_all, -} +// arena_free_all :: proc{ +// static_arena_free_all, +// growing_arena_free_all, +// } -arena_destroy :: proc{ - static_arena_destroy, - growing_arena_destroy, -} \ No newline at end of file +// arena_destroy :: proc{ +// static_arena_destroy, +// growing_arena_destroy, +// } \ No newline at end of file diff --git a/core/mem/virtual/growing_arena.odin b/core/mem/virtual/growing_arena.odin deleted file mode 100644 index 44d56866e..000000000 --- a/core/mem/virtual/growing_arena.odin +++ /dev/null @@ -1,170 +0,0 @@ -package mem_virtual - -import "core:mem" - -Growing_Arena :: struct { - curr_block: ^Memory_Block, - total_used: uint, - total_reserved: uint, - - minimum_block_size: uint, - temp_count: int, -} - -DEFAULT_MINIMUM_BLOCK_SIZE :: 1<<20 // 1 MiB should be enough - -growing_arena_init :: proc(arena: ^Growing_Arena, reserved: uint = DEFAULT_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { - arena.curr_block = memory_block_alloc(0, reserved, {}) or_return - arena.total_used = 0 - arena.total_reserved = arena.curr_block.reserved - return -} - -growing_arena_alloc :: proc(arena: ^Growing_Arena, min_size: int, alignment: int) -> (data: []byte, err: Allocator_Error) { - align_forward_offset :: proc "contextless" (arena: ^Growing_Arena, alignment: int) -> uint #no_bounds_check { - alignment_offset := uint(0) - ptr := uintptr(arena.curr_block.base[arena.curr_block.used:]) - mask := uintptr(alignment-1) - if ptr & mask != 0 { - alignment_offset = uint(alignment) - uint(ptr & mask) - } - return alignment_offset - } - - assert(mem.is_power_of_two(uintptr(alignment))) - - size := uint(0) - if arena.curr_block != nil { - size = uint(min_size) + align_forward_offset(arena, alignment) - } - - if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved { - size = uint(mem.align_forward_int(min_size, alignment)) - arena.minimum_block_size = max(DEFAULT_MINIMUM_BLOCK_SIZE, arena.minimum_block_size) - - block_size := max(size, arena.minimum_block_size) - - new_block := memory_block_alloc(size, block_size, {}) or_return - new_block.prev = arena.curr_block - arena.curr_block = new_block - arena.total_reserved += new_block.reserved - } - - - data, err = alloc_from_memory_block(arena.curr_block, int(size), alignment) - if err == nil { - arena.total_used += size - } - return -} - -growing_arena_free_last_memory_block :: proc(arena: ^Growing_Arena) { - free_block := arena.curr_block - arena.curr_block = free_block.prev - memory_block_dealloc(free_block) -} - -growing_arena_free_all :: proc(arena: ^Growing_Arena) { - for arena.curr_block != nil { - growing_arena_free_last_memory_block(arena) - } - arena.total_used = 0 - arena.total_reserved = 0 -} - -growing_arena_destroy :: proc(arena: ^Growing_Arena) { - growing_arena_free_all(arena) -} - -growing_arena_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size: uint = DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { bootstrap: Growing_Arena - bootstrap.minimum_block_size = minimum_block_size - - data := growing_arena_alloc(&bootstrap, size_of(T), align_of(T)) or_return - - ptr = (^T)(raw_data(data)) - - (^Growing_Arena)(uintptr(ptr) + offset_to_arena)^ = bootstrap - - return -} - -growing_arena_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size: uint = DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { - return growing_arena_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size) -} -growing_arena_bootstrap_new :: proc{ - growing_arena_bootstrap_new_by_offset, - growing_arena_bootstrap_new_by_name, -} - -growing_arena_allocator :: proc(arena: ^Growing_Arena) -> mem.Allocator { - return mem.Allocator{growing_arena_allocator_proc, arena} -} - -growing_arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, - location := #caller_location) -> (data: []byte, err: Allocator_Error) { - arena := (^Growing_Arena)(allocator_data) - - switch mode { - case .Alloc: - return growing_arena_alloc(arena, size, alignment) - case .Free: - err = .Mode_Not_Implemented - return - case .Free_All: - growing_arena_free_all(arena) - return - case .Resize: - return mem.default_resize_bytes_align(mem.byte_slice(old_memory, old_size), size, alignment, growing_arena_allocator(arena), location) - - case .Query_Features, .Query_Info: - err = .Mode_Not_Implemented - return - } - - err = .Mode_Not_Implemented - return -} - -Growing_Arena_Temp :: struct { - arena: ^Growing_Arena, - block: ^Memory_Block, - used: uint, -} - -growing_arena_temp_begin :: proc(arena: ^Growing_Arena) -> (temp: Growing_Arena_Temp) { - temp.arena = arena - temp.block = arena.curr_block - if arena.curr_block != nil { - temp.used = arena.curr_block.used - } - arena.temp_count += 1 - return -} - -growing_arena_temp_end :: proc(temp: Growing_Arena_Temp, loc := #caller_location) { - assert(temp.arena != nil, "nil arena", loc) - arena := temp.arena - - for arena.curr_block != temp.block { - growing_arena_free_last_memory_block(arena) - } - - if block := arena.curr_block; block != nil { - assert(block.used >= temp.used, "out of order use of growing_arena_temp_end", loc) - amount_to_zero := min(block.used-temp.used, block.reserved-block.used) - mem.zero_slice(block.base[temp.used:][:amount_to_zero]) - block.used = temp.used - } - - assert(arena.temp_count > 0, "double-use of growing_arena_temp_end", loc) - arena.temp_count -= 1 -} - -growing_arena_check_temp :: proc(arena: ^Growing_Arena, loc := #caller_location) { - assert(arena.temp_count == 0, "Growing_Arena_Temp not been ended", loc) -} - - - diff --git a/core/mem/virtual/static_arena.odin b/core/mem/virtual/static_arena.odin deleted file mode 100644 index 7e8a62f4a..000000000 --- a/core/mem/virtual/static_arena.odin +++ /dev/null @@ -1,153 +0,0 @@ -package mem_virtual - -import "core:mem" - -Static_Arena :: struct { - block: ^Memory_Block, - total_used: uint, - total_reserved: uint, - - minimum_block_size: uint, - temp_count: int, -} - -STATIC_ARENA_DEFAULT_COMMIT_SIZE :: 1<<20 // 1 MiB should be enough to start with - -// 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default -STATIC_ARENA_DEFAULT_RESERVE_SIZE :: 1<<30 when size_of(uintptr) == 8 else 1<<27 - -static_arena_init :: proc(arena: ^Static_Arena, reserved: uint, commit_size: uint = STATIC_ARENA_DEFAULT_COMMIT_SIZE) -> (err: Allocator_Error) { - arena.block = memory_block_alloc(commit_size, reserved, {}) or_return - arena.total_used = 0 - arena.total_reserved = arena.block.reserved - return -} - -static_arena_destroy :: proc(arena: ^Static_Arena) { - memory_block_dealloc(arena.block) - arena^ = {} -} - - -static_arena_alloc :: proc(arena: ^Static_Arena, size: int, alignment: int) -> (data: []byte, err: Allocator_Error) { - align_forward :: #force_inline proc "contextless" (ptr: uint, align: uint) -> uint { - mask := align-1 - return (ptr + mask) &~ mask - } - - if arena.block == nil { - reserve_size := max(arena.minimum_block_size, STATIC_ARENA_DEFAULT_RESERVE_SIZE) - static_arena_init(arena, reserve_size, STATIC_ARENA_DEFAULT_COMMIT_SIZE) or_return - } - - MINIMUM_ALIGN :: 2*align_of(uintptr) - - defer arena.total_used = arena.block.used - return alloc_from_memory_block(arena.block, size, max(MINIMUM_ALIGN, alignment)) -} - -static_arena_reset_to :: proc(arena: ^Static_Arena, pos: uint) -> bool { - if arena.block != nil { - prev_pos := arena.block.used - arena.block.used = clamp(pos, 0, arena.block.reserved) - - if prev_pos < pos { - mem.zero_slice(arena.block.base[arena.block.used:][:pos-prev_pos]) - } - return true - } else if pos == 0 { - return true - } - return false -} - -static_arena_free_all :: proc(arena: ^Static_Arena) { - static_arena_reset_to(arena, 0) -} - - -static_arena_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { - bootstrap: Static_Arena - bootstrap.minimum_block_size = reserved - - data := static_arena_alloc(&bootstrap, size_of(T), align_of(T)) or_return - - ptr = (^T)(raw_data(data)) - - (^Static_Arena)(uintptr(ptr) + offset_to_arena)^ = bootstrap - - return -} - -static_arena_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { - return static_arena_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), reserved) -} -static_arena_bootstrap_new :: proc{ - static_arena_bootstrap_new_by_offset, - static_arena_bootstrap_new_by_name, -} - - -static_arena_allocator :: proc(arena: ^Static_Arena) -> mem.Allocator { - return mem.Allocator{static_arena_allocator_proc, arena} -} - -static_arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, - location := #caller_location) -> (data: []byte, err: Allocator_Error) { - arena := (^Static_Arena)(allocator_data) - - switch mode { - case .Alloc: - return static_arena_alloc(arena, size, alignment) - case .Free: - err = .Mode_Not_Implemented - return - case .Free_All: - static_arena_free_all(arena) - return - case .Resize: - return mem.default_resize_bytes_align(mem.byte_slice(old_memory, old_size), size, alignment, static_arena_allocator(arena), location) - - case .Query_Features, .Query_Info: - err = .Mode_Not_Implemented - return - } - - err = .Mode_Not_Implemented - return -} - - -Static_Arena_Temp :: struct { - arena: ^Static_Arena, - used: uint, -} - - -static_arena_temp_begin :: proc(arena: ^Static_Arena) -> (temp: Static_Arena_Temp) { - temp.arena = arena - temp.used = arena.block.used if arena.block != nil else 0 - arena.temp_count += 1 - return -} - -static_arena_temp_end :: proc(temp: Static_Arena_Temp, loc := #caller_location) { - assert(temp.arena != nil, "nil arena", loc) - arena := temp.arena - - used := arena.block.used if arena.block != nil else 0 - - assert(temp.used >= used, "invalid Static_Arena_Temp", loc) - - static_arena_reset_to(arena, temp.used) - - assert(arena.temp_count > 0, "double-use of static_arena_temp_end", loc) - arena.temp_count -= 1 -} - - -static_arena_check_temp :: proc(arena: ^Static_Arena, loc := #caller_location) { - assert(arena.temp_count == 0, "Static_Arena_Temp not been ended", loc) -} \ No newline at end of file From b84108c4b55e94c495dc7d9d57404455d023ca7f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 20:28:51 +0100 Subject: [PATCH 21/56] Inline align forward offset code --- core/mem/virtual/arena.odin | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 21c3db2ee..ba2708fc3 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -44,23 +44,18 @@ arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = STA } arena_alloc :: proc(arena: ^Arena, min_size: int, alignment: int, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { - align_forward_offset :: proc "contextless" (arena: ^Arena, alignment: int) -> uint #no_bounds_check { - alignment_offset := uint(0) - ptr := uintptr(arena.curr_block.base[arena.curr_block.used:]) - mask := uintptr(alignment-1) - if ptr & mask != 0 { - alignment_offset = uint(alignment) - uint(ptr & mask) - } - return alignment_offset - } - assert(mem.is_power_of_two(uintptr(alignment)), "non-power of two alignment", loc) switch arena.kind { case .Growing: - size := uint(0) + size := uint(min_size) if arena.curr_block != nil { - size = uint(min_size) + align_forward_offset(arena, alignment) + // align forward offset + ptr := uintptr(arena.curr_block.base[arena.curr_block.used:]) + mask := uintptr(alignment-1) + if ptr & mask != 0 { + size += uint(alignment) - uint(ptr & mask) + } } if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved { From 835b8ffa22d7dce1a4b3cd1677a50095200a3883 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 20:30:48 +0100 Subject: [PATCH 22/56] Update `total_used` for `arena_static_reset_to` --- core/mem/virtual/arena.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index ba2708fc3..d2ffa73f2 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -96,8 +96,10 @@ arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) if prev_pos < pos { mem.zero_slice(arena.curr_block.base[arena.curr_block.used:][:pos-prev_pos]) } + arena.total_used = arena.curr_block.used return true } else if pos == 0 { + arena.total_used = 0 return true } return false From 5c62211f00ca1f11a92e7a97b3727b9e29fb0ebd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 20:44:36 +0100 Subject: [PATCH 23/56] Inline resize logic for `virtual.Arena` --- core/mem/alloc.odin | 15 +++++++------ core/mem/virtual/arena.odin | 45 +++++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index 54004d333..b5788c8a8 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -243,13 +243,11 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a return alloc_bytes(new_size, alignment, allocator, loc) } - if new_size == 0 { - err := free_bytes(old_data, allocator, loc) - return nil, err - } - if new_size == old_size { - return old_data, .None + return old_data, nil + } + if new_size == 0 { + return nil, free_bytes(old_data, allocator, loc) } new_memory, err := alloc_bytes(new_size, alignment, allocator, loc) @@ -258,6 +256,9 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a } runtime.copy(new_memory, old_data) - free_bytes(old_data, allocator, loc) + err1 := free_bytes(old_data, allocator, loc) + if err == nil { + err = err1 + } return new_memory, err } diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index d2ffa73f2..1dd8d249c 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -46,6 +46,10 @@ arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = STA arena_alloc :: proc(arena: ^Arena, min_size: int, alignment: int, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { assert(mem.is_power_of_two(uintptr(alignment)), "non-power of two alignment", loc) + if min_size == 0 { + return nil, nil + } + switch arena.kind { case .Growing: size := uint(min_size) @@ -186,9 +190,9 @@ arena_allocator :: proc(arena: ^Arena) -> mem.Allocator { } arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, - location := #caller_location) -> (data: []byte, err: Allocator_Error) { + size, alignment: int, + old_memory: rawptr, old_size: int, + location := #caller_location) -> (data: []byte, err: Allocator_Error) { arena := (^Arena)(allocator_data) switch mode { @@ -196,19 +200,42 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, return arena_alloc(arena, size, alignment) case .Free: err = .Mode_Not_Implemented - return case .Free_All: arena_free_all(arena) - return case .Resize: - return mem.default_resize_bytes_align(mem.byte_slice(old_memory, old_size), size, alignment, arena_allocator(arena), location) + old_data := ([^]byte)(old_memory) - case .Query_Features, .Query_Info: + switch { + case old_data == nil: + return arena_alloc(arena, size, alignment) + case size == old_size: + // return old memory + data = old_data[:size] + return + case size == 0: + err = .Mode_Not_Implemented + return + case (uintptr(old_data) & uintptr(alignment-1) == 0) && size < old_size: + // shrink data in-place + data = old_data[:size] + return + } + + new_memory := arena_alloc(arena, size, alignment) or_return + if new_memory == nil { + return + } + copy(new_memory, old_data[:old_size]) + return new_memory, nil + case .Query_Features: + set := (^mem.Allocator_Mode_Set)(old_memory) + if set != nil { + set^ = {.Alloc, .Free_All, .Resize, .Query_Features} + } + case .Query_Info: err = .Mode_Not_Implemented - return } - err = .Mode_Not_Implemented return } From 5a8fbc230da9d16a1f8f4345bc7c803fe8f77bab Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 21:16:34 +0100 Subject: [PATCH 24/56] Sanity corrections to virtual calls --- core/mem/virtual/arena.odin | 57 ++++++++++++-------------- core/mem/virtual/virtual.odin | 2 +- core/mem/virtual/virtual_platform.odin | 1 - 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 1dd8d249c..e95dc227c 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -18,7 +18,8 @@ Arena :: struct { } -STATIC_ARENA_DEFAULT_COMMIT_SIZE :: 1<<20 // 1 MiB should be enough to start with +// 1 MiB should be enough to start with +STATIC_ARENA_DEFAULT_COMMIT_SIZE :: 1<<20 GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE :: STATIC_ARENA_DEFAULT_COMMIT_SIZE // 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default @@ -43,27 +44,18 @@ arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = STA return } -arena_alloc :: proc(arena: ^Arena, min_size: int, alignment: int, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { +arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { assert(mem.is_power_of_two(uintptr(alignment)), "non-power of two alignment", loc) - if min_size == 0 { + size := size + if size == 0 { return nil, nil } switch arena.kind { case .Growing: - size := uint(min_size) - if arena.curr_block != nil { - // align forward offset - ptr := uintptr(arena.curr_block.base[arena.curr_block.used:]) - mask := uintptr(alignment-1) - if ptr & mask != 0 { - size += uint(alignment) - uint(ptr & mask) - } - } - if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved { - size = uint(mem.align_forward_int(min_size, alignment)) + size = mem.align_forward_uint(size, alignment) arena.minimum_block_size = max(GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE, arena.minimum_block_size) block_size := max(size, arena.minimum_block_size) @@ -74,17 +66,15 @@ arena_alloc :: proc(arena: ^Arena, min_size: int, alignment: int, loc := #caller arena.total_reserved += new_block.reserved } - - data, err = alloc_from_memory_block(arena.curr_block, int(size), alignment) - if err == nil { - arena.total_used += size - } + prev_used := arena.curr_block.used + data, err = alloc_from_memory_block(arena.curr_block, size, alignment) + arena.total_used += arena.curr_block.used - prev_used case .Static: if arena.curr_block == nil { reserve_size := max(arena.minimum_block_size, STATIC_ARENA_DEFAULT_RESERVE_SIZE) arena_init_static(arena, reserve_size, STATIC_ARENA_DEFAULT_COMMIT_SIZE) or_return } - data, err = alloc_from_memory_block(arena.curr_block, min_size, alignment) + data, err = alloc_from_memory_block(arena.curr_block, size, alignment) arena.total_used = arena.curr_block.used } return @@ -123,11 +113,11 @@ arena_free_all :: proc(arena: ^Arena) { for arena.curr_block != nil { arena_growing_free_last_memory_block(arena) } + arena.total_reserved = 0 case .Static: arena_static_reset_to(arena, 0) } arena.total_used = 0 - arena.total_reserved = 0 } arena_destroy :: proc(arena: ^Arena) { @@ -139,6 +129,16 @@ arena_destroy :: proc(arena: ^Arena) { arena.temp_count = 0 } +arena_growing_bootstrap_new :: proc{ + arena_growing_bootstrap_new_by_offset, + arena_growing_bootstrap_new_by_name, +} + +arena_static_bootstrap_new :: proc{ + arena_static_bootstrap_new_by_offset, + arena_static_bootstrap_new_by_name, +} + arena_growing_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size: uint = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { bootstrap: Arena bootstrap.kind = .Growing @@ -157,11 +157,6 @@ arena_growing_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, min return arena_growing_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size) } -arena_growing_bootstrap_new :: proc{ - arena_growing_bootstrap_new_by_offset, - arena_growing_bootstrap_new_by_name, -} - arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { bootstrap: Arena bootstrap.kind = .Static @@ -179,10 +174,6 @@ arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintpt arena_static_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { return arena_static_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), reserved) } -arena_static_bootstrap_new :: proc{ - arena_static_bootstrap_new_by_offset, - arena_static_bootstrap_new_by_name, -} arena_allocator :: proc(arena: ^Arena) -> mem.Allocator { @@ -195,6 +186,9 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, location := #caller_location) -> (data: []byte, err: Allocator_Error) { arena := (^Arena)(allocator_data) + size, alignment := uint(size), uint(alignment) + old_size := uint(old_size) + switch mode { case .Alloc: return arena_alloc(arena, size, alignment) @@ -239,6 +233,9 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, return } + + + Arena_Temp :: struct { arena: ^Arena, block: ^Memory_Block, diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index 22e96f6bd..e023b2324 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -106,7 +106,7 @@ memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags) return &pmblock.block, nil } -alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: int) -> (data: []byte, err: Allocator_Error) { +alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) -> (data: []byte, err: Allocator_Error) { calc_alignment_offset :: proc "contextless" (block: ^Memory_Block, alignment: uintptr) -> uint { alignment_offset := uint(0) ptr := uintptr(block.base[block.used:]) diff --git a/core/mem/virtual/virtual_platform.odin b/core/mem/virtual/virtual_platform.odin index 367346f63..2f167cbeb 100644 --- a/core/mem/virtual/virtual_platform.odin +++ b/core/mem/virtual/virtual_platform.odin @@ -63,7 +63,6 @@ platform_memory_commit :: proc "contextless" (block: ^Platform_Memory_Block, to_ return .Out_Of_Memory } - commit(block, to_commit) or_return block.committed = to_commit return nil From 765cd66b30f2da13ffc911b56e258a92f0d8ebdb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 21:20:31 +0100 Subject: [PATCH 25/56] Clean up `minimum_block_size` default implicit initialization --- core/mem/virtual/arena.odin | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index e95dc227c..33d25e3a5 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -56,7 +56,9 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l case .Growing: if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved { size = mem.align_forward_uint(size, alignment) - arena.minimum_block_size = max(GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE, arena.minimum_block_size) + if arena.minimum_block_size == 0 { + arena.minimum_block_size = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE + } block_size := max(size, arena.minimum_block_size) @@ -71,8 +73,10 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l arena.total_used += arena.curr_block.used - prev_used case .Static: if arena.curr_block == nil { - reserve_size := max(arena.minimum_block_size, STATIC_ARENA_DEFAULT_RESERVE_SIZE) - arena_init_static(arena, reserve_size, STATIC_ARENA_DEFAULT_COMMIT_SIZE) or_return + if arena.minimum_block_size == 0 { + arena.minimum_block_size = STATIC_ARENA_DEFAULT_RESERVE_SIZE + } + arena_init_static(arena=arena, reserved=arena.minimum_block_size, commit_size=STATIC_ARENA_DEFAULT_COMMIT_SIZE) or_return } data, err = alloc_from_memory_block(arena.curr_block, size, alignment) arena.total_used = arena.curr_block.used From 5ed06f7eb8b2e84844d7384e5e91ce59ab94340e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 21:23:45 +0100 Subject: [PATCH 26/56] Rename constants; minor rearrange of `Arena` layout --- core/mem/virtual/arena.odin | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 33d25e3a5..af26b950e 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -2,32 +2,31 @@ package mem_virtual import "core:mem" -Arena_Kind :: enum u8 { - Growing = 0, // chained memory block - Static = 1, // fixed reservation +Arena_Kind :: enum uint { + Growing = 0, // chained memory blocks (singly linked list) + Static = 1, // fixed reservation sized } Arena :: struct { - curr_block: ^Memory_Block, - total_used: uint, - total_reserved: uint, - kind: Arena_Kind, + curr_block: ^Memory_Block, + total_used: uint, + total_reserved: uint, minimum_block_size: uint, - temp_count: int, + temp_count: uint, } // 1 MiB should be enough to start with -STATIC_ARENA_DEFAULT_COMMIT_SIZE :: 1<<20 -GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE :: STATIC_ARENA_DEFAULT_COMMIT_SIZE +DEFAULT_ARENA_STATIC_COMMIT_SIZE :: 1<<20 +DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE :: DEFAULT_ARENA_STATIC_COMMIT_SIZE // 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default -STATIC_ARENA_DEFAULT_RESERVE_SIZE :: 1<<30 when size_of(uintptr) == 8 else 1<<27 +DEFAULT_ARENA_STATIC_RESERVE_SIZE :: 1<<30 when size_of(uintptr) == 8 else 1<<27 -arena_init_growing :: proc(arena: ^Arena, reserved: uint = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { +arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { arena.kind = .Growing arena.curr_block = memory_block_alloc(0, reserved, {}) or_return arena.total_used = 0 @@ -36,7 +35,7 @@ arena_init_growing :: proc(arena: ^Arena, reserved: uint = GROWING_ARENA_DEFAULT } -arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = STATIC_ARENA_DEFAULT_COMMIT_SIZE) -> (err: Allocator_Error) { +arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = DEFAULT_ARENA_STATIC_COMMIT_SIZE) -> (err: Allocator_Error) { arena.kind = .Static arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return arena.total_used = 0 @@ -57,7 +56,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved { size = mem.align_forward_uint(size, alignment) if arena.minimum_block_size == 0 { - arena.minimum_block_size = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE + arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE } block_size := max(size, arena.minimum_block_size) @@ -74,9 +73,9 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l case .Static: if arena.curr_block == nil { if arena.minimum_block_size == 0 { - arena.minimum_block_size = STATIC_ARENA_DEFAULT_RESERVE_SIZE + arena.minimum_block_size = DEFAULT_ARENA_STATIC_RESERVE_SIZE } - arena_init_static(arena=arena, reserved=arena.minimum_block_size, commit_size=STATIC_ARENA_DEFAULT_COMMIT_SIZE) or_return + arena_init_static(arena=arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return } data, err = alloc_from_memory_block(arena.curr_block, size, alignment) arena.total_used = arena.curr_block.used @@ -143,7 +142,7 @@ arena_static_bootstrap_new :: proc{ arena_static_bootstrap_new_by_name, } -arena_growing_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size: uint = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { +arena_growing_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { bootstrap: Arena bootstrap.kind = .Growing bootstrap.minimum_block_size = minimum_block_size @@ -157,7 +156,7 @@ arena_growing_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintp return } -arena_growing_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size: uint = GROWING_ARENA_DEFAULT_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { +arena_growing_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { return arena_growing_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size) } From cf4afc2e7b2e6a5219cbc25ca9d2039261d1e939 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 12 Oct 2022 21:26:50 +0100 Subject: [PATCH 27/56] Inline `assert` condition --- core/mem/virtual/arena.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index af26b950e..ab66f3685 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -44,7 +44,7 @@ arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = DEF } arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { - assert(mem.is_power_of_two(uintptr(alignment)), "non-power of two alignment", loc) + assert(alignment & (alignment-1) == 0, "non-power of two alignment", loc) size := size if size == 0 { From 2c14f0a109a25730fbe568a6710a1b943ff08132 Mon Sep 17 00:00:00 2001 From: hikari Date: Thu, 13 Oct 2022 11:19:05 +0300 Subject: [PATCH 28/56] sys/windows: add ITaskbarList interfaces --- core/sys/windows/types.odin | 82 +++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index b9ff6998a..af28a9060 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -3232,10 +3232,14 @@ LWSTDAPI :: HRESULT CLSID_FileOpenDialog := &GUID{0xDC1C5A9C, 0xE88A, 0x4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}} CLSID_FileSaveDialog := &GUID{0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}} +CLSID_TaskbarList := &GUID{0x56FDF344, 0xFD6D, 0x11d0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}} IID_IFileDialog := &GUID{0x42F85136, 0xDB7E, 0x439C, {0x85, 0xF1, 0xE4, 0x07, 0x5D, 0x13, 0x5F, 0xC8}} IID_IFileSaveDialog := &GUID{0x84BCCD23, 0x5FDE, 0x4CDB, {0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB}} IID_IFileOpenDialog := &GUID{0xD57C7288, 0xD4AD, 0x4768, {0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60}} +IID_ITaskbarList := &GUID{0x56FDF342, 0xFD6D, 0x11d0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}} +IID_ITaskbarList2 := &GUID{0x602D4995, 0xB13A, 0x429b, {0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17}} +IID_ITaskbarList3 := &GUID{0xea1afb91, 0x9e28, 0x4b86, {0x90, 0xe9, 0x9e, 0x9f, 0x8a, 0x5e, 0xef, 0xaf}} IModalWindow :: struct #raw_union { #subtype IUnknown: IUnknown, @@ -3540,6 +3544,84 @@ IFileSaveDialogVtbl :: struct { ApplyProperties: proc "stdcall" (this: ^IFileSaveDialog, psi: ^IShellItem, pStore: ^IPropertyStore, hwnd: HWND, pSink: ^IFileOperationProgressSink) -> HRESULT, } +ITaskbarList :: struct #raw_union { + #subtype IUnknown: IUnknown, + using Vtbl: ^ITaskbarListVtbl, +} +ITaskbarListVtbl :: struct { + using IUnknownVtbl: IUnknownVtbl, + HrInit: proc "stdcall" (this: ^ITaskbarList) -> HRESULT, + AddTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, + DeleteTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, + ActivateTab: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, + SetActiveAlt: proc "stdcall" (this: ^ITaskbarList, hwnd: HWND) -> HRESULT, +} + +ITaskbarList2 :: struct #raw_union { + #subtype ITaskbarList: ITaskbarList, + using Vtbl: ^ITaskbarList2Vtbl, +} +ITaskbarList2Vtbl :: struct { + using ITaskbarListVtbl: ITaskbarListVtbl, + MarkFullscreenWindow: proc "stdcall" (this: ^ITaskbarList2, hwnd: HWND, fFullscreen: BOOL) -> HRESULT, +} + +TBPFLAG :: enum c_int { + NOPROGRESS = 0, + INDETERMINATE = 0x1, + NORMAL = 0x2, + ERROR = 0x4, + PAUSED = 0x8, +} + +THUMBBUTTONFLAGS :: enum c_int { + ENABLED = 0, + DISABLED = 0x1, + DISMISSONCLICK = 0x2, + NOBACKGROUND = 0x4, + HIDDEN = 0x8, + NONINTERACTIVE = 0x10, +} + +THUMBBUTTONMASK :: enum c_int { + BITMAP = 0x1, + ICON = 0x2, + TOOLTIP = 0x4, + FLAGS = 0x8, +} + +THUMBBUTTON :: struct { + dwMask: THUMBBUTTONMASK, + iId: UINT, + iBitmap: UINT, + hIcon: HICON, + szTip: [260]WCHAR, + dwFlags: THUMBBUTTONFLAGS, +} +LPTHUMBBUTTON :: ^THUMBBUTTON + +HIMAGELIST :: ^IUnknown + +ITaskbarList3 :: struct #raw_union { + #subtype ITaskbarList2: ITaskbarList2, + using Vtbl: ^ITaskbarList3Vtbl, +} +ITaskbarList3Vtbl :: struct { + using ITaskbarList2Vtbl: ITaskbarList2Vtbl, + SetProgressValue: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, ullCompleted: ULONGLONG, ullTotal: ULONGLONG) -> HRESULT, + SetProgressState: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, tbpFlags: TBPFLAG) -> HRESULT, + RegisterTab: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndMDI: HWND) -> HRESULT, + UnregisterTab: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND) -> HRESULT, + SetTabOrder: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndInsertBefore: HWND) -> HRESULT, + SetTabActive: proc "stdcall" (this: ^ITaskbarList3, hwndTab: HWND, hwndMDI: HWND, dwReserved: DWORD) -> HRESULT, + ThumbBarAddButtons: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, cButtons: UINT, pButton: LPTHUMBBUTTON) -> HRESULT, + ThumbBarUpdateButtons: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, cButtons: UINT, pButton: LPTHUMBBUTTON) -> HRESULT, + ThumbBarSetImageList: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, himl: HIMAGELIST) -> HRESULT, + SetOverlayIcon: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, hIcon: HICON, pszDescription: LPCWSTR) -> HRESULT, + SetThumbnailTooltip: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, pszTip: LPCWSTR) -> HRESULT, + SetThumbnailClip: proc "stdcall" (this: ^ITaskbarList3, hwnd: HWND, prcClip: ^RECT) -> HRESULT, +} + MEMORYSTATUSEX :: struct { dwLength: DWORD, dwMemoryLoad: DWORD, From b725e01cddc32045b35fc44ed0b1e1df1bb7fbfe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 13 Oct 2022 11:10:16 +0100 Subject: [PATCH 29/56] Add @(require_results) to many procedures --- core/mem/virtual/arena.odin | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index ab66f3685..3cc4cdbd6 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -26,6 +26,7 @@ DEFAULT_ARENA_STATIC_RESERVE_SIZE :: 1<<30 when size_of(uintptr) == 8 else 1<<27 +@(require_results) arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { arena.kind = .Growing arena.curr_block = memory_block_alloc(0, reserved, {}) or_return @@ -35,6 +36,7 @@ arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING } +@(require_results) arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = DEFAULT_ARENA_STATIC_COMMIT_SIZE) -> (err: Allocator_Error) { arena.kind = .Static arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return @@ -43,6 +45,7 @@ arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = DEF return } +@(require_results) arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_location) -> (data: []byte, err: Allocator_Error) { assert(alignment & (alignment-1) == 0, "non-power of two alignment", loc) @@ -142,6 +145,7 @@ arena_static_bootstrap_new :: proc{ arena_static_bootstrap_new_by_name, } +@(require_results) arena_growing_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, minimum_block_size: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { bootstrap: Arena bootstrap.kind = .Growing @@ -156,10 +160,12 @@ arena_growing_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintp return } +@(require_results) arena_growing_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, minimum_block_size: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (ptr: ^T, err: Allocator_Error) { return arena_growing_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size) } +@(require_results) arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { bootstrap: Arena bootstrap.kind = .Static @@ -174,11 +180,13 @@ arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintpt return } +@(require_results) arena_static_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { return arena_static_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), reserved) } +@(require_results) arena_allocator :: proc(arena: ^Arena) -> mem.Allocator { return mem.Allocator{arena_allocator_proc, arena} } @@ -245,6 +253,7 @@ Arena_Temp :: struct { used: uint, } +@(require_results) arena_temp_begin :: proc(arena: ^Arena, loc := #caller_location) -> (temp: Arena_Temp) { assert(arena != nil, "nil arena", loc) temp.arena = arena From d48828dd80ef8419e8b1dab4178340e654322719 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 13 Oct 2022 12:45:17 +0100 Subject: [PATCH 30/56] Add overflow check when using a growing arena --- core/mem/virtual/arena.odin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 3cc4cdbd6..57dbc2168 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -1,6 +1,7 @@ package mem_virtual import "core:mem" +import "core:intrinsics" Arena_Kind :: enum uint { Growing = 0, // chained memory blocks (singly linked list) @@ -56,7 +57,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l switch arena.kind { case .Growing: - if arena.curr_block == nil || arena.curr_block.used + size > arena.curr_block.reserved { + if arena.curr_block == nil || (intrinsics.overflow_add(arena.curr_block.used, size) or_else 0) > arena.curr_block.reserved { size = mem.align_forward_uint(size, alignment) if arena.minimum_block_size == 0 { arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE From 7662808bc92271bbd5c9d6fad27301055f7e00ce Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 13 Oct 2022 12:53:33 +0100 Subject: [PATCH 31/56] Add `overflow_add` checks to `alloc_from_memory_block` --- core/mem/virtual/virtual.odin | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index e023b2324..b209d06e4 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -1,6 +1,7 @@ package mem_virtual import "core:mem" +import "core:intrinsics" DEFAULT_PAGE_SIZE := uint(4096) @@ -134,11 +135,14 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) return nil } - alignment_offset := calc_alignment_offset(block, uintptr(alignment)) - size := uint(min_size) + alignment_offset + size, size_ok := intrinsics.overflow_add(min_size, alignment_offset) + if !size_ok { + err = .Out_Of_Memory + return + } - if block.used + size > block.reserved { + if to_be_used, ok := intrinsics.overflow_add(block.used, size); !ok || to_be_used > block.reserved { err = .Out_Of_Memory return } From 06d1df4cae548e5baee226c570920e96eaca3ca1 Mon Sep 17 00:00:00 2001 From: terids Date: Fri, 14 Oct 2022 02:03:57 +0100 Subject: [PATCH 32/56] Fix GetInstanceProcAddr crash It was trying to initialise itself with itself when calling load_proc_addresses(Instance) Discord bug channel reference https://discord.com/channels/568138951836172421/585072813954564100/1030265964572450867 --- vendor/vulkan/_gen/create_vulkan_odin_wrapper.py | 14 +++++++------- vendor/vulkan/procedures.odin | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py index 9a32f5796..1dbac58d8 100644 --- a/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py +++ b/vendor/vulkan/_gen/create_vulkan_odin_wrapper.py @@ -84,7 +84,7 @@ def convert_type(t, prev_name, curr_name): else: ttype = t[:len(t)-1] elem = convert_type(ttype, prev_name, curr_name) - + if curr_name.endswith("s") or curr_name.endswith("Table"): if prev_name.endswith("Count") or prev_name.endswith("Counts"): pointer = "[^]" @@ -95,10 +95,10 @@ def convert_type(t, prev_name, curr_name): pointer = "[^]" elif curr_name.startswith("p"): pointer = "[^]" - + if curr_name and elem.endswith("Flags"): pointer = "[^]" - + return "{}{}".format(pointer, elem) elif t[0].isupper(): return t @@ -276,7 +276,7 @@ def parse_enums(f): f.write("// Enums\n") data = re.findall(r"typedef enum Vk(\w+) {(.+?)} \w+;", src, re.S) - + data.sort(key=lambda x: x[0]) generated_flags = set() @@ -458,14 +458,14 @@ def parse_procedures(f): for rt, name, fields in data: proc_name = no_vk(name) - + pf = [] prev_name = "" for type_, fname in re.findall(r"(?:\s*|)(.+?)\s*(\w+)(?:,|$)", fields): curr_name = fix_arg(fname) pf.append((do_type(type_, prev_name, curr_name), curr_name)) prev_name = curr_name - + data_fields = ', '.join(["{}: {}".format(n, t) for t, n in pf if t != ""]) ts = "proc \"c\" ({})".format(data_fields) @@ -510,7 +510,7 @@ def group_functions(f): if table_name in ('Device', 'Queue', 'CommandBuffer') and name != 'GetDeviceProcAddr': group_map["Device"].append(nn) - elif table_name in ('Instance', 'PhysicalDevice') or name == 'GetDeviceProcAddr': + elif table_name in ('Instance', 'PhysicalDevice') and name != 'ProcGetInstanceProcAddr' or name == 'GetDeviceProcAddr': group_map["Instance"].append(nn) elif table_name in ('rawptr', '', 'DebugReportFlagsEXT') or name == 'GetInstanceProcAddr': # Skip the allocation function and the dll entry point diff --git a/vendor/vulkan/procedures.odin b/vendor/vulkan/procedures.odin index 227f02a87..02cfa9dbf 100644 --- a/vendor/vulkan/procedures.odin +++ b/vendor/vulkan/procedures.odin @@ -533,6 +533,7 @@ DeviceMemoryReportCallbackEXT: ProcDeviceMemoryReportCallbackEXT EnumerateInstanceExtensionProperties: ProcEnumerateInstanceExtensionProperties EnumerateInstanceLayerProperties: ProcEnumerateInstanceLayerProperties EnumerateInstanceVersion: ProcEnumerateInstanceVersion +GetInstanceProcAddr: ProcGetInstanceProcAddr // Instance Procedures AcquireDrmDisplayEXT: ProcAcquireDrmDisplayEXT @@ -564,7 +565,6 @@ GetDisplayPlaneCapabilities2KHR: ProcGetDisplayP GetDisplayPlaneCapabilitiesKHR: ProcGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneSupportedDisplaysKHR: ProcGetDisplayPlaneSupportedDisplaysKHR GetDrmDisplayEXT: ProcGetDrmDisplayEXT -GetInstanceProcAddr: ProcGetInstanceProcAddr GetPhysicalDeviceCalibrateableTimeDomainsEXT: ProcGetPhysicalDeviceCalibrateableTimeDomainsEXT GetPhysicalDeviceCooperativeMatrixPropertiesNV: ProcGetPhysicalDeviceCooperativeMatrixPropertiesNV GetPhysicalDeviceDisplayPlaneProperties2KHR: ProcGetPhysicalDeviceDisplayPlaneProperties2KHR @@ -1045,6 +1045,7 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&EnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties") set_proc_address(&EnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties") set_proc_address(&EnumerateInstanceVersion, "vkEnumerateInstanceVersion") + set_proc_address(&GetInstanceProcAddr, "vkGetInstanceProcAddr") // Instance Procedures set_proc_address(&AcquireDrmDisplayEXT, "vkAcquireDrmDisplayEXT") @@ -1076,7 +1077,6 @@ load_proc_addresses_custom :: proc(set_proc_address: SetProcAddressType) { set_proc_address(&GetDisplayPlaneCapabilitiesKHR, "vkGetDisplayPlaneCapabilitiesKHR") set_proc_address(&GetDisplayPlaneSupportedDisplaysKHR, "vkGetDisplayPlaneSupportedDisplaysKHR") set_proc_address(&GetDrmDisplayEXT, "vkGetDrmDisplayEXT") - set_proc_address(&GetInstanceProcAddr, "vkGetInstanceProcAddr") set_proc_address(&GetPhysicalDeviceCalibrateableTimeDomainsEXT, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT") set_proc_address(&GetPhysicalDeviceCooperativeMatrixPropertiesNV, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") set_proc_address(&GetPhysicalDeviceDisplayPlaneProperties2KHR, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") @@ -2839,7 +2839,6 @@ load_proc_addresses_instance :: proc(instance: Instance) { GetDisplayPlaneCapabilitiesKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR") GetDisplayPlaneSupportedDisplaysKHR = auto_cast GetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR") GetDrmDisplayEXT = auto_cast GetInstanceProcAddr(instance, "vkGetDrmDisplayEXT") - GetInstanceProcAddr = auto_cast GetInstanceProcAddr(instance, "vkGetInstanceProcAddr") GetPhysicalDeviceCalibrateableTimeDomainsEXT = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT") GetPhysicalDeviceCooperativeMatrixPropertiesNV = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceCooperativeMatrixPropertiesNV") GetPhysicalDeviceDisplayPlaneProperties2KHR = auto_cast GetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlaneProperties2KHR") @@ -3322,6 +3321,7 @@ load_proc_addresses_global :: proc(vk_get_instance_proc_addr: rawptr) { EnumerateInstanceExtensionProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceExtensionProperties") EnumerateInstanceLayerProperties = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceLayerProperties") EnumerateInstanceVersion = auto_cast GetInstanceProcAddr(nil, "vkEnumerateInstanceVersion") + GetInstanceProcAddr = auto_cast GetInstanceProcAddr(nil, "vkGetInstanceProcAddr") } load_proc_addresses :: proc{ From 73c1f08776688f18940abcbff5d5b9f0f594049d Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Fri, 14 Oct 2022 18:22:59 +1100 Subject: [PATCH 33/56] Improve error messages with 'using _' --- src/check_decl.cpp | 5 +++++ src/check_stmt.cpp | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 9d043e60a..bb56749af 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1488,6 +1488,11 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty if (!(e->flags & EntityFlag_Using)) { continue; } + if (is_blank_ident(e->token)) { + error(e->token, "'using' a procedure parameter requires a non blank identifier"); + break; + } + bool is_value = (e->flags & EntityFlag_Value) != 0 && !is_type_pointer(e->type); String name = e->token.string; Type *t = base_type(type_deref(e->type)); diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 630182273..9cacb4a35 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -584,7 +584,11 @@ void check_label(CheckerContext *ctx, Ast *label, Ast *parent) { // Returns 'true' for 'continue', 'false' for 'return' bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, bool is_selector, Entity *e) { if (e == nullptr) { - error(us->token, "'using' applied to an unknown entity"); + if (is_blank_ident(expr)) { + error(us->token, "'using' in a statement is not allowed with the blank identifier '_'"); + } else { + error(us->token, "'using' applied to an unknown entity"); + } return true; } From ff51c5ee5628774574f63e72f5efe6c49aaae54e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 15 Oct 2022 12:52:07 +0100 Subject: [PATCH 34/56] Wrap `intrinsics.overflow_add` to `safe_add` --- core/mem/virtual/arena.odin | 6 +---- core/mem/virtual/arena_util.odin | 41 -------------------------------- core/mem/virtual/virtual.odin | 11 +++++++-- 3 files changed, 10 insertions(+), 48 deletions(-) delete mode 100644 core/mem/virtual/arena_util.odin diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 57dbc2168..45426eddc 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -1,7 +1,6 @@ package mem_virtual import "core:mem" -import "core:intrinsics" Arena_Kind :: enum uint { Growing = 0, // chained memory blocks (singly linked list) @@ -57,7 +56,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l switch arena.kind { case .Growing: - if arena.curr_block == nil || (intrinsics.overflow_add(arena.curr_block.used, size) or_else 0) > arena.curr_block.reserved { + if arena.curr_block == nil || (safe_add(arena.curr_block.used, size) or_else 0) > arena.curr_block.reserved { size = mem.align_forward_uint(size, alignment) if arena.minimum_block_size == 0 { arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE @@ -299,6 +298,3 @@ arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) { arena_check_temp :: proc(arena: ^Arena, loc := #caller_location) { assert(arena.temp_count == 0, "Arena_Temp not been ended", loc) } - - - diff --git a/core/mem/virtual/arena_util.odin b/core/mem/virtual/arena_util.odin deleted file mode 100644 index f721c4ffa..000000000 --- a/core/mem/virtual/arena_util.odin +++ /dev/null @@ -1,41 +0,0 @@ -package mem_virtual - -// arena_init :: proc{ -// static_arena_init, -// growing_arena_init, -// } - -// arena_temp_begin :: proc{ -// static_arena_temp_begin, -// growing_arena_temp_begin, -// } - -// arena_temp_end :: proc{ -// static_arena_temp_end, -// growing_arena_temp_end, -// } - -// arena_check_temp :: proc{ -// static_arena_check_temp, -// growing_arena_check_temp, -// } - -// arena_allocator :: proc{ -// static_arena_allocator, -// growing_arena_allocator, -// } - -// arena_alloc :: proc{ -// static_arena_alloc, -// growing_arena_alloc, -// } - -// arena_free_all :: proc{ -// static_arena_free_all, -// growing_arena_free_all, -// } - -// arena_destroy :: proc{ -// static_arena_destroy, -// growing_arena_destroy, -// } \ No newline at end of file diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index b209d06e4..426482fff 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -136,13 +136,13 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) } alignment_offset := calc_alignment_offset(block, uintptr(alignment)) - size, size_ok := intrinsics.overflow_add(min_size, alignment_offset) + size, size_ok := safe_add(min_size, alignment_offset) if !size_ok { err = .Out_Of_Memory return } - if to_be_used, ok := intrinsics.overflow_add(block.used, size); !ok || to_be_used > block.reserved { + if to_be_used, ok := safe_add(block.used, size); !ok || to_be_used > block.reserved { err = .Out_Of_Memory return } @@ -166,3 +166,10 @@ memory_block_dealloc :: proc(block_to_free: ^Memory_Block) { } } + + +@(private) +safe_add :: #force_inline proc "contextless" (x, y: uint) -> (uint, bool) { + z, did_overflow := intrinsics.overflow_add(x, y) + return z, !did_overflow +} \ No newline at end of file From 075040ae057e48bb9df4cb03bc0ea39e98a804ad Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 18 Oct 2022 00:06:21 +0100 Subject: [PATCH 35/56] Update sort_private.odin --- core/slice/sort_private.odin | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/slice/sort_private.odin b/core/slice/sort_private.odin index 86a6f5928..32eb7d417 100644 --- a/core/slice/sort_private.odin +++ b/core/slice/sort_private.odin @@ -177,7 +177,6 @@ _quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND } -// merge sort _stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check { less :: #force_inline proc(a, b: E, call: P) -> bool { when KIND == .Ordered { @@ -190,7 +189,9 @@ _stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (O #panic("unhandled Sort_Kind") } } - + + // insertion sort + // TODO(bill): use a different algorithm as insertion sort is O(n^2) n := len(data) for i in 1.. 0 && less(data[j], data[j-1], call); j -= 1 { From 9f55404845adb10a933cc725c019faa140efb202 Mon Sep 17 00:00:00 2001 From: Julian Fondren Date: Mon, 17 Oct 2022 22:32:10 -0500 Subject: [PATCH 36/56] fix core:c/libc.errno link_name for Linux and FreeBSD Although the FreeBSD link matches Darwin, its EILSEQ still matches Linux. Confirmed with the following program: ```odin package main import "core:c/libc" main :: proc() { libc.printf("%d\n", libc.errno()^) // 0 _ = libc.fopen("nonexistent file", "r") libc.printf("%d\n", libc.errno()^) // 2 } ``` on Linux: Odin: dev-2022-10:075040ae OS: Manjaro Linux, Linux 5.10.147-1-MANJARO CPU: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz RAM: 15953 MiB and FreeBSD: Odin: dev-2022-10:075040ae OS: FreeBSD: Unknown CPU: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz RAM: 990 MiB FreeBSD uname -r: 13.0-RELEASE --- core/c/libc/errno.odin | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/core/c/libc/errno.odin b/core/c/libc/errno.odin index 53437f42f..fe6fbb073 100644 --- a/core/c/libc/errno.odin +++ b/core/c/libc/errno.odin @@ -14,11 +14,24 @@ when ODIN_OS == .Windows { // EDOM, // EILSEQ // ERANGE -when ODIN_OS == .Linux || ODIN_OS == .FreeBSD { +when ODIN_OS == .Linux { @(private="file") @(default_calling_convention="c") foreign libc { - @(link_name="__libc_errno_location") + @(link_name="__errno_location") + _get_errno :: proc() -> ^int --- + } + + EDOM :: 33 + EILSEQ :: 84 + ERANGE :: 34 +} + +when ODIN_OS == .FreeBSD { + @(private="file") + @(default_calling_convention="c") + foreign libc { + @(link_name="__error") _get_errno :: proc() -> ^int --- } From 80ce1b7d850d264f5d8538724aa2b43e8e4a5c09 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 18 Oct 2022 10:28:17 +0100 Subject: [PATCH 37/56] Allow for `N = -1` in `wstring_to_utf8` --- core/sys/windows/util.odin | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/sys/windows/util.odin b/core/sys/windows/util.odin index 36383a2c7..298588cb6 100644 --- a/core/sys/windows/util.odin +++ b/core/sys/windows/util.odin @@ -62,19 +62,19 @@ utf8_to_wstring :: proc(s: string, allocator := context.temp_allocator) -> wstri wstring_to_utf8 :: proc(s: wstring, N: int, allocator := context.temp_allocator) -> (res: string, err: runtime.Allocator_Error) { context.allocator = allocator - if N <= 0 { + if N == 0 { return } - n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N), nil, 0, nil, nil) + n := WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, s, i32(N) if N > 0 else -1, nil, 0, nil, nil) if n == 0 { return } - // If N == -1 the call to WideCharToMultiByte assume the wide string is null terminated + // If N < 0 the call to WideCharToMultiByte assume the wide string is null terminated // and will scan it to find the first null terminated character. The resulting string will // also be null terminated. - // If N != -1 it assumes the wide string is not null terminated and the resulting string + // If N > 0 it assumes the wide string is not null terminated and the resulting string // will not be null terminated. text := make([]byte, n) or_return From 765969e6a3c449b4fab8da0b5b672a5a436010c9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 19 Oct 2022 16:06:36 +0100 Subject: [PATCH 38/56] Revert `default_resize_bytes_align` logic to previous behaviour --- core/mem/alloc.odin | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/mem/alloc.odin b/core/mem/alloc.odin index b5788c8a8..54004d333 100644 --- a/core/mem/alloc.odin +++ b/core/mem/alloc.odin @@ -243,11 +243,13 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a return alloc_bytes(new_size, alignment, allocator, loc) } - if new_size == old_size { - return old_data, nil - } if new_size == 0 { - return nil, free_bytes(old_data, allocator, loc) + err := free_bytes(old_data, allocator, loc) + return nil, err + } + + if new_size == old_size { + return old_data, .None } new_memory, err := alloc_bytes(new_size, alignment, allocator, loc) @@ -256,9 +258,6 @@ default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, a } runtime.copy(new_memory, old_data) - err1 := free_bytes(old_data, allocator, loc) - if err == nil { - err = err1 - } + free_bytes(old_data, allocator, loc) return new_memory, err } From 098f51aa800a8d2efd06ea54911b8ec067c586ed Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 19 Oct 2022 16:59:38 +0100 Subject: [PATCH 39/56] Allow `transmute` to be constant for integers of the same internal endianness --- src/big_int.cpp | 2 +- src/check_expr.cpp | 61 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/big_int.cpp b/src/big_int.cpp index 5509545ca..d8b3e63a7 100644 --- a/src/big_int.cpp +++ b/src/big_int.cpp @@ -71,7 +71,7 @@ void big_int_and (BigInt *dst, BigInt const *x, BigInt const *y); void big_int_and_not(BigInt *dst, BigInt const *x, BigInt const *y); void big_int_xor (BigInt *dst, BigInt const *x, BigInt const *y); void big_int_or (BigInt *dst, BigInt const *x, BigInt const *y); -void big_int_not (BigInt *dst, BigInt const *x, u64 bit_count, bool is_signed); +void big_int_not (BigInt *dst, BigInt const *x, i32 bit_count, bool is_signed); void big_int_add_eq(BigInt *dst, BigInt const *x); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6edd4a93c..ab5838bf5 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2916,7 +2916,12 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) { // return false; // } - if (is_type_untyped(o->type)) { + Type *src_t = o->type; + Type *dst_t = t; + Type *src_bt = base_type(src_t); + Type *dst_bt = base_type(dst_t); + + if (is_type_untyped(src_t)) { gbString expr_str = expr_to_string(o->expr); error(o->expr, "Cannot transmute untyped expression: '%s'", expr_str); gb_string_free(expr_str); @@ -2925,7 +2930,6 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) { return false; } - Type *dst_bt = base_type(t); if (dst_bt == nullptr || dst_bt == t_invalid) { GB_ASSERT(global_error_collector.count != 0); @@ -2934,21 +2938,21 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) { return false; } - Type *src_bt = base_type(o->type); if (src_bt == nullptr || src_bt == t_invalid) { // NOTE(bill): this should be an error GB_ASSERT(global_error_collector.count != 0); o->mode = Addressing_Value; o->expr = node; - o->type = t; + o->type = dst_t; return true; } - i64 srcz = type_size_of(o->type); - i64 dstz = type_size_of(t); + + i64 srcz = type_size_of(src_t); + i64 dstz = type_size_of(dst_t); if (srcz != dstz) { gbString expr_str = expr_to_string(o->expr); - gbString type_str = type_to_string(t); + gbString type_str = type_to_string(dst_t); error(o->expr, "Cannot transmute '%s' to '%s', %lld vs %lld bytes", expr_str, type_str, srcz, dstz); gb_string_free(type_str); gb_string_free(expr_str); @@ -2958,16 +2962,53 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) { } if (build_context.vet_extra) { - if (are_types_identical(o->type, t)) { - gbString str = type_to_string(t); + if (are_types_identical(o->type, dst_t)) { + gbString str = type_to_string(dst_t); warning(o->expr, "Unneeded transmute to the same type '%s'", str); gb_string_free(str); } } o->expr = node; + o->type = dst_t; + if (o->mode == Addressing_Constant) { + if (are_types_identical(src_bt, dst_bt)) { + return true; + } + if (is_type_integer(src_t) && is_type_integer(dst_t)) { + if (types_have_same_internal_endian(src_t, dst_t)) { + ExactValue src_v = exact_value_to_integer(o->value); + GB_ASSERT(src_v.kind == ExactValue_Integer); + BigInt v = src_v.value_integer; + + BigInt smax = {}; + BigInt umax = {}; + + big_int_from_u64(&smax, 0); + big_int_not(&smax, &smax, cast(i32)(srcz*8 - 1), false); + + big_int_from_u64(&umax, 1); + BigInt sz_in_bits = big_int_make_i64(srcz*8); + big_int_shl_eq(&umax, &sz_in_bits); + + if (is_type_unsigned(src_t) && !is_type_unsigned(dst_t)) { + if (big_int_cmp(&v, &smax) >= 0) { + big_int_sub_eq(&v, &umax); + } + } else if (!is_type_unsigned(src_t) && is_type_unsigned(dst_t)) { + if (big_int_is_neg(&v)) { + big_int_add_eq(&v, &umax); + } + } + + o->value.kind = ExactValue_Integer; + o->value.value_integer = v; + return true; + } + } + } + o->mode = Addressing_Value; - o->type = t; o->value = {}; return true; } From 53e84b7f31a218102034c60e157b60d22adcf303 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 19 Oct 2022 23:39:47 +0100 Subject: [PATCH 40/56] Remove doubly linked list of `Platform_Memory_Block` fields --- core/mem/virtual/virtual.odin | 12 ------------ core/mem/virtual/virtual_platform.odin | 25 ------------------------- 2 files changed, 37 deletions(-) diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index 426482fff..c4a475dba 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -96,13 +96,6 @@ memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags) pmblock.block.committed = committed pmblock.block.reserved = reserved - sentinel := &global_platform_memory_block_sentinel - platform_mutex_lock() - pmblock.next = sentinel - pmblock.prev = sentinel.prev - pmblock.prev.next = pmblock - pmblock.next.prev = pmblock - platform_mutex_unlock() return &pmblock.block, nil } @@ -157,11 +150,6 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) memory_block_dealloc :: proc(block_to_free: ^Memory_Block) { if block := (^Platform_Memory_Block)(block_to_free); block != nil { - platform_mutex_lock() - block.prev.next = block.next - block.next.prev = block.prev - platform_mutex_unlock() - platform_memory_free(block) } } diff --git a/core/mem/virtual/virtual_platform.odin b/core/mem/virtual/virtual_platform.odin index 2f167cbeb..c2b505cd2 100644 --- a/core/mem/virtual/virtual_platform.odin +++ b/core/mem/virtual/virtual_platform.odin @@ -1,13 +1,10 @@ //+private package mem_virtual -import "core:sync" - Platform_Memory_Block :: struct { block: Memory_Block, committed: uint, reserved: uint, - prev, next: ^Platform_Memory_Block, } platform_memory_alloc :: proc "contextless" (to_commit, to_reserve: uint) -> (block: ^Platform_Memory_Block, err: Allocator_Error) { @@ -33,28 +30,6 @@ platform_memory_free :: proc "contextless" (block: ^Platform_Memory_Block) { } } -platform_mutex_lock :: proc() { - sync.mutex_lock(&global_memory_block_mutex) -} - -platform_mutex_unlock :: proc() { - sync.mutex_unlock(&global_memory_block_mutex) -} - -global_memory_block_mutex: sync.Mutex -global_platform_memory_block_sentinel: Platform_Memory_Block -global_platform_memory_block_sentinel_set: bool - -@(init) -platform_memory_init :: proc() { - if !global_platform_memory_block_sentinel_set { - _platform_memory_init() - global_platform_memory_block_sentinel.prev = &global_platform_memory_block_sentinel - global_platform_memory_block_sentinel.next = &global_platform_memory_block_sentinel - global_platform_memory_block_sentinel_set = true - } -} - platform_memory_commit :: proc "contextless" (block: ^Platform_Memory_Block, to_commit: uint) -> (err: Allocator_Error) { if to_commit < block.committed { return nil From 2242178d967d01cdcf70c2b64b7fa52b91e338fe Mon Sep 17 00:00:00 2001 From: Julian Ceipek Date: Thu, 20 Oct 2022 21:07:14 -0400 Subject: [PATCH 41/56] Fix signature for `objc_allocateClassPair` --- core/runtime/procs_darwin.odin | 2 +- vendor/darwin/Foundation/objc.odin | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/runtime/procs_darwin.odin b/core/runtime/procs_darwin.odin index b54a28dcc..9c53b5b16 100644 --- a/core/runtime/procs_darwin.odin +++ b/core/runtime/procs_darwin.odin @@ -12,7 +12,7 @@ objc_SEL :: ^intrinsics.objc_selector foreign Foundation { objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class --- sel_registerName :: proc "c" (name: cstring) -> objc_SEL --- - objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) --- + objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) -> objc_Class --- objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) --- objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 --- diff --git a/vendor/darwin/Foundation/objc.odin b/vendor/darwin/Foundation/objc.odin index 78f1f7780..2ece561f3 100644 --- a/vendor/darwin/Foundation/objc.odin +++ b/vendor/darwin/Foundation/objc.odin @@ -10,7 +10,7 @@ IMP :: proc "c" (object: id, sel: SEL, #c_vararg args: ..any) -> id foreign Foundation { objc_lookUpClass :: proc "c" (name: cstring) -> Class --- sel_registerName :: proc "c" (name: cstring) -> SEL --- - objc_allocateClassPair :: proc "c" (superclass: Class, name: cstring, extraBytes: uint) --- + objc_allocateClassPair :: proc "c" (superclass: Class, name: cstring, extraBytes: uint) -> Class --- class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL --- class_getInstanceMethod :: proc "c" (cls: Class, name: SEL) -> Method --- From fda8e8a30b36c71b08642668f18ee7f8d12f417b Mon Sep 17 00:00:00 2001 From: Julian Ceipek Date: Thu, 20 Oct 2022 21:16:53 -0400 Subject: [PATCH 42/56] Use `c.size_t` to match C declaration more directly --- vendor/darwin/Foundation/objc.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/darwin/Foundation/objc.odin b/vendor/darwin/Foundation/objc.odin index 2ece561f3..9468b971a 100644 --- a/vendor/darwin/Foundation/objc.odin +++ b/vendor/darwin/Foundation/objc.odin @@ -10,7 +10,7 @@ IMP :: proc "c" (object: id, sel: SEL, #c_vararg args: ..any) -> id foreign Foundation { objc_lookUpClass :: proc "c" (name: cstring) -> Class --- sel_registerName :: proc "c" (name: cstring) -> SEL --- - objc_allocateClassPair :: proc "c" (superclass: Class, name: cstring, extraBytes: uint) -> Class --- + objc_allocateClassPair :: proc "c" (superclass : Class, name : cstring, extraBytes : c.size_t) -> Class --- class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL --- class_getInstanceMethod :: proc "c" (cls: Class, name: SEL) -> Method --- From f26516f6faf337f39bab172ebba7ae2cb1337fcc Mon Sep 17 00:00:00 2001 From: Julian Ceipek Date: Thu, 20 Oct 2022 21:18:11 -0400 Subject: [PATCH 43/56] Add `objc_registerClassPair` to allow subclassing --- vendor/darwin/Foundation/objc.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/darwin/Foundation/objc.odin b/vendor/darwin/Foundation/objc.odin index 9468b971a..03cc7648e 100644 --- a/vendor/darwin/Foundation/objc.odin +++ b/vendor/darwin/Foundation/objc.odin @@ -11,6 +11,7 @@ foreign Foundation { objc_lookUpClass :: proc "c" (name: cstring) -> Class --- sel_registerName :: proc "c" (name: cstring) -> SEL --- objc_allocateClassPair :: proc "c" (superclass : Class, name : cstring, extraBytes : c.size_t) -> Class --- + objc_registerClassPair :: proc "c" (cls : Class) --- class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL --- class_getInstanceMethod :: proc "c" (cls: Class, name: SEL) -> Method --- From 8ceb691cec2d950b0f9700a2eb31aa085823b3bb Mon Sep 17 00:00:00 2001 From: Julian Ceipek Date: Thu, 20 Oct 2022 21:38:43 -0400 Subject: [PATCH 44/56] Fix indentation --- vendor/darwin/Foundation/objc.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/darwin/Foundation/objc.odin b/vendor/darwin/Foundation/objc.odin index 03cc7648e..722065564 100644 --- a/vendor/darwin/Foundation/objc.odin +++ b/vendor/darwin/Foundation/objc.odin @@ -10,7 +10,7 @@ IMP :: proc "c" (object: id, sel: SEL, #c_vararg args: ..any) -> id foreign Foundation { objc_lookUpClass :: proc "c" (name: cstring) -> Class --- sel_registerName :: proc "c" (name: cstring) -> SEL --- - objc_allocateClassPair :: proc "c" (superclass : Class, name : cstring, extraBytes : c.size_t) -> Class --- + objc_allocateClassPair :: proc "c" (superclass : Class, name : cstring, extraBytes : c.size_t) -> Class --- objc_registerClassPair :: proc "c" (cls : Class) --- class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL --- From 648e3c65eadbfcc01da4b9a13216772c63cfb765 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 21 Oct 2022 19:20:15 +0200 Subject: [PATCH 45/56] Add RawMouseMotionSupported --- vendor/glfw/bindings/bindings.odin | 1 + vendor/glfw/constants.odin | 3 +++ 2 files changed, 4 insertions(+) diff --git a/vendor/glfw/bindings/bindings.odin b/vendor/glfw/bindings/bindings.odin index aea09e31d..e7287e316 100644 --- a/vendor/glfw/bindings/bindings.odin +++ b/vendor/glfw/bindings/bindings.odin @@ -110,6 +110,7 @@ foreign glfw { WaitEventsTimeout :: proc(timeout: f64) --- PostEmptyEvent :: proc() --- + RawMouseMotionSupported :: proc() -> b32 --- GetInputMode :: proc(window: WindowHandle, mode: c.int) -> c.int --- SetInputMode :: proc(window: WindowHandle, mode, value: c.int) --- diff --git a/vendor/glfw/constants.odin b/vendor/glfw/constants.odin index 245cfef52..ec1364e07 100644 --- a/vendor/glfw/constants.odin +++ b/vendor/glfw/constants.odin @@ -339,6 +339,9 @@ CURSOR_NORMAL :: 0x00034001 CURSOR_HIDDEN :: 0x00034002 CURSOR_DISABLED :: 0x00034003 +/* Mouse motion */ +RAW_MOUSE_MOTION :: 0x00033005 + /* Behavior? */ ANY_RELEASE_BEHAVIOR :: 0 RELEASE_BEHAVIOR_FLUSH :: 0x00035001 From 989107094c64b6f74dadb40df2374a9db625778a Mon Sep 17 00:00:00 2001 From: Jasper Geer Date: Fri, 21 Oct 2022 15:41:58 -0400 Subject: [PATCH 46/56] throw type checker error when scalar cast to non-square matrix --- src/check_expr.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index ab5838bf5..b3c04caa4 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -821,11 +821,12 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type if (are_types_identical(src, dst)) { return 5; } - - Type *dst_elem = base_array_type(dst); - i64 distance = check_distance_between_types(c, operand, dst_elem); - if (distance >= 0) { - return distance + 7; + if (dst->Matrix.row_count == dst->Matrix.column_count) { + Type *dst_elem = base_array_type(dst); + i64 distance = check_distance_between_types(c, operand, dst_elem); + if (distance >= 0) { + return distance + 7; + } } } From a51943e27f625552c4a56ec7389ff2d06e8c7a8d Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 23 Oct 2022 04:18:58 +0200 Subject: [PATCH 47/56] Add `core:math/rand.choice` --- core/math/rand/rand.odin | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index f7dfcb3b8..2d92d29ff 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -182,3 +182,12 @@ shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) { array[i], array[j] = array[j], array[i] } } + +// Returns a random element from the given slice +choice :: proc(array: $T/[]$E, r: ^Rand = nil) -> (res: E) { + n := i64(len(array)) + if n < 1 { + return E{} + } + return array[int63_max(n, r)] +} \ No newline at end of file From 92fb65cf2eed21e5f97d7818172290271eaee63e Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 23 Oct 2022 04:32:45 +0200 Subject: [PATCH 48/56] Fix `#defined(I)`. --- src/check_builtin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index a00dd5def..fc889fb28 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1533,10 +1533,10 @@ bool check_builtin_procedure_directive(CheckerContext *c, Operand *operand, Ast } bool is_defined = check_identifier_exists(c->scope, arg); - gb_unused(is_defined); + // gb_unused(is_defined); operand->type = t_untyped_bool; operand->mode = Addressing_Constant; - operand->value = exact_value_bool(false); + operand->value = exact_value_bool(is_defined); } else if (name == "config") { if (ce->args.count != 2) { From a5f8c3f692ff802104b81416513396981409c2f3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 23 Oct 2022 13:17:37 +0100 Subject: [PATCH 49/56] Update many `enum`s to `bit_set`s for D3D11 --- vendor/directx/d3d11/d3d11.odin | 312 ++++++++++++++++++-------------- 1 file changed, 177 insertions(+), 135 deletions(-) diff --git a/vendor/directx/d3d11/d3d11.odin b/vendor/directx/d3d11/d3d11.odin index a41ce1190..42a860c4b 100644 --- a/vendor/directx/d3d11/d3d11.odin +++ b/vendor/directx/d3d11/d3d11.odin @@ -30,7 +30,7 @@ foreign d3d11 { DriverType: DRIVER_TYPE, Software: HMODULE, Flags: CREATE_DEVICE_FLAGS, - pFeatureLevels: ^FEATURE_LEVEL, + pFeatureLevels: [^]FEATURE_LEVEL, FeatureLevels: u32, SDKVersion: u32, ppDevice: ^^IDevice, @@ -41,8 +41,8 @@ foreign d3d11 { pAdapter: ^dxgi.IAdapter, DriverType: DRIVER_TYPE, Software: HMODULE, - Flags: u32, - pFeatureLevels: ^FEATURE_LEVEL, + Flags: CREATE_DEVICE_FLAGS, + pFeatureLevels: [^]FEATURE_LEVEL, FeatureLevels: u32, SDKVersion: u32, pSwapChainDesc: ^dxgi.SWAP_CHAIN_DESC, @@ -539,25 +539,37 @@ ANISOTROPIC_FILTERING_BIT :: 0x40 SDK_VERSION :: 7 RETURN_PARAMETER_INDEX :: -1 -COMPONENT_MASK :: enum u32 { // TODO: make bit_set +COMPONENT_MASK :: distinct bit_set[COMPONENT_MASK_ELEMENT; u32] +COMPONENT_MASK_ELEMENT :: enum u32 { X = 1, Y = 2, Z = 4, W = 8, } -SHADER_REQUIRES :: enum u32 { // TODO: make bit_set - DOUBLES = 0x00000001, - EARLY_DEPTH_STENCIL = 0x00000002, - UAVS_AT_EVERY_STAGE = 0x00000004, - _64_UAVS = 0x00000008, - MINIMUM_PRECISION = 0x00000010, - _11_1_DOUBLE_EXTENSIONS = 0x00000020, - _11_1_SHADER_EXTENSIONS = 0x00000040, - LEVEL_9_COMPARISON_FILTERING = 0x00000080, - TILED_RESOURCES = 0x00000100, +SHADER_REQUIRES_FLAGS :: distinct bit_set[SHADER_REQUIRES_FLAG; u64] +SHADER_REQUIRES_FLAG :: enum u64 { + DOUBLES = 0, + EARLY_DEPTH_STENCIL = 1, + UAVS_AT_EVERY_STAGE = 2, + _64_UAVS = 3, + MINIMUM_PRECISION = 4, + _11_1_DOUBLE_EXTENSIONS = 5, + _11_1_SHADER_EXTENSIONS = 6, + LEVEL_9_COMPARISON_FILTERING = 7, + TILED_RESOURCES = 8, } +SHADER_REQUIRES_DOUBLES :: SHADER_REQUIRES_FLAGS{.DOUBLES} +SHADER_REQUIRES_EARLY_DEPTH_STENCIL :: SHADER_REQUIRES_FLAGS{.EARLY_DEPTH_STENCIL} +SHADER_REQUIRES_UAVS_AT_EVERY_STAGE :: SHADER_REQUIRES_FLAGS{.UAVS_AT_EVERY_STAGE} +SHADER_REQUIRES_64_UAVS :: SHADER_REQUIRES_FLAGS{._64_UAVS} +SHADER_REQUIRES_MINIMUM_PRECISION :: SHADER_REQUIRES_FLAGS{.MINIMUM_PRECISION} +SHADER_REQUIRES_11_1_DOUBLE_EXTENSIONS :: SHADER_REQUIRES_FLAGS{._11_1_DOUBLE_EXTENSIONS} +SHADER_REQUIRES_11_1_SHADER_EXTENSIONS :: SHADER_REQUIRES_FLAGS{._11_1_SHADER_EXTENSIONS} +SHADER_REQUIRES_LEVEL_9_COMPARISON_FILTERING :: SHADER_REQUIRES_FLAGS{.LEVEL_9_COMPARISON_FILTERING} +SHADER_REQUIRES_TILED_RESOURCES :: SHADER_REQUIRES_FLAGS{.TILED_RESOURCES} + DRIVER_TYPE :: enum i32 { UNKNOWN = 0, HARDWARE = 1, @@ -708,11 +720,12 @@ SHADER_VARIABLE_CLASS :: enum i32 { INTERFACE_POINTER = 7, } -SHADER_VARIABLE_FLAGS :: enum u32 { // TODO: make bit_set - USERPACKED = 0x1, - USED = 0x2, - INTERFACE_POINTER = 0x4, - INTERFACE_PARAMETER = 0x8, +SHADER_VARIABLE_FLAGS :: distinct bit_set[SHADER_VARIABLE_FLAG; u32] +SHADER_VARIABLE_FLAG :: enum u32 { + USERPACKED = 0, + USED = 1, + INTERFACE_POINTER = 2, + INTERFACE_PARAMETER = 3, } SHADER_VARIABLE_TYPE :: enum i32 { @@ -776,14 +789,21 @@ SHADER_VARIABLE_TYPE :: enum i32 { MIN16UINT = 57, } -SHADER_INPUT_FLAGS :: enum u32 { // TODO: make bit_set - USERPACKED = 0x1, - COMPARISON_SAMPLER = 0x2, - TEXTURE_COMPONENT_0 = 0x4, - TEXTURE_COMPONENT_1 = 0x8, +SHADER_INPUT_FLAGS :: distinct bit_set[SHADER_INPUT_FLAG; u32] +SHADER_INPUT_FLAG :: enum u32 { + USERPACKED = 0, + COMPARISON_SAMPLER = 1, + TEXTURE_COMPONENT_0 = 2, + TEXTURE_COMPONENT_1 = 3, TEXTURE_COMPONENTS = 0xc, - UNUSED = 0x10, + UNUSED = 4, } +SHADER_INPUT_FLAG_USERPACKED :: SHADER_INPUT_FLAGS{.USERPACKED} +SHADER_INPUT_FLAG_COMPARISON_SAMPLER :: SHADER_INPUT_FLAGS{.COMPARISON_SAMPLER} +SHADER_INPUT_FLAG_TEXTURE_COMPONENT_0 :: SHADER_INPUT_FLAGS{.TEXTURE_COMPONENT_0} +SHADER_INPUT_FLAG_TEXTURE_COMPONENT_1 :: SHADER_INPUT_FLAGS{.TEXTURE_COMPONENT_1} +SHADER_INPUT_FLAG_TEXTURE_COMPONENTS :: SHADER_INPUT_FLAGS{.TEXTURE_COMPONENT_0, .TEXTURE_COMPONENT_1} +SHADER_INPUT_FLAG_UNUSED :: SHADER_INPUT_FLAGS{.UNUSED} SHADER_INPUT_TYPE :: enum i32 { CBUFFER = 0, @@ -802,8 +822,9 @@ SHADER_INPUT_TYPE :: enum i32 { UAV_FEEDBACKTEXTURE = 13, } -SHADER_CBUFFER_FLAGS :: enum u32 { // TODO: make bit_set - USERPACKED = 0x1, +SHADER_CBUFFER_FLAGS :: distinct bit_set[SHADER_CBUFFER_FLAG; u32] +SHADER_CBUFFER_FLAG :: enum u32 { + USERPACKED = 0, } CBUFFER_TYPE :: enum i32 { @@ -906,10 +927,10 @@ INTERPOLATION_MODE :: enum i32 { LINEAR_NOPERSPECTIVE_SAMPLE = 7, } -PARAMETER_FLAGS :: enum u32 { // TODO: make bit_set - NONE = 0x0, - IN = 0x1, - OUT = 0x2, +PARAMETER_FLAGS :: distinct bit_set[PARAMETER_FLAG; u32] +PARAMETER_FLAG :: enum u32 { + IN = 0, + OUT = 1, } CDEFAULT :: struct { @@ -1022,43 +1043,46 @@ USAGE :: enum i32 { STAGING = 3, } -BIND_FLAG :: enum u32 { // TODO: make bit_set - VERTEX_BUFFER = 0x1, - INDEX_BUFFER = 0x2, - CONSTANT_BUFFER = 0x4, - SHADER_RESOURCE = 0x8, - STREAM_OUTPUT = 0x10, - RENDER_TARGET = 0x20, - DEPTH_STENCIL = 0x40, - UNORDERED_ACCESS = 0x80, - DECODER = 0x200, - VIDEO_ENCODER = 0x400, +BIND_FLAGS :: distinct bit_set[BIND_FLAG; u32] +BIND_FLAG :: enum u32 { + VERTEX_BUFFER = 0, + INDEX_BUFFER = 1, + CONSTANT_BUFFER = 2, + SHADER_RESOURCE = 3, + STREAM_OUTPUT = 4, + RENDER_TARGET = 5, + DEPTH_STENCIL = 6, + UNORDERED_ACCESS = 7, + DECODER = 9, + VIDEO_ENCODER = 10, } -CPU_ACCESS_FLAG :: enum u32 { // TODO: make bit_set - WRITE = 0x10000, - READ = 0x20000, +CPU_ACCESS_FLAGS :: distinct bit_set[CPU_ACCESS_FLAG; u32] +CPU_ACCESS_FLAG :: enum u32 { + WRITE = 16, + READ = 17, } -RESOURCE_MISC_FLAG :: enum u32 { // TODO: make bit_set - GENERATE_MIPS = 0x1, - SHARED = 0x2, - TEXTURECUBE = 0x4, - DRAWINDIRECT_ARGS = 0x10, - BUFFER_ALLOW_RAW_VIEWS = 0x20, - BUFFER_STRUCTURED = 0x40, - RESOURCE_CLAMP = 0x80, - SHARED_KEYEDMUTEX = 0x100, - GDI_COMPATIBLE = 0x200, - SHARED_NTHANDLE = 0x800, - RESTRICTED_CONTENT = 0x1000, - RESTRICT_SHARED_RESOURCE = 0x2000, - RESTRICT_SHARED_RESOURCE_DRIVER = 0x4000, - GUARDED = 0x8000, - TILE_POOL = 0x20000, - TILED = 0x40000, - HW_PROTECTED = 0x80000, +RESOURCE_MISC_FLAGS :: distinct bit_set[RESOURCE_MISC_FLAG; u32] +RESOURCE_MISC_FLAG :: enum u32 { + GENERATE_MIPS = 0, + SHARED = 1, + TEXTURECUBE = 2, + DRAWINDIRECT_ARGS = 4, + BUFFER_ALLOW_RAW_VIEWS = 5, + BUFFER_STRUCTURED = 6, + RESOURCE_CLAMP = 7, + SHARED_KEYEDMUTEX = 8, + GDI_COMPATIBLE = 9, + SHARED_NTHANDLE = 11, + RESTRICTED_CONTENT = 12, + RESTRICT_SHARED_RESOURCE = 13, + RESTRICT_SHARED_RESOURCE_DRIVER = 14, + GUARDED = 15, + TILE_POOL = 17, + TILED = 18, + HW_PROTECTED = 19, } MAP :: enum i32 { @@ -1069,17 +1093,20 @@ MAP :: enum i32 { WRITE_NO_OVERWRITE = 5, } -MAP_FLAG :: enum u32 { // TODO: make bit_set - DO_NOT_WAIT = 0x100000, +MAP_FLAGS :: distinct bit_set[MAP_FLAG; u32] +MAP_FLAG :: enum u32 { + DO_NOT_WAIT = 20, } -RAISE_FLAG :: enum u32 { // TODO: make bit_set - DRIVER_INTERNAL_ERROR = 0x1, +RAISE_FLAGS :: distinct bit_set[RAISE_FLAG; u32] +RAISE_FLAG :: enum u32 { + DRIVER_INTERNAL_ERROR = 0, } -CLEAR_FLAG :: enum u32 { // TODO: make bit_set - DEPTH = 0x1, - STENCIL = 0x2, +CLEAR_FLAGS :: distinct bit_set[CLEAR_FLAG; u32] +CLEAR_FLAG :: enum u32 { + DEPTH = 0, + STENCIL = 1, } @@ -1206,7 +1233,15 @@ BLEND_OP :: enum i32 { MAX = 5, } -COLOR_WRITE_ENABLE :: enum i32 { // TODO: make bit_set +COLOR_WRITE_ENABLE_MASK :: distinct bit_set[COLOR_WRITE_ENABLE; u32] + +COLOR_WRITE_ENABLE_RED :: COLOR_WRITE_ENABLE_MASK{.RED} +COLOR_WRITE_ENABLE_GREEN :: COLOR_WRITE_ENABLE_MASK{.GREEN} +COLOR_WRITE_ENABLE_BLUE :: COLOR_WRITE_ENABLE_MASK{.BLUE} +COLOR_WRITE_ENABLE_ALPHA :: COLOR_WRITE_ENABLE_MASK{.ALPHA} +COLOR_WRITE_ENABLE_ALL :: COLOR_WRITE_ENABLE_MASK{.RED, .GREEN, .BLUE, .ALPHA} + +COLOR_WRITE_ENABLE :: enum i32 { RED = 1, GREEN = 2, BLUE = 4, @@ -1308,9 +1343,9 @@ IResource_VTable :: struct { BUFFER_DESC :: struct { ByteWidth: u32, Usage: USAGE, - BindFlags: BIND_FLAG, - CPUAccessFlags: CPU_ACCESS_FLAG, - MiscFlags: RESOURCE_MISC_FLAG, + BindFlags: BIND_FLAGS, + CPUAccessFlags: CPU_ACCESS_FLAGS, + MiscFlags: RESOURCE_MISC_FLAGS, StructureByteStride: u32, } @@ -1337,9 +1372,9 @@ TEXTURE1D_DESC :: struct { ArraySize: u32, Format: dxgi.FORMAT, Usage: USAGE, - BindFlags: BIND_FLAG, - CPUAccessFlags: CPU_ACCESS_FLAG, - MiscFlags: RESOURCE_MISC_FLAG, + BindFlags: BIND_FLAGS, + CPUAccessFlags: CPU_ACCESS_FLAGS, + MiscFlags: RESOURCE_MISC_FLAGS, } CTEXTURE1D_DESC :: struct { @@ -1367,9 +1402,9 @@ TEXTURE2D_DESC :: struct { Format: dxgi.FORMAT, SampleDesc: dxgi.SAMPLE_DESC, Usage: USAGE, - BindFlags: BIND_FLAG, - CPUAccessFlags: CPU_ACCESS_FLAG, - MiscFlags: RESOURCE_MISC_FLAG, + BindFlags: BIND_FLAGS, + CPUAccessFlags: CPU_ACCESS_FLAGS, + MiscFlags: RESOURCE_MISC_FLAGS, } CTEXTURE2D_DESC :: struct { @@ -1396,9 +1431,9 @@ TEXTURE3D_DESC :: struct { MipLevels: u32, Format: dxgi.FORMAT, Usage: USAGE, - BindFlags: BIND_FLAG, - CPUAccessFlags: CPU_ACCESS_FLAG, - MiscFlags: RESOURCE_MISC_FLAG, + BindFlags: BIND_FLAGS, + CPUAccessFlags: CPU_ACCESS_FLAGS, + MiscFlags: RESOURCE_MISC_FLAGS, } CTEXTURE3D_DESC :: struct { @@ -1451,14 +1486,15 @@ BUFFER_SRV :: struct { }, } -BUFFEREX_SRV_FLAG :: enum u32 { // TODO: make bit_set - RAW = 0x1, +BUFFEREX_SRV_FLAGS :: distinct bit_set[BUFFEREX_SRV_FLAG; u32] +BUFFEREX_SRV_FLAG :: enum u32 { + RAW = 0, } BUFFEREX_SRV :: struct { FirstElement: u32, NumElements: u32, - Flags: u32, + Flags: BUFFEREX_SRV_FLAGS, } TEX1D_SRV :: struct { @@ -1657,15 +1693,16 @@ TEX2DMS_ARRAY_DSV :: struct { ArraySize: u32, } -DSV_FLAG :: enum u32 { // TODO: make bit_set - DEPTH = 0x1, - STENCIL = 0x2, +DSV_FLAGS :: distinct bit_set[DSV_FLAG; u32] +DSV_FLAG :: enum u32 { + DEPTH = 0, + STENCIL = 1, } DEPTH_STENCIL_VIEW_DESC :: struct { Format: dxgi.FORMAT, ViewDimension: DSV_DIMENSION, - Flags: u32, + Flags: DSV_FLAGS, using _: struct #raw_union { Texture1D: TEX1D_DSV, Texture1DArray: TEX1D_ARRAY_DSV, @@ -1693,16 +1730,17 @@ IDepthStencilView_VTable :: struct { } -BUFFER_UAV_FLAG :: enum u32 { // TODO: make bit_set - RAW = 0x1, - APPEND = 0x2, - COUNTER = 0x4, +BUFFER_UAV_FLAGS :: distinct bit_set[BUFFER_UAV_FLAG; u32] +BUFFER_UAV_FLAG :: enum u32 { + RAW = 0, + APPEND = 1, + COUNTER = 2, } BUFFER_UAV :: struct { FirstElement: u32, NumElements: u32, - Flags: u32, + Flags: BUFFER_UAV_FLAGS, } TEX1D_UAV :: struct { @@ -1961,8 +1999,9 @@ IAsynchronous_VTable :: struct { } -ASYNC_GETDATA_FLAG :: enum u32 { // TODO: make bit_set - DONOTFLUSH = 0x1, +ASYNC_GETDATA_FLAGS :: distinct bit_set[ASYNC_GETDATA_FLAG; u32] +ASYNC_GETDATA_FLAG :: enum u32 { + DONOTFLUSH = 0, } QUERY :: enum i32 { @@ -1984,13 +2023,14 @@ QUERY :: enum i32 { SO_OVERFLOW_PREDICATE_STREAM3 = 15, } -QUERY_MISC_FLAG :: enum u32 { // TODO: make bit_set - QUERY_MISC_PREDICATEHINT = 0x1, +QUERY_MISC_FLAGS :: distinct bit_set[QUERY_MISC_FLAG; u32] +QUERY_MISC_FLAG :: enum u32 { + PREDICATEHINT = 0, } QUERY_DESC :: struct { Query: QUERY, - MiscFlags: RESOURCE_MISC_FLAG, + MiscFlags: QUERY_MISC_FLAGS, } CQUERY_DESC :: struct { @@ -2054,7 +2094,7 @@ COUNTER_TYPE :: enum i32 { COUNTER_DESC :: struct { Counter: COUNTER, - MiscFlags: RESOURCE_MISC_FLAG, + MiscFlags: RESOURCE_MISC_FLAGS, } CCOUNTER_DESC :: struct { @@ -2150,21 +2190,21 @@ FEATURE :: enum i32 { FORMAT_SUPPORT = 2, FORMAT_SUPPORT2 = 3, D3D10_X_HARDWARE_OPTIONS = 4, - OPTIONS = 5, + OPTIONS = 5, ARCHITECTURE_INFO = 6, D3D9_OPTIONS = 7, SHADER_MIN_PRECISION_SUPPORT = 8, D3D9_SHADOW_SUPPORT = 9, - OPTIONS1 = 10, + OPTIONS1 = 10, D3D9_SIMPLE_INSTANCING_SUPPORT = 11, MARKER_SUPPORT = 12, D3D9_OPTIONS1 = 13, - OPTIONS2 = 14, - OPTIONS3 = 15, + OPTIONS2 = 14, + OPTIONS3 = 15, GPU_VIRTUAL_ADDRESS_SUPPORT = 16, - OPTIONS4 = 17, + OPTIONS4 = 17, SHADER_CACHE = 18, - OPTIONS5 = 19, + OPTIONS5 = 19, } FEATURE_DATA_THREADING :: struct { @@ -2285,14 +2325,14 @@ FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT :: struct { MaxGPUVirtualAddressBitsPerProcess: u32, } -SHADER_CACHE_SUPPORT_FLAGS :: enum u32 { // TODO: make bit_set - NONE = 0x0, - AUTOMATIC_INPROC_CACHE = 0x1, - AUTOMATIC_DISK_CACHE = 0x2, +SHADER_CACHE_SUPPORT_FLAGS :: distinct bit_set[SHADER_CACHE_SUPPORT_FLAG; u32] +SHADER_CACHE_SUPPORT_FLAG :: enum u32 { + AUTOMATIC_INPROC_CACHE = 0, + AUTOMATIC_DISK_CACHE = 1, } FEATURE_DATA_SHADER_CACHE :: struct { - SupportFlags: u32, + SupportFlags: SHADER_CACHE_SUPPORT_FLAGS, } SHARED_RESOURCE_TIER :: enum i32 { @@ -2322,7 +2362,7 @@ IDeviceContext_VTable :: struct { VSSetShader: proc "stdcall" (this: ^IDeviceContext, pVertexShader: ^IVertexShader, ppClassInstances: ^^IClassInstance, NumClassInstances: u32), DrawIndexed: proc "stdcall" (this: ^IDeviceContext, IndexCount: u32, StartIndexLocation: u32, BaseVertexLocation: i32), Draw: proc "stdcall" (this: ^IDeviceContext, VertexCount: u32, StartVertexLocation: u32), - Map: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, Subresource: u32, MapType: MAP, MapFlags: u32, pMappedResource: ^MAPPED_SUBRESOURCE) -> HRESULT, + Map: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, Subresource: u32, MapType: MAP, MapFlags: MAP_FLAGS, pMappedResource: ^MAPPED_SUBRESOURCE) -> HRESULT, Unmap: proc "stdcall" (this: ^IDeviceContext, pResource: ^IResource, Subresource: u32), PSSetConstantBuffers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumBuffers: u32, ppConstantBuffers: ^^IBuffer), IASetInputLayout: proc "stdcall" (this: ^IDeviceContext, pInputLayout: ^IInputLayout), @@ -2343,7 +2383,7 @@ IDeviceContext_VTable :: struct { GSSetSamplers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumSamplers: u32, ppSamplers: ^^ISamplerState), OMSetRenderTargets: proc "stdcall" (this: ^IDeviceContext, NumViews: u32, ppRenderTargetViews: ^^IRenderTargetView, pDepthStencilView: ^IDepthStencilView), OMSetRenderTargetsAndUnorderedAccessViews: proc "stdcall" (this: ^IDeviceContext, NumRTVs: u32, ppRenderTargetViews: ^^IRenderTargetView, pDepthStencilView: ^IDepthStencilView, UAVStartSlot: u32, NumUAVs: u32, ppUnorderedAccessViews: ^^IUnorderedAccessView, pUAVInitialCounts: ^u32), - OMSetBlendState: proc "stdcall" (this: ^IDeviceContext, pBlendState: ^IBlendState, BlendFactor: ^[4]f32, SampleMask: u32), + OMSetBlendState: proc "stdcall" (this: ^IDeviceContext, pBlendState: ^IBlendState, BlendFactor: ^[4]f32, SampleMask: COLOR_WRITE_ENABLE_MASK), OMSetDepthStencilState: proc "stdcall" (this: ^IDeviceContext, pDepthStencilState: ^IDepthStencilState, StencilRef: u32), SOSetTargets: proc "stdcall" (this: ^IDeviceContext, NumBuffers: u32, ppSOTargets: ^^IBuffer, pOffsets: ^u32), DrawAuto: proc "stdcall" (this: ^IDeviceContext), @@ -2399,7 +2439,7 @@ IDeviceContext_VTable :: struct { GSGetSamplers: proc "stdcall" (this: ^IDeviceContext, StartSlot: u32, NumSamplers: u32, ppSamplers: ^^ISamplerState), OMGetRenderTargets: proc "stdcall" (this: ^IDeviceContext, NumViews: u32, ppRenderTargetViews: ^^IRenderTargetView, ppDepthStencilView: ^^IDepthStencilView), OMGetRenderTargetsAndUnorderedAccessViews: proc "stdcall" (this: ^IDeviceContext, NumRTVs: u32, ppRenderTargetViews: ^^IRenderTargetView, ppDepthStencilView: ^^IDepthStencilView, UAVStartSlot: u32, NumUAVs: u32, ppUnorderedAccessViews: ^^IUnorderedAccessView), - OMGetBlendState: proc "stdcall" (this: ^IDeviceContext, ppBlendState: ^^IBlendState, BlendFactor: ^[4]f32, pSampleMask: ^u32), + OMGetBlendState: proc "stdcall" (this: ^IDeviceContext, ppBlendState: ^^IBlendState, BlendFactor: ^[4]f32, pSampleMask: ^COLOR_WRITE_ENABLE_MASK), OMGetDepthStencilState: proc "stdcall" (this: ^IDeviceContext, ppDepthStencilState: ^^IDepthStencilState, pStencilRef: ^u32), SOGetTargets: proc "stdcall" (this: ^IDeviceContext, NumBuffers: u32, ppSOTargets: ^^IBuffer), RSGetState: proc "stdcall" (this: ^IDeviceContext, ppRasterizerState: ^^IRasterizerState), @@ -3315,13 +3355,13 @@ IDevice_VTable :: struct { GetCreationFlags: proc "stdcall" (this: ^IDevice) -> u32, GetDeviceRemovedReason: proc "stdcall" (this: ^IDevice) -> HRESULT, GetImmediateContext: proc "stdcall" (this: ^IDevice, ppImmediateContext: ^^IDeviceContext), - SetExceptionMode: proc "stdcall" (this: ^IDevice, RaiseFlags: u32) -> HRESULT, + SetExceptionMode: proc "stdcall" (this: ^IDevice, RaiseFlags: RAISE_FLAGS) -> HRESULT, GetExceptionMode: proc "stdcall" (this: ^IDevice) -> u32, } CREATE_DEVICE_FLAGS :: distinct bit_set[CREATE_DEVICE_FLAG; u32] -CREATE_DEVICE_FLAG :: enum u32 { // TODO: make bit_set +CREATE_DEVICE_FLAG :: enum u32 { SINGLETHREADED = 0, DEBUG = 1, SWITCH_TO_REF = 2, @@ -3367,14 +3407,14 @@ SHADER_BUFFER_DESC :: struct { Type: CBUFFER_TYPE, Variables: u32, Size: u32, - uFlags: u32, + uFlags: SHADER_CBUFFER_FLAGS, } SHADER_VARIABLE_DESC :: struct { Name: cstring, StartOffset: u32, Size: u32, - uFlags: u32, + uFlags: SHADER_VARIABLE_FLAGS, DefaultValue: rawptr, StartTexture: u32, TextureSize: u32, @@ -3443,7 +3483,7 @@ SHADER_INPUT_BIND_DESC :: struct { BindPoint: u32, BindCount: u32, - uFlags: u32, + uFlags: SHADER_INPUT_FLAGS, ReturnType: RESOURCE_RETURN_TYPE, Dimension: SRV_DIMENSION, NumSamples: u32, @@ -3485,7 +3525,7 @@ FUNCTION_DESC :: struct { ConversionInstructionCount: u32, BitwiseInstructionCount: u32, MinFeatureLevel: FEATURE_LEVEL, - RequiredFeatureFlags: u64, + RequiredFeatureFlags: SHADER_REQUIRES_FLAGS, Name: cstring, FunctionParameterCount: i32, @@ -3571,7 +3611,7 @@ IShaderReflection_VTable :: struct { GetNumInterfaceSlots: proc "stdcall" (this: ^IShaderReflection) -> u32, GetMinFeatureLevel: proc "stdcall" (this: ^IShaderReflection, pLevel: ^FEATURE_LEVEL) -> HRESULT, GetThreadGroupSize: proc "stdcall" (this: ^IShaderReflection, pSizeX: ^u32, pSizeY: ^u32, pSizeZ: ^u32) -> u32, - GetRequiresFlags: proc "stdcall" (this: ^IShaderReflection) -> u64, + GetRequiresFlags: proc "stdcall" (this: ^IShaderReflection) -> SHADER_REQUIRES_FLAGS, } @@ -3634,22 +3674,24 @@ IDebug :: struct #raw_union { using id3d11debug_vtable: ^IDebug_VTable, } -RLDO_FLAGS :: enum u32 { // TODO: make bit_set - SUMMARY = 0x1, - DETAIL = 0x2, - IGNORE_INTERNAL = 0x4, +RLDO_FLAGS :: distinct bit_set[RLDO_FLAG; u32] +RLDO_FLAG :: enum u32 { + SUMMARY = 0, + DETAIL = 1, + IGNORE_INTERNAL = 2, } -DEBUG_FEATURE :: enum u32 { // TODO: make bit_set - FLUSH_PER_RENDER_OP = 0x1, - FINISH_PER_RENDER_OP = 0x2, - FEATURE_PRESENT_PER_RENDER_OP = 0x4, +DEBUG_FEATURES :: distinct bit_set[DEBUG_FEATURE; u32] +DEBUG_FEATURE :: enum u32 { + FLUSH_PER_RENDER_OP = 0, + FINISH_PER_RENDER_OP = 1, + FEATURE_PRESENT_PER_RENDER_OP = 2, } IDebug_VTable :: struct { using iunkown_vtable: IUnknown_VTable, - SetFeatureMask: proc "stdcall" (this: ^IDebug, mask: DEBUG_FEATURE) -> HRESULT, - GetFeatureMask: proc "stdcall" (this: ^IDebug) -> DEBUG_FEATURE, + SetFeatureMask: proc "stdcall" (this: ^IDebug, mask: DEBUG_FEATURES) -> HRESULT, + GetFeatureMask: proc "stdcall" (this: ^IDebug) -> DEBUG_FEATURES, SetPresentPerRenderOpDelay: proc "stdcall" (this: ^IDebug, Milliseconds: u32) -> HRESULT, GetPresentPerRenderOpDelay: proc "stdcall" (this: ^IDebug) -> u32, SetSwapChain: proc "stdcall" (this: ^IDebug, pSwapChain: ^dxgi.ISwapChain) -> HRESULT, @@ -3667,7 +3709,7 @@ IInfoQueue :: struct #raw_union { using id3d11infoqueue_vtable: ^IInfoQueue_VTable, } -MESSAGE_SEVERITY :: enum u32 { // TODO: make bit_set +MESSAGE_SEVERITY :: enum u32 { CORRUPTION = 0, ERROR, WARNING, @@ -3675,7 +3717,7 @@ MESSAGE_SEVERITY :: enum u32 { // TODO: make bit_set MESSAGE, // Not supported until D3D 11.1 } -MESSAGE_CATEGORY :: enum u32 { // TODO: make bit_set +MESSAGE_CATEGORY :: enum u32 { APPLICATION_DEFINED = 0, MISCELLANEOUS, INITIALIZATION, @@ -3750,7 +3792,7 @@ IInfoQueue_VTable :: struct { SetMuteDebugOutput: proc "stdcall" (this: ^IInfoQueue, bMute: BOOL), } -MESSAGE_ID :: enum u32 { // TODO: make bit_set +MESSAGE_ID :: enum u32 { UNKNOWN = 0, DEVICE_IASETVERTEXBUFFERS_HAZARD, DEVICE_IASETINDEXBUFFER_HAZARD, From f58f922487cd5b2861b02065bd7f0229facb2199 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Tue, 25 Oct 2022 16:45:38 +0200 Subject: [PATCH 50/56] Detect `which` and complain if not found. --- build_odin.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build_odin.sh b/build_odin.sh index 4d2e461dd..f131e088d 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -134,6 +134,14 @@ run_demo() { ./odin run examples/demo/demo.odin -file } +have_which() { + if ! which which > /dev/null 2>&1; then + panic "Could not find \`which\`" + fi +} + +have_which + case $OS in Linux) config_linux From 43890598344842921760b38da846f3248ecbb0e0 Mon Sep 17 00:00:00 2001 From: nowheredevel <113222579+nowheredevel@users.noreply.github.com> Date: Tue, 25 Oct 2022 19:06:15 -0400 Subject: [PATCH 51/56] Fix printf typo in documentation --- core/fmt/fmt_os.odin | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/fmt/fmt_os.odin b/core/fmt/fmt_os.odin index f5c8d75bd..52280a3f7 100644 --- a/core/fmt/fmt_os.odin +++ b/core/fmt/fmt_os.odin @@ -16,7 +16,7 @@ fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int { w := io.to_writer(os.stream_from_handle(fd)) return wprintln(w=w, args=args, sep=sep) } -// fprintf formats according to the specififed format string and writes to fd +// fprintf formats according to the specified format string and writes to fd fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { w := io.to_writer(os.stream_from_handle(fd)) return wprintf(w, fmt, ..args) @@ -34,12 +34,12 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) { print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) } // println formats using the default print settings and writes to os.stdout println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) } -// printf formats according to the specififed format string and writes to os.stdout +// printf formats according to the specified format string and writes to os.stdout printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) } // eprint formats using the default print settings and writes to os.stderr eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) } // eprintln formats using the default print settings and writes to os.stderr eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) } -// eprintf formats according to the specififed format string and writes to os.stderr +// eprintf formats according to the specified format string and writes to os.stderr eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) } From 7d217269b5b05b10dc45abde1e021dcf5b7eef42 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Oct 2022 13:37:20 +0100 Subject: [PATCH 52/56] Add `Arena_Kind.Buffer` to `core:mem/virtual` --- core/mem/virtual/arena.odin | 51 ++++++++++++++++++++++++++++------- core/mem/virtual/virtual.odin | 4 +++ 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 45426eddc..a93430687 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -3,8 +3,9 @@ package mem_virtual import "core:mem" Arena_Kind :: enum uint { - Growing = 0, // chained memory blocks (singly linked list) - Static = 1, // fixed reservation sized + Growing = 0, // Chained memory blocks (singly linked list). + Static = 1, // Fixed reservation sized. + Buffer = 2, // Uses a fixed sized buffer. } Arena :: struct { @@ -28,9 +29,9 @@ DEFAULT_ARENA_STATIC_RESERVE_SIZE :: 1<<30 when size_of(uintptr) == 8 else 1<<27 @(require_results) arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { - arena.kind = .Growing - arena.curr_block = memory_block_alloc(0, reserved, {}) or_return - arena.total_used = 0 + arena.kind = .Growing + arena.curr_block = memory_block_alloc(0, reserved, {}) or_return + arena.total_used = 0 arena.total_reserved = arena.curr_block.reserved return } @@ -38,8 +39,31 @@ arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING @(require_results) arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = DEFAULT_ARENA_STATIC_COMMIT_SIZE) -> (err: Allocator_Error) { - arena.kind = .Static - arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return + arena.kind = .Static + arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return + arena.total_used = 0 + arena.total_reserved = arena.curr_block.reserved + return +} + +@(require_results) +arena_init_buffer :: proc(arena: ^Arena, buffer: []byte) -> (err: Allocator_Error) { + if len(buffer) < size_of(Memory_Block) { + return .Out_Of_Memory + } + + arena.kind = .Buffer + + mem.zero_slice(buffer) + + block_base := raw_data(buffer) + block := (^Memory_Block)(block_base) + block.base = block_base[size_of(Memory_Block):] + block.reserved = len(buffer) - size_of(Memory_Block) + block.committed = block.reserved + block.used = 0 + + arena.curr_block = block arena.total_used = 0 arena.total_reserved = arena.curr_block.reserved return @@ -80,6 +104,11 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l } arena_init_static(arena=arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return } + fallthrough + case .Buffer: + if arena.curr_block == nil { + return nil, .Out_Of_Memory + } data, err = alloc_from_memory_block(arena.curr_block, size, alignment) arena.total_used = arena.curr_block.used } @@ -88,7 +117,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) -> bool { if arena.curr_block != nil { - assert(arena.kind == .Static, "expected a .Static arena", loc) + assert(arena.kind != .Growing, "expected a non .Growing arena", loc) prev_pos := arena.curr_block.used arena.curr_block.used = clamp(pos, 0, arena.curr_block.reserved) @@ -120,7 +149,7 @@ arena_free_all :: proc(arena: ^Arena) { arena_growing_free_last_memory_block(arena) } arena.total_reserved = 0 - case .Static: + case .Static, .Buffer: arena_static_reset_to(arena, 0) } arena.total_used = 0 @@ -128,7 +157,9 @@ arena_free_all :: proc(arena: ^Arena) { arena_destroy :: proc(arena: ^Arena) { arena_free_all(arena) - memory_block_dealloc(arena.curr_block) + if arena.kind != .Buffer { + memory_block_dealloc(arena.curr_block) + } arena.curr_block = nil arena.total_used = 0 arena.total_reserved = 0 diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index c4a475dba..5e831a0c3 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -128,6 +128,10 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) return nil } + if block == nil { + return nil, .Out_Of_Memory + } + alignment_offset := calc_alignment_offset(block, uintptr(alignment)) size, size_ok := safe_add(min_size, alignment_offset) if !size_ok { From 4003b76fd34325f231418e94ca7f075d15dde733 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Oct 2022 15:00:25 +0100 Subject: [PATCH 53/56] Add `GetSystemTimePreciseAsFileTime` --- core/sys/windows/kernel32.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 05686b7d2..b8049674b 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -248,6 +248,7 @@ foreign kernel32 { GetModuleHandleW :: proc(lpModuleName: LPCWSTR) -> HMODULE --- GetModuleHandleA :: proc(lpModuleName: LPCSTR) -> HMODULE --- GetSystemTimeAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- + GetSystemTimePreciseAsFileTime :: proc(lpSystemTimeAsFileTimeL LPFILETIME) --- CreateEventW :: proc( lpEventAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, From 7743e34596a8a369334d8e6c2ee872800907d6cb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Oct 2022 15:01:35 +0100 Subject: [PATCH 54/56] Fix typo --- core/sys/windows/kernel32.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index b8049674b..304710be2 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -248,7 +248,7 @@ foreign kernel32 { GetModuleHandleW :: proc(lpModuleName: LPCWSTR) -> HMODULE --- GetModuleHandleA :: proc(lpModuleName: LPCSTR) -> HMODULE --- GetSystemTimeAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- - GetSystemTimePreciseAsFileTime :: proc(lpSystemTimeAsFileTimeL LPFILETIME) --- + GetSystemTimePreciseAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- CreateEventW :: proc( lpEventAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, From 7bcde35651619f5990234d3e084dcbfdc8e69db4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Oct 2022 16:05:49 +0100 Subject: [PATCH 55/56] Heavily improve time handling on Windows for `time.now()` and `os.File_Info` --- core/os/dir_windows.odin | 4 +-- core/os/stat_windows.odin | 20 +++++------ core/sys/windows/kernel32.odin | 10 ++++++ core/sys/windows/types.odin | 13 ++++++- core/time/time.odin | 66 +++++++++++++++++----------------- core/time/time_windows.odin | 13 +++++-- 6 files changed, 77 insertions(+), 49 deletions(-) diff --git a/core/os/dir_windows.odin b/core/os/dir_windows.odin index 89a09d403..cf1452abd 100644 --- a/core/os/dir_windows.odin +++ b/core/os/dir_windows.odin @@ -41,9 +41,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F // fi.mode |= file_type_mode(h); } - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) + window_set_file_info_times(&fi, d) fi.is_dir = fi.mode & File_Mode_Dir != 0 return diff --git a/core/os/stat_windows.odin b/core/os/stat_windows.odin index 79bb8c42e..54f8003d6 100644 --- a/core/os/stat_windows.odin +++ b/core/os/stat_windows.odin @@ -228,6 +228,13 @@ file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HAN return } +@(private) +window_set_file_info_times :: proc(fi: ^File_Info, d: ^$T) { + fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) + fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) + fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) +} + @(private) file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string) -> (fi: File_Info, e: Errno) { fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) @@ -235,9 +242,7 @@ file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_ fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) fi.is_dir = fi.mode & File_Mode_Dir != 0 - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) + window_set_file_info_times(&fi, d) fi.fullpath, e = full_path_from_name(name) fi.name = basename(fi.fullpath) @@ -252,9 +257,7 @@ file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string) fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) fi.is_dir = fi.mode & File_Mode_Dir != 0 - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) + window_set_file_info_times(&fi, d) fi.fullpath, e = full_path_from_name(name) fi.name = basename(fi.fullpath) @@ -290,10 +293,7 @@ file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HAN fi.mode |= file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag) fi.is_dir = fi.mode & File_Mode_Dir != 0 - fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) - fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) - fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) - + window_set_file_info_times(&fi, &d) return fi, ERROR_NONE } diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 304710be2..4f7d24ce8 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -249,6 +249,16 @@ foreign kernel32 { GetModuleHandleA :: proc(lpModuleName: LPCSTR) -> HMODULE --- GetSystemTimeAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- GetSystemTimePreciseAsFileTime :: proc(lpSystemTimeAsFileTime: LPFILETIME) --- + FileTimeToSystemTime :: proc(lpFileTime: ^FILETIME, lpSystemTime: ^SYSTEMTIME) -> BOOL --- + SystemTimeToTzSpecificLocalTime :: proc( + lpTimeZoneInformation: ^TIME_ZONE_INFORMATION, + lpUniversalTime: ^SYSTEMTIME, + lpLocalTime: ^SYSTEMTIME, + ) -> BOOL --- + SystemTimeToFileTime :: proc( + lpSystemTime: ^SYSTEMTIME, + lpFileTime: LPFILETIME, + ) -> BOOL --- CreateEventW :: proc( lpEventAttributes: LPSECURITY_ATTRIBUTES, bManualReset: BOOL, diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index af28a9060..62b7d25a7 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -2267,9 +2267,10 @@ FILETIME :: struct { FILETIME_as_unix_nanoseconds :: proc "contextless" (ft: FILETIME) -> i64 { t := i64(u64(ft.dwLowDateTime) | u64(ft.dwHighDateTime) << 32) - return (t - 0x019db1ded53e8000) * 100 + return (t - 116444736000000000) * 100 } + OVERLAPPED :: struct { Internal: ^c_ulong, InternalHigh: ^c_ulong, @@ -2943,6 +2944,16 @@ SYSTEMTIME :: struct { milliseconds: WORD, } +TIME_ZONE_INFORMATION :: struct { + Bias: LONG, + StandardName: [32]WCHAR, + StandardDate: SYSTEMTIME, + StandardBias: LONG, + DaylightName: [32]WCHAR, + DaylightDate: SYSTEMTIME, + DaylightBias: LONG, +} + @(private="file") IMAGE_DOS_HEADER :: struct { diff --git a/core/time/time.odin b/core/time/time.odin index 6c6e47dc0..74c80c8f7 100644 --- a/core/time/time.odin +++ b/core/time/time.odin @@ -17,7 +17,7 @@ MAX_DURATION :: Duration(1<<63 - 1) IS_SUPPORTED :: _IS_SUPPORTED Time :: struct { - _nsec: i64, // zero is 1970-01-01 00:00:00 + _nsec: i64, // Measured in UNIX nanonseconds } Month :: enum int { @@ -59,36 +59,36 @@ sleep :: proc "contextless" (d: Duration) { _sleep(d) } -stopwatch_start :: proc(using stopwatch: ^Stopwatch) { +stopwatch_start :: proc "contextless" (using stopwatch: ^Stopwatch) { if !running { _start_time = tick_now() running = true } } -stopwatch_stop :: proc(using stopwatch: ^Stopwatch) { +stopwatch_stop :: proc "contextless" (using stopwatch: ^Stopwatch) { if running { _accumulation += tick_diff(_start_time, tick_now()) running = false } } -stopwatch_reset :: proc(using stopwatch: ^Stopwatch) { +stopwatch_reset :: proc "contextless" (using stopwatch: ^Stopwatch) { _accumulation = {} running = false } -stopwatch_duration :: proc(using stopwatch: Stopwatch) -> Duration { +stopwatch_duration :: proc "contextless" (using stopwatch: Stopwatch) -> Duration { if !running { return _accumulation } return _accumulation + tick_diff(_start_time, tick_now()) } -diff :: proc(start, end: Time) -> Duration { +diff :: proc "contextless" (start, end: Time) -> Duration { d := end._nsec - start._nsec return Duration(d) } -since :: proc(start: Time) -> Duration { +since :: proc "contextless" (start: Time) -> Duration { return diff(start, now()) } @@ -117,8 +117,8 @@ duration_hours :: proc "contextless" (d: Duration) -> f64 { return f64(hour) + f64(nsec)/(60*60*1e9) } -duration_round :: proc(d, m: Duration) -> Duration { - _less_than_half :: #force_inline proc(x, y: Duration) -> bool { +duration_round :: proc "contextless" (d, m: Duration) -> Duration { + _less_than_half :: #force_inline proc "contextless" (x, y: Duration) -> bool { return u64(x)+u64(x) < u64(y) } @@ -146,45 +146,45 @@ duration_round :: proc(d, m: Duration) -> Duration { return MAX_DURATION } -duration_truncate :: proc(d, m: Duration) -> Duration { +duration_truncate :: proc "contextless" (d, m: Duration) -> Duration { return d if m <= 0 else d - d%m } -date :: proc(t: Time) -> (year: int, month: Month, day: int) { +date :: proc "contextless" (t: Time) -> (year: int, month: Month, day: int) { year, month, day, _ = _abs_date(_time_abs(t), true) return } -year :: proc(t: Time) -> (year: int) { +year :: proc "contextless" (t: Time) -> (year: int) { year, _, _, _ = _date(t, true) return } -month :: proc(t: Time) -> (month: Month) { +month :: proc "contextless" (t: Time) -> (month: Month) { _, month, _, _ = _date(t, true) return } -day :: proc(t: Time) -> (day: int) { +day :: proc "contextless" (t: Time) -> (day: int) { _, _, day, _ = _date(t, true) return } clock :: proc { clock_from_time, clock_from_duration, clock_from_stopwatch } -clock_from_time :: proc(t: Time) -> (hour, min, sec: int) { +clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) { return clock_from_seconds(_time_abs(t)) } -clock_from_duration :: proc(d: Duration) -> (hour, min, sec: int) { +clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, sec: int) { return clock_from_seconds(u64(d/1e9)) } -clock_from_stopwatch :: proc(s: Stopwatch) -> (hour, min, sec: int) { +clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, sec: int) { return clock_from_duration(stopwatch_duration(s)) } -clock_from_seconds :: proc(nsec: u64) -> (hour, min, sec: int) { +clock_from_seconds :: proc "contextless" (nsec: u64) -> (hour, min, sec: int) { sec = int(nsec % SECONDS_PER_DAY) hour = sec / SECONDS_PER_HOUR sec -= hour * SECONDS_PER_HOUR @@ -193,11 +193,11 @@ clock_from_seconds :: proc(nsec: u64) -> (hour, min, sec: int) { return } -read_cycle_counter :: proc() -> u64 { +read_cycle_counter :: proc "contextless" () -> u64 { return u64(intrinsics.read_cycle_counter()) } -unix :: proc(sec: i64, nsec: i64) -> Time { +unix :: proc "contextless" (sec: i64, nsec: i64) -> Time { sec, nsec := sec, nsec if nsec < 0 || nsec >= 1e9 { n := nsec / 1e9 @@ -208,20 +208,20 @@ unix :: proc(sec: i64, nsec: i64) -> Time { sec -= 1 } } - return Time{(sec*1e9 + nsec) + UNIX_TO_INTERNAL} + return Time{(sec*1e9 + nsec)} } to_unix_seconds :: time_to_unix -time_to_unix :: proc(t: Time) -> i64 { +time_to_unix :: proc "contextless" (t: Time) -> i64 { return t._nsec/1e9 } to_unix_nanoseconds :: time_to_unix_nano -time_to_unix_nano :: proc(t: Time) -> i64 { +time_to_unix_nano :: proc "contextless" (t: Time) -> i64 { return t._nsec } -time_add :: proc(t: Time, d: Duration) -> Time { +time_add :: proc "contextless" (t: Time, d: Duration) -> Time { return Time{t._nsec + i64(d)} } @@ -231,7 +231,7 @@ time_add :: proc(t: Time, d: Duration) -> Time { // On Windows it depends but is comparable with regular sleep in the worst case. // To get the same kind of accuracy as on Linux, have your program call `win32.time_begin_period(1)` to // tell Windows to use a more accurate timer for your process. -accurate_sleep :: proc(d: Duration) { +accurate_sleep :: proc "contextless" (d: Duration) { to_sleep, estimate, mean, m2, count: Duration to_sleep = d @@ -279,19 +279,19 @@ ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE @(private) -_date :: proc(t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) { +_date :: proc "contextless" (t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) { year, month, day, yday = _abs_date(_time_abs(t), full) return } @(private) -_time_abs :: proc(t: Time) -> u64 { +_time_abs :: proc "contextless" (t: Time) -> u64 { return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE) } @(private) -_abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) { - _is_leap_year :: proc(year: int) -> bool { +_abs_date :: proc "contextless" (abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) { + _is_leap_year :: proc "contextless" (year: int) -> bool { return year%4 == 0 && (year%100 != 0 || year%400 == 0) } @@ -352,9 +352,11 @@ _abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, y return } -datetime_to_time :: proc(year, month, day, hour, minute, second: int, nsec := int(0)) -> (t: Time, ok: bool) { - divmod :: proc(year: int, divisor: int) -> (div: int, mod: int) { - assert(divisor > 0) +datetime_to_time :: proc "contextless" (year, month, day, hour, minute, second: int, nsec := int(0)) -> (t: Time, ok: bool) { + divmod :: proc "contextless" (year: int, divisor: int) -> (div: int, mod: int) { + if divisor <= 0 { + intrinsics.debug_trap() + } div = int(year / divisor) mod = year % divisor return diff --git a/core/time/time_windows.odin b/core/time/time_windows.odin index 20863c323..378b914b0 100644 --- a/core/time/time_windows.odin +++ b/core/time/time_windows.odin @@ -7,9 +7,16 @@ _IS_SUPPORTED :: true _now :: proc "contextless" () -> Time { file_time: win32.FILETIME - win32.GetSystemTimeAsFileTime(&file_time) - ns := win32.FILETIME_as_unix_nanoseconds(file_time) - return Time{_nsec=ns} + + ns: i64 + + // monotonic + win32.GetSystemTimePreciseAsFileTime(&file_time) + + dt := u64(transmute(u64le)file_time) // in 100ns units + ns = i64((dt - 116444736000000000) * 100) // convert to ns + + return unix(0, ns) } _sleep :: proc "contextless" (d: Duration) { From 62ab2987b608b2320c93675d34410c9a59bb578a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Oct 2022 16:08:49 +0100 Subject: [PATCH 56/56] Change name to `windows_set_file_info_times` --- core/os/dir_windows.odin | 3 +-- core/os/stat_windows.odin | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/core/os/dir_windows.odin b/core/os/dir_windows.odin index cf1452abd..9333548cf 100644 --- a/core/os/dir_windows.odin +++ b/core/os/dir_windows.odin @@ -2,7 +2,6 @@ package os import win32 "core:sys/windows" import "core:strings" -import "core:time" read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) { find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) { @@ -41,7 +40,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F // fi.mode |= file_type_mode(h); } - window_set_file_info_times(&fi, d) + windows_set_file_info_times(&fi, d) fi.is_dir = fi.mode & File_Mode_Dir != 0 return diff --git a/core/os/stat_windows.odin b/core/os/stat_windows.odin index 54f8003d6..c63fb4cf0 100644 --- a/core/os/stat_windows.odin +++ b/core/os/stat_windows.odin @@ -229,7 +229,7 @@ file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HAN } @(private) -window_set_file_info_times :: proc(fi: ^File_Info, d: ^$T) { +windows_set_file_info_times :: proc(fi: ^File_Info, d: ^$T) { fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) @@ -242,7 +242,7 @@ file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_ fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) fi.is_dir = fi.mode & File_Mode_Dir != 0 - window_set_file_info_times(&fi, d) + windows_set_file_info_times(&fi, d) fi.fullpath, e = full_path_from_name(name) fi.name = basename(fi.fullpath) @@ -257,7 +257,7 @@ file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string) fi.mode |= file_mode_from_file_attributes(d.dwFileAttributes, nil, 0) fi.is_dir = fi.mode & File_Mode_Dir != 0 - window_set_file_info_times(&fi, d) + windows_set_file_info_times(&fi, d) fi.fullpath, e = full_path_from_name(name) fi.name = basename(fi.fullpath) @@ -293,7 +293,7 @@ file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HAN fi.mode |= file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag) fi.is_dir = fi.mode & File_Mode_Dir != 0 - window_set_file_info_times(&fi, &d) + windows_set_file_info_times(&fi, &d) return fi, ERROR_NONE }