@@ -16556,6 +16556,275 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
16556
16556
return 1;
16557
16557
}
16558
16558
16559
+ #ifdef HAVE_FFI
16560
+ static int zend_jit_ffi_incdec_helper(zend_jit_ctx *jit,
16561
+ const zend_op *opline,
16562
+ uint8_t opcode,
16563
+ zend_ffi_type *el_type,
16564
+ ir_ref op1,
16565
+ zend_jit_addr res_addr)
16566
+ {
16567
+ ir_op op;
16568
+ ir_type type;
16569
+ ir_ref op2;
16570
+ ir_ref ref = IR_UNUSED;
16571
+
16572
+ switch (opcode) {
16573
+ case ZEND_PRE_INC_OBJ:
16574
+ case ZEND_POST_INC_OBJ:
16575
+ op = IR_ADD;
16576
+ break;
16577
+ case ZEND_PRE_DEC_OBJ:
16578
+ case ZEND_POST_DEC_OBJ:
16579
+ op = IR_SUB;
16580
+ break;
16581
+ default:
16582
+ ZEND_UNREACHABLE();
16583
+ return 0;
16584
+ }
16585
+
16586
+ switch (el_type->kind) {
16587
+ case ZEND_FFI_TYPE_FLOAT:
16588
+ type = IR_FLOAT;
16589
+ op2 = ir_CONST_FLOAT(1.0);
16590
+ break;
16591
+ case ZEND_FFI_TYPE_DOUBLE:
16592
+ type = IR_DOUBLE;
16593
+ op2 = ir_CONST_DOUBLE(1.0);
16594
+ break;
16595
+ case ZEND_FFI_TYPE_UINT8:
16596
+ type = IR_U8;
16597
+ op2 = ir_CONST_U8(1);
16598
+ break;
16599
+ case ZEND_FFI_TYPE_SINT8:
16600
+ case ZEND_FFI_TYPE_CHAR:
16601
+ type = IR_I8;
16602
+ op2 = ir_CONST_I8(1);
16603
+ break;
16604
+ case ZEND_FFI_TYPE_UINT16:
16605
+ type = IR_U16;
16606
+ op2 = ir_CONST_U16(1);
16607
+ break;
16608
+ case ZEND_FFI_TYPE_SINT16:
16609
+ type = IR_I16;
16610
+ op2 = ir_CONST_I16(1);
16611
+ break;
16612
+ case ZEND_FFI_TYPE_UINT32:
16613
+ type = IR_U32;
16614
+ op2 = ir_CONST_U32(1);
16615
+ break;
16616
+ case ZEND_FFI_TYPE_SINT32:
16617
+ type = IR_I32;
16618
+ op2 = ir_CONST_I32(1);
16619
+ break;
16620
+ case ZEND_FFI_TYPE_UINT64:
16621
+ type = IR_U64;
16622
+ op2 = ir_CONST_U64(1);
16623
+ break;
16624
+ case ZEND_FFI_TYPE_SINT64:
16625
+ type = IR_I64;
16626
+ op2 = ir_CONST_I64(1);
16627
+ break;
16628
+ case ZEND_FFI_TYPE_POINTER:
16629
+ ZEND_ASSERT(ZEND_FFI_TYPE(el_type->pointer.type)->size != 0);
16630
+ type = IR_ADDR;
16631
+ op2 = ir_CONST_LONG(ZEND_FFI_TYPE(el_type->pointer.type)->size);
16632
+ break;
16633
+ default:
16634
+ ZEND_UNREACHABLE();
16635
+ return 0;
16636
+ }
16637
+
16638
+ ref = ir_LOAD(type, op1);
16639
+
16640
+ if (res_addr && (opcode == ZEND_POST_INC_OBJ || opcode == ZEND_POST_DEC_OBJ)) {
16641
+ uint32_t res_type = IS_UNDEF;
16642
+
16643
+ switch (type) {
16644
+ case IR_FLOAT:
16645
+ jit_set_Z_DVAL(jit, res_addr, ir_F2D(ref));
16646
+ res_type = IS_DOUBLE;
16647
+ break;
16648
+ case IR_DOUBLE:
16649
+ jit_set_Z_DVAL(jit, res_addr, ref);
16650
+ res_type = IS_DOUBLE;
16651
+ break;
16652
+ case IR_I8:
16653
+ case IR_I16:
16654
+ #ifdef ZEND_ENABLE_ZVAL_LONG64
16655
+ case IR_I32:
16656
+ jit_set_Z_LVAL(jit, res_addr, ir_SEXT_L(ref));
16657
+ res_type = IS_LONG;
16658
+ break;
16659
+ case IR_I64:
16660
+ #else
16661
+ case IR_I32:
16662
+ #endif
16663
+ jit_set_Z_LVAL(jit, res_addr, ref);
16664
+ res_type = IS_LONG;
16665
+ break;
16666
+ case IR_U8:
16667
+ case IR_U16:
16668
+ #ifdef ZEND_ENABLE_ZVAL_LONG64
16669
+ case IR_U32:
16670
+ jit_set_Z_LVAL(jit, res_addr, ir_ZEXT_L(ref));
16671
+ res_type = IS_LONG;
16672
+ break;
16673
+ case IR_U64:
16674
+ #else
16675
+ case IR_U32:
16676
+ #endif
16677
+ jit_set_Z_LVAL(jit, res_addr, ref);
16678
+ res_type = IS_LONG;
16679
+ break;
16680
+ case IR_ADDR:
16681
+ if ((el_type->attr & ZEND_FFI_ATTR_CONST)
16682
+ && ZEND_FFI_TYPE(el_type->pointer.type)->kind == ZEND_FFI_TYPE_CHAR) {
16683
+ ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_zval_string), jit_ZVAL_ADDR(jit, res_addr), ref);
16684
+ } else {
16685
+ ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_zval_ffi_ptr),
16686
+ jit_ZVAL_ADDR(jit, res_addr), ir_CONST_ADDR(el_type), ref);
16687
+ }
16688
+ break;
16689
+ default:
16690
+ ZEND_UNREACHABLE();
16691
+ return 0;
16692
+ }
16693
+ if (res_type && Z_MODE(res_addr) != IS_REG) {
16694
+ jit_set_Z_TYPE_INFO(jit, res_addr, res_type);
16695
+ }
16696
+ }
16697
+
16698
+ ref = ir_BINARY_OP(op, type, ref, op2);
16699
+ ir_STORE(op1, ref);
16700
+
16701
+ if (res_addr && (opcode == ZEND_PRE_INC_OBJ || opcode == ZEND_PRE_DEC_OBJ)) {
16702
+ uint32_t res_type = IS_UNDEF;
16703
+
16704
+ switch (type) {
16705
+ case IR_FLOAT:
16706
+ jit_set_Z_DVAL(jit, res_addr, ir_F2D(ref));
16707
+ res_type = IS_DOUBLE;
16708
+ break;
16709
+ case IR_DOUBLE:
16710
+ jit_set_Z_DVAL(jit, res_addr, ref);
16711
+ res_type = IS_DOUBLE;
16712
+ break;
16713
+ case IR_I8:
16714
+ case IR_I16:
16715
+ #ifdef ZEND_ENABLE_ZVAL_LONG64
16716
+ case IR_I32:
16717
+ jit_set_Z_LVAL(jit, res_addr, ir_SEXT_L(ref));
16718
+ res_type = IS_LONG;
16719
+ break;
16720
+ case IR_I64:
16721
+ #else
16722
+ case IR_I32:
16723
+ #endif
16724
+ jit_set_Z_LVAL(jit, res_addr, ref);
16725
+ res_type = IS_LONG;
16726
+ break;
16727
+ case IR_U8:
16728
+ case IR_U16:
16729
+ #ifdef ZEND_ENABLE_ZVAL_LONG64
16730
+ case IR_U32:
16731
+ jit_set_Z_LVAL(jit, res_addr, ir_ZEXT_L(ref));
16732
+ res_type = IS_LONG;
16733
+ break;
16734
+ case IR_U64:
16735
+ #else
16736
+ case IR_U32:
16737
+ #endif
16738
+ jit_set_Z_LVAL(jit, res_addr, ref);
16739
+ res_type = IS_LONG;
16740
+ break;
16741
+ case IR_ADDR:
16742
+ if ((el_type->attr & ZEND_FFI_ATTR_CONST)
16743
+ && ZEND_FFI_TYPE(el_type->pointer.type)->kind == ZEND_FFI_TYPE_CHAR) {
16744
+ ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_zval_string), jit_ZVAL_ADDR(jit, res_addr), ref);
16745
+ } else {
16746
+ ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_zval_ffi_ptr),
16747
+ jit_ZVAL_ADDR(jit, res_addr), ir_CONST_ADDR(el_type), ref);
16748
+ }
16749
+ break;
16750
+ default:
16751
+ ZEND_UNREACHABLE();
16752
+ return 0;
16753
+ }
16754
+ if (res_type && Z_MODE(res_addr) != IS_REG) {
16755
+ jit_set_Z_TYPE_INFO(jit, res_addr, res_type);
16756
+ }
16757
+ }
16758
+
16759
+ return 1;
16760
+ }
16761
+
16762
+ static int zend_jit_ffi_incdec_obj(zend_jit_ctx *jit,
16763
+ const zend_op *opline,
16764
+ const zend_op_array *op_array,
16765
+ zend_ssa *ssa,
16766
+ const zend_ssa_op *ssa_op,
16767
+ uint32_t op1_info,
16768
+ zend_jit_addr op1_addr,
16769
+ bool op1_indirect,
16770
+ zend_ffi_field *field,
16771
+ zend_jit_addr res_addr,
16772
+ zend_ffi_type *op1_ffi_type,
16773
+ zend_jit_ffi_info *ffi_info)
16774
+ {
16775
+ zend_ffi_type *field_type = ZEND_FFI_TYPE(field->type);
16776
+ ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
16777
+
16778
+ if (!zend_jit_ffi_guard(jit, opline, ssa, ssa_op->op1_use, ssa_op->op1_def, obj_ref, op1_ffi_type, ffi_info)) {
16779
+ return 0;
16780
+ }
16781
+
16782
+ ir_ref cdata_ref = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
16783
+ ir_ref ptr = ir_ADD_A(cdata_ref, ir_CONST_LONG(field->offset));
16784
+
16785
+ if (!zend_jit_ffi_incdec_helper(jit, opline, opline->opcode, field_type, ptr, res_addr)) {
16786
+ return 0;
16787
+ }
16788
+
16789
+ if (!op1_indirect) {
16790
+ jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
16791
+ }
16792
+
16793
+ return 1;
16794
+ }
16795
+
16796
+ static int zend_jit_ffi_incdec_sym(zend_jit_ctx *jit,
16797
+ const zend_op *opline,
16798
+ const zend_op_array *op_array,
16799
+ zend_ssa *ssa,
16800
+ const zend_ssa_op *ssa_op,
16801
+ uint32_t op1_info,
16802
+ zend_jit_addr op1_addr,
16803
+ bool op1_indirect,
16804
+ zend_ffi_symbol *sym,
16805
+ zend_jit_addr res_addr,
16806
+ HashTable *op1_ffi_symbols,
16807
+ zend_jit_ffi_info *ffi_info)
16808
+ {
16809
+ zend_ffi_type *sym_type = ZEND_FFI_TYPE(sym->type);
16810
+
16811
+ if (!zend_jit_ffi_symbols_guard(jit, opline, ssa, ssa_op->op1_use, ssa_op->op1_def, op1_addr, op1_ffi_symbols, ffi_info)) {
16812
+ return 0;
16813
+ }
16814
+
16815
+ ir_ref ptr = ir_CONST_ADDR(sym->addr);
16816
+ if (!zend_jit_ffi_incdec_helper(jit, opline, opline->opcode, sym_type, ptr, res_addr)) {
16817
+ return 0;
16818
+ }
16819
+
16820
+ if (!op1_indirect) {
16821
+ jit_FREE_OP(jit, opline->op1_type, opline->op1, op1_info, opline);
16822
+ }
16823
+
16824
+ return 1;
16825
+ }
16826
+ #endif
16827
+
16559
16828
static int zend_jit_incdec_obj(zend_jit_ctx *jit,
16560
16829
const zend_op *opline,
16561
16830
const zend_op_array *op_array,
0 commit comments