summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2021-03-23 17:12:15 +0300
committerDmitry Stogov <dmitry@zend.com>2021-03-23 17:12:15 +0300
commit7adaec1ce8312995f65f1c177d1a2184c2f80671 (patch)
tree9d371a7c2d00a9c2e76930b4ad33138cdc049a18
parentc290de157caa03b34f9c5ee7cb987e35cca0e468 (diff)
downloadphp-git-7adaec1ce8312995f65f1c177d1a2184c2f80671.tar.gz
Move system independent code out from x86 specific header
-rw-r--r--ext/opcache/jit/zend_jit_internal.h185
-rw-r--r--ext/opcache/jit/zend_jit_x86.dasc13
-rw-r--r--ext/opcache/jit/zend_jit_x86.h196
3 files changed, 204 insertions, 190 deletions
diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h
index 906262773f..a351dec030 100644
--- a/ext/opcache/jit/zend_jit_internal.h
+++ b/ext/opcache/jit/zend_jit_internal.h
@@ -20,6 +20,191 @@
#ifndef ZEND_JIT_INTERNAL_H
#define ZEND_JIT_INTERNAL_H
+/* Register Set */
+#define ZEND_REGSET_EMPTY 0
+
+#define ZEND_REGSET_IS_EMPTY(regset) \
+ (regset == ZEND_REGSET_EMPTY)
+
+#define ZEND_REGSET(reg) \
+ (1u << (reg))
+
+#define ZEND_REGSET_INTERVAL(reg1, reg2) \
+ (((1u << ((reg2) - (reg1) + 1)) - 1) << (reg1))
+
+#define ZEND_REGSET_IN(regset, reg) \
+ (((regset) & ZEND_REGSET(reg)) != 0)
+
+#define ZEND_REGSET_INCL(regset, reg) \
+ (regset) |= ZEND_REGSET(reg)
+
+#define ZEND_REGSET_EXCL(regset, reg) \
+ (regset) &= ~ZEND_REGSET(reg)
+
+#define ZEND_REGSET_UNION(set1, set2) \
+ ((set1) | (set2))
+
+#define ZEND_REGSET_INTERSECTION(set1, set2) \
+ ((set1) & (set2))
+
+#define ZEND_REGSET_DIFFERENCE(set1, set2) \
+ ((set1) & ~(set2))
+
+#ifndef _WIN32
+# if (ZREG_NUM <= 32)
+# define ZEND_REGSET_FIRST(set) ((zend_reg)__builtin_ctz(set))
+# define ZEND_REGSET_LAST(set) ((zend_reg)(__builtin_clz(set)^31)))
+# elif(ZREG_NUM <= 64)
+# define ZEND_REGSET_FIRST(set) ((zend_reg)__builtin_ctzll(set))
+# define ZEND_REGSET_LAST(set) ((zend_reg)(__builtin_clzll(set)^63)))
+# else
+# errir "Too many registers"
+# endif
+#else
+# include <intrin.h>
+uint32_t __inline __zend_jit_ctz(uint32_t value) {
+ DWORD trailing_zero = 0;
+ if (_BitScanForward(&trailing_zero, value)) {
+ return trailing_zero;
+ }
+ return 32;
+}
+uint32_t __inline __zend_jit_clz(uint32_t value) {
+ DWORD leading_zero = 0;
+ if (_BitScanReverse(&leading_zero, value)) {
+ return 31 - leading_zero;
+ }
+ return 32;
+}
+# define ZEND_REGSET_FIRST(set) ((zend_reg)__zend_jit_ctz(set))
+# define ZEND_REGSET_LAST(set) ((zend_reg)(__zend_jit_clz(set)^31)))
+#endif
+
+#define ZEND_REGSET_FOREACH(set, reg) \
+ do { \
+ zend_regset _tmp = (set); \
+ while (!ZEND_REGSET_IS_EMPTY(_tmp)) { \
+ zend_reg _reg = ZEND_REGSET_FIRST(_tmp); \
+ ZEND_REGSET_EXCL(_tmp, _reg); \
+ reg = _reg; \
+
+#define ZEND_REGSET_FOREACH_END() \
+ } \
+ } while (0)
+
+/* Register Names */
+extern const char *zend_reg_name[];
+
+/* Address Encoding */
+typedef uintptr_t zend_jit_addr;
+
+#define IS_CONST_ZVAL 0
+#define IS_MEM_ZVAL 1
+#define IS_REG 2
+
+#define _ZEND_ADDR_MODE_MASK 0x3
+#define _ZEND_ADDR_REG_SHIFT 2
+#define _ZEND_ADDR_REG_MASK 0x3f /* no more than 64 registers */
+#define _ZEND_ADDR_OFFSET_SHIFT 8
+#define _ZEND_ADDR_REG_STORE_BIT 8
+#define _ZEND_ADDR_REG_LOAD_BIT 9
+#define _ZEND_ADDR_REG_LAST_USE_BIT 10
+
+#define ZEND_ADDR_CONST_ZVAL(zv) \
+ (((zend_jit_addr)(uintptr_t)(zv)) | IS_CONST_ZVAL)
+#define ZEND_ADDR_MEM_ZVAL(reg, offset) \
+ ((((zend_jit_addr)(uintptr_t)(offset)) << _ZEND_ADDR_OFFSET_SHIFT) | \
+ (((zend_jit_addr)(uintptr_t)(reg)) << _ZEND_ADDR_REG_SHIFT) | \
+ IS_MEM_ZVAL)
+#define ZEND_ADDR_REG(reg) \
+ ((((zend_jit_addr)(uintptr_t)(reg)) << _ZEND_ADDR_REG_SHIFT) | \
+ IS_REG)
+
+#define Z_MODE(addr) (((addr) & _ZEND_ADDR_MODE_MASK))
+#define Z_ZV(addr) ((zval*)(addr))
+#define Z_OFFSET(addr) ((uint32_t)((addr)>>_ZEND_ADDR_OFFSET_SHIFT))
+#define Z_REG(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_SHIFT) & _ZEND_ADDR_REG_MASK))
+#define Z_STORE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_STORE_BIT) & 1))
+#define Z_LOAD(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LOAD_BIT) & 1))
+#define Z_LAST_USE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LAST_USE_BIT) & 1))
+
+#define OP_REG_EX(reg, store, load, last_use) \
+ ((reg) | \
+ ((store) ? (1 << (_ZEND_ADDR_REG_STORE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \
+ ((load) ? (1 << (_ZEND_ADDR_REG_LOAD_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \
+ ((last_use) ? (1 << (_ZEND_ADDR_REG_LAST_USE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) \
+ )
+
+#define OP_REG(ssa_op, op) \
+ (ra && ssa_op->op >= 0 && ra[ssa_op->op] ? \
+ OP_REG_EX(ra[ssa_op->op]->reg, \
+ (ra[ssa_op->op]->flags & ZREG_STORE), \
+ (ra[ssa_op->op]->flags & ZREG_LOAD), \
+ zend_ival_is_last_use(ra[ssa_op->op], ssa_op - ssa->ops) \
+ ) : ZREG_NONE)
+
+static zend_always_inline zend_jit_addr _zend_jit_decode_op(zend_uchar op_type, znode_op op, const zend_op *opline, zend_reg reg)
+{
+ if (op_type == IS_CONST) {
+#if ZEND_USE_ABS_CONST_ADDR
+ return ZEND_ADDR_CONST_ZVAL(op.zv);
+#else
+ return ZEND_ADDR_CONST_ZVAL(RT_CONSTANT(opline, op));
+#endif
+ } else {
+ ZEND_ASSERT(op_type & (IS_CV|IS_TMP_VAR|IS_VAR));
+ if (reg != ZREG_NONE) {
+ return ZEND_ADDR_REG(reg);
+ } else {
+ return ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var);
+ }
+ }
+}
+
+#define OP_ADDR(opline, type, op) \
+ _zend_jit_decode_op((opline)->type, (opline)->op, opline, ZREG_NONE)
+
+#define OP1_ADDR() \
+ OP_ADDR(opline, op1_type, op1)
+#define OP2_ADDR() \
+ OP_ADDR(opline, op2_type, op2)
+#define RES_ADDR() \
+ OP_ADDR(opline, result_type, result)
+#define OP1_DATA_ADDR() \
+ OP_ADDR(opline + 1, op1_type, op1)
+
+#define OP_REG_ADDR(opline, type, _op, _ssa_op) \
+ _zend_jit_decode_op((opline)->type, (opline)->_op, opline, \
+ OP_REG(ssa_op, _ssa_op))
+
+#define OP1_REG_ADDR() \
+ OP_REG_ADDR(opline, op1_type, op1, op1_use)
+#define OP2_REG_ADDR() \
+ OP_REG_ADDR(opline, op2_type, op2, op2_use)
+#define RES_REG_ADDR() \
+ OP_REG_ADDR(opline, result_type, result, result_def)
+#define OP1_DATA_REG_ADDR() \
+ OP_REG_ADDR(opline + 1, op1_type, op1, op1_use)
+
+#define OP1_DEF_REG_ADDR() \
+ OP_REG_ADDR(opline, op1_type, op1, op1_def)
+#define OP2_DEF_REG_ADDR() \
+ OP_REG_ADDR(opline, op2_type, op2, op2_def)
+#define RES_USE_REG_ADDR() \
+ OP_REG_ADDR(opline, result_type, result, result_use)
+#define OP1_DATA_DEF_REG_ADDR() \
+ OP_REG_ADDR(opline + 1, op1_type, op1, op1_def)
+
+static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_addr addr2)
+{
+ if (addr1 == addr2) {
+ return 1;
+ } else if (Z_MODE(addr1) == IS_REG && Z_MODE(addr2) == IS_REG) {
+ return Z_REG(addr1) == Z_REG(addr2);
+ }
+ return 0;
+}
+
typedef struct _zend_jit_op_array_extension {
zend_func_info func_info;
const void *orig_handler;
diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc
index 142b08eed6..6bb4c78778 100644
--- a/ext/opcache/jit/zend_jit_x86.dasc
+++ b/ext/opcache/jit/zend_jit_x86.dasc
@@ -110,7 +110,6 @@
*/
#include "Zend/zend_cpuinfo.h"
-#include "jit/zend_jit_x86.h"
#ifdef HAVE_VALGRIND
# include <valgrind/valgrind.h>
@@ -141,6 +140,18 @@ const char* zend_reg_name[] = {
# define GCC_GLOBAL_REGS 0
#endif
+/* Simulate x86 fastcall */
+#ifdef _WIN64
+# define ZREG_FCARG1a ZREG_RCX
+# define ZREG_FCARG2a ZREG_RDX
+#elif defined(__x86_64__)
+# define ZREG_FCARG1a ZREG_RDI
+# define ZREG_FCARG2a ZREG_RSI
+#else
+# define ZREG_FCARG1a ZREG_RCX
+# define ZREG_FCARG2a ZREG_RDX
+#endif
+
#if ZTS
static size_t tsrm_ls_cache_tcb_offset = 0;
static size_t tsrm_tls_index;
diff --git a/ext/opcache/jit/zend_jit_x86.h b/ext/opcache/jit/zend_jit_x86.h
index d47c5be056..f811a1d520 100644
--- a/ext/opcache/jit/zend_jit_x86.h
+++ b/ext/opcache/jit/zend_jit_x86.h
@@ -99,58 +99,20 @@ typedef struct _zend_jit_registers_buf {
#define ZREG_RDI ZREG_R7
#ifdef _WIN64
-# define ZREG_FP ZREG_R14
-# define ZREG_IP ZREG_R15
-# define ZREG_RX ZREG_IP
-# define ZREG_FCARG1a ZREG_RCX
-# define ZREG_FCARG2a ZREG_RDX
+# define ZREG_FP ZREG_R14
+# define ZREG_IP ZREG_R15
#elif defined(__x86_64__)
-# define ZREG_FP ZREG_R14
-# define ZREG_IP ZREG_R15
-# define ZREG_RX ZREG_IP
-# define ZREG_FCARG1a ZREG_RDI
-# define ZREG_FCARG2a ZREG_RSI
+# define ZREG_FP ZREG_R14
+# define ZREG_IP ZREG_R15
#else
-# define ZREG_FP ZREG_RSI
-# define ZREG_IP ZREG_RDI
-# define ZREG_RX ZREG_IP
-# define ZREG_FCARG1a ZREG_RCX
-# define ZREG_FCARG2a ZREG_RDX
+# define ZREG_FP ZREG_RSI
+# define ZREG_IP ZREG_RDI
#endif
-extern const char *zend_reg_name[];
+#define ZREG_RX ZREG_IP
typedef uint32_t zend_regset;
-#define ZEND_REGSET_EMPTY 0
-
-#define ZEND_REGSET_IS_EMPTY(regset) \
- (regset == ZEND_REGSET_EMPTY)
-
-#define ZEND_REGSET(reg) \
- (1u << (reg))
-
-#define ZEND_REGSET_INTERVAL(reg1, reg2) \
- (((1u << ((reg2) - (reg1) + 1)) - 1) << (reg1))
-
-#define ZEND_REGSET_IN(regset, reg) \
- (((regset) & ZEND_REGSET(reg)) != 0)
-
-#define ZEND_REGSET_INCL(regset, reg) \
- (regset) |= ZEND_REGSET(reg)
-
-#define ZEND_REGSET_EXCL(regset, reg) \
- (regset) &= ~ZEND_REGSET(reg)
-
-#define ZEND_REGSET_UNION(set1, set2) \
- ((set1) | (set2))
-
-#define ZEND_REGSET_INTERSECTION(set1, set2) \
- ((set1) & (set2))
-
-#define ZEND_REGSET_DIFFERENCE(set1, set2) \
- ((set1) & ~(set2))
-
#ifdef _WIN64
# define ZEND_REGSET_FIXED \
(ZEND_REGSET(ZREG_RSP) | ZEND_REGSET(ZREG_R14) | ZEND_REGSET(ZREG_R15))
@@ -186,148 +148,4 @@ typedef uint32_t zend_regset;
(ZEND_REGSET(ZREG_RBX) | ZEND_REGSET(ZREG_RBP))
#endif
-#ifndef _WIN32
-#define ZEND_REGSET_FIRST(set) ((zend_reg)__builtin_ctz(set))
-#define ZEND_REGSET_LAST(set) ((zend_reg)(__builtin_clz(set)^31)))
-#else
-#include <intrin.h>
-uint32_t __inline __zend_jit_ctz( uint32_t value ) {
- DWORD trailing_zero = 0;
- if (_BitScanForward(&trailing_zero, value)) {
- return trailing_zero;
- }
- return 32;
-}
-uint32_t __inline __zend_jit_clz(uint32_t value) {
- DWORD leading_zero = 0;
- if (_BitScanReverse(&leading_zero, value)) {
- return 31 - leading_zero;
- }
- return 32;
-}
-#define ZEND_REGSET_FIRST(set) ((zend_reg)__zend_jit_ctz(set))
-#define ZEND_REGSET_LAST(set) ((zend_reg)(__zend_jit_clz(set)^31)))
-#endif
-
-#define ZEND_REGSET_FOREACH(set, reg) \
- do { \
- zend_regset _tmp = (set); \
- while (!ZEND_REGSET_IS_EMPTY(_tmp)) { \
- zend_reg _reg = ZEND_REGSET_FIRST(_tmp); \
- ZEND_REGSET_EXCL(_tmp, _reg); \
- reg = _reg; \
-
-#define ZEND_REGSET_FOREACH_END() \
- } \
- } while (0)
-
-typedef uintptr_t zend_jit_addr;
-
-#define IS_CONST_ZVAL 0
-#define IS_MEM_ZVAL 1
-#define IS_REG 2
-
-#define _ZEND_ADDR_MODE_MASK 0x3
-#define _ZEND_ADDR_REG_SHIFT 2
-#define _ZEND_ADDR_REG_MASK 0x3f
-#define _ZEND_ADDR_OFFSET_SHIFT 8
-#define _ZEND_ADDR_REG_STORE_BIT 8
-#define _ZEND_ADDR_REG_LOAD_BIT 9
-#define _ZEND_ADDR_REG_LAST_USE_BIT 10
-
-#define ZEND_ADDR_CONST_ZVAL(zv) \
- (((zend_jit_addr)(uintptr_t)(zv)) | IS_CONST_ZVAL)
-#define ZEND_ADDR_MEM_ZVAL(reg, offset) \
- ((((zend_jit_addr)(uintptr_t)(offset)) << _ZEND_ADDR_OFFSET_SHIFT) | \
- (((zend_jit_addr)(uintptr_t)(reg)) << _ZEND_ADDR_REG_SHIFT) | \
- IS_MEM_ZVAL)
-#define ZEND_ADDR_REG(reg) \
- ((((zend_jit_addr)(uintptr_t)(reg)) << _ZEND_ADDR_REG_SHIFT) | \
- IS_REG)
-
-#define Z_MODE(addr) (((addr) & _ZEND_ADDR_MODE_MASK))
-#define Z_ZV(addr) ((zval*)(addr))
-#define Z_OFFSET(addr) ((uint32_t)((addr)>>_ZEND_ADDR_OFFSET_SHIFT))
-#define Z_REG(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_SHIFT) & _ZEND_ADDR_REG_MASK))
-#define Z_STORE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_STORE_BIT) & 1))
-#define Z_LOAD(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LOAD_BIT) & 1))
-#define Z_LAST_USE(addr) ((zend_reg)(((addr)>>_ZEND_ADDR_REG_LAST_USE_BIT) & 1))
-
-#define OP_REG_EX(reg, store, load, last_use) \
- ((reg) | \
- ((store) ? (1 << (_ZEND_ADDR_REG_STORE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \
- ((load) ? (1 << (_ZEND_ADDR_REG_LOAD_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) | \
- ((last_use) ? (1 << (_ZEND_ADDR_REG_LAST_USE_BIT-_ZEND_ADDR_REG_SHIFT)) : 0) \
- )
-
-#define OP_REG(ssa_op, op) \
- (ra && ssa_op->op >= 0 && ra[ssa_op->op] ? \
- OP_REG_EX(ra[ssa_op->op]->reg, \
- (ra[ssa_op->op]->flags & ZREG_STORE), \
- (ra[ssa_op->op]->flags & ZREG_LOAD), \
- zend_ival_is_last_use(ra[ssa_op->op], ssa_op - ssa->ops) \
- ) : ZREG_NONE)
-
-static zend_always_inline zend_jit_addr _zend_jit_decode_op(zend_uchar op_type, znode_op op, const zend_op *opline, zend_reg reg)
-{
- if (op_type == IS_CONST) {
-#if ZEND_USE_ABS_CONST_ADDR
- return ZEND_ADDR_CONST_ZVAL(op.zv);
-#else
- return ZEND_ADDR_CONST_ZVAL(RT_CONSTANT(opline, op));
-#endif
- } else {
- ZEND_ASSERT(op_type & (IS_CV|IS_TMP_VAR|IS_VAR));
- if (reg != ZREG_NONE) {
- return ZEND_ADDR_REG(reg);
- } else {
- return ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var);
- }
- }
-}
-
-#define OP_ADDR(opline, type, op) \
- _zend_jit_decode_op((opline)->type, (opline)->op, opline, ZREG_NONE)
-
-#define OP1_ADDR() \
- OP_ADDR(opline, op1_type, op1)
-#define OP2_ADDR() \
- OP_ADDR(opline, op2_type, op2)
-#define RES_ADDR() \
- OP_ADDR(opline, result_type, result)
-#define OP1_DATA_ADDR() \
- OP_ADDR(opline + 1, op1_type, op1)
-
-#define OP_REG_ADDR(opline, type, _op, _ssa_op) \
- _zend_jit_decode_op((opline)->type, (opline)->_op, opline, \
- OP_REG(ssa_op, _ssa_op))
-
-#define OP1_REG_ADDR() \
- OP_REG_ADDR(opline, op1_type, op1, op1_use)
-#define OP2_REG_ADDR() \
- OP_REG_ADDR(opline, op2_type, op2, op2_use)
-#define RES_REG_ADDR() \
- OP_REG_ADDR(opline, result_type, result, result_def)
-#define OP1_DATA_REG_ADDR() \
- OP_REG_ADDR(opline + 1, op1_type, op1, op1_use)
-
-#define OP1_DEF_REG_ADDR() \
- OP_REG_ADDR(opline, op1_type, op1, op1_def)
-#define OP2_DEF_REG_ADDR() \
- OP_REG_ADDR(opline, op2_type, op2, op2_def)
-#define RES_USE_REG_ADDR() \
- OP_REG_ADDR(opline, result_type, result, result_use)
-#define OP1_DATA_DEF_REG_ADDR() \
- OP_REG_ADDR(opline + 1, op1_type, op1, op1_def)
-
-static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_addr addr2)
-{
- if (addr1 == addr2) {
- return 1;
- } else if (Z_MODE(addr1) == IS_REG && Z_MODE(addr2) == IS_REG) {
- return Z_REG(addr1) == Z_REG(addr2);
- }
- return 0;
-}
-
#endif /* ZEND_JIT_X86_H */