2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Dmitry Stogov <dmitry@php.net> |
16 | Xinchen Hui <laruence@php.net> |
17 | Hao Sun <hao.sun@arm.com> |
18 +----------------------------------------------------------------------+
23 # define HAVE_DISASM 1
24 # include <capstone/capstone.h>
25 # define HAVE_CAPSTONE_ITER 1
27 # define HAVE_DISASM 1
28 # define DISASM_INTEL_SYNTAX 0
30 # include "jit/libudis86/itab.c"
31 # include "jit/libudis86/decode.c"
32 # include "jit/libudis86/syn.c"
33 # if DISASM_INTEL_SYNTAX
34 # include "jit/libudis86/syn-intel.c"
36 # include "jit/libudis86/syn-att.c"
38 # include "jit/libudis86/udis86.c"
39 #endif /* HAVE_CAPSTONE */
41 static void zend_jit_disasm_add_symbol(const char *name,
46 # include "jit/zend_elf.c"
49 #include "zend_sort.h"
62 struct _sym_node *parent;
63 struct _sym_node *child[2];
68 static void zend_syms_rotateleft(zend_sym_node *p) {
69 zend_sym_node *r = p->child[1];
70 p->child[1] = r->child[0];
72 r->child[0]->parent = p;
74 r->parent = p->parent;
75 if (p->parent == NULL) {
77 } else if (p->parent->child[0] == p) {
78 p->parent->child[0] = r;
80 p->parent->child[1] = r;
86 static void zend_syms_rotateright(zend_sym_node *p) {
87 zend_sym_node *l = p->child[0];
88 p->child[0] = l->child[1];
90 l->child[1]->parent = p;
92 l->parent = p->parent;
93 if (p->parent == NULL) {
95 } else if (p->parent->child[1] == p) {
96 p->parent->child[1] = l;
98 p->parent->child[0] = l;
104 static void zend_jit_disasm_add_symbol(const char *name,
109 size_t len = strlen(name);
111 sym = malloc(sizeof(zend_sym_node) + len + 1);
116 sym->end = (addr + size - 1);
117 memcpy((char*)&sym->name, name, len + 1);
118 sym->parent = sym->child[0] = sym->child[1] = NULL;
120 if (JIT_G(symbols)) {
121 zend_sym_node *node = JIT_G(symbols);
123 /* insert it into rbtree */
125 if (sym->addr > node->addr) {
126 ZEND_ASSERT(sym->addr > (node->end));
127 if (node->child[1]) {
128 node = node->child[1];
130 node->child[1] = sym;
134 } else if (sym->addr < node->addr) {
135 if (node->child[0]) {
136 node = node->child[0];
138 node->child[0] = sym;
143 ZEND_ASSERT(sym->addr == node->addr);
144 if (strcmp(name, node->name) == 0 && sym->end < node->end) {
145 /* reduce size of the existing symbol */
146 node->end = sym->end;
153 /* fix rbtree after instering */
154 while (sym && sym != JIT_G(symbols) && sym->parent->info == 1) {
155 if (sym->parent == sym->parent->parent->child[0]) {
156 node = sym->parent->parent->child[1];
157 if (node && node->info == 1) {
158 sym->parent->info = 0;
160 sym->parent->parent->info = 1;
161 sym = sym->parent->parent;
163 if (sym == sym->parent->child[1]) {
165 zend_syms_rotateleft(sym);
167 sym->parent->info = 0;
168 sym->parent->parent->info = 1;
169 zend_syms_rotateright(sym->parent->parent);
172 node = sym->parent->parent->child[0];
173 if (node && node->info == 1) {
174 sym->parent->info = 0;
176 sym->parent->parent->info = 1;
177 sym = sym->parent->parent;
179 if (sym == sym->parent->child[0]) {
181 zend_syms_rotateright(sym);
183 sym->parent->info = 0;
184 sym->parent->parent->info = 1;
185 zend_syms_rotateleft(sym->parent->parent);
190 JIT_G(symbols) = sym;
192 JIT_G(symbols)->info = 0;
195 static void zend_jit_disasm_destroy_symbols(zend_sym_node *n) {
198 zend_jit_disasm_destroy_symbols(n->child[0]);
201 zend_jit_disasm_destroy_symbols(n->child[1]);
207 static const char* zend_jit_disasm_find_symbol(uint64_t addr,
209 zend_sym_node *node = JIT_G(symbols);
211 if (addr < node->addr) {
212 node = node->child[0];
213 } else if (addr > node->end) {
214 node = node->child[1];
216 *offset = addr - node->addr;
224 static uint64_t zend_jit_disasm_branch_target(csh cs, const cs_insn *insn)
228 if (cs_insn_group(cs, insn, X86_GRP_JUMP)) {
229 for (i = 0; i < insn->detail->x86.op_count; i++) {
230 if (insn->detail->x86.operands[i].type == X86_OP_IMM) {
231 return insn->detail->x86.operands[i].imm;
240 static const char* zend_jit_disasm_resolver(
241 #ifndef HAVE_CAPSTONE
248 # ifndef HAVE_CAPSTONE
252 void *a = (void*)(zend_uintptr_t)(addr);
255 name = zend_jit_disasm_find_symbol(addr, offset);
261 && info.dli_sname != NULL
262 && info.dli_saddr == a) {
263 return info.dli_sname;
267 name = zend_jit_disasm_find_symbol(addr, offset);
276 static int zend_jit_cmp_labels(Bucket *b1, Bucket *b2)
278 return ((b1->h > b2->h) > 0) ? 1 : -1;
281 static int zend_jit_disasm(const char *name,
282 const char *filename,
283 const zend_op_array *op_array,
288 const void *end = (void *)((char *)start + size);
297 # ifdef HAVE_CAPSTONE_ITER
298 const uint8_t *cs_code;
309 const struct ud_operand *op;
313 # if defined(__x86_64__) || defined(_WIN64)
314 if (cs_open(CS_ARCH_X86, CS_MODE_64, &cs) != CS_ERR_OK)
316 cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON);
317 # if DISASM_INTEL_SYNTAX
318 cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
320 cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
323 if (cs_open(CS_ARCH_X86, CS_MODE_32, &cs) != CS_ERR_OK)
325 cs_option(cs, CS_OPT_DETAIL, CS_OPT_ON);
326 # if DISASM_INTEL_SYNTAX
327 cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
329 cs_option(cs, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
334 # if defined(__x86_64__) || defined(_WIN64)
335 ud_set_mode(&ud, 64);
337 ud_set_mode(&ud, 32);
339 # if DISASM_INTEL_SYNTAX
340 ud_set_syntax(&ud, UD_SYN_INTEL);
342 ud_set_syntax(&ud, UD_SYN_ATT);
344 ud_set_sym_resolver(&ud, zend_jit_disasm_resolver);
345 #endif /* HAVE_CAPSTONE */
348 fprintf(stderr, "%s: ; (%s)\n", name, filename ? filename : "unknown");
351 #ifndef HAVE_CAPSTONE
352 ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
353 ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
356 zend_hash_init(&labels, 8, NULL, NULL, 0);
357 if (op_array && cfg) {
359 for (b = 0; b < cfg->blocks_count; b++) {
360 if (cfg->blocks[b].flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) {
361 addr = (uint64_t)(uintptr_t)op_array->opcodes[cfg->blocks[b].start].handler;
362 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
363 zend_hash_index_add(&labels, addr, &zv);
370 # ifdef HAVE_CAPSTONE_ITER
372 cs_size = (uint8_t*)end - (uint8_t*)start;
373 cs_addr = (uint64_t)(uintptr_t)cs_code;
374 insn = cs_malloc(cs);
375 while (cs_disasm_iter(cs, &cs_code, &cs_size, &cs_addr, insn)) {
376 if ((addr = zend_jit_disasm_branch_target(cs, insn))) {
378 count = cs_disasm(cs, start, (uint8_t*)end - (uint8_t*)start, (uintptr_t)start, 0, &insn);
379 for (i = 0; i < count; i++) {
380 if ((addr = zend_jit_disasm_branch_target(cs, &(insn[i])))) {
382 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
383 zend_hash_index_add(&labels, addr, &zv);
389 while (ud_disassemble(&ud)) {
390 op = ud_insn_opr(&ud, 0);
391 if (op && op->type == UD_OP_JIMM) {
392 addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
393 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
394 zend_hash_index_add(&labels, addr, &zv);
400 zend_hash_sort(&labels, zend_jit_cmp_labels, 0);
402 /* label numbering */
404 ZEND_HASH_FOREACH_VAL(&labels, z) {
405 if (Z_TYPE_P(z) == IS_FALSE) {
412 } ZEND_HASH_FOREACH_END();
415 # ifdef HAVE_CAPSTONE_ITER
417 cs_size = (uint8_t*)end - (uint8_t*)start;
418 cs_addr = (uint64_t)(uintptr_t)cs_code;
419 while (cs_disasm_iter(cs, &cs_code, &cs_size, &cs_addr, insn)) {
420 z = zend_hash_index_find(&labels, insn->address);
422 for (i = 0; i < count; i++) {
423 z = zend_hash_index_find(&labels, insn[i].address);
426 if (Z_LVAL_P(z) < 0) {
427 fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
429 fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
433 # ifdef HAVE_CAPSTONE_ITER
434 fprintf(stderr, "\t%s ", insn->mnemonic);
437 fprintf(stderr, "\t%s ", insn[i].mnemonic);
440 /* Try to replace the target addresses with a symbols */
441 while ((q = strchr(p, 'x')) != NULL) {
442 if (p != q && *(q-1) == '0') {
446 if (*r >= '0' && *r <= '9') {
447 addr = addr * 16 + (*r - '0');
448 } else if (*r >= 'A' && *r <= 'F') {
449 addr = addr * 16 + (*r - 'A' + 10);
450 } else if (*r >= 'a' && *r <= 'f') {
451 addr = addr * 16 + (*r - 'a' + 10);
457 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
458 if ((z = zend_hash_index_find(&labels, addr))) {
459 if (Z_LVAL_P(z) < 0) {
460 fwrite(p, 1, q - p - 1, stderr);
461 fprintf(stderr, ".ENTRY" ZEND_LONG_FMT, -Z_LVAL_P(z));
463 fwrite(p, 1, q - p - 1, stderr);
464 fprintf(stderr, ".L" ZEND_LONG_FMT, Z_LVAL_P(z));
467 fwrite(p, 1, r - p, stderr);
469 } else if ((sym = zend_jit_disasm_resolver(addr, &offset))) {
470 fwrite(p, 1, q - p - 1, stderr);
474 fprintf(stderr, "+%" PRIx64, offset);
476 fprintf(stderr, "-%" PRIx64, offset);
480 fwrite(p, 1, r - p, stderr);
484 fwrite(p, 1, q - p + 1, stderr);
488 fprintf(stderr, "%s\n", p);
490 # ifdef HAVE_CAPSTONE_ITER
493 cs_free(insn, count);
496 ud_set_input_buffer(&ud, (uint8_t*)start, (uint8_t*)end - (uint8_t*)start);
497 ud_set_pc(&ud, (uint64_t)(uintptr_t)start);
499 while (ud_disassemble(&ud)) {
500 addr = ud_insn_off(&ud);
501 z = zend_hash_index_find(&labels, addr);
503 if (Z_LVAL_P(z) < 0) {
504 fprintf(stderr, ".ENTRY" ZEND_LONG_FMT ":\n", -Z_LVAL_P(z));
506 fprintf(stderr, ".L" ZEND_LONG_FMT ":\n", Z_LVAL_P(z));
509 op = ud_insn_opr(&ud, 0);
510 if (op && op->type == UD_OP_JIMM) {
511 addr = ud_syn_rel_target(&ud, (struct ud_operand*)op);
512 if (addr >= (uint64_t)(uintptr_t)start && addr < (uint64_t)(uintptr_t)end) {
513 z = zend_hash_index_find(&labels, addr);
515 const char *str = ud_insn_asm(&ud);
519 while (str[len] != 0 && str[len] != ' ' && str[len] != '\t') {
523 while (str[len] == ' ' || str[len] == '\t') {
526 if (Z_LVAL_P(z) < 0) {
527 fprintf(stderr, "\t%.*s.ENTRY" ZEND_LONG_FMT "\n", len, str, -Z_LVAL_P(z));
529 fprintf(stderr, "\t%.*s.L" ZEND_LONG_FMT "\n", len, str, Z_LVAL_P(z));
536 fprintf(stderr, "\t%s\n", ud_insn_asm(&ud));
539 fprintf(stderr, "\n");
541 zend_hash_destroy(&labels);
550 static int zend_jit_disasm_init(void)
553 #define REGISTER_EG(n) \
554 zend_jit_disasm_add_symbol("EG("#n")", \
555 (uint64_t)(uintptr_t)&executor_globals.n, sizeof(executor_globals.n))
556 REGISTER_EG(uninitialized_zval);
557 REGISTER_EG(exception);
558 REGISTER_EG(vm_interrupt);
559 REGISTER_EG(exception_op);
560 REGISTER_EG(timed_out);
561 REGISTER_EG(current_execute_data);
562 REGISTER_EG(vm_stack_top);
563 REGISTER_EG(vm_stack_end);
564 REGISTER_EG(symbol_table);
565 REGISTER_EG(jit_trace_num);
569 /* Register JIT helper functions */
570 #define REGISTER_HELPER(n) \
571 zend_jit_disasm_add_symbol(#n, \
572 (uint64_t)(uintptr_t)n, sizeof(void*));
573 REGISTER_HELPER(memcmp);
574 REGISTER_HELPER(zend_jit_init_func_run_time_cache_helper);
575 REGISTER_HELPER(zend_jit_find_func_helper);
576 REGISTER_HELPER(zend_jit_find_ns_func_helper);
577 REGISTER_HELPER(zend_jit_find_method_helper);
578 REGISTER_HELPER(zend_jit_find_method_tmp_helper);
579 REGISTER_HELPER(zend_jit_push_static_metod_call_frame);
580 REGISTER_HELPER(zend_jit_push_static_metod_call_frame_tmp);
581 REGISTER_HELPER(zend_jit_invalid_method_call);
582 REGISTER_HELPER(zend_jit_invalid_method_call_tmp);
583 REGISTER_HELPER(zend_jit_unref_helper);
584 REGISTER_HELPER(zend_jit_extend_stack_helper);
585 REGISTER_HELPER(zend_jit_int_extend_stack_helper);
586 REGISTER_HELPER(zend_jit_leave_nested_func_helper);
587 REGISTER_HELPER(zend_jit_leave_top_func_helper);
588 REGISTER_HELPER(zend_jit_leave_func_helper);
589 REGISTER_HELPER(zend_jit_symtable_find);
590 REGISTER_HELPER(zend_jit_hash_index_lookup_rw);
591 REGISTER_HELPER(zend_jit_hash_lookup_rw);
592 REGISTER_HELPER(zend_jit_symtable_lookup_rw);
593 REGISTER_HELPER(zend_jit_symtable_lookup_w);
594 REGISTER_HELPER(zend_jit_undefined_op_helper);
595 REGISTER_HELPER(zend_jit_fetch_dim_r_helper);
596 REGISTER_HELPER(zend_jit_fetch_dim_is_helper);
597 REGISTER_HELPER(zend_jit_fetch_dim_isset_helper);
598 REGISTER_HELPER(zend_jit_fetch_dim_str_offset_r_helper);
599 REGISTER_HELPER(zend_jit_fetch_dim_str_r_helper);
600 REGISTER_HELPER(zend_jit_fetch_dim_str_is_helper);
601 REGISTER_HELPER(zend_jit_fetch_dim_obj_r_helper);
602 REGISTER_HELPER(zend_jit_fetch_dim_obj_is_helper);
603 REGISTER_HELPER(zend_jit_fetch_dim_rw_helper);
604 REGISTER_HELPER(zend_jit_fetch_dim_w_helper);
605 REGISTER_HELPER(zend_jit_fetch_dim_obj_rw_helper);
606 REGISTER_HELPER(zend_jit_fetch_dim_obj_w_helper);
607 // REGISTER_HELPER(zend_jit_fetch_dim_obj_unset_helper);
608 REGISTER_HELPER(zend_jit_assign_dim_helper);
609 REGISTER_HELPER(zend_jit_assign_dim_op_helper);
610 REGISTER_HELPER(zend_jit_fast_assign_concat_helper);
611 REGISTER_HELPER(zend_jit_fast_concat_helper);
612 REGISTER_HELPER(zend_jit_isset_dim_helper);
613 REGISTER_HELPER(zend_jit_free_call_frame);
614 REGISTER_HELPER(zend_jit_fetch_global_helper);
615 REGISTER_HELPER(zend_jit_verify_arg_slow);
616 REGISTER_HELPER(zend_jit_verify_return_slow);
617 REGISTER_HELPER(zend_jit_fetch_obj_r_slow);
618 REGISTER_HELPER(zend_jit_fetch_obj_r_dynamic);
619 REGISTER_HELPER(zend_jit_fetch_obj_is_slow);
620 REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic);
621 REGISTER_HELPER(zend_jit_fetch_obj_w_slow);
622 REGISTER_HELPER(zend_jit_check_array_promotion);
623 REGISTER_HELPER(zend_jit_create_typed_ref);
624 REGISTER_HELPER(zend_jit_extract_helper);
625 REGISTER_HELPER(zend_jit_vm_stack_free_args_helper);
626 REGISTER_HELPER(zend_jit_copy_extra_args_helper);
627 REGISTER_HELPER(zend_jit_deprecated_helper);
628 REGISTER_HELPER(zend_jit_assign_const_to_typed_ref);
629 REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref);
630 REGISTER_HELPER(zend_jit_assign_var_to_typed_ref);
631 REGISTER_HELPER(zend_jit_assign_cv_to_typed_ref);
632 REGISTER_HELPER(zend_jit_pre_inc_typed_ref);
633 REGISTER_HELPER(zend_jit_pre_dec_typed_ref);
634 REGISTER_HELPER(zend_jit_post_inc_typed_ref);
635 REGISTER_HELPER(zend_jit_post_dec_typed_ref);
636 REGISTER_HELPER(zend_jit_assign_op_to_typed_ref);
637 REGISTER_HELPER(zend_jit_only_vars_by_reference);
638 REGISTER_HELPER(zend_jit_invalid_array_access);
639 REGISTER_HELPER(zend_jit_invalid_property_read);
640 REGISTER_HELPER(zend_jit_invalid_property_write);
641 REGISTER_HELPER(zend_jit_invalid_property_incdec);
642 REGISTER_HELPER(zend_jit_invalid_property_assign);
643 REGISTER_HELPER(zend_jit_invalid_property_assign_op);
644 REGISTER_HELPER(zend_jit_prepare_assign_dim_ref);
645 REGISTER_HELPER(zend_jit_pre_inc);
646 REGISTER_HELPER(zend_jit_pre_dec);
647 REGISTER_HELPER(zend_runtime_jit);
648 REGISTER_HELPER(zend_jit_hot_func);
649 REGISTER_HELPER(zend_jit_check_constant);
650 REGISTER_HELPER(zend_jit_get_constant);
651 REGISTER_HELPER(zend_jit_array_free);
652 REGISTER_HELPER(zend_jit_zval_array_dup);
653 REGISTER_HELPER(zend_jit_add_arrays_helper);
654 REGISTER_HELPER(zend_jit_assign_obj_helper);
655 REGISTER_HELPER(zend_jit_assign_obj_op_helper);
656 REGISTER_HELPER(zend_jit_assign_to_typed_prop);
657 REGISTER_HELPER(zend_jit_assign_op_to_typed_prop);
658 REGISTER_HELPER(zend_jit_inc_typed_prop);
659 REGISTER_HELPER(zend_jit_dec_typed_prop);
660 REGISTER_HELPER(zend_jit_pre_inc_typed_prop);
661 REGISTER_HELPER(zend_jit_pre_dec_typed_prop);
662 REGISTER_HELPER(zend_jit_post_inc_typed_prop);
663 REGISTER_HELPER(zend_jit_post_dec_typed_prop);
664 REGISTER_HELPER(zend_jit_pre_inc_obj_helper);
665 REGISTER_HELPER(zend_jit_pre_dec_obj_helper);
666 REGISTER_HELPER(zend_jit_post_inc_obj_helper);
667 REGISTER_HELPER(zend_jit_post_dec_obj_helper);
668 #if (PHP_VERSION_ID <= 80100) && (SIZEOF_SIZE_T == 4)
669 REGISTER_HELPER(zval_jit_update_constant_ex);
671 REGISTER_HELPER(zend_jit_free_trampoline_helper);
672 #undef REGISTER_HELPER
675 zend_elf_load_symbols();
678 if (zend_vm_kind() == ZEND_VM_KIND_HYBRID) {
681 memset(&opline, 0, sizeof(opline));
683 opline.opcode = ZEND_DO_UCALL;
684 opline.result_type = IS_UNUSED;
685 zend_vm_set_opcode_handler(&opline);
686 zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
688 opline.opcode = ZEND_DO_UCALL;
689 opline.result_type = IS_VAR;
690 zend_vm_set_opcode_handler(&opline);
691 zend_jit_disasm_add_symbol("ZEND_DO_UCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
693 opline.opcode = ZEND_DO_FCALL_BY_NAME;
694 opline.result_type = IS_UNUSED;
695 zend_vm_set_opcode_handler(&opline);
696 zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
698 opline.opcode = ZEND_DO_FCALL_BY_NAME;
699 opline.result_type = IS_VAR;
700 zend_vm_set_opcode_handler(&opline);
701 zend_jit_disasm_add_symbol("ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
703 opline.opcode = ZEND_DO_FCALL;
704 opline.result_type = IS_UNUSED;
705 zend_vm_set_opcode_handler(&opline);
706 zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
708 opline.opcode = ZEND_DO_FCALL;
709 opline.result_type = IS_VAR;
710 zend_vm_set_opcode_handler(&opline);
711 zend_jit_disasm_add_symbol("ZEND_DO_FCALL_SPEC_RETVAL_USED_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
713 opline.opcode = ZEND_RETURN;
714 opline.op1_type = IS_CONST;
715 zend_vm_set_opcode_handler(&opline);
716 zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CONST_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
718 opline.opcode = ZEND_RETURN;
719 opline.op1_type = IS_TMP_VAR;
720 zend_vm_set_opcode_handler(&opline);
721 zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_TMP_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
723 opline.opcode = ZEND_RETURN;
724 opline.op1_type = IS_VAR;
725 zend_vm_set_opcode_handler(&opline);
726 zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_VAR_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
728 opline.opcode = ZEND_RETURN;
729 opline.op1_type = IS_CV;
730 zend_vm_set_opcode_handler(&opline);
731 zend_jit_disasm_add_symbol("ZEND_RETURN_SPEC_CV_LABEL", (uint64_t)(uintptr_t)opline.handler, sizeof(void*));
733 zend_jit_disasm_add_symbol("ZEND_HYBRID_HALT_LABEL", (uint64_t)(uintptr_t)zend_jit_halt_op->handler, sizeof(void*));
739 static void zend_jit_disasm_shutdown(void)
741 if (JIT_G(symbols)) {
742 zend_jit_disasm_destroy_symbols(JIT_G(symbols));
743 JIT_G(symbols) = NULL;