@@ -169,6 +169,7 @@ ZEND_CHECK_STACK_DIRECTION
169
169
ZEND_CHECK_FLOAT_PRECISION
170
170
ZEND_DLSYM_CHECK
171
171
ZEND_CHECK_GLOBAL_REGISTER_VARIABLES
172
+ ZEND_CHECK_PRESERVE_NONE
172
173
ZEND_CHECK_CPUID_COUNT
173
174
174
175
AC_MSG_CHECKING ( [ whether to enable thread safety] )
@@ -470,3 +471,103 @@ AS_VAR_IF([ZEND_MAX_EXECUTION_TIMERS], [yes],
470
471
AC_MSG_CHECKING ( [ whether to enable Zend max execution timers] )
471
472
AC_MSG_RESULT ( [ $ZEND_MAX_EXECUTION_TIMERS] )
472
473
] )
474
+
475
+ dnl
476
+ dnl ZEND_CHECK_PRESERVE_NONE
477
+ dnl
478
+ dnl Check if the preserve_none calling convention is supported and matches our
479
+ dnl expectations.
480
+ dnl
481
+ AC_DEFUN ( [ ZEND_CHECK_PRESERVE_NONE] , [ dnl
482
+ AC_CACHE_CHECK ( [ for preserve_none calling convention] ,
483
+ [ php_cv_preverve_none] ,
484
+ [ AC_RUN_IFELSE ( [ AC_LANG_SOURCE ( [ [
485
+ #include <stdio.h>
486
+ #include <stdint.h>
487
+
488
+ const char * const1 = "str1";
489
+ const char * const2 = "str2";
490
+ const char * const3 = "str3";
491
+ uint64_t key = UINT64_C(0x9d7f71d2bd296364);
492
+
493
+ uintptr_t _a = 0;
494
+ uintptr_t _b = 0;
495
+
496
+ uintptr_t __attribute__((preserve_none)) fun(uintptr_t a, uintptr_t b) {
497
+ _a = a;
498
+ _b = b;
499
+ return (uintptr_t)const3;
500
+ }
501
+
502
+ uintptr_t __attribute__((preserve_none)) test(void) {
503
+ uintptr_t ret;
504
+
505
+ #if defined(__x86_64__)
506
+ __asm__ __volatile__(
507
+ /* XORing to make it unlikely the value exists in any other register */
508
+ "movq %1, %%r12\n"
509
+ "xorq %3, %%r12\n"
510
+ "movq %2, %%r13\n"
511
+ "xorq %3, %%r13\n"
512
+ "xorq %%rax, %%rax\n"
513
+ "call fun\n"
514
+ : "=a" (ret)
515
+ : "r" (const1), "r" (const2), "r" (key)
516
+ : "r12", "r13"
517
+ );
518
+ #elif defined(__aarch64__)
519
+ __asm__ __volatile__(
520
+ /* XORing to make it unlikely the value exists in any other register */
521
+ "eor x20, %1, %3\n"
522
+ "eor x21, %2, %3\n"
523
+ "eor x0, x0, x0\n"
524
+ "bl fun\n"
525
+ "mov %0, x0\n"
526
+ : "=r" (ret)
527
+ : "r" (const1), "r" (const2), "r" (key)
528
+ : "x0", "x21", "x22", "x30"
529
+ );
530
+ #else
531
+ # error
532
+ #endif
533
+
534
+ return ret;
535
+ }
536
+
537
+ int main(void) {
538
+
539
+ /* JIT is making the following expectations about preserve_none:
540
+ * - The registers used for integer args 1 and 2
541
+ * - The register used for a single integer return value
542
+ *
543
+ * We check these expectations here:
544
+ */
545
+
546
+ uintptr_t ret = test();
547
+
548
+ if (_a != ((uintptr_t)const1 ^ key)) {
549
+ fprintf(stderr, "arg1 mismatch\n");
550
+ return 1;
551
+ }
552
+ if (_b != ((uintptr_t)const2 ^ key)) {
553
+ fprintf(stderr, "arg2 mismatch\n");
554
+ return 2;
555
+ }
556
+ if (ret != (uintptr_t)const3) {
557
+ fprintf(stderr, "ret mismatch\n");
558
+ return 3;
559
+ }
560
+
561
+ fprintf(stderr, "OK\n");
562
+
563
+ return 0;
564
+ }] ] ) ] ,
565
+ [ php_cv_preserve_none=yes] ,
566
+ [ php_cv_preserve_none=no] ,
567
+ [ php_cv_preserve_none=no] )
568
+ ] )
569
+ AS_VAR_IF ( [ php_cv_preserve_none] , [ yes] , [
570
+ AC_DEFINE ( [ HAVE_PRESERVE_NONE] , [ 1] ,
571
+ [ Define to 1 if you have preserve_none support.] )
572
+ ] )
573
+ ] )
0 commit comments