Skip to content

Commit fa7ab23

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Update IR (#22019)
2 parents ac8248b + 8fa692b commit fa7ab23

15 files changed

Lines changed: 549 additions & 116 deletions

File tree

ext/opcache/jit/ir/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ tests/**/*.log
2020

2121
win32/vcpkg
2222
win32/build_*
23+
24+
fuzz/build/
25+
fuzz/corpus/

ext/opcache/jit/ir/ir.c

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted
161161
case IR_CHAR:
162162
if (insn->val.c == '\\') {
163163
fprintf(f, "'\\\\'");
164+
} else if (insn->val.c == '\'') {
165+
fprintf(f, "'\\\''");
164166
} else if (insn->val.c >= ' ') {
165167
fprintf(f, "'%c'", insn->val.c);
166168
} else if (insn->val.c == '\t') {
@@ -283,6 +285,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted
283285
#define ir_op_kind_src IR_OPND_CONTROL
284286
#define ir_op_kind_reg IR_OPND_CONTROL_DEP
285287
#define ir_op_kind_ret IR_OPND_CONTROL_REF
288+
#define ir_op_kind_grd IR_OPND_CONTROL_GUARD
286289
#define ir_op_kind_str IR_OPND_STR
287290
#define ir_op_kind_num IR_OPND_NUM
288291
#define ir_op_kind_fld IR_OPND_STR
@@ -1843,7 +1846,7 @@ int ir_mem_unprotect(void *ptr, size_t size)
18431846

18441847
int ir_mem_flush(void *ptr, size_t size)
18451848
{
1846-
return 1;
1849+
return FlushInstructionCache(GetCurrentProcess(), ptr, size) == TRUE ? 1 : 0;
18471850
}
18481851
#else
18491852

@@ -2168,7 +2171,10 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_load_i(const ir_ctx *ctx, ir_ref ref, i
21682171
if (!(proto->flags & (IR_CONST_FUNC|IR_PURE_FUNC))) {
21692172
break;
21702173
}
2171-
} else if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_VSTORE) {
2174+
} else if (insn->op == IR_MERGE
2175+
|| insn->op == IR_LOOP_BEGIN
2176+
|| insn->op == IR_VSTORE
2177+
|| (insn->op == IR_BEGIN && insn->op2)) {
21722178
return IR_UNUSED;
21732179
}
21742180
ref = insn->op1;
@@ -2233,7 +2239,10 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vload_i(const ir_ctx *ctx, ir_ref ref,
22332239
if (!(proto->flags & (IR_CONST_FUNC|IR_PURE_FUNC))) {
22342240
break;
22352241
}
2236-
} else if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_STORE) {
2242+
} else if (insn->op == IR_MERGE
2243+
|| insn->op == IR_LOOP_BEGIN
2244+
|| insn->op == IR_STORE
2245+
|| (insn->op == IR_BEGIN && insn->op2)) {
22372246
break;
22382247
}
22392248
ref = insn->op1;
@@ -2326,7 +2335,15 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_store_i(ir_ctx *ctx, ir_ref ref, ir_ref
23262335
}
23272336
} else if (insn->op == IR_GUARD || insn->op == IR_GUARD_NOT) {
23282337
guarded = 1;
2329-
} else if (insn->op >= IR_START || insn->op == IR_CALL) {
2338+
} else if (insn->op >= IR_START) {
2339+
if (insn->op == IR_BEGIN && insn->op1 && !insn->op2) {
2340+
/* skip END */
2341+
ref = insn->op1;
2342+
insn = &ctx->ir_base[ref];
2343+
} else {
2344+
break;
2345+
}
2346+
} else if (insn->op == IR_CALL) {
23302347
break;
23312348
}
23322349
next = ref;
@@ -2407,7 +2424,15 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vstore_i(ir_ctx *ctx, ir_ref ref, ir_re
24072424
}
24082425
} else if (insn->op == IR_GUARD || insn->op == IR_GUARD_NOT) {
24092426
guarded = 1;
2410-
} else if (insn->op >= IR_START || insn->op == IR_CALL || insn->op == IR_LOAD || insn->op == IR_STORE) {
2427+
} else if (insn->op >= IR_START) {
2428+
if (insn->op == IR_BEGIN && insn->op1 && !insn->op2) {
2429+
/* skip END */
2430+
ref = insn->op1;
2431+
insn = &ctx->ir_base[ref];
2432+
} else {
2433+
break;
2434+
}
2435+
} else if (insn->op == IR_CALL || insn->op == IR_LOAD || insn->op == IR_STORE) {
24112436
break;
24122437
}
24132438
next = ref;
@@ -2422,6 +2447,37 @@ ir_ref ir_find_aliasing_vstore(ir_ctx *ctx, ir_ref ref, ir_ref var, ir_ref val)
24222447
}
24232448

24242449
/* IR Construction API */
2450+
static ir_ref ir_last_guard(ir_ctx *ctx)
2451+
{
2452+
ir_ref ref;
2453+
ir_insn *insn;
2454+
2455+
IR_ASSERT(ctx->control);
2456+
ref = ctx->control;
2457+
while (1) {
2458+
insn = &ctx->ir_base[ref];
2459+
if (IR_IS_BB_START(insn->op) || insn->op == IR_GUARD || insn->op == IR_GUARD_NOT) {
2460+
if (insn->op == IR_START) ref = IR_UNUSED;
2461+
break;
2462+
}
2463+
ref = insn->op1;
2464+
}
2465+
return ref;
2466+
}
2467+
2468+
ir_ref _ir_DIV(ir_ctx *ctx, ir_type type, ir_ref op1, ir_ref op2)
2469+
{
2470+
ir_ref guard = (IR_IS_TYPE_FP(type) || (IR_IS_CONST_REF(op2) && ctx->ir_base[op2].val.u64 != 0)) ?
2471+
IR_UNUSED : ir_last_guard(ctx);
2472+
return ir_fold3(ctx, IR_OPT(IR_DIV, type), op1, op2, guard);
2473+
}
2474+
2475+
ir_ref _ir_MOD(ir_ctx *ctx, ir_type type, ir_ref op1, ir_ref op2)
2476+
{
2477+
ir_ref guard = (IR_IS_CONST_REF(op2) && ctx->ir_base[op2].val.u64 != 0) ?
2478+
IR_UNUSED : ir_last_guard(ctx);
2479+
return ir_fold3(ctx, IR_OPT(IR_MOD, type), op1, op2, guard);
2480+
}
24252481

24262482
ir_ref _ir_PARAM(ir_ctx *ctx, ir_type type, const char* name, ir_ref num)
24272483
{

ext/opcache/jit/ir/ir.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ typedef enum _ir_type {
210210
* arg - argument reference CALL/TAILCALL/CARG->CARG
211211
* src - reference to a previous control region (IF, IF_TRUE, IF_FALSE, MERGE, LOOP_BEGIN, LOOP_END, RETURN)
212212
* reg - data-control dependency on region (PHI, VAR, PARAM)
213+
* grd - optional data-control dependency guard (DIV, MOD)
213214
* ret - reference to a previous RETURN instruction (RETURN)
214215
* str - string: variable/argument name (VAR, PARAM, CALL, TAILCALL)
215216
* num - number: argument number (PARAM)
@@ -265,8 +266,8 @@ typedef enum _ir_type {
265266
_(ADD, d2C, def, def, ___) /* addition */ \
266267
_(SUB, d2, def, def, ___) /* subtraction (must be ADD+1) */ \
267268
_(MUL, d2C, def, def, ___) /* multiplication */ \
268-
_(DIV, d2, def, def, ___) /* division */ \
269-
_(MOD, d2, def, def, ___) /* modulo */ \
269+
_(DIV, d3, def, def, grd) /* division */ \
270+
_(MOD, d3, def, def, grd) /* modulo */ \
270271
_(NEG, d1, def, ___, ___) /* change sign */ \
271272
_(ABS, d1, def, ___, ___) /* absolute value */ \
272273
/* (LDEXP, MIN, MAX, FPMATH) */ \
@@ -383,6 +384,14 @@ typedef enum _ir_type {
383384
_(RETURN, T2X1, src, def, ret) /* function return */ \
384385
_(UNREACHABLE, T1X2, src, ___, ret) /* unreachable (tailcall, etc) */ \
385386
\
387+
/* inline assembler */ \
388+
_(ASM, xN, src, def, def) /* GCC inline assembler */ \
389+
/* op2 - asm template string */ \
390+
/* op3 - asm constraint string */ \
391+
/* opN - asm input argument */ \
392+
_(ASM_OUT, x1, src, ___, ___) /* ASM data output projection */ \
393+
_(ASM_GOTO, E1, src, ___, ___) /* ASM goto (bb end after ASM) */ \
394+
\
386395
/* deoptimization helper */ \
387396
_(EXITCALL, x2, src, def, ___) /* save CPU regs and call op2 */ \
388397

ext/opcache/jit/ir/ir_aarch64.dasc

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
402402
int flags = IR_USE_MUST_BE_IN_REG | IR_OP1_MUST_BE_IN_REG | IR_OP2_MUST_BE_IN_REG | IR_OP3_MUST_BE_IN_REG;
403403
const ir_proto_t *proto;
404404
const ir_call_conv_dsc *cc;
405+
ir_ref next;
405406

406407
constraints->def_reg = IR_REG_NONE;
407408
constraints->hints_count = 0;
@@ -562,11 +563,13 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
562563
constraints->tmp_regs[0] = IR_TMP_REG(1, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
563564
n = 1;
564565
}
565-
if (IR_IS_CONST_REF(insn->op2) && insn->op1 != insn->op2) {
566-
insn = &ctx->ir_base[insn->op2];
567-
if (IR_IS_SYM_CONST(insn->op) || !aarch64_may_encode_imm12(insn->val.u64)) {
568-
constraints->tmp_regs[n] = IR_TMP_REG(2, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
569-
n++;
566+
if (IR_IS_CONST_REF(insn->op2)) {
567+
if (insn->op1 != insn->op2) {
568+
insn = &ctx->ir_base[insn->op2];
569+
if (IR_IS_SYM_CONST(insn->op) || !aarch64_may_encode_imm12(insn->val.u64)) {
570+
constraints->tmp_regs[n] = IR_TMP_REG(2, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
571+
n++;
572+
}
570573
}
571574
} else if (ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) {
572575
constraints->tmp_regs[n] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
@@ -751,6 +754,10 @@ get_arg_hints:
751754
break;
752755
case IR_SNAPSHOT:
753756
flags = 0;
757+
next = ir_next_control(ctx, ref);
758+
if (ctx->ir_base[next].op == IR_GUARD || ctx->ir_base[next].op == IR_GUARD_NOT) {
759+
flags = IR_EXTEND_INPUTS_TO_NEXT;
760+
}
754761
break;
755762
case IR_VA_START:
756763
flags = IR_OP2_MUST_BE_IN_REG;
@@ -1199,10 +1206,6 @@ binop_fp:
11991206
if (!IR_IS_CONST_REF(insn->op2) && (ctx->use_lists[insn->op2].count == 1 || all_usages_are_fusable(ctx, insn->op2))) {
12001207
op2_insn = &ctx->ir_base[insn->op2];
12011208
if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED) {
1202-
// TODO: register allocator may clobber operands of CMP before they are used in the GUARD_CMP
1203-
//??? && (insn->op2 == ref - 1 ||
1204-
//??? (insn->op2 == ctx->prev_ref[ref] - 1
1205-
//??? && ctx->ir_base[ctx->prev_ref[ref]].op == IR_SNAPSHOT))) {
12061209
if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) {
12071210
ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT;
12081211
return IR_GUARD_CMP_INT;
@@ -1265,6 +1268,12 @@ binop_fp:
12651268
return IR_FUSED | IR_ARGVAL;
12661269
case IR_NOP:
12671270
return IR_SKIPPED | IR_NOP;
1271+
case IR_ASM:
1272+
case IR_ASM_OUT:
1273+
case IR_ASM_GOTO:
1274+
fprintf(stderr, "ERROR: IR_ASM is not implemented yet\n");
1275+
exit(1);
1276+
return IR_SKIPPED | IR_NOP;
12681277
default:
12691278
break;
12701279
}
@@ -4996,7 +5005,8 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
49965005
void *addr = ir_jmp_addr(ctx, insn, &ctx->ir_base[insn->op2]);
49975006

49985007
| .addr &addr
4999-
if (ctx->ir_base[bb->start].op != IR_CASE_DEFAULT) {
5008+
if (ctx->ir_base[bb->start].op1 == def
5009+
&& ctx->ir_base[bb->start].op != IR_CASE_DEFAULT) {
50005010
bb->flags |= IR_BB_EMPTY;
50015011
}
50025012
continue;

ext/opcache/jit/ir/ir_builder.h

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -118,31 +118,31 @@ extern "C" {
118118
#define ir_MUL_D(_op1, _op2) ir_BINARY_OP_D(IR_MUL, (_op1), (_op2))
119119
#define ir_MUL_F(_op1, _op2) ir_BINARY_OP_F(IR_MUL, (_op1), (_op2))
120120

121-
#define ir_DIV(_type, _op1, _op2) ir_BINARY_OP(IR_DIV, (_type), (_op1), (_op2))
122-
#define ir_DIV_U8(_op1, _op2) ir_BINARY_OP_U8(IR_DIV, (_op1), (_op2))
123-
#define ir_DIV_U16(_op1, _op2) ir_BINARY_OP_U16(IR_DIV, (_op1), (_op2))
124-
#define ir_DIV_U32(_op1, _op2) ir_BINARY_OP_U32(IR_DIV, (_op1), (_op2))
125-
#define ir_DIV_U64(_op1, _op2) ir_BINARY_OP_U64(IR_DIV, (_op1), (_op2))
126-
#define ir_DIV_A(_op1, _op2) ir_BINARY_OP_A(IR_DIV, (_op1), (_op2))
127-
#define ir_DIV_C(_op1, _op2) ir_BINARY_OP_C(IR_DIV, (_op1), (_op2))
128-
#define ir_DIV_I8(_op1, _op2) ir_BINARY_OP_I8(IR_DIV, (_op1), (_op2))
129-
#define ir_DIV_I16(_op1, _op2) ir_BINARY_OP_I16(IR_DIV, (_op1), (_op2))
130-
#define ir_DIV_I32(_op1, _op2) ir_BINARY_OP_I32(IR_DIV, (_op1), (_op2))
131-
#define ir_DIV_I64(_op1, _op2) ir_BINARY_OP_I64(IR_DIV, (_op1), (_op2))
121+
#define ir_DIV(_type, _op1, _op2) _ir_DIV(_ir_CTX, (_type), (_op1), (_op2))
122+
#define ir_DIV_U8(_op1, _op2) ir_DIV(IR_U8, (_op1), (_op2))
123+
#define ir_DIV_U16(_op1, _op2) ir_DIV(IR_U16, (_op1), (_op2))
124+
#define ir_DIV_U32(_op1, _op2) ir_DIV(IR_U32, (_op1), (_op2))
125+
#define ir_DIV_U64(_op1, _op2) ir_DIV(IR_U64, (_op1), (_op2))
126+
#define ir_DIV_A(_op1, _op2) ir_DIV(IR_ADDR, (_op1), (_op2))
127+
#define ir_DIV_C(_op1, _op2) ir_DIV(IR_CHAR, (_op1), (_op2))
128+
#define ir_DIV_I8(_op1, _op2) ir_DIV(IR_I8, (_op1), (_op2))
129+
#define ir_DIV_I16(_op1, _op2) ir_DIV(IR_I16, (_op1), (_op2))
130+
#define ir_DIV_I32(_op1, _op2) ir_DIV(IR_I32, (_op1), (_op2))
131+
#define ir_DIV_I64(_op1, _op2) ir_DIV(IR_I64, (_op1), (_op2))
132132
#define ir_DIV_D(_op1, _op2) ir_BINARY_OP_D(IR_DIV, (_op1), (_op2))
133133
#define ir_DIV_F(_op1, _op2) ir_BINARY_OP_F(IR_DIV, (_op1), (_op2))
134134

135-
#define ir_MOD(_type, _op1, _op2) ir_BINARY_OP(IR_MOD, (_type), (_op1), (_op2))
136-
#define ir_MOD_U8(_op1, _op2) ir_BINARY_OP_U8(IR_MOD, (_op1), (_op2))
137-
#define ir_MOD_U16(_op1, _op2) ir_BINARY_OP_U16(IR_MOD, (_op1), (_op2))
138-
#define ir_MOD_U32(_op1, _op2) ir_BINARY_OP_U32(IR_MOD, (_op1), (_op2))
139-
#define ir_MOD_U64(_op1, _op2) ir_BINARY_OP_U64(IR_MOD, (_op1), (_op2))
140-
#define ir_MOD_A(_op1, _op2) ir_BINARY_OP_A(IR_MOD, (_op1), (_op2))
141-
#define ir_MOD_C(_op1, _op2) ir_BINARY_OP_C(IR_MOD, (_op1), (_op2))
142-
#define ir_MOD_I8(_op1, _op2) ir_BINARY_OP_I8(IR_MOD, (_op1), (_op2))
143-
#define ir_MOD_I16(_op1, _op2) ir_BINARY_OP_I16(IR_MOD, (_op1), (_op2))
144-
#define ir_MOD_I32(_op1, _op2) ir_BINARY_OP_I32(IR_MOD, (_op1), (_op2))
145-
#define ir_MOD_I64(_op1, _op2) ir_BINARY_OP_I64(IR_MOD, (_op1), (_op2))
135+
#define ir_MOD(_type, _op1, _op2) _ir_MOD(_ir_CTX, (_type), (_op1), (_op2))
136+
#define ir_MOD_U8(_op1, _op2) ir_MOD(IR_U8, (_op1), (_op2))
137+
#define ir_MOD_U16(_op1, _op2) ir_MOD(IR_U16, (_op1), (_op2))
138+
#define ir_MOD_U32(_op1, _op2) ir_MOD(IR_U32, (_op1), (_op2))
139+
#define ir_MOD_U64(_op1, _op2) ir_MOD(IR_U64, (_op1), (_op2))
140+
#define ir_MOD_A(_op1, _op2) ir_MOD(IR_ADDR, (_op1), (_op2))
141+
#define ir_MOD_C(_op1, _op2) ir_MOD(IR_CHAR, (_op1), (_op2))
142+
#define ir_MOD_I8(_op1, _op2) ir_MOD(IR_I8, (_op1), (_op2))
143+
#define ir_MOD_I16(_op1, _op2) ir_MOD(IR_I16, (_op1), (_op2))
144+
#define ir_MOD_I32(_op1, _op2) ir_MOD(IR_I32, (_op1), (_op2))
145+
#define ir_MOD_I64(_op1, _op2) ir_MOD(IR_I64, (_op1), (_op2))
146146

147147
#define ir_NEG(_type, _op1) ir_UNARY_OP(IR_NEG, (_type), (_op1))
148148
#define ir_NEG_C(_op1) ir_UNARY_OP_C(IR_NEG, (_op1))
@@ -633,6 +633,8 @@ extern "C" {
633633
#define ir_MERGE_WITH_EMPTY_TRUE(_if) do {ir_ref end = ir_END(); ir_IF_TRUE(_if); ir_MERGE_2(end, ir_END());} while (0)
634634
#define ir_MERGE_WITH_EMPTY_FALSE(_if) do {ir_ref end = ir_END(); ir_IF_FALSE(_if); ir_MERGE_2(end, ir_END());} while (0)
635635

636+
ir_ref _ir_DIV(ir_ctx *ctx, ir_type type, ir_ref op1, ir_ref op2);
637+
ir_ref _ir_MOD(ir_ctx *ctx, ir_type type, ir_ref op1, ir_ref op2);
636638
ir_ref _ir_ADD_OFFSET(ir_ctx *ctx, ir_ref addr, uintptr_t offset);
637639
ir_ref _ir_PHI_2(ir_ctx *ctx, ir_type type, ir_ref src1, ir_ref src2);
638640
ir_ref _ir_PHI_N(ir_ctx *ctx, ir_type type, ir_ref n, ir_ref *inputs);

ext/opcache/jit/ir/ir_cfg.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,23 @@ static bool ir_is_merged_loop_back_edge(ir_ctx *ctx, uint32_t hdr, uint32_t b)
15021502
}
15031503
#endif
15041504

1505+
static bool ir_should_align_loop(ir_ctx *ctx, ir_chain *chains, uint32_t b, ir_block *bb)
1506+
{
1507+
uint32_t n = bb->predecessors_count;
1508+
uint32_t *p = ctx->cfg_edges + bb->predecessors;
1509+
1510+
for (; n > 0; p++, n--) {
1511+
uint32_t pred = *p;
1512+
if (chains[pred].head) {
1513+
if (ir_chain_head(chains, pred) == b) return 1;
1514+
} else {
1515+
if (ir_should_align_loop(ctx, chains, b, &ctx->cfg_blocks[pred])) return 1;
1516+
}
1517+
}
1518+
1519+
return 0;
1520+
}
1521+
15051522
static int ir_schedule_blocks_bottom_up(ir_ctx *ctx)
15061523
{
15071524
uint32_t max_edges_count = ctx->cfg_edges_count / 2;
@@ -1862,7 +1879,7 @@ static int ir_schedule_blocks_bottom_up(ir_ctx *ctx)
18621879
if (chains[b].head == b) {
18631880
bb = &ctx->cfg_blocks[b];
18641881
if (bb->loop_depth) {
1865-
if ((bb->flags & IR_BB_LOOP_HEADER) || ir_chain_head(chains, bb->loop_header) == b) {
1882+
if (ir_should_align_loop(ctx, chains, b, bb)) {
18661883
bb->flags |= IR_BB_ALIGN_LOOP;
18671884
}
18681885
}

ext/opcache/jit/ir/ir_check.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ bool ir_check(const ir_ctx *ctx)
148148
bool ok = 1;
149149
ir_check_ctx check_ctx;
150150

151+
if (ctx->insns_count < 1 || ctx->ir_base[1].op != IR_START) {
152+
fprintf(stderr, "ir_base[1].op invalid opcode (%d)\n",
153+
(ctx->insns_count < 1) ? IR_NOP : ctx->ir_base[0].op);
154+
ok = 0;
155+
}
156+
151157
check_ctx.arena = NULL;
152158
check_ctx.use_set = NULL;
153159
check_ctx.input_set = NULL;
@@ -297,6 +303,14 @@ bool ir_check(const ir_ctx *ctx)
297303
ok = 0;
298304
}
299305
break;
306+
case IR_OPND_CONTROL_GUARD:
307+
if (!(ir_op_flags[use_insn->op] & IR_OP_FLAG_BB_START)
308+
&& use_insn->op != IR_GUARD
309+
&& use_insn->op != IR_GUARD_NOT) {
310+
fprintf(stderr, "ir_base[%d].ops[%d] reference (%d) must be BB_START or GUARD\n", i, j, use);
311+
ok = 0;
312+
}
313+
break;
300314
default:
301315
fprintf(stderr, "ir_base[%d].ops[%d] reference (%d) of unsupported kind\n", i, j, use);
302316
ok = 0;
@@ -306,6 +320,8 @@ bool ir_check(const ir_ctx *ctx)
306320
/* pass (function returns void) */
307321
} else if (insn->op == IR_BEGIN && j == 1) {
308322
/* pass (start of unreachable basic block) */
323+
} else if (IR_OPND_KIND(flags, j) == IR_OPND_CONTROL_GUARD) {
324+
/* reference to control guard is optional */
309325
} else if (IR_OPND_KIND(flags, j) != IR_OPND_CONTROL_REF
310326
&& (insn->op != IR_SNAPSHOT || j == 1)) {
311327
fprintf(stderr, "ir_base[%d].ops[%d] missing reference (%d)\n", i, j, use);
@@ -413,6 +429,7 @@ bool ir_check(const ir_ctx *ctx)
413429
}
414430
break;
415431
case IR_IGOTO:
432+
case IR_ASM_GOTO:
416433
break;
417434
default:
418435
/* skip data references */
@@ -464,6 +481,10 @@ bool ir_check(const ir_ctx *ctx)
464481
// if (!ok) {
465482
// ir_dump_codegen(ctx, stderr);
466483
// }
484+
485+
#ifndef IR_CHECK_NO_ABORT
467486
IR_ASSERT(ok);
487+
#endif
488+
468489
return ok;
469490
}

0 commit comments

Comments
 (0)