CI: build windows clang-cl

This commit is contained in:
Megamouse 2025-06-13 02:05:15 +02:00
parent c69d7bc758
commit 67a4b020fc
12 changed files with 338 additions and 24 deletions

View file

@ -0,0 +1,139 @@
# .ci/build-windows-clang-cl.ps1
# Enable strict error handling
$ErrorActionPreference = "Stop"
trap {
Write-Host "ERROR: $($_.Exception.Message)"
exit 1
}
Write-Host "Starting RPCS3 build (PowerShell script)"
# Automatically find clang_rt.builtins-x86_64.lib
Write-Host "Searching for clang_rt.builtins-x86_64.lib ..."
$clangBuiltinsLibPath = Get-ChildItem -Path "C:/Program Files/LLVM/lib/clang" -Recurse -Filter "clang_rt.builtins-x86_64.lib" -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -match "windows\\clang_rt\.builtins-x86_64\.lib$" } |
Select-Object -First 1
if (-not $clangBuiltinsLibPath) {
Write-Error "Could not find clang_rt.builtins-x86_64.lib in LLVM installation."
exit 1
}
function Get-ShortPath([string]$path) {
$fso = New-Object -ComObject Scripting.FileSystemObject
return $fso.GetFolder($path).ShortPath
}
$clangBuiltinsDir = Split-Path -Parent $clangBuiltinsLibPath.FullName
$clangBuiltinsDirShort = Get-ShortPath $clangBuiltinsDir
$clangBuiltinsLib = Split-Path -Leaf $clangBuiltinsLibPath.FullName
$clangPath = "C:/Program Files/LLVM/bin"
Write-Host "Found Clang builtins library: $clangBuiltinsLib in $clangBuiltinsDir or short $clangBuiltinsDirShort"
# Get Windows Kits root from registry
$kitsRoot = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name "KitsRoot10"
$kitsRootPath = $kitsRoot.KitsRoot10
# Search for mt.exe in x64 SDK bin directories
Write-Host "Searching for mt.exe ..."
$mtPath = Get-ChildItem -Path "$kitsRootPath\bin" -Recurse -Filter "mt.exe" -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -match "\\x64\\mt\.exe$" } |
Sort-Object FullName -Descending |
Select-Object -First 1
if (-not $mtPath) {
Write-Error "Could not find mt.exe in Windows Kits directories."
exit 1
}
$mtExePath = $mtPath.FullName
Write-Host "Found mt.exe at: $mtExePath"
$VcpkgRoot="$(Get-Location)/vcpkg"
$VcpkgTriplet=$env:VCPKG_TRIPLET
$VcpkgInclude="$VcpkgRoot/installed/$VcpkgTriplet/include"
$VcpkgLib="$VcpkgRoot/installed/$VcpkgTriplet/lib"
# Configure git safe directory
Write-Host "Configuring git safe directory"
& git config --global --add safe.directory '*'
# Initialize submodules except certain ones
Write-Host "Initializing submodules"
$excludedSubs = @('llvm','opencv','ffmpeg','FAudio','zlib','libpng','feralinteractive')
# Get submodule paths excluding those in $excludedSubs
$submodules = Select-String -Path .gitmodules -Pattern 'path = (.+)' | ForEach-Object {
$_.Matches[0].Groups[1].Value
} | Where-Object {
$path = $_
-not ($excludedSubs | Where-Object { $path -like "*$_*" })
}
Write-Host "Updating submodules: $($submodules -join ', ')"
& git submodule update --init --quiet $submodules
# Create and enter build directory
Write-Host "Creating build directory"
if (!(Test-Path build)) {
New-Item -ItemType Directory -Path build | Out-Null
}
Set-Location build
Write-Host "Changed directory to: $(Get-Location)"
# Run CMake with Ninja generator and required flags
Write-Host "Running CMake configuration"
& cmake .. `
-G Ninja `
-DCMAKE_BUILD_TYPE=Release `
-DCMAKE_C_COMPILER="$clangPath/clang-cl.exe" `
-DCMAKE_CXX_COMPILER="$clangPath/clang-cl.exe" `
-DCMAKE_LINKER="$clangPath/lld-link.exe" `
-DCMAKE_INSTALL_PREFIX=/usr `
-DCMAKE_TOOLCHAIN_FILE="$VcpkgRoot/scripts/buildsystems/vcpkg.cmake" `
-DCMAKE_EXE_LINKER_FLAGS="/LIBPATH:$clangBuiltinsDirShort /defaultlib:$clangBuiltinsLib" `
-DCMAKE_MT="$mtExePath" `
-DUSE_NATIVE_INSTRUCTIONS=OFF `
-DUSE_PRECOMPILED_HEADERS=OFF `
-DVCPKG_TARGET_TRIPLET="$VcpkgTriplet" `
-DFFMPEG_INCLUDE_DIR="$VcpkgInclude" `
-DFFMPEG_LIBAVCODEC="$VcpkgLib/avcodec.lib" `
-DFFMPEG_LIBAVFORMAT="$VcpkgLib/avformat.lib" `
-DFFMPEG_LIBAVUTIL="$VcpkgLib/avutil.lib" `
-DFFMPEG_LIBSWSCALE="$VcpkgLib/swscale.lib" `
-DFFMPEG_LIBSWRESAMPLE="$VcpkgLib/swresample.lib" `
-DUSE_SYSTEM_CURL=OFF `
-DUSE_FAUDIO=OFF `
-DUSE_SDL=ON `
-DUSE_SYSTEM_SDL=OFF `
-DUSE_SYSTEM_FFMPEG=ON `
-DUSE_SYSTEM_OPENCV=ON `
-DUSE_SYSTEM_OPENAL=OFF `
-DUSE_SYSTEM_LIBPNG=ON `
-DUSE_DISCORD_RPC=ON `
-DOpenGL_GL_PREFERENCE=LEGACY `
-DWITH_LLVM=ON `
-DSTATIC_LINK_LLVM=ON `
-DBUILD_RPCS3_TESTS=OFF `
-DRUN_RPCS3_TESTS=OFF
Write-Host "CMake configuration complete"
# Build with ninja
Write-Host "Starting build with Ninja..."
& ninja
if ($LASTEXITCODE -ne 0) {
Write-Host "Build failed with exit code $LASTEXITCODE"
exit 1
}
Write-Host "Build succeeded"
# Go back to root directory
Set-Location ..
Write-Host "Returned to root directory: $(Get-Location)"
# Deploy if build succeeded
Write-Host "Running deployment script"
& .ci/deploy-windows-clang-cl.sh x86_64

View file

@ -0,0 +1,29 @@
#!/bin/sh -ex
cd build || exit 1
CPU_ARCH="${1:-x86_64}"
echo "Deploying rpcs3 windows clang-cl $CPU_ARCH"
# BUILD_blablabla is CI specific, so we wrap it for portability
ARTIFACT_DIR=$(cygpath -u "$BUILD_ARTIFACTSTAGINGDIRECTORY")
# Prepare compatibility and SDL database for packaging
mkdir ./bin/config
mkdir ./bin/config/input_configs
curl -fsSL 'https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt' 1> ./bin/config/input_configs/gamecontrollerdb.txt
curl -fsSL 'https://rpcs3.net/compatibility?api=v1&export' | iconv -t UTF-8 1> ./bin/GuiConfigs/compat_database.dat
# Package artifacts
7z a -m0=LZMA2 -mx9 "$BUILD" ./bin/*
# Generate sha256 hashes
# Write to file for GitHub releases
sha256sum "$BUILD" | awk '{ print $1 }' | tee "$BUILD.sha256"
echo "$(cat "$BUILD.sha256");$(stat -c %s "$BUILD")B" > GitHubReleaseMessage.txt
# Move files to publishing directory
mkdir -p "$ARTIFACT_DIR"
cp -- "$BUILD" "$ARTIFACT_DIR"
cp -- "$BUILD.sha256" "$ARTIFACT_DIR"

View file

@ -5,8 +5,6 @@ defaults:
shell: bash shell: bash
on: on:
push: push:
branches:
- master # Only trigger push event on 'master' branch
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
@ -404,6 +402,106 @@ jobs:
compression-level: 0 compression-level: 0
if-no-files-found: error if-no-files-found: error
Windows_Build_ClangCL:
if: always()
name: RPCS3 Windows Clang-CL
runs-on: windows-2025
strategy:
matrix:
include:
- compiler: clangcl
arch: win64
env:
CCACHE_DIR: 'C:\ccache'
VCPKG_TRIPLET: x64-windows-release
steps:
- name: Checkout repository
uses: actions/checkout@main
with:
fetch-depth: 0
- name: Clone vcpkg
run: git clone https://github.com/microsoft/vcpkg.git
- name: Bootstrap vcpkg
shell: pwsh
run: .\vcpkg\bootstrap-vcpkg.bat
- name: Restore vcpkg cache
uses: actions/cache/restore@main
id: restore-vcpkg-cache
with:
path: |
vcpkg/installed
vcpkg/buildtrees
key: vcpkg-${{ runner.os }}-${{ matrix.compiler }}-${{ runner.arch }}-${{ github.run_id }}
restore-keys: vcpkg-${{ runner.os }}-${{ matrix.compiler }}-${{ runner.arch }}-
- name: Install dependencies with vcpkg
shell: pwsh
run: |
.\vcpkg\vcpkg.exe install `
ffmpeg[avcodec,avformat,swscale,swresample] `
llvm `
opencv `
qtbase `
qtsvg `
qtmultimedia `
zlib `
vulkan `
libpng `
--triplet $env:VCPKG_TRIPLET `
--clean-after-build
- name: Save vcpkg cache
if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main
with:
path: |
vcpkg/installed
vcpkg/buildtrees
key: ${{ steps.restore-vcpkg-cache.outputs.cache-primary-key }}
- name: Add LLVM and Ninja to PATH
shell: pwsh
run: |
Add-Content -Path $env:GITHUB_PATH -Value "C:\Program Files\LLVM\bin"
Add-Content -Path $env:GITHUB_PATH -Value "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin"
Add-Content -Path $env:GITHUB_PATH -Value "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin"
Add-Content -Path $env:GITHUB_PATH -Value "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja"
- name: Restore build Ccache
uses: actions/cache/restore@main
id: restore-build-ccache
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}-${{ github.run_id }}
restore-keys: ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}-
- name: Setup CI Variables
run: .ci/setup-windows-ci-vars.sh ${{ matrix.arch }} ${{ matrix.compiler }}
- name: Build RPCS3
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64
powershell -ExecutionPolicy Bypass -File .ci/build-windows-clang-cl.ps1
- name: Save build Ccache
if: github.ref == 'refs/heads/master'
uses: actions/cache/save@main
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }}
- name: Upload artifacts
uses: actions/upload-artifact@main
with:
name: RPCS3 for Windows (clang-cl)
path: ${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }}
compression-level: 0
if-no-files-found: error
FreeBSD_Build: FreeBSD_Build:
# Only run push event on master branch of main repo, but run all PRs # Only run push event on master branch of main repo, but run all PRs
if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master')

View file

@ -58,9 +58,14 @@ if(WITH_LLVM)
else() else()
message(STATUS "Using prebuilt or system LLVM") message(STATUS "Using prebuilt or system LLVM")
if (LLVM_DIR AND NOT IS_ABSOLUTE "${LLVM_DIR}") if (LLVM_DIR)
message(STATUS "LLVM_DIR: ${LLVM_DIR}")
if (NOT IS_ABSOLUTE "${LLVM_DIR}")
# change relative LLVM_DIR to be relative to the source dir # change relative LLVM_DIR to be relative to the source dir
set(LLVM_DIR ${CMAKE_SOURCE_DIR}/${LLVM_DIR}) set(LLVM_DIR ${CMAKE_SOURCE_DIR}/${LLVM_DIR})
message(STATUS "Changed LLVM_DIR to relative path: ${LLVM_DIR}")
endif()
endif() endif()
find_package(LLVM CONFIG) find_package(LLVM CONFIG)

View file

@ -4,7 +4,11 @@ set(OPENCV_TARGET 3rdparty_dummy_lib PARENT_SCOPE)
if (USE_SYSTEM_OPENCV) if (USE_SYSTEM_OPENCV)
message(STATUS "RPCS3: using system OpenCV") message(STATUS "RPCS3: using system OpenCV")
find_package(OpenCV CONFIG COMPONENTS core photo)
if(NOT OPENCV_FOUND)
find_package(OpenCV COMPONENTS core photo) find_package(OpenCV COMPONENTS core photo)
endif()
if(OPENCV_FOUND) if(OPENCV_FOUND)
message(STATUS "RPCS3: found system OpenCV") message(STATUS "RPCS3: found system OpenCV")

View file

@ -22,5 +22,17 @@ else()
add_subdirectory(wolfssl EXCLUDE_FROM_ALL) add_subdirectory(wolfssl EXCLUDE_FROM_ALL)
target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP FP_MAX_BITS=8192 WOLFSSL_NO_OPTIONS_H) target_compile_definitions(wolfssl PUBLIC WOLFSSL_DES_ECB HAVE_WRITE_DUP WOLFSSL_NO_OPTIONS_H)
if(MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Disable 128-bit Math
set(WOLFSSL_ASM ON CACHE BOOL "" FORCE)
set(WOLFSSL_FAST_MATH OFF CACHE BOOL "" FORCE)
target_compile_definitions(wolfssl PUBLIC WOLFSSL_SP_NO_128BIT FP_MAX_BITS=4096)
# Disable warnings
target_compile_options(wolfssl PRIVATE /w)
else()
target_compile_definitions(wolfssl PUBLIC FP_MAX_BITS=8192)
endif()
endif() endif()

View file

@ -116,8 +116,10 @@ if(MSVC)
message(AUTHOR_WARNING "Debug build currently can not work with static CRT.") message(AUTHOR_WARNING "Debug build currently can not work with static CRT.")
endif() endif()
endif() endif()
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(/MP) add_compile_options(/MP)
endif() endif()
endif()
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8) if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." ) message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." )

View file

@ -525,7 +525,7 @@ void fmt_class_string<u128>::format(std::string& out, u64 arg)
return; return;
} }
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
fmt::append(out, "0x%016llx%016llx", num.hi, num.lo); fmt::append(out, "0x%016llx%016llx", num.hi, num.lo);
#else #else
fmt::append(out, "0x%016llx%016llx", static_cast<u64>(num >> 64), static_cast<u64>(num)); fmt::append(out, "0x%016llx%016llx", static_cast<u64>(num >> 64), static_cast<u64>(num));

View file

@ -1,11 +1,20 @@
# Check and configure compiler options for RPCS3 # Check and configure compiler options for RPCS3
if(MSVC) if(MSVC)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
check_cxx_compiler_flag("-msse -msse2 -mcx16" COMPILER_X86)
if (COMPILER_X86)
add_compile_options(-msse -msse2 -mcx16 -mavx -mavx2 -mavx512f -mavx512vbmi -mavx512vl -mavx512dq -mavx512vpopcntdq -maes -mrtm -mpclmul -mmwaitx -mwaitpkg)
endif()
add_link_options(/dynamicbase)
else()
add_compile_options(/Zc:throwingNew- /constexpr:steps16777216) add_compile_options(/Zc:throwingNew- /constexpr:steps16777216)
add_link_options(/DYNAMICBASE)
endif()
add_compile_definitions( add_compile_definitions(
_CRT_SECURE_NO_DEPRECATE=1 _CRT_NON_CONFORMING_SWPRINTFS=1 _SCL_SECURE_NO_WARNINGS=1 _CRT_SECURE_NO_DEPRECATE=1 _CRT_NON_CONFORMING_SWPRINTFS=1 _SCL_SECURE_NO_WARNINGS=1
NOMINMAX _ENABLE_EXTENDED_ALIGNED_STORAGE=1 _HAS_EXCEPTIONS=0) NOMINMAX _ENABLE_EXTENDED_ALIGNED_STORAGE=1 _HAS_EXCEPTIONS=0)
add_link_options(/DYNAMICBASE)
#TODO: Some of these could be cleaned up #TODO: Some of these could be cleaned up
add_compile_options(/wd4805) # Comparing boolean and int add_compile_options(/wd4805) # Comparing boolean and int

View file

@ -197,6 +197,21 @@ void aesni_gcm_mult( unsigned char c[16],
const unsigned char b[16] ) const unsigned char b[16] )
{ {
#if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS) #if defined(POLARSSL_HAVE_MSVC_X64_INTRINSICS)
#ifdef __clang__
__m128i xa, xb, m0, m1, x10, x32, r;
xa[1] = _byteswap_uint64( *((unsigned __int64*)a + 0) );
xa[0] = _byteswap_uint64( *((unsigned __int64*)a + 1) );
xb[1] = _byteswap_uint64( *((unsigned __int64*)b + 0) );
xb[0] = _byteswap_uint64( *((unsigned __int64*)b + 1) );
clmul256( xa, xb, &m0, &m1 );
sll256( m0, m1, &x10, &x32 );
r = reducemod128( x10, x32 );
*((unsigned __int64*)c + 0) = _byteswap_uint64( r[1] );
*((unsigned __int64*)c + 1) = _byteswap_uint64( r[0] );
#else
__m128i xa, xb, m0, m1, x10, x32, r; __m128i xa, xb, m0, m1, x10, x32, r;
xa.m128i_u64[1] = _byteswap_uint64( *((unsigned __int64*)a + 0) ); xa.m128i_u64[1] = _byteswap_uint64( *((unsigned __int64*)a + 0) );
@ -210,6 +225,7 @@ void aesni_gcm_mult( unsigned char c[16],
*((unsigned __int64*)c + 0) = _byteswap_uint64( r.m128i_u64[1] ); *((unsigned __int64*)c + 0) = _byteswap_uint64( r.m128i_u64[1] );
*((unsigned __int64*)c + 1) = _byteswap_uint64( r.m128i_u64[0] ); *((unsigned __int64*)c + 1) = _byteswap_uint64( r.m128i_u64[0] );
#endif
#else #else
unsigned char aa[16], bb[16], cc[16]; unsigned char aa[16], bb[16], cc[16];
size_t i; size_t i;

View file

@ -9,7 +9,7 @@ extern bool g_use_rtm;
extern u64 g_rtm_tx_limit1; extern u64 g_rtm_tx_limit1;
#ifdef _M_X64 #ifdef _M_X64
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
extern "C" extern "C"
{ {
u32 _xbegin(); u32 _xbegin();
@ -242,7 +242,7 @@ namespace utils
constexpr u32 popcnt128(const u128& v) constexpr u32 popcnt128(const u128& v)
{ {
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
return popcnt64(v.lo) + popcnt64(v.hi); return popcnt64(v.lo) + popcnt64(v.hi);
#else #else
return popcnt64(v) + popcnt64(v >> 64); return popcnt64(v) + popcnt64(v >> 64);
@ -274,7 +274,7 @@ namespace utils
inline s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr) inline s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
{ {
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
s64 rem = 0; s64 rem = 0;
s64 r = _div128(high, low, divisor, &rem); s64 r = _div128(high, low, divisor, &rem);
@ -296,7 +296,7 @@ namespace utils
inline u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr) inline u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
{ {
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
u64 rem = 0; u64 rem = 0;
u64 r = _udiv128(high, low, divisor, &rem); u64 r = _udiv128(high, low, divisor, &rem);
@ -316,7 +316,7 @@ namespace utils
return r; return r;
} }
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
inline u128 operator/(u128 lhs, u64 rhs) inline u128 operator/(u128 lhs, u64 rhs)
{ {
u64 rem = 0; u64 rem = 0;
@ -326,7 +326,7 @@ namespace utils
constexpr u32 ctz128(u128 arg) constexpr u32 ctz128(u128 arg)
{ {
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
if (!arg.lo) if (!arg.lo)
return std::countr_zero(arg.hi) + 64u; return std::countr_zero(arg.hi) + 64u;
else else
@ -341,7 +341,7 @@ namespace utils
constexpr u32 clz128(u128 arg) constexpr u32 clz128(u128 arg)
{ {
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
if (arg.hi) if (arg.hi)
return std::countl_zero(arg.hi); return std::countl_zero(arg.hi);
else else
@ -470,6 +470,6 @@ namespace utils
using utils::busy_wait; using utils::busy_wait;
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
using utils::operator/; using utils::operator/;
#endif #endif

View file

@ -249,13 +249,13 @@ public:
} }
}; };
#if defined(ARCH_X64) && !defined(_MSC_VER) #if defined(ARCH_X64) && !defined(_MSC_VER) && !defined(__m128)
using __m128i = long long __attribute__((vector_size(16))); using __m128i = long long __attribute__((vector_size(16)));
using __m128d = double __attribute__((vector_size(16))); using __m128d = double __attribute__((vector_size(16)));
using __m128 = float __attribute__((vector_size(16))); using __m128 = float __attribute__((vector_size(16)));
#endif #endif
#ifndef _MSC_VER #if !defined(_MSC_VER) || defined(__clang__)
using u128 = __uint128_t; using u128 = __uint128_t;
using s128 = __int128_t; using s128 = __int128_t;
#else #else
@ -266,8 +266,8 @@ extern "C"
union __m128i; union __m128i;
struct __m128d; struct __m128d;
uchar _addcarry_u64(uchar, u64, u64, u64*); constexpr uchar _addcarry_u64(uchar, u64, u64, u64*);
uchar _subborrow_u64(uchar, u64, u64, u64*); constexpr uchar _subborrow_u64(uchar, u64, u64, u64*);
u64 __shiftleft128(u64, u64, uchar); u64 __shiftleft128(u64, u64, uchar);
u64 __shiftright128(u64, u64, uchar); u64 __shiftright128(u64, u64, uchar);
u64 _umul128(u64, u64, u64*); u64 _umul128(u64, u64, u64*);
@ -579,7 +579,7 @@ struct s128 : u128
// Optimization for u64*u64=u128 // Optimization for u64*u64=u128
constexpr u128 u128_from_mul(u64 a, u64 b) constexpr u128 u128_from_mul(u64 a, u64 b)
{ {
#ifdef _MSC_VER #if defined(_MSC_VER) && !defined(__clang__)
if (!std::is_constant_evaluated()) if (!std::is_constant_evaluated())
{ {
u64 hi; u64 hi;