Skip to content

Commit eb66ff9

Browse files
committed
Quietly abort codegen if we don't have enough registers
This temporarily paves over the register allocator issue that allocates basic block parameters from a small fixed list of physical registers.
1 parent 3e94b5f commit eb66ff9

1 file changed

Lines changed: 16 additions & 12 deletions

File tree

zjit/src/codegen.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ fn gen_entry(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function, function_pt
141141
// Set up registers for CFP, EC, SP, and basic block arguments
142142
let mut asm = Assembler::new();
143143
gen_entry_prologue(&mut asm, iseq);
144-
gen_method_params(&mut asm, iseq, function.block(BlockId(0)));
144+
gen_method_params(&mut asm, iseq, function.block(BlockId(0)))?;
145145

146146
// Jump to the first block using a call instruction
147147
asm.ccall(function_ptr.raw_ptr(cb) as *const u8, vec![]);
@@ -207,7 +207,7 @@ fn gen_function(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function) -> Optio
207207
for &insn_id in block.params() {
208208
match function.find(insn_id) {
209209
Insn::Param { idx } => {
210-
jit.opnds[insn_id.0] = Some(gen_param(&mut asm, idx));
210+
jit.opnds[insn_id.0] = Some(gen_param(&mut asm, idx)?);
211211
},
212212
insn => unreachable!("Non-param insn found in block.params: {insn:?}"),
213213
}
@@ -319,14 +319,17 @@ fn gen_entry_prologue(asm: &mut Assembler, iseq: IseqPtr) {
319319
}
320320

321321
/// Assign method arguments to basic block arguments at JIT entry
322-
fn gen_method_params(asm: &mut Assembler, iseq: IseqPtr, entry_block: &Block) {
322+
fn gen_method_params(asm: &mut Assembler, iseq: IseqPtr, entry_block: &Block) -> Option<()> {
323323
let num_params = entry_block.params().len();
324324
if num_params > 0 {
325325
asm_comment!(asm, "set method params: {num_params}");
326326

327327
// Allocate registers for basic block arguments
328+
if num_params >= ALLOC_REGS.len() {
329+
return None;
330+
}
328331
let params: Vec<Opnd> = (0..num_params).map(|idx|
329-
gen_param(asm, idx)
332+
gen_param(asm, idx).unwrap()
330333
).collect();
331334

332335
// Assign local variables to the basic block arguments
@@ -335,6 +338,7 @@ fn gen_method_params(asm: &mut Assembler, iseq: IseqPtr, entry_block: &Block) {
335338
asm.load_into(param, local);
336339
}
337340
}
341+
Some(())
338342
}
339343

340344
/// Set branch params to basic block arguments
@@ -343,7 +347,7 @@ fn gen_branch_params(jit: &mut JITState, asm: &mut Assembler, branch: &BranchEdg
343347
asm_comment!(asm, "set branch params: {}", branch.args.len());
344348
let mut moves: Vec<(Reg, Opnd)> = vec![];
345349
for (idx, &arg) in branch.args.iter().enumerate() {
346-
moves.push((param_reg(idx), jit.get_opnd(arg)?));
350+
moves.push((param_reg(idx)?, jit.get_opnd(arg)?));
347351
}
348352
asm.parallel_mov(moves);
349353
}
@@ -382,14 +386,14 @@ fn gen_const(val: VALUE) -> lir::Opnd {
382386
}
383387

384388
/// Compile a basic block argument
385-
fn gen_param(asm: &mut Assembler, idx: usize) -> lir::Opnd {
386-
asm.live_reg_opnd(Opnd::Reg(param_reg(idx)))
389+
fn gen_param(asm: &mut Assembler, idx: usize) -> Option<lir::Opnd> {
390+
Some(asm.live_reg_opnd(Opnd::Reg(param_reg(idx)?)))
387391
}
388392

389393
/// Compile a jump to a basic block
390394
fn gen_jump(jit: &mut JITState, asm: &mut Assembler, branch: &BranchEdge) -> Option<()> {
391395
// Set basic block arguments
392-
gen_branch_params(jit, asm, branch);
396+
gen_branch_params(jit, asm, branch)?;
393397

394398
// Jump to the basic block
395399
let target = jit.get_label(asm, branch.target);
@@ -407,7 +411,7 @@ fn gen_if_true(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, branch:
407411
// If val is not zero, set basic block arguments and jump to the branch target.
408412
// TODO: Consider generating the loads out-of-line
409413
let if_true = jit.get_label(asm, branch.target);
410-
gen_branch_params(jit, asm, branch);
414+
gen_branch_params(jit, asm, branch)?;
411415
asm.jmp(if_true);
412416

413417
asm.write_label(if_false);
@@ -425,7 +429,7 @@ fn gen_if_false(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, branch:
425429
// If val is zero, set basic block arguments and jump to the branch target.
426430
// TODO: Consider generating the loads out-of-line
427431
let if_false = jit.get_label(asm, branch.target);
428-
gen_branch_params(jit, asm, branch);
432+
gen_branch_params(jit, asm, branch)?;
429433
asm.jmp(if_false);
430434

431435
asm.write_label(if_true);
@@ -699,10 +703,10 @@ fn gen_push_frame(asm: &mut Assembler, recv: Opnd) {
699703
}
700704

701705
/// Return a register we use for the basic block argument at a given index
702-
fn param_reg(idx: usize) -> Reg {
706+
fn param_reg(idx: usize) -> Option<Reg> {
703707
// To simplify the implementation, allocate a fixed register for each basic block argument for now.
704708
// TODO: Allow allocating arbitrary registers for basic block arguments
705-
ALLOC_REGS[idx]
709+
ALLOC_REGS.get(idx).copied()
706710
}
707711

708712
/// Inverse of ep_offset_to_local_idx(). See ep_offset_to_local_idx() for details.

0 commit comments

Comments
 (0)