@@ -15017,6 +15017,133 @@ static zend_regset zend_jit_get_scratch_regset(const zend_op *opline, const zend
15017
15017
return regset;
15018
15018
}
15019
15019
15020
+ static size_t dasm_venners_size = 0;
15021
+ void **dasm_labels_veneers = NULL;
15022
+
15023
+ static int zend_jit_add_veneer(dasm_State *Dst, void *buffer, uint32_t ins, int *b, uint32_t *cp, ptrdiff_t offset)
15024
+ {
15025
+ void *veneer;
15026
+ ptrdiff_t na;
15027
+ int n, m;
15028
+
15029
+ /* try to reuse veneers for global labels */
15030
+ if ((ins >> 16) == DASM_REL_LG
15031
+ && *(b-1) < 0
15032
+ && dasm_labels_veneers[-*(b-1)]) {
15033
+
15034
+ veneer = dasm_labels_veneers[-*(b-1)];
15035
+ na = (ptrdiff_t)veneer - (ptrdiff_t)cp + 4;
15036
+ n = (int)na;
15037
+
15038
+ /* check if we can jump to veneer */
15039
+ if ((ptrdiff_t)n != na) {
15040
+ /* pass */
15041
+ } else if (!(ins & 0xf800)) { /* B, BL */
15042
+ if ((n & 3) == 0 && ((n+0x08000000) >> 28) == 0) {
15043
+ return n;
15044
+ }
15045
+ } else if ((ins & 0x800)) { /* B.cond, CBZ, CBNZ, LDR* literal */
15046
+ if ((n & 3) == 0 && ((n+0x00100000) >> 21) == 0) {
15047
+ return n;
15048
+ }
15049
+ } else if ((ins & 0x3000) == 0x2000) { /* ADR */
15050
+ /* pass */
15051
+ } else if ((ins & 0x3000) == 0x3000) { /* ADRP */
15052
+ /* pass */
15053
+ } else if ((ins & 0x1000)) { /* TBZ, TBNZ */
15054
+ if ((n & 3) == 0 && ((n+0x00008000) >> 16) == 0) {
15055
+ return n;
15056
+ }
15057
+ }
15058
+ }
15059
+
15060
+ veneer = (char*)buffer + (Dst->codesize + dasm_venners_size);
15061
+
15062
+ if (veneer > dasm_end) {
15063
+ return 0; /* jit_buffer_size overflow */
15064
+ }
15065
+
15066
+ na = (ptrdiff_t)veneer - (ptrdiff_t)cp + 4;
15067
+ n = (int)na;
15068
+
15069
+ /* check if we can jump to veneer */
15070
+ if ((ptrdiff_t)n != na) {
15071
+ ZEND_ASSERT(0);
15072
+ return 0;
15073
+ } else if (!(ins & 0xf800)) { /* B, BL */
15074
+ if ((n & 3) != 0 || ((n+0x08000000) >> 28) != 0) {
15075
+ ZEND_ASSERT(0);
15076
+ return 0;
15077
+ }
15078
+ } else if ((ins & 0x800)) { /* B.cond, CBZ, CBNZ, LDR* literal */
15079
+ if ((n & 3) != 0 || ((n+0x00100000) >> 21) != 0) {
15080
+ ZEND_ASSERT(0);
15081
+ return 0;
15082
+ }
15083
+ } else if ((ins & 0x3000) == 0x2000) { /* ADR */
15084
+ ZEND_ASSERT(0);
15085
+ return 0;
15086
+ } else if ((ins & 0x3000) == 0x3000) { /* ADRP */
15087
+ ZEND_ASSERT(0);
15088
+ return 0;
15089
+ } else if ((ins & 0x1000)) { /* TBZ, TBNZ */
15090
+ if ((n & 3) != 0 || ((n+0x00008000) >> 16) != 0) {
15091
+ ZEND_ASSERT(0);
15092
+ return 0;
15093
+ }
15094
+ } else if ((ins & 0x8000)) { /* absolute */
15095
+ ZEND_ASSERT(0);
15096
+ return 0;
15097
+ } else {
15098
+ ZEND_ASSERT(0);
15099
+ return 0;
15100
+ }
15101
+
15102
+ // TODO: support for long veneers (above 128MB) ???
15103
+
15104
+ /* check if we can use B to jump from veneer */
15105
+ na = (ptrdiff_t)cp + offset - (ptrdiff_t)veneer - 4;
15106
+ m = (int)na;
15107
+ if ((ptrdiff_t)m != na) {
15108
+ ZEND_ASSERT(0);
15109
+ return 0;
15110
+ } else if ((m & 3) != 0 || ((m+0x08000000) >> 28) != 0) {
15111
+ ZEND_ASSERT(0);
15112
+ return 0;
15113
+ }
15114
+
15115
+ /* generate B instruction */
15116
+ *(uint32_t*)veneer = 0x14000000 | ((m >> 2) & 0x03ffffff);
15117
+ dasm_venners_size += 4;
15118
+
15119
+ if ((ins >> 16) == DASM_REL_LG
15120
+ && *(b-1) < 0) {
15121
+ /* reuse this veneer for the future jumps to global label */
15122
+ dasm_labels_veneers[-*(b-1)] = veneer;
15123
+ /* Dst->globals[*(b-1)] = veneer; */
15124
+
15125
+ #ifdef HAVE_DISASM
15126
+ if (JIT_G(debug) & ZEND_JIT_DEBUG_ASM) {
15127
+ const char *name = zend_jit_disasm_find_symbol((ptrdiff_t)cp + offset - 4, &offset);
15128
+
15129
+ if (name && !offset) {
15130
+ if (strstr(name, "@veneer") == NULL) {
15131
+ char *new_name;
15132
+
15133
+ zend_spprintf(&new_name, 0, "%s@veneer", name);
15134
+ zend_jit_disasm_add_symbol(new_name, (uint64_t)(uintptr_t)veneer, 4);
15135
+ efree(new_name);
15136
+ } else {
15137
+ zend_jit_disasm_add_symbol(name, (uint64_t)(uintptr_t)veneer, 4);
15138
+ }
15139
+ }
15140
+ }
15141
+ #endif
15142
+ }
15143
+
15144
+ return n;
15145
+ }
15146
+
15020
15147
#if defined(__clang__)
15021
15148
# pragma clang diagnostic pop
15022
15149
#endif
0 commit comments