Skip to content

Commit 7cd8a0a

Browse files
authored
[Windows] Improve clang-cl support (#21618)
* fix compiling (intl) C++ extensions --with-toolset=clang * guard the double extern "C" { ... } for clang-only * don't error on warnings with clang * enable compiler intrinsics for clang too * make --enable-compiler-intrinsics=no same as disabled * add clang windows x64 ZTS test * remove check if it's clang * debloat logs from common warning * @shivammathur feedback * remove CI changes * rebase on #21630 * fix default to asan => false * bring back explicit error * fix typo
1 parent 2bd6579 commit 7cd8a0a

File tree

5 files changed

+90
-59
lines changed

5 files changed

+90
-59
lines changed

.github/matrix.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,15 @@ function select_jobs($repository, $trigger, $nightly, $labels, $php_version, $re
144144
$jobs['SOLARIS'] = true;
145145
}
146146
if ($all_jobs || !$no_jobs || $test_windows) {
147-
$jobs['WINDOWS']['matrix'] = $all_variations
148-
? ['include' => [
149-
['asan' => true, 'opcache' => true, 'x64' => true, 'zts' => true],
150-
['asan' => false, 'opcache' => false, 'x64' => false, 'zts' => false],
151-
]]
152-
: ['include' => [['asan' => false, 'opcache' => true, 'x64' => true, 'zts' => true]]];
147+
$matrix = [['asan' => false, 'opcache' => true, 'x64' => true, 'zts' => true]];
148+
if ($all_variations) {
149+
$matrix[] = ['asan' => true, 'opcache' => true, 'x64' => true, 'zts' => true];
150+
$matrix[] = ['asan' => false, 'opcache' => false, 'x64' => false, 'zts' => false];
151+
if (version_compare($php_version, '8.5', '>=')) {
152+
$matrix[] = ['asan' => false, 'opcache' => true, 'x64' => true, 'zts' => true, 'clang' => true];
153+
}
154+
}
155+
$jobs['WINDOWS']['matrix'] = ['include' => $matrix];
153156
$jobs['WINDOWS']['config'] = version_compare($php_version, '8.4', '>=')
154157
? ['vs_crt_version' => 'vs17']
155158
: ['vs_crt_version' => 'vs16'];

.github/scripts/windows/build_task.bat

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,18 @@ if %errorlevel% neq 0 exit /b 3
2626
if "%THREAD_SAFE%" equ "0" set ADD_CONF=%ADD_CONF% --disable-zts
2727
if "%INTRINSICS%" neq "" set ADD_CONF=%ADD_CONF% --enable-native-intrinsics=%INTRINSICS%
2828
if "%ASAN%" equ "1" set ADD_CONF=%ADD_CONF% --enable-sanitizer --enable-debug-pack
29+
if "%CLANG_TOOLSET%" equ "1" set ADD_CONF=%ADD_CONF% --with-toolset=clang
2930

3031
rem C4018: comparison: signed/unsigned mismatch
3132
rem C4146: unary minus operator applied to unsigned type
3233
rem C4244: type conversion, possible loss of data
3334
rem C4267: 'size_t' type conversion, possible loss of data
34-
set CFLAGS=/W3 /WX /wd4018 /wd4146 /wd4244 /wd4267
35+
if "%CLANG_TOOLSET%" equ "1" (
36+
rem Clang is much stricter than MSVC, produces too many warnings that would fail the build with /WX
37+
set CFLAGS=/W3 /wd4018 /wd4146 /wd4244 /wd4267
38+
) else (
39+
set CFLAGS=/W3 /WX /wd4018 /wd4146 /wd4244 /wd4267
40+
)
3541

3642
cmd /c configure.bat ^
3743
--enable-snapshot-build ^

.github/workflows/test-suite.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ jobs:
940940
strategy:
941941
fail-fast: false
942942
matrix: ${{ fromJson(inputs.branch).jobs.WINDOWS.matrix }}
943-
name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || ''}}"
943+
name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || ''}}${{ matrix.clang && '_CLANG' || ''}}"
944944
runs-on: windows-2022
945945
env:
946946
PHP_BUILD_CACHE_BASE_DIR: C:\build-cache
@@ -954,6 +954,7 @@ jobs:
954954
PARALLEL: -j2
955955
OPCACHE: "${{ matrix.opcache && '1' || '0' }}"
956956
ASAN: "${{ matrix.asan && '1' || '0' }}"
957+
CLANG_TOOLSET: "${{ matrix.clang && '1' || '0' }}"
957958
steps:
958959
- name: git config
959960
run: git config --global core.autocrlf false && git config --global core.eol lf

TSRM/TSRM.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,14 @@ TSRM_API bool tsrm_is_managed_thread(void);
175175
#define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)])
176176
#define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element)
177177
#define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset)))
178+
#ifdef __cplusplus
179+
#define TSRMLS_MAIN_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR; }
180+
#define TSRMLS_CACHE_EXTERN() extern "C" { extern TSRM_TLS void *TSRMLS_CACHE; }
181+
#else
178182
#define TSRMLS_MAIN_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR;
179-
#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;
180183
#define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
184+
#endif
185+
#define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;
181186
#define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
182187
#define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
183188
#define TSRMLS_CACHE _tsrm_ls_cache

win32/build/confutils.js

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3361,7 +3361,7 @@ function toolset_setup_common_cflags()
33613361

33623362
ADD_FLAG("CFLAGS", "/Zc:wchar_t");
33633363
} else if (CLANG_TOOLSET) {
3364-
ADD_FLAG("CFLAGS", "-Wno-deprecated-declarations");
3364+
ADD_FLAG("CFLAGS", "-Wno-deprecated-declarations -Wno-microsoft-enum-forward-reference");
33653365
if (TARGET_ARCH == 'x86') {
33663366
ADD_FLAG('CFLAGS', '-m32');
33673367
} else {
@@ -3395,24 +3395,25 @@ function toolset_setup_intrinsic_cflags()
33953395
/* From oldest to newest. */
33963396
var scale = new Array("sse", "sse2", "sse3", "ssse3", "sse4.1", "sse4.2", "avx", "avx2", "avx512");
33973397

3398-
if (VS_TOOLSET) {
3399-
if ("disabled" == PHP_NATIVE_INTRINSICS) {
3400-
ERROR("Can't enable intrinsics, --with-codegen-arch passed with an incompatible option. ")
3401-
}
3398+
if ("disabled" == PHP_NATIVE_INTRINSICS) {
3399+
ERROR("Can't enable intrinsics, --with-codegen-arch passed with an incompatible option. ")
3400+
}
34023401

3403-
if (TARGET_ARCH == 'arm64') {
3404-
/* arm64 supports neon */
3405-
configure_subst.Add("PHP_SIMD_SCALE", 'NEON');
3406-
/* all officially supported arm64 cpu supports crc32 (TODO: to be confirmed) */
3407-
AC_DEFINE('HAVE_ARCH64_CRC32', 1);
3408-
return;
3409-
}
3402+
if (TARGET_ARCH == 'arm64') {
3403+
/* arm64 supports neon */
3404+
configure_subst.Add("PHP_SIMD_SCALE", 'NEON');
3405+
/* all officially supported arm64 cpu supports crc32 (TODO: to be confirmed) */
3406+
AC_DEFINE('HAVE_ARCH64_CRC32', 1);
3407+
return;
3408+
}
34103409

3411-
if ("no" == PHP_NATIVE_INTRINSICS || "yes" == PHP_NATIVE_INTRINSICS) {
3412-
PHP_NATIVE_INTRINSICS = default_enabled;
3413-
}
3410+
// if --enable-native-intrisics is not specified, it's "no" - enable default
3411+
if ("no" == PHP_NATIVE_INTRINSICS || "yes" == PHP_NATIVE_INTRINSICS) {
3412+
PHP_NATIVE_INTRINSICS = default_enabled;
3413+
}
34143414

3415-
if ("all" == PHP_NATIVE_INTRINSICS) {
3415+
if ("all" == PHP_NATIVE_INTRINSICS) {
3416+
if (VS_TOOLSET) {
34163417
var list = (new VBArray(avail.Keys())).toArray();
34173418

34183419
for (var i in list) {
@@ -3421,46 +3422,61 @@ function toolset_setup_intrinsic_cflags()
34213422

34223423
/* All means all. __AVX__, __AVX2__, and __AVX512*__ are defined by compiler. */
34233424
ADD_FLAG("CFLAGS","/arch:AVX512");
3424-
configure_subst.Add("PHP_SIMD_SCALE", "AVX512");
3425-
} else {
3426-
var list = PHP_NATIVE_INTRINSICS.split(",");
3427-
var j = 0;
3428-
for (var k = 0; k < scale.length; k++) {
3429-
for (var i = 0; i < list.length; i++) {
3430-
var it = list[i].toLowerCase();
3431-
if (scale[k] == it) {
3432-
j = k > j ? k : j;
3433-
} else if (!avail.Exists(it) && "avx512" != it && "avx2" != it && "avx" != it) {
3434-
WARNING("Unknown intrinsic name '" + it + "' ignored");
3435-
}
3436-
}
3437-
}
3438-
if (TARGET_ARCH == 'x86') {
3439-
/* SSE2 is currently the default on 32-bit. It could change later,
3440-
for now no need to pass it. But, if SSE only was chosen,
3441-
/arch:SSE is required. */
3442-
if ("sse" == scale[j]) {
3443-
ADD_FLAG("CFLAGS","/arch:SSE");
3425+
} else if (CLANG_TOOLSET) {
3426+
ADD_FLAG("CFLAGS","-mavx512f -mavx512cd -mavx512bw -mavx512dq -mavx512vl");
3427+
}
3428+
configure_subst.Add("PHP_SIMD_SCALE", "AVX512");
3429+
} else {
3430+
var list = PHP_NATIVE_INTRINSICS.split(",");
3431+
var j = 0;
3432+
for (var k = 0; k < scale.length; k++) {
3433+
for (var i = 0; i < list.length; i++) {
3434+
var it = list[i].toLowerCase();
3435+
if (scale[k] == it) {
3436+
j = k > j ? k : j;
3437+
} else if (!avail.Exists(it) && "avx512" != it && "avx2" != it && "avx" != it) {
3438+
WARNING("Unknown intrinsic name '" + it + "' ignored");
34443439
}
34453440
}
3446-
configure_subst.Add("PHP_SIMD_SCALE", scale[j].toUpperCase());
3447-
/* There is no explicit way to enable intrinsics between SSE3 and SSE4.2.
3448-
The declared macros therefore won't affect the code generation,
3449-
but will enable the guarded code parts. */
3450-
if ("avx512" == scale[j]) {
3451-
ADD_FLAG("CFLAGS","/arch:AVX512");
3452-
j -= 3;
3453-
} else if ("avx2" == scale[j]) {
3454-
ADD_FLAG("CFLAGS","/arch:AVX2");
3455-
j -= 2;
3456-
} else if ("avx" == scale[j]) {
3457-
ADD_FLAG("CFLAGS","/arch:AVX");
3458-
j -= 1;
3459-
}
3441+
}
3442+
if (TARGET_ARCH == 'x86') {
3443+
/* SSE2 is currently the default on 32-bit. It could change later,
3444+
for now no need to pass it. But, if SSE only was chosen,
3445+
/arch:SSE is required. */
3446+
if ("sse" == scale[j]) {
3447+
ADD_FLAG("CFLAGS", VS_TOOLSET ? "/arch:SSE" : "-msse");
3448+
}
3449+
}
3450+
configure_subst.Add("PHP_SIMD_SCALE", scale[j].toUpperCase());
3451+
if ("avx512" == scale[j]) {
3452+
ADD_FLAG("CFLAGS", VS_TOOLSET ? "/arch:AVX512" : "-mavx512f -mavx512cd -mavx512bw -mavx512dq -mavx512vl");
3453+
j -= 3;
3454+
} else if ("avx2" == scale[j]) {
3455+
ADD_FLAG("CFLAGS", VS_TOOLSET ? "/arch:AVX2" : "-mavx2");
3456+
j -= 2;
3457+
} else if ("avx" == scale[j]) {
3458+
ADD_FLAG("CFLAGS", VS_TOOLSET ? "/arch:AVX" : "-mavx");
3459+
j -= 1;
3460+
}
3461+
if (VS_TOOLSET) {
3462+
/* MSVC has no explicit way to enable intrinsics between SSE3 and SSE4.2.
3463+
The declared macros won't affect code generation, but will enable
3464+
the guarded code parts. */
34603465
for (var i = 0; i <= j; i++) {
34613466
var it = scale[i];
34623467
AC_DEFINE(avail.Item(it), 1);
34633468
}
3469+
} else if (CLANG_TOOLSET) {
3470+
/* clang supports -m flags for each SSE level and auto-defines
3471+
the corresponding __SSE*__ macros. Pass the highest requested
3472+
level; clang implicitly enables all lower levels. */
3473+
var clang_flag_map = {
3474+
"sse": "-msse", "sse2": "-msse2", "sse3": "-msse3",
3475+
"ssse3": "-mssse3", "sse4.1": "-msse4.1", "sse4.2": "-msse4.2"
3476+
};
3477+
if (clang_flag_map[scale[j]]) {
3478+
ADD_FLAG("CFLAGS", clang_flag_map[scale[j]]);
3479+
}
34643480
}
34653481
}
34663482
}

0 commit comments

Comments
 (0)