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