diff --git a/.github/matrix.php b/.github/matrix.php index dec8c7d249c6..18c2ef1269b7 100644 --- a/.github/matrix.php +++ b/.github/matrix.php @@ -144,12 +144,15 @@ function select_jobs($repository, $trigger, $nightly, $labels, $php_version, $re $jobs['SOLARIS'] = true; } if ($all_jobs || !$no_jobs || $test_windows) { - $jobs['WINDOWS']['matrix'] = $all_variations - ? ['include' => [ - ['asan' => true, 'opcache' => true, 'x64' => true, 'zts' => true], - ['asan' => false, 'opcache' => false, 'x64' => false, 'zts' => false], - ]] - : ['include' => [['asan' => false, 'opcache' => true, 'x64' => true, 'zts' => true]]]; + $matrix = [['asan' => false, 'opcache' => true, 'x64' => true, 'zts' => true]]; + if ($all_variations) { + $matrix[] = ['asan' => true, 'opcache' => true, 'x64' => true, 'zts' => true]; + $matrix[] = ['asan' => false, 'opcache' => false, 'x64' => false, 'zts' => false]; + if (version_compare($php_version, '8.5', '>=')) { + $matrix[] = ['asan' => false, 'opcache' => true, 'x64' => true, 'zts' => true, 'clang' => true]; + } + } + $jobs['WINDOWS']['matrix'] = ['include' => $matrix]; $jobs['WINDOWS']['config'] = version_compare($php_version, '8.4', '>=') ? ['vs_crt_version' => 'vs17'] : ['vs_crt_version' => 'vs16']; diff --git a/.github/scripts/windows/build_task.bat b/.github/scripts/windows/build_task.bat index b65479451849..1177cef3be4d 100644 --- a/.github/scripts/windows/build_task.bat +++ b/.github/scripts/windows/build_task.bat @@ -26,12 +26,18 @@ if %errorlevel% neq 0 exit /b 3 if "%THREAD_SAFE%" equ "0" set ADD_CONF=%ADD_CONF% --disable-zts if "%INTRINSICS%" neq "" set ADD_CONF=%ADD_CONF% --enable-native-intrinsics=%INTRINSICS% if "%ASAN%" equ "1" set ADD_CONF=%ADD_CONF% --enable-sanitizer --enable-debug-pack +if "%CLANG_TOOLSET%" equ "1" set ADD_CONF=%ADD_CONF% --with-toolset=clang rem C4018: comparison: signed/unsigned mismatch rem C4146: unary minus operator applied to unsigned type rem C4244: type conversion, possible loss of data rem C4267: 'size_t' type conversion, possible loss of data -set CFLAGS=/W3 /WX /wd4018 /wd4146 /wd4244 /wd4267 +if "%CLANG_TOOLSET%" equ "1" ( + rem Clang is much stricter than MSVC, produces too many warnings that would fail the build with /WX + set CFLAGS=/W3 /wd4018 /wd4146 /wd4244 /wd4267 +) else ( + set CFLAGS=/W3 /WX /wd4018 /wd4146 /wd4244 /wd4267 +) cmd /c configure.bat ^ --enable-snapshot-build ^ diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 90bcafd16307..4905dcb9ccbc 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -940,7 +940,7 @@ jobs: strategy: fail-fast: false matrix: ${{ fromJson(inputs.branch).jobs.WINDOWS.matrix }} - name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || ''}}" + name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || ''}}${{ matrix.clang && '_CLANG' || ''}}" runs-on: windows-2022 env: PHP_BUILD_CACHE_BASE_DIR: C:\build-cache @@ -954,6 +954,7 @@ jobs: PARALLEL: -j2 OPCACHE: "${{ matrix.opcache && '1' || '0' }}" ASAN: "${{ matrix.asan && '1' || '0' }}" + CLANG_TOOLSET: "${{ matrix.clang && '1' || '0' }}" steps: - name: git config run: git config --global core.autocrlf false && git config --global core.eol lf diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h index 80d6cbad0443..ea13552c8374 100644 --- a/TSRM/TSRM.h +++ b/TSRM/TSRM.h @@ -175,9 +175,14 @@ TSRM_API bool tsrm_is_managed_thread(void); #define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)]) #define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element) #define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset))) +#ifdef __cplusplus +#define TSRMLS_MAIN_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR; } +#define TSRMLS_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE; } +#else #define TSRMLS_MAIN_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR; -#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL; #define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE; +#endif +#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL; #define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL; #define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache() #define TSRMLS_CACHE _tsrm_ls_cache diff --git a/win32/build/confutils.js b/win32/build/confutils.js index 36484e71f8fb..fd1e9ce0be10 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -3361,7 +3361,7 @@ function toolset_setup_common_cflags() ADD_FLAG("CFLAGS", "/Zc:wchar_t"); } else if (CLANG_TOOLSET) { - ADD_FLAG("CFLAGS", "-Wno-deprecated-declarations"); + ADD_FLAG("CFLAGS", "-Wno-deprecated-declarations -Wno-microsoft-enum-forward-reference"); if (TARGET_ARCH == 'x86') { ADD_FLAG('CFLAGS', '-m32'); } else { @@ -3395,24 +3395,25 @@ function toolset_setup_intrinsic_cflags() /* From oldest to newest. */ var scale = new Array("sse", "sse2", "sse3", "ssse3", "sse4.1", "sse4.2", "avx", "avx2", "avx512"); - if (VS_TOOLSET) { - if ("disabled" == PHP_NATIVE_INTRINSICS) { - ERROR("Can't enable intrinsics, --with-codegen-arch passed with an incompatible option. ") - } + if ("disabled" == PHP_NATIVE_INTRINSICS) { + ERROR("Can't enable intrinsics, --with-codegen-arch passed with an incompatible option. ") + } - if (TARGET_ARCH == 'arm64') { - /* arm64 supports neon */ - configure_subst.Add("PHP_SIMD_SCALE", 'NEON'); - /* all officially supported arm64 cpu supports crc32 (TODO: to be confirmed) */ - AC_DEFINE('HAVE_ARCH64_CRC32', 1); - return; - } + if (TARGET_ARCH == 'arm64') { + /* arm64 supports neon */ + configure_subst.Add("PHP_SIMD_SCALE", 'NEON'); + /* all officially supported arm64 cpu supports crc32 (TODO: to be confirmed) */ + AC_DEFINE('HAVE_ARCH64_CRC32', 1); + return; + } - if ("no" == PHP_NATIVE_INTRINSICS || "yes" == PHP_NATIVE_INTRINSICS) { - PHP_NATIVE_INTRINSICS = default_enabled; - } + // if --enable-native-intrisics is not specified, it's "no" - enable default + if ("no" == PHP_NATIVE_INTRINSICS || "yes" == PHP_NATIVE_INTRINSICS) { + PHP_NATIVE_INTRINSICS = default_enabled; + } - if ("all" == PHP_NATIVE_INTRINSICS) { + if ("all" == PHP_NATIVE_INTRINSICS) { + if (VS_TOOLSET) { var list = (new VBArray(avail.Keys())).toArray(); for (var i in list) { @@ -3421,46 +3422,61 @@ function toolset_setup_intrinsic_cflags() /* All means all. __AVX__, __AVX2__, and __AVX512*__ are defined by compiler. */ ADD_FLAG("CFLAGS","/arch:AVX512"); - configure_subst.Add("PHP_SIMD_SCALE", "AVX512"); - } else { - var list = PHP_NATIVE_INTRINSICS.split(","); - var j = 0; - for (var k = 0; k < scale.length; k++) { - for (var i = 0; i < list.length; i++) { - var it = list[i].toLowerCase(); - if (scale[k] == it) { - j = k > j ? k : j; - } else if (!avail.Exists(it) && "avx512" != it && "avx2" != it && "avx" != it) { - WARNING("Unknown intrinsic name '" + it + "' ignored"); - } - } - } - if (TARGET_ARCH == 'x86') { - /* SSE2 is currently the default on 32-bit. It could change later, - for now no need to pass it. But, if SSE only was chosen, - /arch:SSE is required. */ - if ("sse" == scale[j]) { - ADD_FLAG("CFLAGS","/arch:SSE"); + } else if (CLANG_TOOLSET) { + ADD_FLAG("CFLAGS","-mavx512f -mavx512cd -mavx512bw -mavx512dq -mavx512vl"); + } + configure_subst.Add("PHP_SIMD_SCALE", "AVX512"); + } else { + var list = PHP_NATIVE_INTRINSICS.split(","); + var j = 0; + for (var k = 0; k < scale.length; k++) { + for (var i = 0; i < list.length; i++) { + var it = list[i].toLowerCase(); + if (scale[k] == it) { + j = k > j ? k : j; + } else if (!avail.Exists(it) && "avx512" != it && "avx2" != it && "avx" != it) { + WARNING("Unknown intrinsic name '" + it + "' ignored"); } } - configure_subst.Add("PHP_SIMD_SCALE", scale[j].toUpperCase()); - /* There is no explicit way to enable intrinsics between SSE3 and SSE4.2. - The declared macros therefore won't affect the code generation, - but will enable the guarded code parts. */ - if ("avx512" == scale[j]) { - ADD_FLAG("CFLAGS","/arch:AVX512"); - j -= 3; - } else if ("avx2" == scale[j]) { - ADD_FLAG("CFLAGS","/arch:AVX2"); - j -= 2; - } else if ("avx" == scale[j]) { - ADD_FLAG("CFLAGS","/arch:AVX"); - j -= 1; - } + } + if (TARGET_ARCH == 'x86') { + /* SSE2 is currently the default on 32-bit. It could change later, + for now no need to pass it. But, if SSE only was chosen, + /arch:SSE is required. */ + if ("sse" == scale[j]) { + ADD_FLAG("CFLAGS", VS_TOOLSET ? "/arch:SSE" : "-msse"); + } + } + configure_subst.Add("PHP_SIMD_SCALE", scale[j].toUpperCase()); + if ("avx512" == scale[j]) { + ADD_FLAG("CFLAGS", VS_TOOLSET ? "/arch:AVX512" : "-mavx512f -mavx512cd -mavx512bw -mavx512dq -mavx512vl"); + j -= 3; + } else if ("avx2" == scale[j]) { + ADD_FLAG("CFLAGS", VS_TOOLSET ? "/arch:AVX2" : "-mavx2"); + j -= 2; + } else if ("avx" == scale[j]) { + ADD_FLAG("CFLAGS", VS_TOOLSET ? "/arch:AVX" : "-mavx"); + j -= 1; + } + if (VS_TOOLSET) { + /* MSVC has no explicit way to enable intrinsics between SSE3 and SSE4.2. + The declared macros won't affect code generation, but will enable + the guarded code parts. */ for (var i = 0; i <= j; i++) { var it = scale[i]; AC_DEFINE(avail.Item(it), 1); } + } else if (CLANG_TOOLSET) { + /* clang supports -m flags for each SSE level and auto-defines + the corresponding __SSE*__ macros. Pass the highest requested + level; clang implicitly enables all lower levels. */ + var clang_flag_map = { + "sse": "-msse", "sse2": "-msse2", "sse3": "-msse3", + "ssse3": "-mssse3", "sse4.1": "-msse4.1", "sse4.2": "-msse4.2" + }; + if (clang_flag_map[scale[j]]) { + ADD_FLAG("CFLAGS", clang_flag_map[scale[j]]); + } } } }