Skip to content
Merged
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ PHP NEWS
. Fixed bug GH-19780 (InvalidUrlException should check $errors argument).
(nielsdos)

- Windows:
. Fix GH-19722 (_get_osfhandle asserts in debug mode when given a socket).
(dktapps)

11 Sep 2025, PHP 8.5.0beta3

- Core:
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/jit/ir/ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ ir_ref ir_const_bool(ir_ctx *ctx, bool c)
ir_ref ir_const_char(ir_ctx *ctx, char c)
{
ir_val val;
val.i64 = c;
val.i64 = (signed char)c;
return ir_const(ctx, val, IR_CHAR);
}

Expand Down
111 changes: 88 additions & 23 deletions ext/opcache/jit/ir/ir_aarch64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -397,15 +397,22 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
n++;
}
break;
case IR_INT2FP:
case IR_FP2INT:
insn = &ctx->ir_base[ref];
n = 0;
if (IR_IS_CONST_REF(insn->op1)) {
constraints->tmp_regs[n] = IR_TMP_REG(1, ctx->ir_base[insn->op1].type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
n++;
}
break;
case IR_MUL_PWR2:
case IR_DIV_PWR2:
case IR_MOD_PWR2:
case IR_SHIFT:
case IR_SHIFT_CONST:
case IR_OP_INT:
case IR_OP_FP:
case IR_INT2FP:
case IR_FP2INT:
case IR_FP2FP:
insn = &ctx->ir_base[ref];
n = 0;
Expand Down Expand Up @@ -1398,7 +1405,7 @@ static void ir_load_local_addr(ir_ctx *ctx, ir_reg reg, ir_ref src)
| add Rx(reg), Rx(base), #offset
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset);
| add sp, sp, Rx(IR_REG_INT_TMP)
| add Rx(reg), sp, Rx(IR_REG_INT_TMP)
}
}

Expand Down Expand Up @@ -1587,19 +1594,31 @@ static void ir_emit_prologue(ir_ctx *ctx)
offset = -(ctx->stack_frame_size+16);
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
| stp x29, x30, [sp, #offset]!
} else {
} else if (aarch64_may_encode_imm12(ctx->stack_frame_size+16)) {
| sub sp, sp, #(ctx->stack_frame_size+16)
| stp x29, x30, [sp]
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->stack_frame_size+16);
| sub sp, sp, Rx(IR_REG_INT_TMP)
| stp x29, x30, [sp]
}
| mov x29, sp
if (ctx->call_stack_size) {
| sub sp, sp, #(ctx->call_stack_size)
if (aarch64_may_encode_imm12(ctx->call_stack_size)) {
| sub sp, sp, #(ctx->call_stack_size)
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->call_stack_size);
| sub sp, sp, Rx(IR_REG_INT_TMP)
}
}
} else if (ctx->stack_frame_size + ctx->call_stack_size) {
if (ctx->fixed_stack_red_zone) {
IR_ASSERT(ctx->stack_frame_size + ctx->call_stack_size <= ctx->fixed_stack_red_zone);
} else if (aarch64_may_encode_imm12(ctx->stack_frame_size + ctx->call_stack_size)) {
| sub sp, sp, #(ctx->stack_frame_size + ctx->call_stack_size)
} else {
| sub sp, sp, #(ctx->stack_frame_size + ctx->call_stack_size)
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->stack_frame_size + ctx->call_stack_size);
| sub sp, sp, Rx(IR_REG_INT_TMP)
}
}
if (ctx->used_preserved_regs) {
Expand All @@ -1623,26 +1642,41 @@ static void ir_emit_prologue(ir_ctx *ctx)
offset -= sizeof(void*) * 2;
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
| stp Rx(prev), Rx(i), [Rx(fp), #offset]
} else {
IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8));
} else if (aarch64_may_encode_addr_offset(offset + 8, 8)) {
| str Rx(prev), [Rx(fp), #offset]
| str Rx(i), [Rx(fp), #(offset+8)]
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset);
| str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)]
| add Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8
| str Rx(i), [Rx(fp), Rx(IR_REG_INT_TMP)]
}
prev = IR_REG_NONE;
} else {
if (prev < IR_REG_FP_FIRST) {
offset -= sizeof(void*);
| str Rx(prev), [Rx(fp), #offset]
offset -= sizeof(void*);
| str Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
if (aarch64_may_encode_addr_offset(offset, 8)) {
| str Rx(prev), [Rx(fp), #offset]
offset -= sizeof(void*);
| str Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset);
| str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)]
| sub Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8
| str Rd(i-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)]
}
} else {
offset -= sizeof(void*) * 2;
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
| stp Rd(prev-IR_REG_FP_FIRST), Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
} else {
IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8));
} else if (aarch64_may_encode_addr_offset(offset + 8, 8)) {
| str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset]
| str Rd(i-IR_REG_FP_FIRST), [Rx(fp), #(offset+8)]
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset);
| str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)]
| add Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8
| str Rd(i-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)]
}
}
prev = IR_REG_NONE;
Expand All @@ -1652,10 +1686,20 @@ static void ir_emit_prologue(ir_ctx *ctx)
if (prev != IR_REG_NONE) {
if (prev < IR_REG_FP_FIRST) {
offset -= sizeof(void*);
| str Rx(prev), [Rx(fp), #offset]
if (aarch64_may_encode_addr_offset(offset, 8)) {
| str Rx(prev), [Rx(fp), #offset]
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset);
| str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)]
}
} else {
offset -= sizeof(void*);
| str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset]
if (aarch64_may_encode_addr_offset(offset, 8)) {
| str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset]
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset);
| str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), Rx(IR_REG_INT_TMP)]
}
}
}
}
Expand Down Expand Up @@ -1685,10 +1729,14 @@ static void ir_emit_prologue(ir_ctx *ctx)
if (prev != IR_REG_NONE) {
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
| stp Rx(prev), Rx(int_reg_params[i]), [Rx(fp), #offset]
} else {
IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8));
} else if (aarch64_may_encode_addr_offset(offset + 8, 8)) {
| str Rx(prev), [Rx(fp), #offset]
| str Rx(int_reg_params[i]), [Rx(fp), #(offset+8)]
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset);
| str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)]
| add Rx(IR_REG_INT_TMP), Rx(IR_REG_INT_TMP), #8
| str Rx(int_reg_params[i]), [Rx(fp), Rx(IR_REG_INT_TMP)]
}
prev = IR_REG_NONE;
offset += sizeof(void*) * 2;
Expand All @@ -1697,7 +1745,12 @@ static void ir_emit_prologue(ir_ctx *ctx)
}
}
if (prev != IR_REG_NONE) {
| str Rx(prev), [Rx(fp), #offset]
if (aarch64_may_encode_addr_offset(offset + 8, 8)) {
| str Rx(prev), [Rx(fp), #offset]
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, offset);
| str Rx(prev), [Rx(fp), Rx(IR_REG_INT_TMP)]
}
offset += sizeof(void*);
}
}
Expand Down Expand Up @@ -1782,15 +1835,22 @@ static void ir_emit_epilogue(ir_ctx *ctx)
}
if (aarch64_may_encode_imm7_addr_offset(ctx->stack_frame_size+16, 8)) {
| ldp x29, x30, [sp], #(ctx->stack_frame_size+16)
} else {
} else if (aarch64_may_encode_imm12(ctx->stack_frame_size+16)) {
| ldp x29, x30, [sp]
| add sp, sp, #(ctx->stack_frame_size+16)
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->stack_frame_size+16);
| ldp x29, x30, [sp]
| add sp, sp, Rx(IR_REG_INT_TMP)
}
} else if (ctx->stack_frame_size + ctx->call_stack_size) {
if (ctx->fixed_stack_red_zone) {
IR_ASSERT(ctx->stack_frame_size + ctx->call_stack_size <= ctx->fixed_stack_red_zone);
} else {
} else if (aarch64_may_encode_imm12(ctx->stack_frame_size + ctx->call_stack_size)) {
| add sp, sp, #(ctx->stack_frame_size + ctx->call_stack_size)
} else {
ir_emit_load_imm_int(ctx, IR_ADDR, IR_REG_INT_TMP, ctx->stack_frame_size + ctx->call_stack_size);
| add sp, sp, Rx(IR_REG_INT_TMP)
}
}
}
Expand Down Expand Up @@ -4808,7 +4868,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
fp_param++;
}
if (dst_reg != IR_REG_NONE) {
if (src_reg == IR_REG_NONE) {
if (IR_IS_CONST_REF(arg) ||
src_reg == IR_REG_NONE ||
(IR_REG_SPILLED(src_reg) && !IR_REGSET_IN(IR_REGSET_PRESERVED, IR_REG_NUM(src_reg)))) {
/* delay CONST->REG and MEM->REG moves to third pass */
do_pass3 = 1;
} else {
Expand Down Expand Up @@ -4874,7 +4936,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
fp_param++;
}
if (dst_reg != IR_REG_NONE) {
if (src_reg == IR_REG_NONE) {
if (IR_IS_CONST_REF(arg) ||
src_reg == IR_REG_NONE ||
(IR_REG_SPILLED(src_reg) && !IR_REGSET_IN(IR_REGSET_PRESERVED, IR_REG_NUM(src_reg)))) {
if (IR_IS_CONST_REF(arg) && IR_IS_TYPE_INT(type)) {
if (ir_type_size[type] == 1) {
type = IR_ADDR;
Expand Down Expand Up @@ -5473,7 +5537,8 @@ static void ir_emit_load_params(ir_ctx *ctx)
int32_t stack_offset = 0;

if (ctx->flags & IR_USE_FRAME_POINTER) {
stack_offset = sizeof(void*) * 2; /* skip old frame pointer and return address */
/* skip old frame pointer and return address */
stack_offset = sizeof(void*) * 2 + ctx->stack_frame_size + ctx->call_stack_size;
} else {
stack_offset = ctx->stack_frame_size + ctx->call_stack_size;
}
Expand Down
4 changes: 2 additions & 2 deletions ext/opcache/jit/ir/ir_aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ typedef struct _ir_tmp_reg {
int8_t reg;
};
uint8_t type;
uint8_t start;
uint8_t end;
int8_t start;
int8_t end;
} ir_tmp_reg;

struct _ir_target_constraints {
Expand Down
8 changes: 6 additions & 2 deletions ext/opcache/jit/ir/ir_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -9000,7 +9000,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
#endif
}
if (dst_reg != IR_REG_NONE) {
if (src_reg == IR_REG_NONE) {
if (IR_IS_CONST_REF(arg) ||
src_reg == IR_REG_NONE ||
(IR_REG_SPILLED(src_reg) && !IR_REGSET_IN(IR_REGSET_PRESERVED, IR_REG_NUM(src_reg)))) {
/* delay CONST->REG and MEM->REG moves to third pass */
do_pass3 = 1;
} else {
Expand Down Expand Up @@ -9068,7 +9070,9 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg
#endif
}
if (dst_reg != IR_REG_NONE) {
if (src_reg == IR_REG_NONE) {
if (IR_IS_CONST_REF(arg) ||
src_reg == IR_REG_NONE ||
(IR_REG_SPILLED(src_reg) && !IR_REGSET_IN(IR_REGSET_PRESERVED, IR_REG_NUM(src_reg)))) {
if (IR_IS_TYPE_INT(type)) {
if (IR_IS_CONST_REF(arg)) {
if (type == IR_I8 || type == IR_I16) {
Expand Down
4 changes: 2 additions & 2 deletions ext/opcache/jit/ir/ir_x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ typedef struct _ir_tmp_reg {
int8_t reg;
};
uint8_t type;
uint8_t start;
uint8_t end;
int8_t start;
int8_t end;
} ir_tmp_reg;

struct _ir_target_constraints {
Expand Down
Loading