diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-10-07 00:46:05 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-10-07 00:46:05 -0700 |
| commit | b5a36f676b1fd69f195d9f1eb6e35f3eb2f15946 (patch) | |
| tree | 92ce1ffa64bc2d32d5ef73dce66daf3c8e893ee6 /lib | |
| parent | d6d05fc84d33c71434a1f8bae51ca5956e08cdf0 (diff) | |
| parent | f2d374e8465042fa5cb6bf2be7b9b086948f3a94 (diff) | |
| download | zig-b5a36f676b1fd69f195d9f1eb6e35f3eb2f15946.tar.gz zig-b5a36f676b1fd69f195d9f1eb6e35f3eb2f15946.zip | |
Merge remote-tracking branch 'origin/master' into llvm11
Conflicts:
cmake/Findllvm.cmake
The llvm11 branch changed 10's to 11's and master branch added the
"using LLVM_CONFIG_EXE" help message, so the resolution was to merge
these changes together.
I also added a check to make sure LLVM is built with AVR enabled, which
is no longer an experimental target.
Diffstat (limited to 'lib')
30 files changed, 2570 insertions, 294 deletions
diff --git a/lib/libc/mingw/lib32/user32.def b/lib/libc/mingw/lib32/user32.def new file mode 100644 index 0000000000..c20d16835a --- /dev/null +++ b/lib/libc/mingw/lib32/user32.def @@ -0,0 +1,998 @@ +LIBRARY USER32.dll +EXPORTS +;ord_1500@16 @1500 +;ord_1501@4 @1501 +;ord_1502@12 @1502 +ActivateKeyboardLayout@8 +AddClipboardFormatListener@4 +AdjustWindowRect@12 +AdjustWindowRectEx@16 +AlignRects@16 +AllowForegroundActivation@0 +AllowSetForegroundWindow@4 +AnimateWindow@12 +AnyPopup@0 +AppendMenuA@16 +AppendMenuW@16 +ArrangeIconicWindows@4 +AttachThreadInput@12 +BeginDeferWindowPos@4 +BeginPaint@8 +BlockInput@4 +BringWindowToTop@4 +BroadcastSystemMessage@20 +BroadcastSystemMessageA@20 +BroadcastSystemMessageExA@24 +BroadcastSystemMessageExW@24 +BroadcastSystemMessageW@20 +BuildReasonArray@12 +CalcChildScroll@8 +CalcMenuBar@20 +CalculatePopupWindowPosition@20 +CallMsgFilter@8 +CallMsgFilterA@8 +CallMsgFilterW@8 +CallNextHookEx@16 +CallWindowProcA@20 +CallWindowProcW@20 +CancelShutdown@0 +CascadeChildWindows@8 +CascadeWindows@20 +ChangeClipboardChain@8 +ChangeDisplaySettingsA@8 +ChangeDisplaySettingsExA@20 +ChangeDisplaySettingsExW@20 +ChangeDisplaySettingsW@8 +ChangeMenuA@20 +ChangeMenuW@20 +ChangeWindowMessageFilter@8 +ChangeWindowMessageFilterEx@16 +CharLowerA@4 +CharLowerBuffA@8 +CharLowerBuffW@8 +CharLowerW@4 +CharNextA@4 +;ord_1550@12 @1550 +;ord_1551@8 @1551 +;ord_1552@8 @1552 +;ord_1553@12 @1553 +;ord_1554@8 @1554 +;ord_1555@16 @1555 +;ord_1556@4 @1556 +CharNextExA@12 +CharNextW@4 +CharPrevA@8 +CharPrevExA@16 +CharPrevW@8 +CharToOemA@8 +CharToOemBuffA@12 +CharToOemBuffW@12 +CharToOemW@8 +CharUpperA@4 +CharUpperBuffA@8 +CharUpperBuffW@8 +CharUpperW@4 +CheckDesktopByThreadId@4 +CheckDBCSEnabledExt@0 +CheckDlgButton@12 +CheckMenuItem@12 +CheckMenuRadioItem@20 +CheckProcessForClipboardAccess@8 +CheckProcessSession@4 +CheckRadioButton@16 +CheckWindowThreadDesktop@8 +ChildWindowFromPoint@12 +ChildWindowFromPointEx@16 +CliImmSetHotKey@16 +ClientThreadSetup@0 +ClientToScreen@8 +ClipCursor@4 +CloseClipboard@0 +CloseDesktop@4 +CloseGestureInfoHandle@4 +CloseTouchInputHandle@4 +CloseWindow@4 +CloseWindowStation@4 +ConsoleControl@12 +ControlMagnification@8 +CopyAcceleratorTableA@12 +CopyAcceleratorTableW@12 +CopyIcon@4 +CopyImage@20 +CopyRect@8 +CountClipboardFormats@0 +CreateAcceleratorTableA@8 +CreateAcceleratorTableW@8 +CreateCaret@16 +CreateCursor@28 +CreateDCompositionHwndTarget@12 +CreateDesktopA@24 +CreateDesktopExA@32 +CreateDesktopExW@32 +CreateDesktopW@24 +CreateDialogIndirectParamA@20 +CreateDialogIndirectParamAorW@24 +CreateDialogIndirectParamW@20 +CreateDialogParamA@20 +CreateDialogParamW@20 +CreateIcon@28 +CreateIconFromResource@16 +CreateIconFromResourceEx@28 +CreateIconIndirect@4 +CreateMDIWindowA@40 +CreateMDIWindowW@40 +CreateMenu@0 +CreatePopupMenu@0 +CreateSystemThreads@16 ; ReactOS has the @8 variant +CreateWindowExA@48 +CreateWindowExW@48 +CreateWindowInBand@52 +CreateWindowIndirect@4 +CreateWindowStationA@16 +CreateWindowStationW@16 +CsrBroadcastSystemMessageExW@24 +CtxInitUser32@0 +DdeAbandonTransaction@12 +DdeAccessData@8 +DdeAddData@16 +DdeClientTransaction@32 +DdeCmpStringHandles@8 +DdeConnect@16 +DdeConnectList@20 +DdeCreateDataHandle@28 +DdeCreateStringHandleA@12 +DdeCreateStringHandleW@12 +DdeDisconnect@4 +DdeDisconnectList@4 +DdeEnableCallback@12 +DdeFreeDataHandle@4 +DdeFreeStringHandle@8 +DdeGetData@16 +DdeGetLastError@4 +DdeGetQualityOfService@12 +DdeImpersonateClient@4 +DdeInitializeA@16 +DdeInitializeW@16 +DdeKeepStringHandle@8 +DdeNameService@16 +DdePostAdvise@12 +DdeQueryConvInfo@12 +DdeQueryNextServer@8 +DdeQueryStringA@20 +DdeQueryStringW@20 +DdeReconnect@4 +DdeSetQualityOfService@12 +DdeSetUserHandle@12 +DdeUnaccessData@4 +DdeUninitialize@4 +DefDlgProcA@16 +DefDlgProcW@16 +DefFrameProcA@20 +DefFrameProcW@20 +DefMDIChildProcA@16 +DefMDIChildProcW@16 +DefRawInputProc@12 +DefWindowProcA@16 +DefWindowProcW@16 +DeferWindowPos@32 +DeferWindowPosAndBand@36 +DeleteMenu@12 +DeregisterShellHookWindow@4 +DestroyAcceleratorTable@4 +DestroyCaret@0 +DestroyCursor@4 +DestroyDCompositionHwndTarget@8 +DestroyIcon@4 +DestroyMenu@4 +DestroyReasons@4 +DestroyWindow@4 +DeviceEventWorker@24 ; No documentation whatsoever, ReactOS has a stub with @20 - https://www.reactos.org/archives/public/ros-diffs/2011-February/040308.html +DialogBoxIndirectParamA@20 +DialogBoxIndirectParamAorW@24 +DialogBoxIndirectParamW@20 +DialogBoxParamA@20 +DialogBoxParamW@20 +DisableProcessWindowsGhosting@0 +DispatchMessageA@4 +DispatchMessageW@4 +DisplayConfigGetDeviceInfo@4 +DisplayConfigSetDeviceInfo@4 +DisplayExitWindowsWarnings@4 +DlgDirListA@20 +DlgDirListComboBoxA@20 +DlgDirListComboBoxW@20 +DlgDirListW@20 +DlgDirSelectComboBoxExA@16 +DlgDirSelectComboBoxExW@16 +DlgDirSelectExA@16 +DlgDirSelectExW@16 +DoSoundConnect@0 +DoSoundDisconnect@0 +DragDetect@12 +DragObject@20 +DrawAnimatedRects@16 +DrawCaption@16 +DrawCaptionTempA@28 +DrawCaptionTempW@28 +DrawEdge@16 +DrawFocusRect@8 +DrawFrame@16 +DrawFrameControl@16 +DrawIcon@16 +DrawIconEx@36 +DrawMenuBar@4 +DrawMenuBarTemp@20 +DrawStateA@40 +DrawStateW@40 +DrawTextA@20 +DrawTextExA@24 +DrawTextExW@24 +DrawTextW@20 +DwmGetDxSharedSurface@24 +DwmGetRemoteSessionOcclusionEvent@0 +DwmGetRemoteSessionOcclusionState@0 +DwmLockScreenUpdates@4 +DwmStartRedirection@8 ; Mentioned on http://habrahabr.ru/post/145174/ , enables GDI virtualization (for security purposes) +DwmStopRedirection@0 +DwmValidateWindow@8 +EditWndProc@16 +EmptyClipboard@0 +EnableMenuItem@12 +EnableMouseInPointer@4 +EnableScrollBar@12 +EnableSessionForMMCSS@4 +EnableWindow@8 +EndDeferWindowPos@4 +EndDeferWindowPosEx@8 +EndDialog@8 +EndMenu@0 +EndPaint@8 +EndTask@12 +EnterReaderModeHelper@4 +EnumChildWindows@12 +EnumClipboardFormats@4 +EnumDesktopWindows@12 +EnumDesktopsA@12 +EnumDesktopsW@12 +EnumDisplayDevicesA@16 +EnumDisplayDevicesW@16 +EnumDisplayMonitors@16 +EnumDisplaySettingsA@12 +EnumDisplaySettingsExA@16 +EnumDisplaySettingsExW@16 +EnumDisplaySettingsW@12 +EnumPropsA@8 +EnumPropsExA@12 +EnumPropsExW@12 +EnumPropsW@8 +EnumThreadWindows@12 +EnumWindowStationsA@8 +EnumWindowStationsW@8 +EnumWindows@8 +EqualRect@8 +EvaluateProximityToPolygon@16 +EvaluateProximityToRect@12 +ExcludeUpdateRgn@8 +ExitWindowsEx@8 +FillRect@12 +FindWindowA@8 +FindWindowExA@16 +FindWindowExW@16 +FindWindowW@8 +FlashWindow@8 +FlashWindowEx@4 +FrameRect@12 +FreeDDElParam@8 +FrostCrashedWindow@8 +GetActiveWindow@0 +GetAltTabInfo@20 +GetAltTabInfoA@20 +GetAltTabInfoW@20 +GetAncestor@8 +GetAppCompatFlags2@4 +GetAppCompatFlags@8 ; ReactOS has @4 version http://doxygen.reactos.org/d9/d71/undocuser_8h_a9b76cdc68c523a061c86a40367049ed2.html +GetAsyncKeyState@4 +GetAutoRotationState@4 +GetCIMSSM@4 +GetCapture@0 +GetCaretBlinkTime@0 +GetCaretPos@4 +GetClassInfoA@12 +GetClassInfoExA@12 +GetClassInfoExW@12 +GetClassInfoW@12 +GetClassLongA@8 +GetClassLongW@8 +GetClassNameA@12 +GetClassNameW@12 +GetClassWord@8 +GetClientRect@8 +GetClipCursor@4 +GetClipboardAccessToken@8 +GetClipboardData@4 +GetClipboardFormatNameA@12 +GetClipboardFormatNameW@12 +GetClipboardOwner@0 +GetClipboardSequenceNumber@0 +GetClipboardViewer@0 +GetComboBoxInfo@8 +GetCurrentInputMessageSource@4 +GetCursor@0 +GetCursorFrameInfo@20 +GetCursorInfo@4 +GetCursorPos@4 +GetDC@4 +GetDCEx@12 +GetDesktopID@8 +GetDesktopWindow@0 +GetDialogBaseUnits@0 +GetDisplayAutoRotationPreferences@4 +GetDisplayConfigBufferSizes@12 +GetDlgCtrlID@4 +GetDlgItem@8 +GetDlgItemInt@16 +GetDlgItemTextA@16 +GetDlgItemTextW@16 +GetDoubleClickTime@0 +GetDpiForMonitorInternal@16 +GetFocus@0 +GetForegroundWindow@0 +GetGUIThreadInfo@8 +GetGestureConfig@24 +GetGestureExtraArgs@12 +GetGestureInfo@8 +GetGuiResources@8 +GetIconInfo@8 +GetIconInfoExA@8 +GetIconInfoExW@8 +GetInputDesktop@0 +GetInputLocaleInfo@8 +GetInputState@0 +GetInternalWindowPos@12 +GetKBCodePage@0 +GetKeyNameTextA@12 +GetKeyNameTextW@12 +GetKeyState@4 +GetKeyboardLayout@4 +GetKeyboardLayoutList@8 +GetKeyboardLayoutNameA@4 +GetKeyboardLayoutNameW@4 +GetKeyboardState@4 +GetKeyboardType@4 +GetLastActivePopup@4 +GetLastInputInfo@4 +GetLayeredWindowAttributes@16 +GetListBoxInfo@4 +GetMagnificationDesktopColorEffect@4 +GetMagnificationDesktopMagnification@12 +GetMagnificationLensCtxInformation@16 +GetMenu@4 +GetMenuBarInfo@16 +GetMenuCheckMarkDimensions@0 +GetMenuContextHelpId@4 +GetMenuDefaultItem@12 +GetMenuInfo@8 +GetMenuItemCount@4 +GetMenuItemID@8 +GetMenuItemInfoA@16 +GetMenuItemInfoW@16 +GetMenuItemRect@16 +GetMenuState@12 +GetMenuStringA@20 +GetMenuStringW@20 +GetMessageA@16 +GetMessageExtraInfo@0 +GetMessagePos@0 +GetMessageTime@0 +GetMessageW@16 +GetMonitorInfoA@8 +GetMonitorInfoW@8 +GetMouseMovePointsEx@20 +GetNextDlgGroupItem@12 +GetNextDlgTabItem@12 +GetOpenClipboardWindow@0 +GetParent@4 +GetPhysicalCursorPos@4 +GetPointerCursorId@8 +GetPointerDevice@8 +GetPointerDeviceCursors@12 +GetPointerDeviceProperties@12 +GetPointerDeviceRects@12 +GetPointerDevices@8 +GetPointerFrameInfo@12 +GetPointerFrameInfoHistory@16 +GetPointerFramePenInfo@12 +GetPointerFramePenInfoHistory@16 +GetPointerFrameTouchInfo@12 +GetPointerFrameTouchInfoHistory@16 +GetPointerInfo@8 +GetPointerInfoHistory@12 +GetPointerInputTransform@12 +GetPointerPenInfo@8 +GetPointerPenInfoHistory@12 +GetPointerTouchInfo@8 +GetPointerTouchInfoHistory@12 +GetPointerType@8 +GetPriorityClipboardFormat@8 +GetProcessDefaultLayout@4 +GetProcessDpiAwarenessInternal@8 +GetProcessWindowStation@0 +GetProgmanWindow@0 +GetPropA@8 +GetPropW@8 +GetQueueStatus@4 +GetRawInputBuffer@12 +GetRawInputData@20 +GetRawInputDeviceInfoA@16 +GetRawInputDeviceInfoW@16 +GetRawInputDeviceList@12 +GetRawPointerDeviceData@20 +GetReasonTitleFromReasonCode@12 +GetRegisteredRawInputDevices@12 +GetQueueStatus@4 +GetScrollBarInfo@12 +GetScrollInfo@12 +GetScrollPos@8 +GetScrollRange@16 +GetSendMessageReceiver@4 +GetShellWindow@0 +GetSubMenu@8 +GetSysColor@4 +GetSysColorBrush@4 +GetSystemMenu@8 +GetSystemMetrics@4 +GetTabbedTextExtentA@20 +GetTabbedTextExtentW@20 +GetTaskmanWindow@0 +GetThreadDesktop@4 +GetTitleBarInfo@8 +GetTopLevelWindow@4 +GetTopWindow@4 +GetTouchInputInfo@16 +GetUnpredictedMessagePos@0 +GetUpdateRect@12 +GetUpdateRgn@12 +GetUpdatedClipboardFormats@12 +GetUserObjectInformationA@20 +GetUserObjectInformationW@20 +GetUserObjectSecurity@20 +GetWinStationInfo@4 +GetWindow@8 +GetWindowBand@8 +GetWindowCompositionAttribute@8 +GetWindowCompositionInfo@8 +GetWindowContextHelpId@4 +GetWindowDC@4 +GetWindowDisplayAffinity@8 +GetWindowFeedbackSetting@20 +GetWindowInfo@8 +GetWindowLongA@8 +GetWindowLongW@8 +GetWindowMinimizeRect@8 +GetWindowModuleFileName@12 +GetWindowModuleFileNameA@12 +GetWindowModuleFileNameW@12 +GetWindowPlacement@8 +GetWindowRect@8 +GetWindowRgn@8 +GetWindowRgnBox@8 +GetWindowRgnEx@12 +GetWindowTextA@12 +GetWindowTextLengthA@4 +GetWindowTextLengthW@4 +GetWindowTextW@12 +GetWindowThreadProcessId@8 +GetWindowWord@8 +GhostWindowFromHungWindow@4 +GrayStringA@36 +GrayStringW@36 +HideCaret@4 +HiliteMenuItem@16 +HungWindowFromGhostWindow@4 +IMPGetIMEA@8 +IMPGetIMEW@8 +IMPQueryIMEA@4 +IMPQueryIMEW@4 +IMPSetIMEA@8 +IMPSetIMEW@8 +ImpersonateDdeClientWindow@8 +InSendMessage@0 +InSendMessageEx@4 +InflateRect@12 +InitializeLpkHooks@4 +InitializeWin32EntryTable@4 +InitializeTouchInjection@8 +InjectTouchInput@8 +InsertMenuA@20 +InsertMenuItemA@16 +InsertMenuItemW@16 +InsertMenuW@20 +InternalGetWindowIcon@8 +;ord_2001@4 @2001 +;ord_2002@4 @2002 +InternalGetWindowText@12 +IntersectRect@12 +;ord_2005@4 @2005 +InvalidateRect@12 +InvalidateRgn@12 +InvertRect@8 +IsCharAlphaA@4 +;ord_2010@16 @2010 +IsCharAlphaNumericA@4 +IsCharAlphaNumericW@4 +IsCharAlphaW@4 +IsCharLowerA@4 +IsCharLowerW@4 +IsCharUpperA@4 +IsCharUpperW@4 +IsChild@8 +IsClipboardFormatAvailable@4 +IsDialogMessage@8 +IsDialogMessageA@8 +IsDialogMessageW@8 +IsDlgButtonChecked@8 +IsGUIThread@4 +IsHungAppWindow@4 +IsIconic@4 +IsImmersiveProcess@4 +IsInDesktopWindowBand@4 +IsMenu@4 +IsProcess16Bit@0 +IsMouseInPointerEnabled@0 +IsProcessDPIAware@0 +IsQueueAttached@0 +IsRectEmpty@4 +IsSETEnabled@0 +IsServerSideWindow@4 +IsThreadDesktopComposited@0 +IsTopLevelWindow@4 +IsTouchWindow@8 +IsWinEventHookInstalled@4 +IsWindow@4 +IsWindowEnabled@4 +IsWindowInDestroy@4 +IsWindowRedirectedForPrint@4 +IsWindowUnicode@4 +IsWindowVisible@4 +IsWow64Message@0 +IsZoomed@4 +KillSystemTimer@8 +KillTimer@8 +LoadAcceleratorsA@8 +LoadAcceleratorsW@8 +LoadBitmapA@8 +LoadBitmapW@8 +LoadCursorA@8 +LoadCursorFromFileA@4 +LoadCursorFromFileW@4 +;ord_2000@0 @2000 +;ord_2001@4 @2001 +;ord_2002@4 @2002 +LoadCursorW@8 +LoadIconA@8 +;ord_2005@4 @2005 +LoadIconW@8 +LoadImageA@24 +LoadImageW@24 +LoadKeyboardLayoutA@8 +LoadKeyboardLayoutEx@12 +LoadKeyboardLayoutW@8 +LoadLocalFonts@0 +LoadMenuA@8 +LoadMenuIndirectA@4 +LoadMenuIndirectW@4 +LoadMenuW@8 +LoadRemoteFonts@0 +LoadStringA@16 +LoadStringW@16 +LockSetForegroundWindow@4 +LockWindowStation@4 +LockWindowUpdate@4 +LockWorkStation@0 +LogicalToPhysicalPoint@8 +LogicalToPhysicalPointForPerMonitorDPI@8 +LookupIconIdFromDirectory@8 +LookupIconIdFromDirectoryEx@20 +MBToWCSEx@24 +MBToWCSExt@20 +MB_GetString@4 +MapDialogRect@8 +MapVirtualKeyA@8 +MapVirtualKeyExA@12 +MapVirtualKeyExW@12 +MapVirtualKeyW@8 +MapWindowPoints@16 +MenuItemFromPoint@16 +MenuWindowProcA@20 +MenuWindowProcW@20 +MessageBeep@4 +MessageBoxA@16 +MessageBoxExA@20 +MessageBoxExW@20 +MessageBoxIndirectA@4 +MessageBoxIndirectW@4 +MessageBoxTimeoutA@24 +MessageBoxTimeoutW@24 +MessageBoxW@16 +ModifyMenuA@20 +ModifyMenuW@20 +MonitorFromPoint@12 +MonitorFromRect@8 +MonitorFromWindow@8 +MoveWindow@24 +MsgWaitForMultipleObjects@20 +MsgWaitForMultipleObjectsEx@20 +NotifyOverlayWindow@8 +NotifyWinEvent@16 +OemKeyScan@4 +OemToCharA@8 +OemToCharBuffA@12 +OemToCharBuffW@12 +OemToCharW@8 +OffsetRect@12 +OpenClipboard@4 +OpenDesktopA@16 +OpenDesktopW@16 +OpenIcon@4 +OpenInputDesktop@12 +OpenThreadDesktop@16 +OpenWindowStationA@12 +OpenWindowStationW@12 +PackDDElParam@12 +PackTouchHitTestingProximityEvaluation@8 +PaintDesktop@4 +PaintMenuBar@24 +PaintMonitor@12 +PeekMessageA@20 +PeekMessageW@20 +PhysicalToLogicalPoint@8 +PhysicalToLogicalPointForPerMonitorDPI@8 +PostMessageA@16 +PostMessageW@16 +PostQuitMessage@4 +PostThreadMessageA@16 +PostThreadMessageW@16 +PrintWindow@12 +PrivateExtractIconExA@20 +PrivateExtractIconExW@20 +PrivateExtractIconsA@32 +PrivateExtractIconsW@32 +PrivateSetDbgTag@8 +PrivateSetRipFlags@8 +PrivateRegisterICSProc@4 +PtInRect@12 +QueryBSDRWindow@0 +QueryDisplayConfig@24 +QuerySendMessage@4 +QueryUserCounters@20 +RealChildWindowFromPoint@12 +RealGetWindowClass@12 +RealGetWindowClassA@12 +RealGetWindowClassW@12 +ReasonCodeNeedsBugID@4 +ReasonCodeNeedsComment@4 +RecordShutdownReason@4 +RedrawWindow@16 +RegisterBSDRWindow@8 +RegisterClassA@4 +RegisterClassExA@4 +RegisterClassExW@4 +RegisterClassW@4 +RegisterClipboardFormatA@4 +RegisterClipboardFormatW@4 +RegisterDeviceNotificationA@12 +RegisterDeviceNotificationW@12 +RegisterErrorReportingDialog@8 +RegisterFrostWindow@8 +RegisterGhostWindow@8 +RegisterHotKey@16 +RegisterPowerSettingNotification@12 +RegisterLogonProcess@8 +RegisterMessagePumpHook@4 +RegisterPointerDeviceNotifications@8 +RegisterPointerInputTarget@8 +RegisterPowerSettingNotification@12 +RegisterRawInputDevices@12 +RegisterServicesProcess@4 +RegisterSessionPort@4 ; Undocumented, rumored to be related to ALPC - http://blogs.msdn.com/b/ntdebugging/archive/2007/07/26/lpc-local-procedure-calls-part-1-architecture.aspx +RegisterShellHookWindow@4 +RegisterSuspendResumeNotification@8 +RegisterSystemThread@8 +RegisterTasklist@4 +RegisterTouchHitTestingWindow@8 +RegisterTouchWindow@8 +RegisterUserApiHook@4 ; Prototype changed in 2003 - https://www.reactos.org/wiki/Techwiki:RegisterUserApiHook +RegisterWindowMessageA@4 +RegisterWindowMessageW@4 +ReleaseCapture@0 +ReleaseDC@8 +RemoveClipboardFormatListener@4 +RemoveMenu@12 +RemovePropA@8 +RemovePropW@8 +ReplyMessage@4 +ResolveDesktopForWOW@4 +ReuseDDElParam@20 +ScreenToClient@8 +ScrollChildren@12 +ScrollDC@28 +ScrollWindow@20 +ScrollWindowEx@32 +SendDlgItemMessageA@20 +SendDlgItemMessageW@20 +SendIMEMessageExA@8 +SendIMEMessageExW@8 +SendInput@12 +SendMessageA@16 +SendMessageCallbackA@24 +SendMessageCallbackW@24 +SendMessageTimeoutA@28 +SendMessageTimeoutW@28 +SendMessageW@16 +SendNotifyMessageA@16 +SendNotifyMessageW@16 +SetActiveWindow@4 +SetCapture@4 +SetCaretBlinkTime@4 +SetCaretPos@8 +SetClassLongA@12 +SetClassLongW@12 +SetClassWord@12 +SetClipboardData@8 +SetClipboardViewer@4 +SetConsoleReserveKeys@8 +SetCoalescableTimer@20 +SetCursor@4 +SetCursorContents@8 +SetCursorPos@8 +SetDebugErrorLevel@4 +SetDeskWallpaper@4 +SetDisplayAutoRotationPreferences@4 +SetDisplayConfig@20 +SetDlgItemInt@16 +SetDlgItemTextA@12 +SetDlgItemTextW@12 +SetDoubleClickTime@4 +SetFocus@4 +SetForegroundWindow@4 +SetGestureConfig@20 +SetImmersiveBackgroundWindow@4 +SetInternalWindowPos@16 +SetKeyboardState@4 +SetLastErrorEx@8 +SetLayeredWindowAttributes@16 +SetLogonNotifyWindow@4 +SetMagnificationDesktopColorEffect@4 +SetMagnificationDesktopMagnification@16 +SetMagnificationLensCtxInformation@16 +SetMenu@8 +SetMenuContextHelpId@8 +SetMenuDefaultItem@12 +SetMenuInfo@8 +SetMenuItemBitmaps@20 +SetMenuItemInfoA@16 +SetMenuItemInfoW@16 +SetMessageExtraInfo@4 +SetMessageQueue@4 +SetMirrorRendering@8 +SetParent@8 +SetPhysicalCursorPos@8 +SetProcessDPIAware@0 +SetProcessDefaultLayout@4 +SetProcessDpiAwarenessInternal@4 +SetProcessRestrictionExemption@4 +SetProcessWindowStation@4 +SetProgmanWindow@4 +SetPropA@12 +SetPropW@12 +SetRect@20 +SetRectEmpty@4 +SetScrollInfo@16 +SetScrollPos@16 +SetScrollRange@20 +SetShellWindow@4 +SetShellWindowEx@8 +SetSysColors@12 +SetSysColorsTemp@12 +SetSystemCursor@8 +SetSystemMenu@8 +SetSystemTimer@16 +SetTaskmanWindow@4 +SetThreadDesktop@4 +SetThreadInputBlocked@8 +SetTimer@16 +SetUserObjectInformationA@16 +SetUserObjectInformationW@16 +SetUserObjectSecurity@12 +SetWinEventHook@28 +SetWindowBand@12 +SetWindowCompositionAttribute@8 +SetWindowCompositionTransition@28 +SetWindowContextHelpId@8 +SetWindowDisplayAffinity@8 +SetWindowFeedbackSetting@20 +SetWindowLongA@12 +SetWindowLongW@12 +SetWindowPlacement@8 +SetWindowPos@28 +SetWindowRgn@12 +SetWindowRgnEx@12 +SetWindowStationUser@16 +SetWindowTextA@8 +SetWindowTextW@8 +SetWindowWord@12 +SetWindowsHookA@8 +SetWindowsHookExA@16 +SetWindowsHookExW@16 +SetWindowsHookW@8 +SfmDxBindSwapChain@12 +SfmDxGetSwapChainStats@8 +SfmDxOpenSwapChain@16 +SfmDxQuerySwapChainBindingStatus@12 +SfmDxReleaseSwapChain@8 +SfmDxReportPendingBindingsToDwm@0 +SfmDxSetSwapChainBindingStatus@8 +SfmDxSetSwapChainStats@8 +ShowCaret@4 +ShowCursor@4 +ShowOwnedPopups@8 +ShowScrollBar@12 +ShowStartGlass@4 +ShowSystemCursor@4 +ShowWindow@8 +ShowWindowAsync@8 +ShutdownBlockReasonCreate@8 +ShutdownBlockReasonDestroy@4 +ShutdownBlockReasonQuery@12 +SignalRedirectionStartComplete@0 +SkipPointerFrameMessages@4 +SoftModalMessageBox@4 +SoundSentry@0 +SubtractRect@12 +SwapMouseButton@4 +SwitchDesktop@4 +SwitchDesktopWithFade@12 ; Same as SwithDesktop(), only with fade (done at log-in), only usable by winlogon - http://blog.airesoft.co.uk/2010/08/things-microsoft-can-do-that-you-cant/ +SwitchToThisWindow@8 +SystemParametersInfoA@16 +SystemParametersInfoW@16 +TabbedTextOutA@32 +TabbedTextOutW@32 +TileChildWindows@8 +TileWindows@20 +ToAscii@20 +ToAsciiEx@24 +ToUnicode@24 +ToUnicodeEx@28 +TrackMouseEvent@4 +TrackPopupMenu@28 +TrackPopupMenuEx@24 +TranslateAccelerator@12 +TranslateAcceleratorA@12 +TranslateAcceleratorW@12 +TranslateMDISysAccel@8 +TranslateMessage@4 +TranslateMessageEx@8 +UnhookWinEvent@4 +UnhookWindowsHook@8 +UnhookWindowsHookEx@4 +UnionRect@12 +UnloadKeyboardLayout@4 +UnlockWindowStation@4 +UnpackDDElParam@16 +UnregisterClassA@8 +UnregisterClassW@8 +UnregisterDeviceNotification@4 +UnregisterHotKey@8 +UnregisterMessagePumpHook@0 +UnregisterPointerInputTarget@8 +UnregisterPowerSettingNotification@4 +UnregisterSessionPort@0 +UnregisterSuspendResumeNotification@4 +UnregisterTouchWindow@4 +UnregisterUserApiHook@0 +UpdateDefaultDesktopThumbnail@20 +UpdateLayeredWindow@36 +UpdateLayeredWindowIndirect@8 +UpdatePerUserSystemParameters@4 ; Undocumented, seems to apply certain registry settings to desktop, etc. ReactOS has @8 version - http://doxygen.reactos.org/d0/d92/win32ss_2user_2user32_2misc_2misc_8c_a1ff565f0af6bac6dce604f9f4473fe79.html ; @4 is rumored to be without the first DWORD +UpdateWindow@4 +UpdateWindowInputSinkHints@8 +UpdateWindowTransform@12 +User32InitializeImmEntryTable@4 +UserClientDllInitialize@12 +UserHandleGrantAccess@12 +UserLpkPSMTextOut@24 +UserLpkTabbedTextOut@48 +UserRealizePalette@4 +UserRegisterWowHandlers@8 +VRipOutput@0 +VTagOutput@0 +ValidateRect@8 +ValidateRgn@8 +VkKeyScanA@4 +VkKeyScanExA@8 +VkKeyScanExW@8 +VkKeyScanW@4 +WCSToMBEx@24 +WINNLSEnableIME@8 +WINNLSGetEnableStatus@4 +WINNLSGetIMEHotkey@4 +WaitForInputIdle@8 +WaitForRedirectionStartComplete@0 +WaitMessage@0 +Win32PoolAllocationStats@24 +WinHelpA@16 +WinHelpW@16 +WindowFromDC@4 +WindowFromPhysicalPoint@8 +WindowFromPoint@8 +_UserTestTokenForInteractive@8 +gSharedInfo DATA +gapfnScSendMessage DATA +keybd_event@16 +mouse_event@20 +wsprintfA +wsprintfW +wvsprintfA@12 +wvsprintfW@12 +;ord_2500@16 @2500 +;ord_2501@12 @2501 +;ord_2502@8 @2502 +;ord_2503@24 @2503 +;ord_2504@8 @2504 +;ord_2505@8 @2505 +;ord_2506@12 @2506 +;ord_2507@4 @2507 +;ord_2508@8 @2508 +;ord_2509@4 @2509 +;ord_2510@12 @2510 +;ord_2511@8 @2511 +;ord_2512@12 @2512 +;ord_2513@4 @2513 +;ord_2514@8 @2514 +;ord_2515@8 @2515 +;ord_2516@12 @2516 +;ord_2517@4 @2517 +;ord_2518@0 @2518 +;ord_2519@4 @2519 +;ord_2520@0 @2520 +;ord_2521@8 @2521 +;ord_2522@4 @2522 +;ord_2523@8 @2523 +;ord_2524@8 @2524 +;ord_2525@12 @2525 +;ord_2526@12 @2526 +;ord_2527@12 @2527 +IsThreadMessageQueueAttached@4 +;ord_2529@4 @2529 +;ord_2530@8 @2530 +;ord_2531@16 @2531 +;ord_2532@8 @2532 +;ord_2533@4 @2533 +;ord_2534@8 @2534 +;ord_2535@0 @2535 +;ord_2536@8 @2536 +;ord_2537@16 @2537 +;ord_2538@4 @2538 +;ord_2539@4 @2539 +;ord_2540@4 @2540 +;ord_2541@0 @2541 +;ord_2544@4 @2544 +;ord_2545@8 @2545 +;ord_2546@4 @2546 +;ord_2547@4 @2547 +;ord_2548@4 @2548 +;ord_2549@4 @2549 +;ord_2550@8 @2550 +;ord_2551@20 @2551 +;ord_2552@8 @2552 +;ord_2553@32 @2553 +;ord_2554@12 @2554 +;ord_2555@16 @2555 +;ord_2556@8 @2556 +;ord_2557@12 @2557 +;ord_2558@12 @2558 +;ord_2559@16 @2559 +;ord_2560@20 @2560 +;ord_2561@0 @2561 +;ord_2562@0 @2562 +;ord_2563@0 @2563 diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index f298d14631..9144d2c644 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -371,7 +371,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ pub fn initCapacity(allocator: *Allocator, num: usize) !Self { var self = Self{}; - const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least); + const new_memory = try allocator.allocAdvanced(T, alignment, num, .at_least); self.items.ptr = new_memory.ptr; self.capacity = new_memory.len; @@ -419,7 +419,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ /// Replace range of elements `list[start..start+len]` with `new_items` /// grows list if `len < new_items.len`. may allocate /// shrinks list if `len > new_items.len` - pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void { + pub fn replaceRange(self: *Self, allocator: *Allocator, start: usize, len: usize, new_items: SliceConst) !void { var managed = self.toManaged(allocator); try managed.replaceRange(start, len, new_items); self.* = managed.toUnmanaged(); @@ -617,201 +617,414 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ }; } -test "std.ArrayList.init" { - var list = ArrayList(i32).init(testing.allocator); - defer list.deinit(); +test "std.ArrayList/ArrayListUnmanaged.init" { + { + var list = ArrayList(i32).init(testing.allocator); + defer list.deinit(); - testing.expect(list.items.len == 0); - testing.expect(list.capacity == 0); -} + testing.expect(list.items.len == 0); + testing.expect(list.capacity == 0); + } -test "std.ArrayList.initCapacity" { - var list = try ArrayList(i8).initCapacity(testing.allocator, 200); - defer list.deinit(); - testing.expect(list.items.len == 0); - testing.expect(list.capacity >= 200); -} + { + var list = ArrayListUnmanaged(i32){}; -test "std.ArrayList.basic" { - var list = ArrayList(i32).init(testing.allocator); - defer list.deinit(); + testing.expect(list.items.len == 0); + testing.expect(list.capacity == 0); + } +} +test "std.ArrayList/ArrayListUnmanaged.initCapacity" { + const a = testing.allocator; { - var i: usize = 0; - while (i < 10) : (i += 1) { - list.append(@intCast(i32, i + 1)) catch unreachable; - } + var list = try ArrayList(i8).initCapacity(a, 200); + defer list.deinit(); + testing.expect(list.items.len == 0); + testing.expect(list.capacity >= 200); + } + { + var list = try ArrayListUnmanaged(i8).initCapacity(a, 200); + defer list.deinit(a); + testing.expect(list.items.len == 0); + testing.expect(list.capacity >= 200); } +} +test "std.ArrayList/ArrayListUnmanaged.basic" { + const a = testing.allocator; { - var i: usize = 0; - while (i < 10) : (i += 1) { - testing.expect(list.items[i] == @intCast(i32, i + 1)); + var list = ArrayList(i32).init(a); + defer list.deinit(); + + { + var i: usize = 0; + while (i < 10) : (i += 1) { + list.append(@intCast(i32, i + 1)) catch unreachable; + } + } + + { + var i: usize = 0; + while (i < 10) : (i += 1) { + testing.expect(list.items[i] == @intCast(i32, i + 1)); + } + } + + for (list.items) |v, i| { + testing.expect(v == @intCast(i32, i + 1)); } - } - for (list.items) |v, i| { - testing.expect(v == @intCast(i32, i + 1)); + testing.expect(list.pop() == 10); + testing.expect(list.items.len == 9); + + list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable; + testing.expect(list.items.len == 12); + testing.expect(list.pop() == 3); + testing.expect(list.pop() == 2); + testing.expect(list.pop() == 1); + testing.expect(list.items.len == 9); + + list.appendSlice(&[_]i32{}) catch unreachable; + testing.expect(list.items.len == 9); + + // can only set on indices < self.items.len + list.items[7] = 33; + list.items[8] = 42; + + testing.expect(list.pop() == 42); + testing.expect(list.pop() == 33); } + { + var list = ArrayListUnmanaged(i32){}; + defer list.deinit(a); + + { + var i: usize = 0; + while (i < 10) : (i += 1) { + list.append(a, @intCast(i32, i + 1)) catch unreachable; + } + } + + { + var i: usize = 0; + while (i < 10) : (i += 1) { + testing.expect(list.items[i] == @intCast(i32, i + 1)); + } + } + + for (list.items) |v, i| { + testing.expect(v == @intCast(i32, i + 1)); + } - testing.expect(list.pop() == 10); - testing.expect(list.items.len == 9); + testing.expect(list.pop() == 10); + testing.expect(list.items.len == 9); - list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable; - testing.expect(list.items.len == 12); - testing.expect(list.pop() == 3); - testing.expect(list.pop() == 2); - testing.expect(list.pop() == 1); - testing.expect(list.items.len == 9); + list.appendSlice(a, &[_]i32{ 1, 2, 3 }) catch unreachable; + testing.expect(list.items.len == 12); + testing.expect(list.pop() == 3); + testing.expect(list.pop() == 2); + testing.expect(list.pop() == 1); + testing.expect(list.items.len == 9); - list.appendSlice(&[_]i32{}) catch unreachable; - testing.expect(list.items.len == 9); + list.appendSlice(a, &[_]i32{}) catch unreachable; + testing.expect(list.items.len == 9); - // can only set on indices < self.items.len - list.items[7] = 33; - list.items[8] = 42; + // can only set on indices < self.items.len + list.items[7] = 33; + list.items[8] = 42; - testing.expect(list.pop() == 42); - testing.expect(list.pop() == 33); + testing.expect(list.pop() == 42); + testing.expect(list.pop() == 33); + } } -test "std.ArrayList.appendNTimes" { - var list = ArrayList(i32).init(testing.allocator); - defer list.deinit(); +test "std.ArrayList/ArrayListUnmanaged.appendNTimes" { + const a = testing.allocator; + { + var list = ArrayList(i32).init(a); + defer list.deinit(); + + try list.appendNTimes(2, 10); + testing.expectEqual(@as(usize, 10), list.items.len); + for (list.items) |element| { + testing.expectEqual(@as(i32, 2), element); + } + } + { + var list = ArrayListUnmanaged(i32){}; + defer list.deinit(a); - try list.appendNTimes(2, 10); - testing.expectEqual(@as(usize, 10), list.items.len); - for (list.items) |element| { - testing.expectEqual(@as(i32, 2), element); + try list.appendNTimes(a, 2, 10); + testing.expectEqual(@as(usize, 10), list.items.len); + for (list.items) |element| { + testing.expectEqual(@as(i32, 2), element); + } } } -test "std.ArrayList.appendNTimes with failing allocator" { - var list = ArrayList(i32).init(testing.failing_allocator); - defer list.deinit(); - testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10)); +test "std.ArrayList/ArrayListUnmanaged.appendNTimes with failing allocator" { + const a = testing.failing_allocator; + { + var list = ArrayList(i32).init(a); + defer list.deinit(); + testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10)); + } + { + var list = ArrayListUnmanaged(i32){}; + defer list.deinit(a); + testing.expectError(error.OutOfMemory, list.appendNTimes(a, 2, 10)); + } } -test "std.ArrayList.orderedRemove" { - var list = ArrayList(i32).init(testing.allocator); - defer list.deinit(); +test "std.ArrayList/ArrayListUnmanaged.orderedRemove" { + const a = testing.allocator; + { + var list = ArrayList(i32).init(a); + defer list.deinit(); + + try list.append(1); + try list.append(2); + try list.append(3); + try list.append(4); + try list.append(5); + try list.append(6); + try list.append(7); + + //remove from middle + testing.expectEqual(@as(i32, 4), list.orderedRemove(3)); + testing.expectEqual(@as(i32, 5), list.items[3]); + testing.expectEqual(@as(usize, 6), list.items.len); + + //remove from end + testing.expectEqual(@as(i32, 7), list.orderedRemove(5)); + testing.expectEqual(@as(usize, 5), list.items.len); + + //remove from front + testing.expectEqual(@as(i32, 1), list.orderedRemove(0)); + testing.expectEqual(@as(i32, 2), list.items[0]); + testing.expectEqual(@as(usize, 4), list.items.len); + } + { + var list = ArrayListUnmanaged(i32){}; + defer list.deinit(a); - try list.append(1); - try list.append(2); - try list.append(3); - try list.append(4); - try list.append(5); - try list.append(6); - try list.append(7); - - //remove from middle - testing.expectEqual(@as(i32, 4), list.orderedRemove(3)); - testing.expectEqual(@as(i32, 5), list.items[3]); - testing.expectEqual(@as(usize, 6), list.items.len); - - //remove from end - testing.expectEqual(@as(i32, 7), list.orderedRemove(5)); - testing.expectEqual(@as(usize, 5), list.items.len); - - //remove from front - testing.expectEqual(@as(i32, 1), list.orderedRemove(0)); - testing.expectEqual(@as(i32, 2), list.items[0]); - testing.expectEqual(@as(usize, 4), list.items.len); + try list.append(a, 1); + try list.append(a, 2); + try list.append(a, 3); + try list.append(a, 4); + try list.append(a, 5); + try list.append(a, 6); + try list.append(a, 7); + + //remove from middle + testing.expectEqual(@as(i32, 4), list.orderedRemove(3)); + testing.expectEqual(@as(i32, 5), list.items[3]); + testing.expectEqual(@as(usize, 6), list.items.len); + + //remove from end + testing.expectEqual(@as(i32, 7), list.orderedRemove(5)); + testing.expectEqual(@as(usize, 5), list.items.len); + + //remove from front + testing.expectEqual(@as(i32, 1), list.orderedRemove(0)); + testing.expectEqual(@as(i32, 2), list.items[0]); + testing.expectEqual(@as(usize, 4), list.items.len); + } } -test "std.ArrayList.swapRemove" { - var list = ArrayList(i32).init(testing.allocator); - defer list.deinit(); +test "std.ArrayList/ArrayListUnmanaged.swapRemove" { + const a = testing.allocator; + { + var list = ArrayList(i32).init(a); + defer list.deinit(); - try list.append(1); - try list.append(2); - try list.append(3); - try list.append(4); - try list.append(5); - try list.append(6); - try list.append(7); - - //remove from middle - testing.expect(list.swapRemove(3) == 4); - testing.expect(list.items[3] == 7); - testing.expect(list.items.len == 6); - - //remove from end - testing.expect(list.swapRemove(5) == 6); - testing.expect(list.items.len == 5); - - //remove from front - testing.expect(list.swapRemove(0) == 1); - testing.expect(list.items[0] == 5); - testing.expect(list.items.len == 4); + try list.append(1); + try list.append(2); + try list.append(3); + try list.append(4); + try list.append(5); + try list.append(6); + try list.append(7); + + //remove from middle + testing.expect(list.swapRemove(3) == 4); + testing.expect(list.items[3] == 7); + testing.expect(list.items.len == 6); + + //remove from end + testing.expect(list.swapRemove(5) == 6); + testing.expect(list.items.len == 5); + + //remove from front + testing.expect(list.swapRemove(0) == 1); + testing.expect(list.items[0] == 5); + testing.expect(list.items.len == 4); + } + { + var list = ArrayListUnmanaged(i32){}; + defer list.deinit(a); + + try list.append(a, 1); + try list.append(a, 2); + try list.append(a, 3); + try list.append(a, 4); + try list.append(a, 5); + try list.append(a, 6); + try list.append(a, 7); + + //remove from middle + testing.expect(list.swapRemove(3) == 4); + testing.expect(list.items[3] == 7); + testing.expect(list.items.len == 6); + + //remove from end + testing.expect(list.swapRemove(5) == 6); + testing.expect(list.items.len == 5); + + //remove from front + testing.expect(list.swapRemove(0) == 1); + testing.expect(list.items[0] == 5); + testing.expect(list.items.len == 4); + } } -test "std.ArrayList.insert" { - var list = ArrayList(i32).init(testing.allocator); - defer list.deinit(); +test "std.ArrayList/ArrayListUnmanaged.insert" { + const a = testing.allocator; + { + var list = ArrayList(i32).init(a); + defer list.deinit(); - try list.append(1); - try list.append(2); - try list.append(3); - try list.insert(0, 5); - testing.expect(list.items[0] == 5); - testing.expect(list.items[1] == 1); - testing.expect(list.items[2] == 2); - testing.expect(list.items[3] == 3); + try list.append(1); + try list.append(2); + try list.append(3); + try list.insert(0, 5); + testing.expect(list.items[0] == 5); + testing.expect(list.items[1] == 1); + testing.expect(list.items[2] == 2); + testing.expect(list.items[3] == 3); + } + { + var list = ArrayListUnmanaged(i32){}; + defer list.deinit(a); + + try list.append(a, 1); + try list.append(a, 2); + try list.append(a, 3); + try list.insert(a, 0, 5); + testing.expect(list.items[0] == 5); + testing.expect(list.items[1] == 1); + testing.expect(list.items[2] == 2); + testing.expect(list.items[3] == 3); + } } -test "std.ArrayList.insertSlice" { - var list = ArrayList(i32).init(testing.allocator); - defer list.deinit(); +test "std.ArrayList/ArrayListUnmanaged.insertSlice" { + const a = testing.allocator; + { + var list = ArrayList(i32).init(a); + defer list.deinit(); - try list.append(1); - try list.append(2); - try list.append(3); - try list.append(4); - try list.insertSlice(1, &[_]i32{ 9, 8 }); - testing.expect(list.items[0] == 1); - testing.expect(list.items[1] == 9); - testing.expect(list.items[2] == 8); - testing.expect(list.items[3] == 2); - testing.expect(list.items[4] == 3); - testing.expect(list.items[5] == 4); - - const items = [_]i32{1}; - try list.insertSlice(0, items[0..0]); - testing.expect(list.items.len == 6); - testing.expect(list.items[0] == 1); + try list.append(1); + try list.append(2); + try list.append(3); + try list.append(4); + try list.insertSlice(1, &[_]i32{ 9, 8 }); + testing.expect(list.items[0] == 1); + testing.expect(list.items[1] == 9); + testing.expect(list.items[2] == 8); + testing.expect(list.items[3] == 2); + testing.expect(list.items[4] == 3); + testing.expect(list.items[5] == 4); + + const items = [_]i32{1}; + try list.insertSlice(0, items[0..0]); + testing.expect(list.items.len == 6); + testing.expect(list.items[0] == 1); + } + { + var list = ArrayListUnmanaged(i32){}; + defer list.deinit(a); + + try list.append(a, 1); + try list.append(a, 2); + try list.append(a, 3); + try list.append(a, 4); + try list.insertSlice(a, 1, &[_]i32{ 9, 8 }); + testing.expect(list.items[0] == 1); + testing.expect(list.items[1] == 9); + testing.expect(list.items[2] == 8); + testing.expect(list.items[3] == 2); + testing.expect(list.items[4] == 3); + testing.expect(list.items[5] == 4); + + const items = [_]i32{1}; + try list.insertSlice(a, 0, items[0..0]); + testing.expect(list.items.len == 6); + testing.expect(list.items[0] == 1); + } } -test "std.ArrayList.replaceRange" { +test "std.ArrayList/ArrayListUnmanaged.replaceRange" { var arena = std.heap.ArenaAllocator.init(testing.allocator); defer arena.deinit(); + const a = &arena.allocator; - const alloc = &arena.allocator; const init = [_]i32{ 1, 2, 3, 4, 5 }; const new = [_]i32{ 0, 0, 0 }; - var list_zero = ArrayList(i32).init(alloc); - var list_eq = ArrayList(i32).init(alloc); - var list_lt = ArrayList(i32).init(alloc); - var list_gt = ArrayList(i32).init(alloc); + const result_zero = [_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 }; + const result_eq = [_]i32{ 1, 0, 0, 0, 5 }; + const result_le = [_]i32{ 1, 0, 0, 0, 4, 5 }; + const result_gt = [_]i32{ 1, 0, 0, 0 }; - try list_zero.appendSlice(&init); - try list_eq.appendSlice(&init); - try list_lt.appendSlice(&init); - try list_gt.appendSlice(&init); - - try list_zero.replaceRange(1, 0, &new); - try list_eq.replaceRange(1, 3, &new); - try list_lt.replaceRange(1, 2, &new); - - // after_range > new_items.len in function body - testing.expect(1 + 4 > new.len); - try list_gt.replaceRange(1, 4, &new); - - testing.expectEqualSlices(i32, list_zero.items, &[_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 }); - testing.expectEqualSlices(i32, list_eq.items, &[_]i32{ 1, 0, 0, 0, 5 }); - testing.expectEqualSlices(i32, list_lt.items, &[_]i32{ 1, 0, 0, 0, 4, 5 }); - testing.expectEqualSlices(i32, list_gt.items, &[_]i32{ 1, 0, 0, 0 }); + { + var list_zero = ArrayList(i32).init(a); + var list_eq = ArrayList(i32).init(a); + var list_lt = ArrayList(i32).init(a); + var list_gt = ArrayList(i32).init(a); + + try list_zero.appendSlice(&init); + try list_eq.appendSlice(&init); + try list_lt.appendSlice(&init); + try list_gt.appendSlice(&init); + + try list_zero.replaceRange(1, 0, &new); + try list_eq.replaceRange(1, 3, &new); + try list_lt.replaceRange(1, 2, &new); + + // after_range > new_items.len in function body + testing.expect(1 + 4 > new.len); + try list_gt.replaceRange(1, 4, &new); + + testing.expectEqualSlices(i32, list_zero.items, &result_zero); + testing.expectEqualSlices(i32, list_eq.items, &result_eq); + testing.expectEqualSlices(i32, list_lt.items, &result_le); + testing.expectEqualSlices(i32, list_gt.items, &result_gt); + } + { + var list_zero = ArrayListUnmanaged(i32){}; + var list_eq = ArrayListUnmanaged(i32){}; + var list_lt = ArrayListUnmanaged(i32){}; + var list_gt = ArrayListUnmanaged(i32){}; + + try list_zero.appendSlice(a, &init); + try list_eq.appendSlice(a, &init); + try list_lt.appendSlice(a, &init); + try list_gt.appendSlice(a, &init); + + try list_zero.replaceRange(a, 1, 0, &new); + try list_eq.replaceRange(a, 1, 3, &new); + try list_lt.replaceRange(a, 1, 2, &new); + + // after_range > new_items.len in function body + testing.expect(1 + 4 > new.len); + try list_gt.replaceRange(a, 1, 4, &new); + + testing.expectEqualSlices(i32, list_zero.items, &result_zero); + testing.expectEqualSlices(i32, list_eq.items, &result_eq); + testing.expectEqualSlices(i32, list_lt.items, &result_le); + testing.expectEqualSlices(i32, list_gt.items, &result_gt); + } } const Item = struct { @@ -819,11 +1032,25 @@ const Item = struct { sub_items: ArrayList(Item), }; -test "std.ArrayList: ArrayList(T) of struct T" { - var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(testing.allocator) }; - defer root.sub_items.deinit(); - try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(testing.allocator) }); - testing.expect(root.sub_items.items[0].integer == 42); +const ItemUnmanaged = struct { + integer: i32, + sub_items: ArrayListUnmanaged(ItemUnmanaged), +}; + +test "std.ArrayList/ArrayListUnmanaged: ArrayList(T) of struct T" { + const a = std.testing.allocator; + { + var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(a) }; + defer root.sub_items.deinit(); + try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(a) }); + testing.expect(root.sub_items.items[0].integer == 42); + } + { + var root = ItemUnmanaged{ .integer = 1, .sub_items = ArrayListUnmanaged(ItemUnmanaged){} }; + defer root.sub_items.deinit(a); + try root.sub_items.append(a, ItemUnmanaged{ .integer = 42, .sub_items = ArrayListUnmanaged(ItemUnmanaged){} }); + testing.expect(root.sub_items.items[0].integer == 42); + } } test "std.ArrayList(u8) implements outStream" { @@ -837,19 +1064,32 @@ test "std.ArrayList(u8) implements outStream" { testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.span()); } -test "std.ArrayList.shrink still sets length on error.OutOfMemory" { +test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" { // use an arena allocator to make sure realloc returns error.OutOfMemory var arena = std.heap.ArenaAllocator.init(testing.allocator); defer arena.deinit(); + const a = &arena.allocator; - var list = ArrayList(i32).init(&arena.allocator); + { + var list = ArrayList(i32).init(a); - try list.append(1); - try list.append(2); - try list.append(3); + try list.append(1); + try list.append(2); + try list.append(3); - list.shrink(1); - testing.expect(list.items.len == 1); + list.shrink(1); + testing.expect(list.items.len == 1); + } + { + var list = ArrayListUnmanaged(i32){}; + + try list.append(a, 1); + try list.append(a, 2); + try list.append(a, 3); + + list.shrink(a, 1); + testing.expect(list.items.len == 1); + } } test "std.ArrayList.writer" { @@ -864,7 +1104,7 @@ test "std.ArrayList.writer" { testing.expectEqualSlices(u8, list.items, "abcdefg"); } -test "addManyAsArray" { +test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" { const a = std.testing.allocator; { var list = ArrayList(u8).init(a); diff --git a/lib/std/build.zig b/lib/std/build.zig index 7e3c75bc78..6575e057e8 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1232,6 +1232,9 @@ pub const LibExeObjStep = struct { installed_path: ?[]const u8, install_step: ?*InstallArtifactStep, + /// Base address for an executable image. + image_base: ?u64 = null, + libc_file: ?[]const u8 = null, valgrind_support: ?bool = null, @@ -1239,6 +1242,7 @@ pub const LibExeObjStep = struct { /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF /// file. link_eh_frame_hdr: bool = false, + link_emit_relocs: bool = false, /// Place every function in its own section so that unused ones may be /// safely garbage-collected during the linking phase. @@ -1384,66 +1388,50 @@ pub const LibExeObjStep = struct { } fn computeOutFileNames(self: *LibExeObjStep) void { - // TODO make this call std.zig.binNameAlloc - switch (self.kind) { - .Obj => { - self.out_filename = self.builder.fmt("{}{}", .{ self.name, self.target.oFileExt() }); - }, - .Exe => { - self.out_filename = self.builder.fmt("{}{}", .{ self.name, self.target.exeFileExt() }); - }, - .Test => { - self.out_filename = self.builder.fmt("test{}", .{self.target.exeFileExt()}); + const target_info = std.zig.system.NativeTargetInfo.detect( + self.builder.allocator, + self.target, + ) catch unreachable; + const target = target_info.target; + self.out_filename = std.zig.binNameAlloc(self.builder.allocator, .{ + .root_name = self.name, + .target = target, + .output_mode = switch (self.kind) { + .Lib => .Lib, + .Obj => .Obj, + .Exe, .Test => .Exe, }, - .Lib => { - if (!self.is_dynamic) { - self.out_filename = self.builder.fmt("{}{}{}", .{ - self.target.libPrefix(), + .link_mode = if (self.is_dynamic) .Dynamic else .Static, + .version = self.version, + }) catch unreachable; + + if (self.kind == .Lib) { + if (!self.is_dynamic) { + self.out_lib_filename = self.out_filename; + } else if (self.version) |version| { + if (target.isDarwin()) { + self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", .{ self.name, - self.target.staticLibSuffix(), + version.major, }); + self.name_only_filename = self.builder.fmt("lib{}.dylib", .{self.name}); self.out_lib_filename = self.out_filename; - } else if (self.version) |version| { - if (self.target.isDarwin()) { - self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", .{ - self.name, - version.major, - version.minor, - version.patch, - }); - self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", .{ - self.name, - version.major, - }); - self.name_only_filename = self.builder.fmt("lib{}.dylib", .{self.name}); - self.out_lib_filename = self.out_filename; - } else if (self.target.isWindows()) { - self.out_filename = self.builder.fmt("{}.dll", .{self.name}); - self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name}); - } else { - self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", .{ - self.name, - version.major, - version.minor, - version.patch, - }); - self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, version.major }); - self.name_only_filename = self.builder.fmt("lib{}.so", .{self.name}); - self.out_lib_filename = self.out_filename; - } + } else if (target.os.tag == .windows) { + self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name}); } else { - if (self.target.isDarwin()) { - self.out_filename = self.builder.fmt("lib{}.dylib", .{self.name}); - self.out_lib_filename = self.out_filename; - } else if (self.target.isWindows()) { - self.out_filename = self.builder.fmt("{}.dll", .{self.name}); - self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name}); - } else { - self.out_filename = self.builder.fmt("lib{}.so", .{self.name}); - self.out_lib_filename = self.out_filename; - } + self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, version.major }); + self.name_only_filename = self.builder.fmt("lib{}.so", .{self.name}); + self.out_lib_filename = self.out_filename; } - }, + } else { + if (target.isDarwin()) { + self.out_lib_filename = self.out_filename; + } else if (target.os.tag == .windows) { + self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name}); + } else { + self.out_lib_filename = self.out_filename; + } + } } } @@ -2040,6 +2028,11 @@ pub const LibExeObjStep = struct { try zig_args.append("--pkg-end"); } + if (self.image_base) |image_base| { + try zig_args.append("--image-base"); + try zig_args.append(builder.fmt("0x{x}", .{image_base})); + } + if (self.filter) |filter| { try zig_args.append("--test-filter"); try zig_args.append(filter); @@ -2075,6 +2068,9 @@ pub const LibExeObjStep = struct { if (self.link_eh_frame_hdr) { try zig_args.append("--eh-frame-hdr"); } + if (self.link_emit_relocs) { + try zig_args.append("--emit-relocs"); + } if (self.link_function_sections) { try zig_args.append("-ffunction-sections"); } @@ -2168,8 +2164,8 @@ pub const LibExeObjStep = struct { } if (self.linker_script) |linker_script| { - zig_args.append("--linker-script") catch unreachable; - zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable; + try zig_args.append("--script"); + try zig_args.append(builder.pathFromRoot(linker_script)); } if (self.version_script) |version_script| { @@ -2335,6 +2331,14 @@ pub const LibExeObjStep = struct { var it = src_dir.iterate(); while (try it.next()) |entry| { + // The compiler can put these files into the same directory, but we don't + // want to copy them over. + if (mem.eql(u8, entry.name, "stage1.id") or + mem.eql(u8, entry.name, "llvm-ar.id") or + mem.eql(u8, entry.name, "libs.txt") or + mem.eql(u8, entry.name, "builtin.zig") or + mem.eql(u8, entry.name, "lld.id")) continue; + _ = try src_dir.updateFile(entry.name, dest_dir, entry.name, .{}); } } else { diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 52b8f641cd..68bbbe3b2d 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -100,6 +100,16 @@ pub const AtomicOrder = enum { /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. +pub const ReduceOp = enum { + And, + Or, + Xor, + Min, + Max, +}; + +/// This data structure is used by the Zig language code generation and +/// therefore must be kept in sync with the compiler implementation. pub const AtomicRmwOp = enum { Xchg, Add, @@ -262,6 +272,7 @@ pub const TypeInfo = union(enum) { field_type: type, default_value: anytype, is_comptime: bool, + alignment: comptime_int, }; /// This data structure is used by the Zig language code generation and @@ -318,6 +329,7 @@ pub const TypeInfo = union(enum) { pub const UnionField = struct { name: []const u8, field_type: type, + alignment: comptime_int, }; /// This data structure is used by the Zig language code generation and @@ -341,6 +353,7 @@ pub const TypeInfo = union(enum) { /// therefore must be kept in sync with the compiler implementation. pub const Fn = struct { calling_convention: CallingConvention, + alignment: comptime_int, is_generic: bool, is_var_args: bool, return_type: ?type, diff --git a/lib/std/c.zig b/lib/std/c.zig index aa50fff90e..7cfc44714f 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -342,3 +342,6 @@ pub extern "c" fn fsync(fd: c_int) c_int; pub extern "c" fn fdatasync(fd: c_int) c_int; pub extern "c" fn prctl(option: c_int, ...) c_int; + +pub extern "c" fn getrlimit(resource: rlimit_resource, rlim: *rlimit) c_int; +pub extern "c" fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) c_int; diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index ed1ddb7d91..976690d6b7 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -12,7 +12,7 @@ usingnamespace @import("../os/bits.zig"); extern "c" fn __error() *c_int; pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32; -pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int; +pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int; pub extern "c" fn _dyld_image_count() u32; pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header; pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize; diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index 538fbdfd7d..d48c76c7a6 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -100,6 +100,8 @@ pub extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_ pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: c_uint) c_int; +pub extern "c" fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: *const rlimit, old_limit: *rlimit) c_int; + pub const pthread_attr_t = extern struct { __size: [56]u8, __align: c_long, diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index e706302ebd..52e9ac99ba 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -105,8 +105,8 @@ pub const ChildProcess = struct { .term = null, .env_map = null, .cwd = null, - .uid = if (builtin.os.tag == .windows) {} else null, - .gid = if (builtin.os.tag == .windows) {} else null, + .uid = if (builtin.os.tag == .windows or builtin.os.tag == .wasi) {} else null, + .gid = if (builtin.os.tag == .windows or builtin.os.tag == .wasi) {} else null, .stdin = null, .stdout = null, .stderr = null, diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig index fa69d51d4d..8c225aa719 100644 --- a/lib/std/crypto.zig +++ b/lib/std/crypto.zig @@ -4,6 +4,50 @@ // The MIT license requires this copyright notice to be included in all copies // and substantial portions of the software. +/// Authenticated Encryption with Associated Data +pub const aead = struct { + const chacha20 = @import("crypto/chacha20.zig"); + + pub const Gimli = @import("crypto/gimli.zig").Aead; + pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305; + pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305; + pub const AEGIS128L = @import("crypto/aegis.zig").AEGIS128L; + pub const AEGIS256 = @import("crypto/aegis.zig").AEGIS256; + pub const AES128GCM = @import("crypto/aes_gcm.zig").AES128GCM; + pub const AES256GCM = @import("crypto/aes_gcm.zig").AES256GCM; +}; + +/// Authentication (MAC) functions. +pub const auth = struct { + pub const hmac = @import("crypto/hmac.zig"); + pub const siphash = @import("crypto/siphash.zig"); +}; + +/// Core functions, that should rarely be used directly by applications. +pub const core = struct { + pub const aes = @import("crypto/aes.zig"); + pub const Gimli = @import("crypto/gimli.zig").State; + + /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations. + /// + /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees. + /// + /// Most applications may want to use AEADs instead. + pub const modes = @import("crypto/modes.zig"); +}; + +/// Diffie-Hellman key exchange functions. +pub const dh = struct { + pub const X25519 = @import("crypto/25519/x25519.zig").X25519; +}; + +/// Elliptic-curve arithmetic. +pub const ecc = struct { + pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; + pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; + pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; +}; + /// Hash functions. pub const hash = struct { pub const Md5 = @import("crypto/md5.zig").Md5; @@ -15,26 +59,15 @@ pub const hash = struct { pub const Gimli = @import("crypto/gimli.zig").Hash; }; -/// Authentication (MAC) functions. -pub const auth = struct { - pub const hmac = @import("crypto/hmac.zig"); - pub const siphash = @import("crypto/siphash.zig"); -}; - -/// Authenticated Encryption with Associated Data -pub const aead = struct { - const chacha20 = @import("crypto/chacha20.zig"); - - pub const Gimli = @import("crypto/gimli.zig").Aead; - pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305; - pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305; - pub const AEGIS128L = @import("crypto/aegis.zig").AEGIS128L; - pub const AEGIS256 = @import("crypto/aegis.zig").AEGIS256; +/// Key derivation functions. +pub const kdf = struct { + pub const hkdf = @import("crypto/hkdf.zig"); }; /// MAC functions requiring single-use secret keys. pub const onetimeauth = struct { pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; + pub const Ghash = @import("crypto/ghash.zig").Ghash; }; /// A password hashing function derives a uniform key from low-entropy input material such as passwords. @@ -57,31 +90,6 @@ pub const pwhash = struct { pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2; }; -/// Core functions, that should rarely be used directly by applications. -pub const core = struct { - pub const aes = @import("crypto/aes.zig"); - pub const Gimli = @import("crypto/gimli.zig").State; - - /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations. - /// - /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees. - /// - /// Most applications may want to use AEADs instead. - pub const modes = @import("crypto/modes.zig"); -}; - -/// Elliptic-curve arithmetic. -pub const ecc = struct { - pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; - pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; - pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; -}; - -/// Diffie-Hellman key exchange functions. -pub const dh = struct { - pub const X25519 = @import("crypto/25519/x25519.zig").X25519; -}; - /// Digital signature functions. pub const sign = struct { pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519; diff --git a/lib/std/crypto/25519/field.zig b/lib/std/crypto/25519/field.zig index 61929ba044..0bc0ead5f2 100644 --- a/lib/std/crypto/25519/field.zig +++ b/lib/std/crypto/25519/field.zig @@ -307,12 +307,14 @@ pub const Fe = struct { } pub fn pow2523(a: Fe) Fe { - var c = a; - var i: usize = 0; - while (i < 249) : (i += 1) { - c = c.sq().mul(a); - } - return c.sq().sq().mul(a); + var t0 = a.mul(a.sq()); + var t1 = t0.mul(t0.sqn(2)).sq().mul(a); + t0 = t1.sqn(5).mul(t1); + var t2 = t0.sqn(5).mul(t1); + t1 = t2.sqn(15).mul(t2); + t2 = t1.sqn(30).mul(t1); + t1 = t2.sqn(60).mul(t2); + return t1.sqn(120).mul(t1).sqn(10).mul(t0).sqn(2).mul(a); } pub fn abs(a: Fe) Fe { diff --git a/lib/std/crypto/aes_gcm.zig b/lib/std/crypto/aes_gcm.zig new file mode 100644 index 0000000000..c7093a7593 --- /dev/null +++ b/lib/std/crypto/aes_gcm.zig @@ -0,0 +1,161 @@ +const std = @import("std"); +const assert = std.debug.assert; +const builtin = std.builtin; +const crypto = std.crypto; +const debug = std.debug; +const Ghash = std.crypto.onetimeauth.Ghash; +const mem = std.mem; +const modes = crypto.core.modes; + +pub const AES128GCM = AESGCM(crypto.core.aes.AES128); +pub const AES256GCM = AESGCM(crypto.core.aes.AES256); + +fn AESGCM(comptime AES: anytype) type { + debug.assert(AES.block.block_size == 16); + + return struct { + pub const tag_length = 16; + pub const nonce_length = 12; + pub const key_length = AES.key_bits / 8; + + const zeros = [_]u8{0} ** 16; + + pub fn encrypt(c: []u8, tag: *[tag_length]u8, m: []const u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) void { + debug.assert(c.len == m.len); + debug.assert(m.len <= 16 * ((1 << 32) - 2)); + + const aes = AES.initEnc(key); + var h: [16]u8 = undefined; + aes.encrypt(&h, &zeros); + + var t: [16]u8 = undefined; + var j: [16]u8 = undefined; + mem.copy(u8, j[0..nonce_length], npub[0..]); + mem.writeIntBig(u32, j[nonce_length..][0..4], 1); + aes.encrypt(&t, &j); + + var mac = Ghash.init(&h); + mac.update(ad); + mac.pad(); + + mem.writeIntBig(u32, j[nonce_length..][0..4], 2); + modes.ctr(@TypeOf(aes), aes, c, m, j, builtin.Endian.Big); + mac.update(c[0..m.len][0..]); + mac.pad(); + + var final_block = h; + mem.writeIntBig(u64, final_block[0..8], ad.len * 8); + mem.writeIntBig(u64, final_block[8..16], m.len * 8); + mac.update(&final_block); + mac.final(tag); + for (t) |x, i| { + tag[i] ^= x; + } + } + + pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { + assert(c.len == m.len); + + const aes = AES.initEnc(key); + var h: [16]u8 = undefined; + aes.encrypt(&h, &zeros); + + var t: [16]u8 = undefined; + var j: [16]u8 = undefined; + mem.copy(u8, j[0..nonce_length], npub[0..]); + mem.writeIntBig(u32, j[nonce_length..][0..4], 1); + aes.encrypt(&t, &j); + + var mac = Ghash.init(&h); + mac.update(ad); + mac.pad(); + + mac.update(c); + mac.pad(); + + var final_block = h; + mem.writeIntBig(u64, final_block[0..8], ad.len * 8); + mem.writeIntBig(u64, final_block[8..16], m.len * 8); + mac.update(&final_block); + var computed_tag: [Ghash.mac_length]u8 = undefined; + mac.final(&computed_tag); + for (t) |x, i| { + computed_tag[i] ^= x; + } + + var acc: u8 = 0; + for (computed_tag) |_, p| { + acc |= (computed_tag[p] ^ tag[p]); + } + if (acc != 0) { + mem.set(u8, m, 0xaa); + return error.AuthenticationFailed; + } + + mem.writeIntBig(u32, j[nonce_length..][0..4], 2); + modes.ctr(@TypeOf(aes), aes, m, c, j, builtin.Endian.Big); + } + }; +} + +const htest = @import("test.zig"); +const testing = std.testing; + +test "AES256GCM - Empty message and no associated data" { + const key: [AES256GCM.key_length]u8 = [_]u8{0x69} ** AES256GCM.key_length; + const nonce: [AES256GCM.nonce_length]u8 = [_]u8{0x42} ** AES256GCM.nonce_length; + const ad = ""; + const m = ""; + var c: [m.len]u8 = undefined; + var m2: [m.len]u8 = undefined; + var tag: [AES256GCM.tag_length]u8 = undefined; + + AES256GCM.encrypt(&c, &tag, m, ad, nonce, key); + htest.assertEqual("6b6ff610a16fa4cd59f1fb7903154e92", &tag); +} + +test "AES256GCM - Associated data only" { + const key: [AES256GCM.key_length]u8 = [_]u8{0x69} ** AES256GCM.key_length; + const nonce: [AES256GCM.nonce_length]u8 = [_]u8{0x42} ** AES256GCM.nonce_length; + const m = ""; + const ad = "Test with associated data"; + var c: [m.len]u8 = undefined; + var tag: [AES256GCM.tag_length]u8 = undefined; + + AES256GCM.encrypt(&c, &tag, m, ad, nonce, key); + htest.assertEqual("262ed164c2dfb26e080a9d108dd9dd4c", &tag); +} + +test "AES256GCM - Message only" { + const key: [AES256GCM.key_length]u8 = [_]u8{0x69} ** AES256GCM.key_length; + const nonce: [AES256GCM.nonce_length]u8 = [_]u8{0x42} ** AES256GCM.nonce_length; + const m = "Test with message only"; + const ad = ""; + var c: [m.len]u8 = undefined; + var m2: [m.len]u8 = undefined; + var tag: [AES256GCM.tag_length]u8 = undefined; + + AES256GCM.encrypt(&c, &tag, m, ad, nonce, key); + try AES256GCM.decrypt(&m2, &c, tag, ad, nonce, key); + testing.expectEqualSlices(u8, m[0..], m2[0..]); + + htest.assertEqual("5ca1642d90009fea33d01f78cf6eefaf01d539472f7c", &c); + htest.assertEqual("07cd7fc9103e2f9e9bf2dfaa319caff4", &tag); +} + +test "AES256GCM - Message and associated data" { + const key: [AES256GCM.key_length]u8 = [_]u8{0x69} ** AES256GCM.key_length; + const nonce: [AES256GCM.nonce_length]u8 = [_]u8{0x42} ** AES256GCM.nonce_length; + const m = "Test with message"; + const ad = "Test with associated data"; + var c: [m.len]u8 = undefined; + var m2: [m.len]u8 = undefined; + var tag: [AES256GCM.tag_length]u8 = undefined; + + AES256GCM.encrypt(&c, &tag, m, ad, nonce, key); + try AES256GCM.decrypt(&m2, &c, tag, ad, nonce, key); + testing.expectEqualSlices(u8, m[0..], m2[0..]); + + htest.assertEqual("5ca1642d90009fea33d01f78cf6eefaf01", &c); + htest.assertEqual("64accec679d444e2373bd9f6796c0d2c", &tag); +} diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig index 3c7e3445a2..1db3a1e870 100644 --- a/lib/std/crypto/benchmark.zig +++ b/lib/std/crypto/benchmark.zig @@ -57,6 +57,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 } const macs = [_]Crypto{ + Crypto{ .ty = crypto.onetimeauth.Ghash, .name = "ghash" }, Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" }, Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" }, Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" }, @@ -151,6 +152,8 @@ const aeads = [_]Crypto{ Crypto{ .ty = crypto.aead.Gimli, .name = "gimli-aead" }, Crypto{ .ty = crypto.aead.AEGIS128L, .name = "aegis-128l" }, Crypto{ .ty = crypto.aead.AEGIS256, .name = "aegis-256" }, + Crypto{ .ty = crypto.aead.AES128GCM, .name = "aes128-gcm" }, + Crypto{ .ty = crypto.aead.AES256GCM, .name = "aes256-gcm" }, }; pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 { diff --git a/lib/std/crypto/ghash.zig b/lib/std/crypto/ghash.zig new file mode 100644 index 0000000000..04bc6a8275 --- /dev/null +++ b/lib/std/crypto/ghash.zig @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2015-2020 Zig Contributors +// This file is part of [zig](https://ziglang.org/), which is MIT licensed. +// The MIT license requires this copyright notice to be included in all copies +// and substantial portions of the software. +// +// Adapted from BearSSL's ctmul64 implementation originally written by Thomas Pornin <pornin@bolet.org> + +const std = @import("../std.zig"); +const assert = std.debug.assert; +const math = std.math; +const mem = std.mem; + +/// GHASH is a universal hash function that features multiplication +/// by a fixed parameter within a Galois field. +/// +/// It is not a general purpose hash function - The key must be secret, unpredictable and never reused. +/// +/// GHASH is typically used to compute the authentication tag in the AES-GCM construction. +pub const Ghash = struct { + pub const block_size: usize = 16; + pub const mac_length = 16; + pub const minimum_key_length = 16; + + y0: u64 = 0, + y1: u64 = 0, + h0: u64, + h1: u64, + h2: u64, + h0r: u64, + h1r: u64, + h2r: u64, + + hh0: u64 = undefined, + hh1: u64 = undefined, + hh2: u64 = undefined, + hh0r: u64 = undefined, + hh1r: u64 = undefined, + hh2r: u64 = undefined, + + leftover: usize = 0, + buf: [block_size]u8 align(16) = undefined, + + pub fn init(key: *const [minimum_key_length]u8) Ghash { + const h1 = mem.readIntBig(u64, key[0..8]); + const h0 = mem.readIntBig(u64, key[8..16]); + const h1r = @bitReverse(u64, h1); + const h0r = @bitReverse(u64, h0); + const h2 = h0 ^ h1; + const h2r = h0r ^ h1r; + + if (std.builtin.mode == .ReleaseSmall) { + return Ghash{ + .h0 = h0, + .h1 = h1, + .h2 = h2, + .h0r = h0r, + .h1r = h1r, + .h2r = h2r, + }; + } else { + // Precompute H^2 + var hh = Ghash{ + .h0 = h0, + .h1 = h1, + .h2 = h2, + .h0r = h0r, + .h1r = h1r, + .h2r = h2r, + }; + hh.update(key); + const hh1 = hh.y1; + const hh0 = hh.y0; + const hh1r = @bitReverse(u64, hh1); + const hh0r = @bitReverse(u64, hh0); + const hh2 = hh0 ^ hh1; + const hh2r = hh0r ^ hh1r; + + return Ghash{ + .h0 = h0, + .h1 = h1, + .h2 = h2, + .h0r = h0r, + .h1r = h1r, + .h2r = h2r, + + .hh0 = hh0, + .hh1 = hh1, + .hh2 = hh2, + .hh0r = hh0r, + .hh1r = hh1r, + .hh2r = hh2r, + }; + } + } + + inline fn clmul_pclmul(x: u64, y: u64) u64 { + const Vector = std.meta.Vector; + const product = asm ( + \\ vpclmulqdq $0x00, %[x], %[y], %[out] + : [out] "=x" (-> Vector(2, u64)) + : [x] "x" (@bitCast(Vector(2, u64), @as(u128, x))), + [y] "x" (@bitCast(Vector(2, u64), @as(u128, y))) + ); + return product[0]; + } + + fn clmul_soft(x: u64, y: u64) u64 { + const x0 = x & 0x1111111111111111; + const x1 = x & 0x2222222222222222; + const x2 = x & 0x4444444444444444; + const x3 = x & 0x8888888888888888; + const y0 = y & 0x1111111111111111; + const y1 = y & 0x2222222222222222; + const y2 = y & 0x4444444444444444; + const y3 = y & 0x8888888888888888; + var z0 = (x0 *% y0) ^ (x1 *% y3) ^ (x2 *% y2) ^ (x3 *% y1); + var z1 = (x0 *% y1) ^ (x1 *% y0) ^ (x2 *% y3) ^ (x3 *% y2); + var z2 = (x0 *% y2) ^ (x1 *% y1) ^ (x2 *% y0) ^ (x3 *% y3); + var z3 = (x0 *% y3) ^ (x1 *% y2) ^ (x2 *% y1) ^ (x3 *% y0); + z0 &= 0x1111111111111111; + z1 &= 0x2222222222222222; + z2 &= 0x4444444444444444; + z3 &= 0x8888888888888888; + return z0 | z1 | z2 | z3; + } + + const has_pclmul = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .pclmul); + const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx); + const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) clmul_pclmul else clmul_soft; + + fn blocks(st: *Ghash, msg: []const u8) void { + assert(msg.len % 16 == 0); // GHASH blocks() expects full blocks + var y1 = st.y1; + var y0 = st.y0; + + var i: usize = 0; + + // 2-blocks aggregated reduction + if (std.builtin.mode != .ReleaseSmall) { + while (i + 32 <= msg.len) : (i += 32) { + // B0 * H^2 unreduced + y1 ^= mem.readIntBig(u64, msg[i..][0..8]); + y0 ^= mem.readIntBig(u64, msg[i..][8..16]); + + const y1r = @bitReverse(u64, y1); + const y0r = @bitReverse(u64, y0); + const y2 = y0 ^ y1; + const y2r = y0r ^ y1r; + + var z0 = clmul(y0, st.hh0); + var z1 = clmul(y1, st.hh1); + var z2 = clmul(y2, st.hh2) ^ z0 ^ z1; + var z0h = clmul(y0r, st.hh0r); + var z1h = clmul(y1r, st.hh1r); + var z2h = clmul(y2r, st.hh2r) ^ z0h ^ z1h; + + // B1 * H unreduced + const sy1 = mem.readIntBig(u64, msg[i..][16..24]); + const sy0 = mem.readIntBig(u64, msg[i..][24..32]); + + const sy1r = @bitReverse(u64, sy1); + const sy0r = @bitReverse(u64, sy0); + const sy2 = sy0 ^ sy1; + const sy2r = sy0r ^ sy1r; + + const sz0 = clmul(sy0, st.h0); + const sz1 = clmul(sy1, st.h1); + const sz2 = clmul(sy2, st.h2) ^ sz0 ^ sz1; + const sz0h = clmul(sy0r, st.h0r); + const sz1h = clmul(sy1r, st.h1r); + const sz2h = clmul(sy2r, st.h2r) ^ sz0h ^ sz1h; + + // ((B0 * H^2) + B1 * H) (mod M) + z0 ^= sz0; + z1 ^= sz1; + z2 ^= sz2; + z0h ^= sz0h; + z1h ^= sz1h; + z2h ^= sz2h; + z0h = @bitReverse(u64, z0h) >> 1; + z1h = @bitReverse(u64, z1h) >> 1; + z2h = @bitReverse(u64, z2h) >> 1; + + var v3 = z1h; + var v2 = z1 ^ z2h; + var v1 = z0h ^ z2; + var v0 = z0; + + v3 = (v3 << 1) | (v2 >> 63); + v2 = (v2 << 1) | (v1 >> 63); + v1 = (v1 << 1) | (v0 >> 63); + v0 = (v0 << 1); + + v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7); + v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57); + y1 = v3 ^ v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7); + y0 = v2 ^ (v1 << 63) ^ (v1 << 62) ^ (v1 << 57); + } + } + + // single block + while (i + 16 <= msg.len) : (i += 16) { + y1 ^= mem.readIntBig(u64, msg[i..][0..8]); + y0 ^= mem.readIntBig(u64, msg[i..][8..16]); + + const y1r = @bitReverse(u64, y1); + const y0r = @bitReverse(u64, y0); + const y2 = y0 ^ y1; + const y2r = y0r ^ y1r; + + const z0 = clmul(y0, st.h0); + const z1 = clmul(y1, st.h1); + var z2 = clmul(y2, st.h2) ^ z0 ^ z1; + var z0h = clmul(y0r, st.h0r); + var z1h = clmul(y1r, st.h1r); + var z2h = clmul(y2r, st.h2r) ^ z0h ^ z1h; + z0h = @bitReverse(u64, z0h) >> 1; + z1h = @bitReverse(u64, z1h) >> 1; + z2h = @bitReverse(u64, z2h) >> 1; + + // shift & reduce + var v3 = z1h; + var v2 = z1 ^ z2h; + var v1 = z0h ^ z2; + var v0 = z0; + + v3 = (v3 << 1) | (v2 >> 63); + v2 = (v2 << 1) | (v1 >> 63); + v1 = (v1 << 1) | (v0 >> 63); + v0 = (v0 << 1); + + v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7); + v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57); + y1 = v3 ^ v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7); + y0 = v2 ^ (v1 << 63) ^ (v1 << 62) ^ (v1 << 57); + } + st.y1 = y1; + st.y0 = y0; + } + + pub fn update(st: *Ghash, m: []const u8) void { + var mb = m; + + if (st.leftover > 0) { + const want = math.min(block_size - st.leftover, mb.len); + const mc = mb[0..want]; + for (mc) |x, i| { + st.buf[st.leftover + i] = x; + } + mb = mb[want..]; + st.leftover += want; + if (st.leftover < block_size) { + return; + } + st.blocks(&st.buf); + st.leftover = 0; + } + if (mb.len >= block_size) { + const want = mb.len & ~(block_size - 1); + st.blocks(mb[0..want]); + mb = mb[want..]; + } + if (mb.len > 0) { + for (mb) |x, i| { + st.buf[st.leftover + i] = x; + } + st.leftover += mb.len; + } + } + + /// Zero-pad to align the next input to the first byte of a block + pub fn pad(st: *Ghash) void { + if (st.leftover == 0) { + return; + } + var i = st.leftover; + while (i < block_size) : (i += 1) { + st.buf[i] = 0; + } + st.blocks(&st.buf); + st.leftover = 0; + } + + pub fn final(st: *Ghash, out: *[mac_length]u8) void { + st.pad(); + mem.writeIntBig(u64, out[0..8], st.y1); + mem.writeIntBig(u64, out[8..16], st.y0); + + mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Ghash)]); + } + + pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void { + var st = Ghash.init(key); + st.update(msg); + st.final(out); + } +}; + +const htest = @import("test.zig"); + +test "ghash" { + const key = [_]u8{0x42} ** 16; + const m = [_]u8{0x69} ** 256; + + var st = Ghash.init(&key); + st.update(&m); + var out: [16]u8 = undefined; + st.final(&out); + htest.assertEqual("889295fa746e8b174bf4ec80a65dea41", &out); + + st = Ghash.init(&key); + st.update(m[0..100]); + st.update(m[100..]); + st.final(&out); + htest.assertEqual("889295fa746e8b174bf4ec80a65dea41", &out); +} diff --git a/lib/std/crypto/hkdf.zig b/lib/std/crypto/hkdf.zig new file mode 100644 index 0000000000..7ac3603637 --- /dev/null +++ b/lib/std/crypto/hkdf.zig @@ -0,0 +1,66 @@ +const std = @import("../std.zig"); +const assert = std.debug.assert; +const hmac = std.crypto.auth.hmac; +const mem = std.mem; + +/// HKDF-SHA256 +pub const HkdfSha256 = Hkdf(hmac.sha2.HmacSha256); + +/// HKDF-SHA512 +pub const HkdfSha512 = Hkdf(hmac.sha2.HmacSha512); + +/// The Hkdf construction takes some source of initial keying material and +/// derives one or more uniform keys from it. +pub fn Hkdf(comptime Hmac: type) type { + return struct { + /// Return a master key from a salt and initial keying material. + fn extract(salt: []const u8, ikm: []const u8) [Hmac.mac_length]u8 { + var prk: [Hmac.mac_length]u8 = undefined; + Hmac.create(&prk, ikm, salt); + return prk; + } + + /// Derive a subkey from a master key `prk` and a subkey description `ctx`. + fn expand(out: []u8, ctx: []const u8, prk: [Hmac.mac_length]u8) void { + assert(out.len < Hmac.mac_length * 255); // output size is too large for the Hkdf construction + var i: usize = 0; + var counter = [1]u8{1}; + while (i + Hmac.mac_length <= out.len) : (i += Hmac.mac_length) { + var st = Hmac.init(&prk); + if (i != 0) { + st.update(out[i - Hmac.mac_length ..][0..Hmac.mac_length]); + } + st.update(ctx); + st.update(&counter); + st.final(out[i..][0..Hmac.mac_length]); + counter[0] += 1; + } + const left = out.len % Hmac.mac_length; + if (left > 0) { + var st = Hmac.init(&prk); + if (i != 0) { + st.update(out[i - Hmac.mac_length ..][0..Hmac.mac_length]); + } + st.update(ctx); + st.update(&counter); + var tmp: [Hmac.mac_length]u8 = undefined; + st.final(tmp[0..Hmac.mac_length]); + mem.copy(u8, out[i..][0..left], tmp[0..left]); + } + } + }; +} + +const htest = @import("test.zig"); + +test "Hkdf" { + const ikm = [_]u8{0x0b} ** 22; + const salt = [_]u8{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c }; + const context = [_]u8{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 }; + const kdf = HkdfSha256; + const prk = kdf.extract(&salt, &ikm); + htest.assertEqual("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", &prk); + var out: [42]u8 = undefined; + kdf.expand(&out, &context, prk); + htest.assertEqual("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", &out); +} diff --git a/lib/std/crypto/poly1305.zig b/lib/std/crypto/poly1305.zig index a95b9d7cb3..c6613f64ba 100644 --- a/lib/std/crypto/poly1305.zig +++ b/lib/std/crypto/poly1305.zig @@ -22,8 +22,7 @@ pub const Poly1305 = struct { // partial block buffer buf: [block_size]u8 align(16) = undefined, - pub fn init(key: []const u8) Poly1305 { - std.debug.assert(key.len >= minimum_key_length); + pub fn init(key: *const [minimum_key_length]u8) Poly1305 { const t0 = mem.readIntLittle(u64, key[0..8]); const t1 = mem.readIntLittle(u64, key[8..16]); return Poly1305{ @@ -92,7 +91,7 @@ pub const Poly1305 = struct { } mb = mb[want..]; st.leftover += want; - if (st.leftover > block_size) { + if (st.leftover < block_size) { return; } st.blocks(&st.buf, false); @@ -115,8 +114,20 @@ pub const Poly1305 = struct { } } - pub fn final(st: *Poly1305, out: []u8) void { - std.debug.assert(out.len >= mac_length); + /// Zero-pad to align the next input to the first byte of a block + pub fn pad(st: *Poly1305) void { + if (st.leftover == 0) { + return; + } + var i = st.leftover; + while (i < block_size) : (i += 1) { + st.buf[i] = 0; + } + st.blocks(&st.buf); + st.leftover = 0; + } + + pub fn final(st: *Poly1305, out: *[mac_length]u8) void { if (st.leftover > 0) { var i = st.leftover; st.buf[i] = 1; @@ -187,10 +198,7 @@ pub const Poly1305 = struct { std.mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Poly1305)]); } - pub fn create(out: []u8, msg: []const u8, key: []const u8) void { - std.debug.assert(out.len >= mac_length); - std.debug.assert(key.len >= minimum_key_length); - + pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void { var st = Poly1305.init(key); st.update(msg); st.final(out); diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 2ed9f938d8..226d5f1d52 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -647,6 +647,31 @@ pub const Loop = struct { } } + /// Runs the provided function asynchronously. The function's frame is allocated + /// with `allocator` and freed when the function returns. + /// `func` must return void and it can be an async function. + /// Yields to the event loop, running the function on the next tick. + pub fn runDetached(self: *Loop, alloc: *mem.Allocator, comptime func: anytype, args: anytype) error{OutOfMemory}!void { + if (!std.io.is_async) @compileError("Can't use runDetached in non-async mode!"); + if (@TypeOf(@call(.{}, func, args)) != void) { + @compileError("`func` must not have a return value"); + } + + const Wrapper = struct { + const Args = @TypeOf(args); + fn run(func_args: Args, loop: *Loop, allocator: *mem.Allocator) void { + loop.yield(); + const result = @call(.{}, func, func_args); + suspend { + allocator.destroy(@frame()); + } + } + }; + + var run_frame = try alloc.create(@Frame(Wrapper.run)); + run_frame.* = async Wrapper.run(args, self, alloc); + } + /// Yielding lets the event loop run, starting any unstarted async operations. /// Note that async operations automatically start when a function yields for any other reason, /// for example, when async I/O is performed. This function is intended to be used only when @@ -1493,3 +1518,33 @@ fn testEventLoop2(h: anyframe->i32, did_it: *bool) void { testing.expect(value == 1234); did_it.* = true; } + +var testRunDetachedData: usize = 0; +test "std.event.Loop - runDetached" { + // https://github.com/ziglang/zig/issues/1908 + if (builtin.single_threaded) return error.SkipZigTest; + if (!std.io.is_async) return error.SkipZigTest; + if (true) { + // https://github.com/ziglang/zig/issues/4922 + return error.SkipZigTest; + } + + var loop: Loop = undefined; + try loop.initMultiThreaded(); + defer loop.deinit(); + + // Schedule the execution, won't actually start until we start the + // event loop. + try loop.runDetached(std.testing.allocator, testRunDetached, .{}); + + // Now we can start the event loop. The function will return only + // after all tasks have been completed, allowing us to synchonize + // with the previous runDetached. + loop.run(); + + testing.expect(testRunDetachedData == 1); +} + +fn testRunDetached() void { + testRunDetachedData += 1; +} diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 56a1aba217..ab2cc1577d 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1181,6 +1181,16 @@ fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, uppercase: bool, opti return buf[0..formatIntBuf(buf, value, base, uppercase, options)]; } +pub fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args)]u8 { + comptime var buf: [count(fmt, args)]u8 = undefined; + _ = bufPrint(&buf, fmt, args) catch unreachable; + return &buf; +} + +test "comptimePrint" { + std.testing.expectEqualSlices(u8, "100", comptime comptimePrint("{}", .{100})); +} + test "parse u64 digit too big" { _ = parseUnsigned(u64, "123a", 10) catch |err| { if (err == error.InvalidCharacter) return; diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 1890d7e136..22d243612a 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -1856,7 +1856,7 @@ pub const Dir = struct { } }; -/// Returns an handle to the current working directory. It is not opened with iteration capability. +/// Returns a handle to the current working directory. It is not opened with iteration capability. /// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior. /// On POSIX targets, this function is comptime-callable. pub fn cwd() Dir { @@ -2162,7 +2162,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File { return openFileAbsoluteZ(buf[0..self_exe_path.len :0].ptr, flags); } -pub const SelfExePathError = os.ReadLinkError || os.SysCtlError; +pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathError; /// `selfExePath` except allocates the result on the heap. /// Caller owns returned memory. @@ -2190,10 +2190,18 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 { /// TODO make the return type of this a null terminated pointer pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 { if (is_darwin) { - var u32_len: u32 = @intCast(u32, math.min(out_buffer.len, math.maxInt(u32))); - const rc = std.c._NSGetExecutablePath(out_buffer.ptr, &u32_len); + // Note that _NSGetExecutablePath() will return "a path" to + // the executable not a "real path" to the executable. + var symlink_path_buf: [MAX_PATH_BYTES:0]u8 = undefined; + var u32_len: u32 = MAX_PATH_BYTES + 1; // include the sentinel + const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len); if (rc != 0) return error.NameTooLong; - return mem.spanZ(@ptrCast([*:0]u8, out_buffer)); + + var real_path_buf: [MAX_PATH_BYTES]u8 = undefined; + const real_path = try std.os.realpathZ(&symlink_path_buf, &real_path_buf); + if (real_path.len > out_buffer.len) return error.NameTooLong; + std.mem.copy(u8, out_buffer, real_path); + return out_buffer[0..real_path.len]; } switch (builtin.os.tag) { .linux => return os.readlinkZ("/proc/self/exe", out_buffer), diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 8d4f5df2e8..bfa6dec3ed 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -615,7 +615,7 @@ pub const File = struct { } } - pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: usize) PWriteError!usize { + pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!usize { if (is_windows) { // TODO improve this to use WriteFileScatter if (iovecs.len == 0) return @as(usize, 0); @@ -632,11 +632,11 @@ pub const File = struct { /// The `iovecs` parameter is mutable because this function needs to mutate the fields in /// order to handle partial writes from the underlying OS layer. - pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: usize) PWriteError!void { + pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!void { if (iovecs.len == 0) return; var i: usize = 0; - var off: usize = 0; + var off: u64 = 0; while (true) { var amt = try self.pwritev(iovecs[i..], offset + off); off += amt; @@ -652,14 +652,16 @@ pub const File = struct { pub const CopyRangeError = os.CopyFileRangeError; - pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) CopyRangeError!usize { - return os.copy_file_range(in.handle, in_offset, out.handle, out_offset, len, 0); + pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 { + const adjusted_len = math.cast(usize, len) catch math.maxInt(usize); + const result = try os.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0); + return result; } /// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it /// means the in file reached the end. Reaching the end of a file is not an error condition. - pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) CopyRangeError!usize { - var total_bytes_copied: usize = 0; + pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 { + var total_bytes_copied: u64 = 0; var in_off = in_offset; var out_off = out_offset; while (total_bytes_copied < len) { diff --git a/lib/std/macho.zig b/lib/std/macho.zig index d3296ee171..bb22991d06 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -1257,3 +1257,47 @@ pub const reloc_type_x86_64 = packed enum(u4) { /// for thread local variables X86_64_RELOC_TLV, }; + +/// This symbol is a reference to an external non-lazy (data) symbol. +pub const REFERENCE_FLAG_UNDEFINED_NON_LAZY: u16 = 0x0; + +/// This symbol is a reference to an external lazy symbol—that is, to a function call. +pub const REFERENCE_FLAG_UNDEFINED_LAZY: u16 = 0x1; + +/// This symbol is defined in this module. +pub const REFERENCE_FLAG_DEFINED: u16 = 0x2; + +/// This symbol is defined in this module and is visible only to modules within this shared library. +pub const REFERENCE_FLAG_PRIVATE_DEFINED: u16 = 3; + +/// This symbol is defined in another module in this file, is a non-lazy (data) symbol, and is visible +/// only to modules within this shared library. +pub const REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY: u16 = 4; + +/// This symbol is defined in another module in this file, is a lazy (function) symbol, and is visible +/// only to modules within this shared library. +pub const REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY: u16 = 5; + +/// Must be set for any defined symbol that is referenced by dynamic-loader APIs (such as dlsym and +/// NSLookupSymbolInImage) and not ordinary undefined symbol references. The strip tool uses this bit +/// to avoid removing symbols that must exist: If the symbol has this bit set, strip does not strip it. +pub const REFERENCED_DYNAMICALLY: u16 = 0x10; + +/// Used by the dynamic linker at runtime. Do not set this bit. +pub const N_DESC_DISCARDED: u16 = 0x20; + +/// Indicates that this symbol is a weak reference. If the dynamic linker cannot find a definition +/// for this symbol, it sets the address of this symbol to 0. The static linker sets this symbol given +/// the appropriate weak-linking flags. +pub const N_WEAK_REF: u16 = 0x40; + +/// Indicates that this symbol is a weak definition. If the static linker or the dynamic linker finds +/// another (non-weak) definition for this symbol, the weak definition is ignored. Only symbols in a +/// coalesced section (page 23) can be marked as a weak definition. +pub const N_WEAK_DEF: u16 = 0x80; + +/// The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the +/// that the function is actually a resolver function and should +/// be called to get the address of the real function to use. +/// This bit is only available in .o files (MH_OBJECT filetype) +pub const N_SYMBOL_RESOLVER: u16 = 0x100; diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 19f6d0809e..54ad2f55d0 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -58,6 +58,11 @@ pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize { return (string_len + (limb_bits / base - 1)) / (limb_bits / base); } +pub fn calcPowLimbsBufferLen(a_bit_count: usize, y: usize) usize { + // The 2 accounts for the minimum space requirement for llmulacc + return 2 + (a_bit_count * y + (limb_bits - 1)) / limb_bits; +} + /// a + b * c + *carry, sets carry to the overflow bits pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb { @setRuntimeSafety(debug_safety); @@ -597,6 +602,52 @@ pub const Mutable = struct { return gcdLehmer(rma, x_copy, y_copy, limbs_buffer); } + /// q = a ^ b + /// + /// r may not alias a. + /// + /// Asserts that `r` has enough limbs to store the result. Upper bound is + /// `calcPowLimbsBufferLen(a.bitCountAbs(), b)`. + /// + /// `limbs_buffer` is used for temporary storage. + /// The amount required is given by `calcPowLimbsBufferLen`. + pub fn pow(r: *Mutable, a: Const, b: u32, limbs_buffer: []Limb) !void { + assert(r.limbs.ptr != a.limbs.ptr); // illegal aliasing + + // Handle all the trivial cases first + switch (b) { + 0 => { + // a^0 = 1 + return r.set(1); + }, + 1 => { + // a^1 = a + return r.copy(a); + }, + else => {}, + } + + if (a.eqZero()) { + // 0^b = 0 + return r.set(0); + } else if (a.limbs.len == 1 and a.limbs[0] == 1) { + // 1^b = 1 and -1^b = ±1 + r.set(1); + r.positive = a.positive or (b & 1) == 0; + return; + } + + // Here a>1 and b>1 + const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b); + assert(r.limbs.len >= needed_limbs); + assert(limbs_buffer.len >= needed_limbs); + + llpow(r.limbs, a.limbs, b, limbs_buffer); + + r.normalize(needed_limbs); + r.positive = a.positive or (b & 1) == 0; + } + /// rma may not alias x or y. /// x and y may alias each other. /// Asserts that `rma` has enough limbs to store the result. Upper bound is given by `calcGcdNoAliasLimbLen`. @@ -1775,6 +1826,29 @@ pub const Managed = struct { try m.gcd(x.toConst(), y.toConst(), &limbs_buffer); rma.setMetadata(m.positive, m.len); } + + pub fn pow(rma: *Managed, a: Managed, b: u32) !void { + const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b); + + const limbs_buffer = try rma.allocator.alloc(Limb, needed_limbs); + defer rma.allocator.free(limbs_buffer); + + if (rma.limbs.ptr == a.limbs.ptr) { + var m = try Managed.initCapacity(rma.allocator, needed_limbs); + errdefer m.deinit(); + var m_mut = m.toMutable(); + try m_mut.pow(a.toConst(), b, limbs_buffer); + m.setMetadata(m_mut.positive, m_mut.len); + + rma.deinit(); + rma.swap(&m); + } else { + try rma.ensureCapacity(needed_limbs); + var rma_mut = rma.toMutable(); + try rma_mut.pow(a.toConst(), b, limbs_buffer); + rma.setMetadata(rma_mut.positive, rma_mut.len); + } + } }; /// Knuth 4.3.1, Algorithm M. @@ -2129,6 +2203,56 @@ fn llxor(r: []Limb, a: []const Limb, b: []const Limb) void { } } +/// Knuth 4.6.3 +fn llpow(r: []Limb, a: []const Limb, b: u32, tmp_limbs: []Limb) void { + var tmp1: []Limb = undefined; + var tmp2: []Limb = undefined; + + // Multiplication requires no aliasing between the operand and the result + // variable, use the output limbs and another temporary set to overcome this + // limitation. + // The initial assignment makes the result end in `r` so an extra memory + // copy is saved, each 1 flips the index twice so it's a no-op so count the + // 0. + const b_leading_zeros = @intCast(u5, @clz(u32, b)); + const exp_zeros = @popCount(u32, ~b) - b_leading_zeros; + if (exp_zeros & 1 != 0) { + tmp1 = tmp_limbs; + tmp2 = r; + } else { + tmp1 = r; + tmp2 = tmp_limbs; + } + + const a_norm = a[0..llnormalize(a)]; + + mem.copy(Limb, tmp1, a_norm); + mem.set(Limb, tmp1[a_norm.len..], 0); + + // Scan the exponent as a binary number, from left to right, dropping the + // most significant bit set. + const exp_bits = @intCast(u5, 31 - b_leading_zeros); + var exp = @bitReverse(u32, b) >> 1 + b_leading_zeros; + + var i: u5 = 0; + while (i < exp_bits) : (i += 1) { + // Square + { + mem.set(Limb, tmp2, 0); + const op = tmp1[0..llnormalize(tmp1)]; + llmulacc(null, tmp2, op, op); + mem.swap([]Limb, &tmp1, &tmp2); + } + // Multiply by a + if (exp & 1 != 0) { + mem.set(Limb, tmp2, 0); + llmulacc(null, tmp2, tmp1[0..llnormalize(tmp1)], a_norm); + mem.swap([]Limb, &tmp1, &tmp2); + } + exp >>= 1; + } +} + // Storage must live for the lifetime of the returned value fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable { assert(storage.len >= 2); diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 9de93e94ac..5d07bee9b5 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -1480,3 +1480,55 @@ test "big.int const to managed" { testing.expect(a.toConst().eq(b.toConst())); } + +test "big.int pow" { + { + var a = try Managed.initSet(testing.allocator, 10); + defer a.deinit(); + + try a.pow(a, 8); + testing.expectEqual(@as(u32, 100000000), try a.to(u32)); + } + { + var a = try Managed.initSet(testing.allocator, 10); + defer a.deinit(); + + var y = try Managed.init(testing.allocator); + defer y.deinit(); + + // y and a are not aliased + try y.pow(a, 123); + // y and a are aliased + try a.pow(a, 123); + + testing.expect(a.eq(y)); + + const ys = try y.toString(testing.allocator, 16, false); + defer testing.allocator.free(ys); + testing.expectEqualSlices( + u8, + "183425a5f872f126e00a5ad62c839075cd6846c6fb0230887c7ad7a9dc530fcb" ++ + "4933f60e8000000000000000000000000000000", + ys, + ); + } + // Special cases + { + var a = try Managed.initSet(testing.allocator, 0); + defer a.deinit(); + + try a.pow(a, 100); + testing.expectEqual(@as(i32, 0), try a.to(i32)); + + try a.set(1); + try a.pow(a, 0); + testing.expectEqual(@as(i32, 1), try a.to(i32)); + try a.pow(a, 100); + testing.expectEqual(@as(i32, 1), try a.to(i32)); + try a.set(-1); + try a.pow(a, 15); + testing.expectEqual(@as(i32, -1), try a.to(i32)); + try a.pow(a, 16); + testing.expectEqual(@as(i32, 1), try a.to(i32)); + } +} diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 492e497ff4..79b0424e96 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -854,6 +854,7 @@ pub fn ArgsTuple(comptime Function: type) type { .field_type = arg.arg_type.?, .default_value = @as(?(arg.arg_type.?), null), .is_comptime = false, + .alignment = @alignOf(arg.arg_type.?), }; } @@ -884,6 +885,7 @@ pub fn Tuple(comptime types: []const type) type { .field_type = T, .default_value = @as(?T, null), .is_comptime = false, + .alignment = @alignOf(T), }; } diff --git a/lib/std/meta/trailer_flags.zig b/lib/std/meta/trailer_flags.zig index c8c1323686..6cd8dc9357 100644 --- a/lib/std/meta/trailer_flags.zig +++ b/lib/std/meta/trailer_flags.zig @@ -47,6 +47,7 @@ pub fn TrailerFlags(comptime Fields: type) type { @as(?struct_field.field_type, null), ), .is_comptime = false, + .alignment = @alignOf(?struct_field.field_type), }; } break :blk @Type(.{ diff --git a/lib/std/os.zig b/lib/std/os.zig index c06ce4ed00..c89f122c63 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3993,7 +3993,7 @@ pub const RealPathError = error{ /// Expands all symbolic links and resolves references to `.`, `..`, and /// extra `/` characters in `pathname`. /// The return value is a slice of `out_buffer`, but not necessarily from the beginning. -/// See also `realpathC` and `realpathW`. +/// See also `realpathZ` and `realpathW`. pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { if (builtin.os.tag == .windows) { const pathname_w = try windows.sliceToPrefixedFileW(pathname); @@ -5410,3 +5410,33 @@ pub fn prctl(option: i32, args: anytype) PrctlError!u31 { else => |err| return std.os.unexpectedErrno(err), } } + +pub const GetrlimitError = UnexpectedError; + +pub fn getrlimit(resource: rlimit_resource) GetrlimitError!rlimit { + // TODO implement for systems other than linux and enable test + var limits: rlimit = undefined; + const rc = system.getrlimit(resource, &limits); + switch (errno(rc)) { + 0 => return limits, + EFAULT => unreachable, // bogus pointer + EINVAL => unreachable, + else => |err| return std.os.unexpectedErrno(err), + } +} + +pub const SetrlimitError = error{ + PermissionDenied, +} || UnexpectedError; + +pub fn setrlimit(resource: rlimit_resource, limits: rlimit) SetrlimitError!void { + // TODO implement for systems other than linux and enable test + const rc = system.setrlimit(resource, &limits); + switch (errno(rc)) { + 0 => return, + EFAULT => unreachable, // bogus pointer + EINVAL => unreachable, + EPERM => return error.PermissionDenied, + else => |err| return std.os.unexpectedErrno(err), + } +} diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index df31bc32fd..1ead0c7961 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -1890,3 +1890,79 @@ pub const ifreq = extern struct { data: ?[*]u8, }, }; + +// doc comments copied from musl +pub const rlimit_resource = extern enum(c_int) { + /// Per-process CPU limit, in seconds. + CPU, + + /// Largest file that can be created, in bytes. + FSIZE, + + /// Maximum size of data segment, in bytes. + DATA, + + /// Maximum size of stack segment, in bytes. + STACK, + + /// Largest core file that can be created, in bytes. + CORE, + + /// Largest resident set size, in bytes. + /// This affects swapping; processes that are exceeding their + /// resident set size will be more likely to have physical memory + /// taken from them. + RSS, + + /// Number of processes. + NPROC, + + /// Number of open files. + NOFILE, + + /// Locked-in-memory address space. + MEMLOCK, + + /// Address space limit. + AS, + + /// Maximum number of file locks. + LOCKS, + + /// Maximum number of pending signals. + SIGPENDING, + + /// Maximum bytes in POSIX message queues. + MSGQUEUE, + + /// Maximum nice priority allowed to raise to. + /// Nice levels 19 .. -20 correspond to 0 .. 39 + /// values of this resource limit. + NICE, + + /// Maximum realtime priority allowed for non-priviledged + /// processes. + RTPRIO, + + /// Maximum CPU time in µs that a process scheduled under a real-time + /// scheduling policy may consume without making a blocking system + /// call before being forcibly descheduled. + RTTIME, + + _, +}; + +pub const rlim_t = u64; + +/// No limit +pub const RLIM_INFINITY = ~@as(rlim_t, 0); + +pub const RLIM_SAVED_MAX = RLIM_INFINITY; +pub const RLIM_SAVED_CUR = RLIM_INFINITY; + +pub const rlimit = extern struct { + /// Soft limit + cur: rlim_t, + /// Hard limit + max: rlim_t, +}; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 50d1e4ae78..e38d9bc10d 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1263,6 +1263,26 @@ pub fn prctl(option: i32, arg2: usize, arg3: usize, arg4: usize, arg5: usize) us return syscall5(.prctl, @bitCast(usize, @as(isize, option)), arg2, arg3, arg4, arg5); } +pub fn getrlimit(resource: rlimit_resource, rlim: *rlimit) usize { + // use prlimit64 to have 64 bit limits on 32 bit platforms + return prlimit(0, resource, null, rlim); +} + +pub fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) usize { + // use prlimit64 to have 64 bit limits on 32 bit platforms + return prlimit(0, resource, rlim, null); +} + +pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit, old_limit: ?*rlimit) usize { + return syscall4( + .prlimit64, + @bitCast(usize, @as(isize, pid)), + @bitCast(usize, @as(isize, @enumToInt(resource))), + @ptrToInt(new_limit), + @ptrToInt(old_limit) + ); +} + test "" { if (builtin.os.tag == .linux) { _ = @import("linux/test.zig"); diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 0a453d8b2e..aee1b9549a 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -591,3 +591,13 @@ test "fsync" { try os.fsync(file.handle); try os.fdatasync(file.handle); } + +test "getrlimit and setrlimit" { + // TODO enable for other systems when implemented + if(builtin.os.tag != .linux){ + return error.SkipZigTest; + } + + const cpuLimit = try os.getrlimit(.CPU); + try os.setrlimit(.CPU, cpuLimit); +} diff --git a/lib/std/packed_int_array.zig b/lib/std/packed_int_array.zig index de99afa303..f25ff0b1b8 100644 --- a/lib/std/packed_int_array.zig +++ b/lib/std/packed_int_array.zig @@ -318,9 +318,12 @@ pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian) }; } +const we_are_testing_this_with_stage1_which_leaks_comptime_memory = true; + test "PackedIntArray" { // TODO @setEvalBranchQuota generates panics in wasm32. Investigate. if (builtin.arch == .wasm32) return error.SkipZigTest; + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; @setEvalBranchQuota(10000); const max_bits = 256; @@ -358,6 +361,7 @@ test "PackedIntArray" { } test "PackedIntArray init" { + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; const PackedArray = PackedIntArray(u3, 8); var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 }); var i = @as(usize, 0); @@ -367,6 +371,7 @@ test "PackedIntArray init" { test "PackedIntSlice" { // TODO @setEvalBranchQuota generates panics in wasm32. Investigate. if (builtin.arch == .wasm32) return error.SkipZigTest; + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; @setEvalBranchQuota(10000); const max_bits = 256; @@ -405,6 +410,7 @@ test "PackedIntSlice" { } test "PackedIntSlice of PackedInt(Array/Slice)" { + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; const max_bits = 16; const int_count = 19; @@ -470,6 +476,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)" { } test "PackedIntSlice accumulating bit offsets" { + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; //bit_offset is u3, so standard debugging asserts should catch // anything { @@ -497,6 +504,8 @@ test "PackedIntSlice accumulating bit offsets" { //@NOTE: As I do not have a big endian system to test this on, // big endian values were not tested test "PackedInt(Array/Slice) sliceCast" { + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; + const PackedArray = PackedIntArray(u1, 16); var packed_array = PackedArray.init([_]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }); const packed_slice_cast_2 = packed_array.sliceCast(u2); @@ -537,6 +546,8 @@ test "PackedInt(Array/Slice) sliceCast" { } test "PackedInt(Array/Slice)Endian" { + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; + { const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8); var packed_array_be = PackedArrayBe.init([_]u4{ 0, 1, 2, 3, 4, 5, 6, 7 }); @@ -604,6 +615,8 @@ test "PackedInt(Array/Slice)Endian" { // after this one is not mapped and will cause a segfault if we // don't account for the bounds. test "PackedIntArray at end of available memory" { + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; + switch (builtin.os.tag) { .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {}, else => return, @@ -623,6 +636,8 @@ test "PackedIntArray at end of available memory" { } test "PackedIntSlice at end of available memory" { + if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; + switch (builtin.os.tag) { .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {}, else => return, diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index d13d0b22ef..b1947058cc 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -213,6 +213,8 @@ pub const NativeTargetInfo = struct { // kernel version const kernel_version = if (mem.indexOfScalar(u8, release, '-')) |pos| release[0..pos] + else if (mem.indexOfScalar(u8, release, '_')) |pos| + release[0..pos] else release; |
