Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/scripts/windows/build_task.bat
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ 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" (
set CFLAGS=/W3 /wd4018 /wd4146 /wd4244 /wd4267
) else (
set CFLAGS=/W3 /WX /wd4018 /wd4146 /wd4244 /wd4267
)

cmd /c configure.bat ^
--enable-snapshot-build ^
Expand Down
31 changes: 31 additions & 0 deletions .github/workflows/test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,37 @@ jobs:
run: .github/scripts/windows/build.bat
- name: Test
run: .github/scripts/windows/test.bat
WINDOWS_CLANG:
Copy link
Copy Markdown
Member

@iluuu1994 iluuu1994 Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please unify this with the other windows job. Please also enable it for nightly only. You'll need to adjust this in .github/matrix.php, but it should be pretty self-evident. This should also be done in a separate PR, as these changes will have to land in the PHP-8.2 branch.

If the official builds switch to Clang, it will of course make sense to switch them around (build with MSCV in nightly only).

Edit: Ah I see, that's already GH-21618. I don't know if all these changes are needed just to test in CI though. What matters to me is that .github/matrix.php and .github/workflows/test-suite.yml are synced across all branches. If the other changes are needed for the builds, we can also skip the Clang job for every branch but master, as we do for some other builds.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can refactor the CI addition out to a separate PR targetting 8.4 (8.2?). I'm not sure if clang-cl even manages to build there, though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be great. 8.2 is correct, we keep the build green for security branches. If the aim is to enable the build for master (i.e. 8.6) only, then you can use version_compare() like we do in other places in .github/matrix.php.

if: ${{ fromJson(inputs.branch).jobs.WINDOWS }}
name: "WINDOWS_X64_ZTS_CLANG"
runs-on: windows-2022
env:
PHP_BUILD_CACHE_BASE_DIR: C:\build-cache
PHP_BUILD_OBJ_DIR: C:\obj
PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk
PHP_BUILD_SDK_BRANCH: php-sdk-2.5.0
PHP_BUILD_CRT: ${{ fromJson(inputs.branch).jobs.WINDOWS.config.vs_crt_version }}
PLATFORM: x64
THREAD_SAFE: "1"
INTRINSICS: "AVX2"
PARALLEL: -j2
OPCACHE: "1"
CLANG_TOOLSET: "1"
steps:
- name: git config
run: git config --global core.autocrlf false && git config --global core.eol lf
- name: git checkout
uses: actions/checkout@v6
with:
ref: ${{ fromJson(inputs.branch).ref }}
- name: Setup
uses: ./.github/actions/setup-windows
- name: Build
run: .github/scripts/windows/build.bat
- name: Verify ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL
run: C:\obj\Release_TS\php.exe -r "if (ZEND_VM_KIND !== 'ZEND_VM_KIND_TAILCALL') { echo 'Expected ZEND_VM_KIND_TAILCALL, got ' . ZEND_VM_KIND . PHP_EOL; exit(1); }"
- name: Test
run: .github/scripts/windows/test.bat
FREEBSD:
if: ${{ fromJson(inputs.branch).jobs.FREEBSD }}
strategy:
Expand Down
7 changes: 6 additions & 1 deletion TSRM/TSRM.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
#if defined(__cplusplus) && defined(__clang__)
#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
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_vm_gen.php
Original file line number Diff line number Diff line change
Expand Up @@ -2499,7 +2499,7 @@ function gen_vm_opcodes_header(
$str .= "# define ZEND_VM_KIND\t\tZEND_VM_KIND_HYBRID\n";
}
if ($GLOBALS["vm_kind_name"][ZEND_VM_GEN_KIND] === "ZEND_VM_KIND_HYBRID" || $GLOBALS["vm_kind_name"][ZEND_VM_GEN_KIND] === "ZEND_VM_KIND_CALL") {
$str .= "#elif defined(HAVE_MUSTTAIL) && defined(HAVE_PRESERVE_NONE) && (defined(__x86_64__) || defined(__aarch64__))\n";
$str .= "#elif defined(HAVE_MUSTTAIL) && defined(HAVE_PRESERVE_NONE) && (defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64))\n";
$str .= "# define ZEND_VM_KIND\t\tZEND_VM_KIND_TAILCALL\n";
$str .= "#else\n";
$str .= "# define ZEND_VM_KIND\t\tZEND_VM_KIND_CALL\n";
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_vm_opcodes.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -3315,6 +3315,27 @@ static PRUNTIME_FUNCTION zend_jit_unwind_callback(DWORD64 pc, PVOID context)

static void zend_jit_setup_unwinder(void)
{
#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL
/* TAILCALL VM: fixed_save_regset=0, no registers pushed in prologue.
* fixed_stack_frame_size=40, fixed_call_stack_size=48 (16+IR_SHADOW_ARGS).
* Prologue is: sub rsp, 0x58 (88 bytes = 40+48). */
static const unsigned char uw_data[] = {
0x01, // Version=1, Flags=0
0x04, // Size of prolog (sub rsp,imm8 = 4 bytes: 48 83 ec 58)
0x01, // Count of unwind codes
0x00, // Frame Register=none
0x04, 0xa2, // offset 4: UWOP_ALLOC_SMALL info=10, alloc=(10+1)*8=88
0x00, 0x00, // padding
};
/* Exit call variant: base 88 + 304 (shadow+GP+FP+padding) = 392 (0x188) */
static const unsigned char uw_data_exitcall[] = {
0x01, // Version=1, Flags=0
0x07, // Size of prolog (sub rsp,imm32 = 7 bytes: 48 81 ec 88 01 00 00)
0x02, // Count of unwind codes
0x00, // Frame Register=none
0x07, 0x01, 0x31, 0x00, // offset 7: UWOP_ALLOC_LARGE info=0, size/8=49, alloc=392
};
#else
/* Hardcoded SEH unwind data for JIT-ed PHP functions with "fixed stack frame" */
static const unsigned char uw_data[] = {
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
Expand Down Expand Up @@ -3349,6 +3370,7 @@ static void zend_jit_setup_unwinder(void)
0x02, 0x50, // 1: pushq %rbp
0x01, 0x30, // 0: pushq %rbx
};
#endif

zend_jit_uw_func = (PRUNTIME_FUNCTION)*dasm_ptr;
*dasm_ptr = (char*)*dasm_ptr + ZEND_MM_ALIGNED_SIZE_EX(sizeof(RUNTIME_FUNCTION) * 4 +
Expand Down
109 changes: 59 additions & 50 deletions win32/build/confutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3376,7 +3376,11 @@ function toolset_setup_common_cflags()

var vc_ver = probe_binary(PATH_PROG('cl', null));
ADD_FLAG("CFLAGS"," -fms-compatibility -fms-compatibility-version=" + vc_ver + " -fms-extensions");
}

if (CLANGVERS >= 1900 && (TARGET_ARCH === 'x64' || TARGET_ARCH === 'arm64')) {
AC_DEFINE('HAVE_PRESERVE_NONE', 1, 'Whether the compiler supports __attribute__((preserve_none))');
}
}

if (!CLANG_TOOLSET) {
/* clang uses __builtin_*() instead */
Expand All @@ -3397,24 +3401,24 @@ 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 || "no" == PHP_NATIVE_INTRINSICS) {
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 (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 ("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) {
Expand All @@ -3423,42 +3427,47 @@ 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());
/* 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", 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 doesn't auto-define SSE macros; clang does with -m flags */
for (var i = 0; i <= j; i++) {
var it = scale[i];
AC_DEFINE(avail.Item(it), 1);
Expand Down
Loading