From 279a297172376ef863c7e4809168a10e67618e59 Mon Sep 17 00:00:00 2001 From: dixyes Date: Wed, 20 Jul 2022 17:08:00 +0200 Subject: [PATCH] Windows arm64 build system support Closes GH-9116. --- .gitignore | 3 + Zend/asm/jump_arm64_aapcs_pe_armasm.asm | 133 ++++++++++++++++++++++++ Zend/asm/make_arm64_aapcs_pe_armasm.asm | 107 +++++++++++++++++++ ext/standard/config.w32 | 2 +- win32/build/Makefile | 4 +- win32/build/Makefile.frag.w32 | 7 -- win32/build/config.w32 | 50 +++++++-- win32/build/config.w32.phpize.in | 6 +- win32/build/confutils.js | 113 +++++++++++++------- 9 files changed, 368 insertions(+), 57 deletions(-) create mode 100644 Zend/asm/jump_arm64_aapcs_pe_armasm.asm create mode 100644 Zend/asm/make_arm64_aapcs_pe_armasm.asm delete mode 100644 win32/build/Makefile.frag.w32 diff --git a/.gitignore b/.gitignore index afa85395322f5..7a4ba0e0222ba 100644 --- a/.gitignore +++ b/.gitignore @@ -202,6 +202,9 @@ php # Generated by x64 compiler, includes Debug, Debug_TS, Release, Release_TS /x64/ +# Generated by arm64 compiler, includes Debug, Debug_TS, Release, Release_TS +/arm64/ + # Miscellaneous files generated by Windows build system /main/config.w32.h /win32/build/deplister.exe diff --git a/Zend/asm/jump_arm64_aapcs_pe_armasm.asm b/Zend/asm/jump_arm64_aapcs_pe_armasm.asm new file mode 100644 index 0000000000000..d2e7d221415a3 --- /dev/null +++ b/Zend/asm/jump_arm64_aapcs_pe_armasm.asm @@ -0,0 +1,133 @@ +; Copyright Edward Nevill + Oliver Kowalke 2015 +; Distributed under the Boost Software License, Version 1.0. +; (See accompanying file LICENSE_1_0.txt or copy at +; http://www.boost.org/LICENSE_1_0.txt) + +;******************************************************* +;* * +;* ------------------------------------------------- * +;* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * +;* ------------------------------------------------- * +;* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * +;* ------------------------------------------------- * +;* | d8 | d9 | d10 | d11 | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * +;* ------------------------------------------------- * +;* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * +;* ------------------------------------------------- * +;* | d12 | d13 | d14 | d15 | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * +;* ------------------------------------------------- * +;* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * +;* ------------------------------------------------- * +;* | x19 | x20 | x21 | x22 | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * +;* ------------------------------------------------- * +;* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * +;* ------------------------------------------------- * +;* | x23 | x24 | x25 | x26 | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * +;* ------------------------------------------------- * +;* | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * +;* ------------------------------------------------- * +;* | x27 | x28 | FP | LR | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | * +;* ------------------------------------------------- * +;* | 0xa0| 0xa4| 0xa8| 0xac| 0xb0| 0xb4| 0xb8| 0xbc| * +;* ------------------------------------------------- * +;* | fiber data| base | limit | dealloc | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 48 | 49 | 50 | 51 | | | * +;* ------------------------------------------------- * +;* | 0xc0| 0xc4| 0xc8| 0xcc| | | * +;* ------------------------------------------------- * +;* | PC | align | | | * +;* ------------------------------------------------- * +;* * +;******************************************************* + + AREA |.text|, CODE, READONLY, ALIGN=4, CODEALIGN + EXPORT jump_fcontext + +jump_fcontext proc + ; prepare stack for GP + FPU + sub sp, sp, #0xd0 + + ; save d8 - d15 + stp d8, d9, [sp, #0x00] + stp d10, d11, [sp, #0x10] + stp d12, d13, [sp, #0x20] + stp d14, d15, [sp, #0x30] + + ; save x19-x30 + stp x19, x20, [sp, #0x40] + stp x21, x22, [sp, #0x50] + stp x23, x24, [sp, #0x60] + stp x25, x26, [sp, #0x70] + stp x27, x28, [sp, #0x80] + stp x29, x30, [sp, #0x90] + + ; save LR as PC + str x30, [sp, #0xc0] + + ; save current stack base and limit + ldp x5, x6, [x18, #0x08] ; TeStackBase and TeStackLimit at ksarm64.h + stp x5, x6, [sp, #0xa0] + ; save current fiber data and deallocation stack + ldr x5, [x18, #0x1478] ; TeDeallocationStack at ksarm64.h + ldr x6, [x18, #0x20] ; TeFiberData at ksarm64.h + stp x5, x6, [sp, #0xb0] + + ; store RSP (pointing to context-data) in X0 + mov x4, sp + + ; restore RSP (pointing to context-data) from X1 + mov sp, x0 + + ; restore stack base and limit + ldp x5, x6, [sp, #0xa0] + stp x5, x6, [x18, #0x08] ; TeStackBase and TeStackLimit at ksarm64.h + ; restore fiber data and deallocation stack + ldp x5, x6, [sp, #0xb0] + str x5, [x18, #0x1478] ; TeDeallocationStack at ksarm64.h + str x6, [x18, #0x20] ; TeFiberData at ksarm64.h + + ; load d8 - d15 + ldp d8, d9, [sp, #0x00] + ldp d10, d11, [sp, #0x10] + ldp d12, d13, [sp, #0x20] + ldp d14, d15, [sp, #0x30] + + ; load x19-x30 + ldp x19, x20, [sp, #0x40] + ldp x21, x22, [sp, #0x50] + ldp x23, x24, [sp, #0x60] + ldp x25, x26, [sp, #0x70] + ldp x27, x28, [sp, #0x80] + ldp x29, x30, [sp, #0x90] + + ; return transfer_t from jump + ; pass transfer_t as first arg in context function + ; X0 == FCTX, X1 == DATA + mov x0, x4 + + ; load pc + ldr x4, [sp, #0xc0] + + ; restore stack from GP + FPU + add sp, sp, #0xd0 + + ret x4 + ENDP + END \ No newline at end of file diff --git a/Zend/asm/make_arm64_aapcs_pe_armasm.asm b/Zend/asm/make_arm64_aapcs_pe_armasm.asm new file mode 100644 index 0000000000000..16fcdc7d8f7e8 --- /dev/null +++ b/Zend/asm/make_arm64_aapcs_pe_armasm.asm @@ -0,0 +1,107 @@ +; Copyright Edward Nevill + Oliver Kowalke 2015 +; Distributed under the Boost Software License, Version 1.0. +; (See accompanying file LICENSE_1_0.txt or copy at +; http://www.boost.org/LICENSE_1_0.txt) + +;******************************************************* +;* * +;* ------------------------------------------------- * +;* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * +;* ------------------------------------------------- * +;* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * +;* ------------------------------------------------- * +;* | d8 | d9 | d10 | d11 | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * +;* ------------------------------------------------- * +;* | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * +;* ------------------------------------------------- * +;* | d12 | d13 | d14 | d15 | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * +;* ------------------------------------------------- * +;* | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * +;* ------------------------------------------------- * +;* | x19 | x20 | x21 | x22 | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * +;* ------------------------------------------------- * +;* | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * +;* ------------------------------------------------- * +;* | x23 | x24 | x25 | x26 | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * +;* ------------------------------------------------- * +;* | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * +;* ------------------------------------------------- * +;* | x27 | x28 | FP | LR | * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | * +;* ------------------------------------------------- * +;* | 0xa0| 0xa4| 0xa8| 0xac| 0xb0| 0xb4| 0xb8| 0xbc| * +;* ------------------------------------------------- * +;* | base | limit | dealloc | fiber data| * +;* ------------------------------------------------- * +;* ------------------------------------------------- * +;* | 48 | 49 | 50 | 51 | | | * +;* ------------------------------------------------- * +;* | 0xc0| 0xc4| 0xc8| 0xcc| | | * +;* ------------------------------------------------- * +;* | PC | align | | | * +;* ------------------------------------------------- * +;* * +;******************************************************* + + AREA |.text|, CODE, READONLY, ALIGN=4, CODEALIGN + EXPORT make_fcontext + IMPORT _exit + +make_fcontext proc + ; save stack top address to x3 + mov x3, x0 + + ; shift address in x0 (allocated stack) to lower 16 byte boundary + and x0, x0, ~0xF + + ; reserve space for context-data on context-stack + sub x0, x0, #0xd0 + + ; save top address of context_stack as 'base' + str x3, [x0, #0xa0] + ; save bottom address of context-stack as 'limit' and 'dealloction stack' + sub x3, x3, x1 + stp x3, x3, [x0, #0xa8] + ; save 0 as 'fiber data' + str xzr, [x0, #0xb8] + + ; third arg of make_fcontext() == address of context-function + ; store address as x19 for trampoline + str x2, [x0, #0x40] + ; store trampoline address as pc + adr x2, trampoline + str x2, [x0, #0xc0] + + ; save address of finish as return-address for context-function + ; will be entered after context-function returns (LR register) + adr x1, finish + str x1, [x0, #0x98] + + ret x30 ; return pointer to context-data (x0) + +trampoline + stp fp, lr, [sp, #-0x10]! + mov fp, sp + blr x19 + +finish + ; exit code is zero + mov x0, #0 + ; exit application + bl _exit + ENDP + END diff --git a/ext/standard/config.w32 b/ext/standard/config.w32 index e4c5d65f4acb3..282189c52dade 100644 --- a/ext/standard/config.w32 +++ b/ext/standard/config.w32 @@ -25,7 +25,7 @@ ADD_FLAG("LIBS_STANDARD", "iphlpapi.lib"); EXTENSION("standard", "array.c base64.c basic_functions.c browscap.c \ crc32.c crypt.c crypt_freesec.c crypt_blowfish.c crypt_sha256.c \ - crypt_sha512.c php_crypt_r.c crc32_x86.c \ + crypt_sha512.c php_crypt_r.c " + (TARGET_ARCH != 'arm64'? " crc32_x86.c" : "") + " \ datetime.c dir.c dl.c dns.c dns_win32.c exec.c \ file.c filestat.c formatted_print.c fsock.c head.c html.c image.c \ info.c iptc.c link.c mail.c math.c md5.c metaphone.c microtime.c \ diff --git a/win32/build/Makefile b/win32/build/Makefile index 9d063549113aa..e63a77b121fda 100644 --- a/win32/build/Makefile +++ b/win32/build/Makefile @@ -130,10 +130,10 @@ $(PHPDLL_RES): win32\build\template.rc /I$(BUILD_DIR) /d MC_INCLUDE="\"$(MCFILE)\"" \ win32\build\template.rc -$(BUILD_DIR)\$(PHPDLL): generated_files $(PHPDEF) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(PHPDLL_RES) $(MCFILE) +$(BUILD_DIR)\$(PHPDLL): generated_files $(PHPDEF) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(PHPDLL_RES) $(ASM_OBJS) $(MCFILE) @copy win32\build\default.manifest $(BUILD_DIR)\$(PHPDLL).manifest >nul # @$(CC) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(STATIC_EXT_LIBS) $(LIBS) $(PHPDLL_RES) /link /out:$(BUILD_DIR)\$(PHPDLL) $(PHP8_PGD_OPTION) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS) - @"$(LINK)" $(PHP_GLOBAL_OBJS_RESP) $(STATIC_EXT_OBJS_RESP) $(STATIC_EXT_LIBS) $(LIBS) $(PHPDLL_RES) /out:$(BUILD_DIR)\$(PHPDLL) $(PHP8_PGD_OPTION) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS) + @"$(LINK)" $(PHP_GLOBAL_OBJS_RESP) $(STATIC_EXT_OBJS_RESP) $(STATIC_EXT_LIBS) $(LIBS) $(ASM_OBJS) $(PHPDLL_RES) /out:$(BUILD_DIR)\$(PHPDLL) $(PHP8_PGD_OPTION) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS) -@$(_VC_MANIFEST_EMBED_DLL) $(BUILD_DIR)\$(PHPLIB): $(BUILD_DIR)\$(PHPDLL) diff --git a/win32/build/Makefile.frag.w32 b/win32/build/Makefile.frag.w32 deleted file mode 100644 index 6c74619c986a4..0000000000000 --- a/win32/build/Makefile.frag.w32 +++ /dev/null @@ -1,7 +0,0 @@ -$(BUILD_DIR)\Zend\jump_$(FIBER_ASM_ARCH)_ms_pe_masm.obj: Zend\asm\jump_$(FIBER_ASM_ARCH)_ms_pe_masm.asm - $(FIBER_ASSEMBLER) /DBOOST_CONTEXT_EXPORT=EXPORT /nologo /Fo $(BUILD_DIR)\Zend\jump_$(FIBER_ASM_ARCH)_ms_pe_masm.obj /c Zend\asm\jump_$(FIBER_ASM_ARCH)_ms_pe_masm.asm - -$(BUILD_DIR)\Zend\make_$(FIBER_ASM_ARCH)_ms_pe_masm.obj: Zend\asm\make_$(FIBER_ASM_ARCH)_ms_pe_masm.asm - $(FIBER_ASSEMBLER) /DBOOST_CONTEXT_EXPORT=EXPORT /nologo /Fo $(BUILD_DIR)\Zend\make_$(FIBER_ASM_ARCH)_ms_pe_masm.obj /c Zend\asm\make_$(FIBER_ASM_ARCH)_ms_pe_masm.asm - -$(BUILD_DIR)\$(PHPDLL): $(BUILD_DIR)\Zend\jump_$(FIBER_ASM_ARCH)_ms_pe_masm.obj $(BUILD_DIR)\Zend\make_$(FIBER_ASM_ARCH)_ms_pe_masm.obj diff --git a/win32/build/config.w32 b/win32/build/config.w32 index c66f1e39af6a6..0b1736c8ab70d 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -14,8 +14,10 @@ ARG_WITH('cygwin', 'Path to cygwin utilities on your system', '\\cygwin'); toolset_setup_compiler(); -// do we use x64 or 80x86 version of compiler? -X64 = toolset_is_64(); +HOST_ARCH = toolset_host_arch(); +TARGET_ARCH = toolset_target_arch(); +// for compatible only +X64 = TARGET_ARCH != 'x86'; toolset_setup_arch(); toolset_setup_linker(); @@ -212,7 +214,7 @@ if (PHP_ANALYZER == "vs") { pvscfg.WriteLine("exclude-path = " + PROGRAM_FILES + "\\windows kits\\"); } pvscfg.WriteLine("vcinstalldir = " + VCINSTALLDIR); - pvscfg.WriteLine("platform = " + (X64 ? 'x64' : 'Win32')); + pvscfg.WriteLine("platform = " + (TARGET_ARCH == 'x86' ? 'Win32' : 'x64')); pvscfg.WriteLine("preprocessor = visualcpp"); pvscfg.WriteLine("language = C"); pvscfg.WriteLine("skip-cl-exe = no"); @@ -241,16 +243,44 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \ zend_enum.c zend_fibers.c zend_atomic.c"); ADD_SOURCES("Zend\\Optimizer", "zend_optimizer.c pass1.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c escape_analysis.c compact_vars.c dce.c sccp.c scdf.c"); -var FIBER_ASSEMBLER = X64 ? PATH_PROG('ML64') : PATH_PROG('ML'); -DEFINE('FIBER_ASSEMBLER', FIBER_ASSEMBLER); +var PHP_ASSEMBLER = PATH_PROG({ + 'x64': 'ML64', + 'x86': 'ML', + 'arm64': 'armasm64' +}[TARGET_ARCH]); +if (!PHP_ASSEMBLER) { + ERROR("No assembler found, fiber cannot be built"); +} +DEFINE('PHP_ASSEMBLER', PHP_ASSEMBLER); +DEFINE('FIBER_ASSEMBLER', PHP_ASSEMBLER);// for compatible + +var FIBER_ASM_ARCH = { + 'x64': 'x86_64', + 'x86': 'i386', + 'arm64': 'arm64' +}[TARGET_ARCH]; +DEFINE('FIBER_ASM_ARCH', FIBER_ASM_ARCH); // for compatible only + +var FIBER_ASM_ABI = { + 'x64': 'x86_64_ms_pe_masm', + 'x86': 'i386_ms_pe_masm', + 'arm64': 'arm64_aapcs_pe_armasm' +}[TARGET_ARCH]; +DEFINE('FIBER_ASM_ABI', FIBER_ASM_ABI); + +if (TARGET_ARCH == 'arm64') { + DEFINE('FIBER_ASM_FLAGS', '-nologo -machine ARM64 -o'); +} else { + DEFINE('FIBER_ASM_FLAGS', '/DBOOST_CONTEXT_EXPORT=EXPORT /nologo /c /Fo'); +} -var FIBER_ASM_ARCH = X64 ? 'x86_64' : 'i386'; -DEFINE('FIBER_ASM_ARCH', FIBER_ASM_ARCH); +ADD_FLAG('ASM_OBJS', '$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ABI + '.obj $(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ABI + '.obj'); -ADD_FLAG('LDFLAGS', '$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ARCH + '_ms_pe_masm.obj'); -ADD_FLAG('LDFLAGS', '$(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ARCH + '_ms_pe_masm.obj'); +MFO.WriteLine('$(BUILD_DIR)\\Zend\\jump_' + FIBER_ASM_ABI + '.obj: Zend\\asm\\jump_' + FIBER_ASM_ABI + '.asm'); +MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\jump_$(FIBER_ASM_ABI).obj Zend\\asm\\jump_$(FIBER_ASM_ABI).asm'); -ADD_MAKEFILE_FRAGMENT('win32/build/Makefile.frag.w32'); +MFO.WriteLine('$(BUILD_DIR)\\Zend\\make_' + FIBER_ASM_ABI + '.obj: Zend\\asm\\make_' + FIBER_ASM_ABI + '.asm'); +MFO.WriteLine('\t$(PHP_ASSEMBLER) $(FIBER_ASM_FLAGS) $(BUILD_DIR)\\Zend\\make_$(FIBER_ASM_ABI).obj Zend\\asm\\make_$(FIBER_ASM_ABI).asm'); ADD_FLAG("CFLAGS_BD_ZEND", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); if (VS_TOOLSET && VCVERS >= 1914) { diff --git a/win32/build/config.w32.phpize.in b/win32/build/config.w32.phpize.in index 72205fac34ec0..a82017f4f6579 100644 --- a/win32/build/config.w32.phpize.in +++ b/win32/build/config.w32.phpize.in @@ -14,8 +14,10 @@ var PHP_CYGWIN="notset"; toolset_setup_compiler(); -// do we use x64 or 80x86 version of compiler? -X64 = toolset_is_64(); +HOST_ARCH = toolset_host_arch(); +TARGET_ARCH = toolset_target_arch(); +// for compatible only +X64 = TARGET_ARCH != 'x86'; toolset_setup_arch(); toolset_setup_linker(); diff --git a/win32/build/confutils.js b/win32/build/confutils.js index c7489924554cb..dc6675c6d29d1 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -168,9 +168,13 @@ function probe_binary(EXE, what) } var version = execute(command + '" 2>&1"'); - if (what == "64") { - if (version.match(/x64/)) { - return 1; + if (what == "arch") { + if (version.match(/x86/)) { + return "x86"; + } else if (version.match(/x64/)) { + return "x64"; + } else if (version.match(/ARM64/)) { + return "arm64"; } } else { if (version.match(/(\d+\.\d+(\.\d+)?(\.\d+)?)/)) { @@ -1665,7 +1669,7 @@ function ADD_SOURCES(dir, file_list, target, obj_dir) } if (PHP_ANALYZER == "clang") { - var analyzer_base_args = X64 ? "-m64" : "-m32"; + var analyzer_base_args = TARGET_ARCH == 'x86' ? "-m32" : "-m64"; var analyzer_base_flags = ""; analyzer_base_args += " --analyze"; @@ -1688,10 +1692,14 @@ function ADD_SOURCES(dir, file_list, target, obj_dir) analyzer_base_flags += " -D _MSC_VER=" + probe_binary(PATH_PROG('cl', null)); } - if (X64) { + if (TARGET_ARCH == 'x64') { analyzer_base_flags += " -D _M_X64 -D _WIN64"; - } else { + } else if (TARGET_ARCH == 'ARM64') { + analyzer_base_flags += " -D _M_ARM64 -D _WIN64"; + } else if (TARGET_ARCH == 'x86') { analyzer_base_flags += " -D _M_IX86 "; + } else { + ERROR("analyzer is not supported at arch " + TARGET_ARCH); } analyzer_base_flags += " -D _WIN32 -D WIN32 -D _WINDOWS"; @@ -1703,8 +1711,8 @@ function ADD_SOURCES(dir, file_list, target, obj_dir) analyzer_base_flags += " -I " + "\"" + vc_incs[i] + "\""; } - var cppcheck_platform = X64 ? "win64" : "win32A"; - var cppcheck_lib = "win32\\build\\cppcheck_" + (X64 ? "x64" : "x86") + ".cfg"; + var cppcheck_platform = TARGET_ARCH == 'x86' ? "win32A" : "win64"; + var cppcheck_lib = "win32\\build\\cppcheck_" + (TARGET_ARCH == 'x86' ? "x86" : "x64") + ".cfg"; // use x64 for arm64 yet analyzer_base_args += "--enable=warning,performance,portability,information,missingInclude " + "--platform=" + cppcheck_platform + " " + "--library=windows.cfg --library=microsoft_sal.cfg " + @@ -1955,7 +1963,8 @@ function write_summary() ar[k++] = ['Build type', PHP_DEBUG == "yes" ? "Debug" : "Release"]; ar[k++] = ['Thread Safety', PHP_ZTS == "yes" ? "Yes" : "No"]; ar[k++] = ['Compiler', COMPILER_NAME_LONG]; - ar[k++] = ['Architecture', X64 ? 'x64' : 'x86']; + ar[k++] = ['Target Architecture', TARGET_ARCH]; + ar[k++] = ['Host Architecture', HOST_ARCH]; if (PHP_PGO == "yes") { ar[k++] = ['Optimization', "PGO"]; } else if (PHP_PGI == "yes") { @@ -3128,10 +3137,32 @@ function toolset_get_compiler_name(short) } -function toolset_is_64() +function toolset_host_arch() +{ + var command = 'cmd /c "where cl.exe"'; + var clpath = execute(command).split(/\n/)[0].replace(/\s$/, ''); + + var command = 'cmd /c "dumpbin "' + clpath + '" /nologo /headers"'; + var full = execute(command); + + /* + output is something like + FILE HEADER VALUES + 8664 machine (x64) + */ + var matches = full.match(/FILE HEADER VALUES\s+[A-F0-9]{3,4}\smachine \((x64|x86|ARM64)\)/); + + if(!matches){ + ERROR("Unsupported toolset host"); + } + + return matches[1].toLowerCase(); +} + +function toolset_target_arch() { if (VS_TOOLSET) { - return probe_binary(PHP_CL, 64); + return probe_binary(PHP_CL, 'arch'); } else if (CLANG_TOOLSET) { /*var command = 'cmd /c ""' + PHP_CL + '" -v"'; var full = execute(command + '" 2>&1"'); @@ -3141,26 +3172,22 @@ function toolset_is_64() /* Even executed within an environment setup with vcvars32.bat, clang-cl doesn't recognize the arch toolset. But as it needs the VS environment, checking the arch of cl.exe is correct. */ - return probe_binary(PATH_PROG('cl', null), 64); + return probe_binary(PATH_PROG('cl', null), 'arch'); } else if (ICC_TOOLSET) { - var command = 'cmd /c ""' + PHP_CL + '" -v"'; + var command = 'cmd /c "where cl"'; var full = execute(command + '" 2>&1"'); return null != full.match(/Intel\(R\) 64/); } - ERROR("Unsupported toolset"); + ERROR("Unsupported toolset target"); } function toolset_setup_arch() { - if (X64) { - STDOUT.WriteLine(" Detected 64-bit compiler"); - } else { - STDOUT.WriteLine(" Detected 32-bit compiler"); - } - AC_DEFINE('PHP_BUILD_ARCH', X64 ? 'x64' : 'x86', "Detected compiler architecture"); - DEFINE("PHP_ARCHITECTURE", X64 ? 'x64' : 'x86'); + STDOUT.WriteLine(" Detected " + TARGET_ARCH + " compiler" + (TARGET_ARCH == HOST_ARCH ? "" : " (cross compile from " + HOST_ARCH + ")")); + AC_DEFINE('PHP_BUILD_ARCH', TARGET_ARCH, "Detected compiler architecture"); + DEFINE("PHP_ARCHITECTURE", TARGET_ARCH); } function toolset_setup_codegen_arch() @@ -3174,7 +3201,7 @@ function toolset_setup_codegen_arch() if ("IA32" != arc) { ERROR("Only IA32 arch is supported by --with-codegen-arch, got '" + arc + "'"); - } else if (X64) { + } else if (TARGET_ARCH != 'x86') { ERROR("IA32 arch is only supported with 32-bit build"); } ADD_FLAG("CFLAGS", "/arch:" + arc); @@ -3234,10 +3261,10 @@ function toolset_setup_common_cflags() // fun stuff: MS deprecated ANSI stdio and similar functions // disable annoying warnings. In addition, time_t defaults // to 64-bit. Ask for 32-bit. - if (X64) { - ADD_FLAG('CFLAGS', ' /wd4996 '); - } else { + if (TARGET_ARCH == 'x86') { ADD_FLAG('CFLAGS', ' /wd4996 /D_USE_32BIT_TIME_T=1 '); + } else { + ADD_FLAG('CFLAGS', ' /wd4996 '); } if (PHP_DEBUG == "yes") { @@ -3289,10 +3316,10 @@ function toolset_setup_common_cflags() ADD_FLAG("CFLAGS", "/Zc:wchar_t"); } else if (CLANG_TOOLSET) { - if (X64) { - ADD_FLAG('CFLAGS', '-m64'); - } else { + if (TARGET_ARCH == 'x86') { ADD_FLAG('CFLAGS', '-m32'); + } else { + ADD_FLAG('CFLAGS', '-m64'); } ADD_FLAG("CFLAGS", " /fallback "); ADD_FLAG("CFLAGS", "-Xclang -fmodules"); @@ -3322,6 +3349,14 @@ function toolset_setup_intrinsic_cflags() 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 offically 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; } @@ -3349,7 +3384,7 @@ function toolset_setup_intrinsic_cflags() } } } - if (!X64) { + 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. */ @@ -3420,7 +3455,7 @@ function toolset_setup_build_mode() { if (PHP_DEBUG == "yes") { ADD_FLAG("CFLAGS", "/LDd /MDd /Od /D _DEBUG /D ZEND_DEBUG=1 " + - (X64?"/Zi":"/ZI")); + (TARGET_ARCH == 'x86'?"/ZI":"/Zi")); ADD_FLAG("LDFLAGS", "/debug"); // Avoid problems when linking to release libraries that use the release // version of the libc @@ -3455,11 +3490,16 @@ function object_out_dir_option_handle() } else { PHP_OBJECT_OUT_DIR = FSO.GetAbsolutePathName(".") + '\\'; - if (X64) { + if (TARGET_ARCH == 'x64') { PHP_OBJECT_OUT_DIR += 'x64\\'; if (!FSO.FolderExists(PHP_OBJECT_OUT_DIR)) { FSO.CreateFolder(PHP_OBJECT_OUT_DIR); } + } else if (TARGET_ARCH == 'arm64') { + PHP_OBJECT_OUT_DIR += 'arm64\\'; + if (!FSO.FolderExists(PHP_OBJECT_OUT_DIR)) { + FSO.CreateFolder(PHP_OBJECT_OUT_DIR); + } } } } @@ -3516,7 +3556,7 @@ function php_build_option_handle() if (FSO.FolderExists("..\\php_build")) { PHP_PHP_BUILD = "..\\php_build"; } else { - if (X64) { + if (TARGET_ARCH != 'x86') { if (FSO.FolderExists("..\\win64build")) { PHP_PHP_BUILD = "..\\win64build"; } else if (FSO.FolderExists("..\\php-win64-dev\\php_build")) { @@ -3678,7 +3718,7 @@ function get_clang_lib_dir() ERROR("Failed to determine clang lib path"); } - if (X64) { + if (TARGET_ARCH != 'x86') { ret = PROGRAM_FILES + "\\LLVM\\lib\\clang\\" + ver + "\\lib"; if (!FSO.FolderExists(ret)) { ret = null; @@ -3715,10 +3755,13 @@ function add_asan_opts(cflags_name, libs_name, ldflags_name) ADD_FLAG(cflags_name, "-fsanitize=address,undefined"); } if (!!libs_name) { - if (X64) { + if (TARGET_ARCH == 'x64') { ADD_FLAG(libs_name, "clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib"); - } else { + } else if (TARGET_ARCH == 'x86') { ADD_FLAG(libs_name, "clang_rt.asan_dynamic-i386.lib clang_rt.asan_dynamic_runtime_thunk-i386.lib"); + } else { + // TODO: support arm64? + ERROR("Failed to determine clang lib path"); } }