Skip to content

Commit 61c319c

Browse files
committed
Fix Branch/CondBranch Edge bug: use C++ bridge for in_edges management
Pure C factories wrote edge.to directly, bypassing Edge::set_to() which manages BasicBlock::in_edges_ (predecessor tracking). This causes null in_edge entries → DominatorAnalysis crash at analysis.cpp:524. Root cause: Edge::set_to() updates target block's in_edges_ set (C++ std::unordered_set), which cannot be done from pure C. Branch and CondBranch factories must use C++ bridge to call Edge constructor. Fix: add hir_c_create_branch_cpp and hir_c_create_cond_branch_cpp in hir_c_api.cpp that use Branch::create/CondBranch::create (proper Edge initialization via CondBranchBase constructor → set_true_bb → Edge::set_to → in_edges_.insert).
1 parent bb3b2df commit 61c319c

3 files changed

Lines changed: 33 additions & 4 deletions

File tree

Python/jit/hir/hir_c_api.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,21 @@ HirInstr hir_c_create_check_exc(HirFunction func, HirRegister src,
585585
*static_cast<const FrameState*>(frame_state));
586586
}
587587

588+
/* ---- Branch/CondBranch factories (C++ bridge for Edge management) ---- */
589+
590+
HirInstr hir_c_create_branch_cpp(void *target_block) {
591+
auto* bb = static_cast<BasicBlock*>(target_block);
592+
return Branch::create(bb);
593+
}
594+
595+
HirInstr hir_c_create_cond_branch_cpp(void *cond_reg,
596+
void *true_block,
597+
void *false_block) {
598+
auto* true_bb = static_cast<BasicBlock*>(true_block);
599+
auto* false_bb = static_cast<BasicBlock*>(false_block);
600+
return CondBranch::create(as_reg(cond_reg), true_bb, false_bb);
601+
}
602+
588603
/* ---- Frame state ---- */
589604

590605
void *hir_get_frame_state(HirInstr instr) {

Python/jit/hir/hir_c_api.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,16 @@ HirInstr hir_load_const_bottom_create(HirRegister output);
158158
/* Create an Assign instruction (copy register). */
159159
HirInstr hir_assign_create(HirRegister output, HirRegister value);
160160

161+
/* Create a Branch instruction (0 operands, 1 edge).
162+
* Uses C++ Edge::set_to for proper in_edges management. */
163+
HirInstr hir_c_create_branch_cpp(void *target_block);
164+
165+
/* Create a CondBranch instruction (1 operand, 2 edges).
166+
* Uses C++ Edge::set_to for proper in_edges management. */
167+
HirInstr hir_c_create_cond_branch_cpp(void *cond_reg,
168+
void *true_block,
169+
void *false_block);
170+
161171
/* ---- Instruction query/mutation (T2-D) ---- */
162172

163173
/* Get the Compare operation kind (CompareOp enum as int).

Python/jit/hir/simplify.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,19 @@ struct Env {
176176
&func, src, const_cast<void*>(static_cast<const void*>(&fs)))));
177177
}
178178

179-
// Convenience: create + insert a Branch via pure C factory.
179+
// Convenience: create + insert a Branch via C++ bridge factory.
180+
// Must use C++ bridge (not pure C) because Edge::set_to manages
181+
// target block's in_edges_ set.
180182
Register* emitBranch(BasicBlock* target) {
181-
return emitCInstr(static_cast<Instr*>(hir_c_create_branch(target)));
183+
return emitCInstr(static_cast<Instr*>(hir_c_create_branch_cpp(target)));
182184
}
183185

184-
// Convenience: create + insert a CondBranch via pure C factory.
186+
// Convenience: create + insert a CondBranch via C++ bridge factory.
187+
// Must use C++ bridge (not pure C) because Edge::set_to manages
188+
// target block's in_edges_ set.
185189
Register* emitCondBranch(Register* cond, BasicBlock* true_bb, BasicBlock* false_bb) {
186190
return emitCInstr(static_cast<Instr*>(
187-
hir_c_create_cond_branch(cond, true_bb, false_bb)));
191+
hir_c_create_cond_branch_cpp(cond, true_bb, false_bb)));
188192
}
189193

190194
// Convenience: create + insert a UseType via pure C factory.

0 commit comments

Comments
 (0)