diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs index 41842c9704..066e9dd4ce 100644 --- a/yjit/src/backend/ir.rs +++ b/yjit/src/backend/ir.rs @@ -567,7 +567,7 @@ impl Assembler /// Transform input instructions, consumes the input assembler pub(super) fn forward_pass(mut self, mut map_insn: F) -> Assembler - where F: FnMut(&mut Assembler, usize, Op, Vec, Option, Option, Option) + where F: FnMut(&mut Assembler, usize, Op, Vec, Option, Option, Option, Vec) { let mut asm = Assembler { insns: Vec::default(), @@ -594,6 +594,7 @@ impl Assembler } for (index, insn) in self.insns.drain(..).enumerate() { + let original_opnds = insn.opnds.clone(); let opnds: Vec = insn.opnds.into_iter().map(|opnd| map_opnd(opnd, &mut indices)).collect(); // For each instruction, either handle it here or allow the map_insn @@ -603,7 +604,7 @@ impl Assembler asm.comment(insn.text.unwrap().as_str()); }, _ => { - map_insn(&mut asm, index, insn.op, opnds, insn.target, insn.text, insn.pos_marker); + map_insn(&mut asm, index, insn.op, opnds, insn.target, insn.text, insn.pos_marker, original_opnds); } }; @@ -664,7 +665,7 @@ impl Assembler let live_ranges: Vec = std::mem::take(&mut self.live_ranges); - let asm = self.forward_pass(|asm, index, op, opnds, target, text, pos_marker| { + let asm = self.forward_pass(|asm, index, op, opnds, target, text, pos_marker, original_insns| { // Check if this is the last instruction that uses an operand that // spans more than one instruction. In that case, return the // allocated register to the pool. diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs index 7074c8980b..c3885be811 100644 --- a/yjit/src/backend/x86_64/mod.rs +++ b/yjit/src/backend/x86_64/mod.rs @@ -94,7 +94,7 @@ impl Assembler { let live_ranges: Vec = std::mem::take(&mut self.live_ranges); - self.forward_pass(|asm, index, op, opnds, target, text, pos_marker| { + self.forward_pass(|asm, index, op, opnds, target, text, pos_marker, original_opnds| { // Load heap object operands into registers because most // instructions can't directly work with 64-bit constants let opnds = match op { @@ -134,7 +134,17 @@ impl Assembler } }, // Instruction output whose live range spans beyond this instruction - (Opnd::InsnOut { idx, .. }, _) => { + (Opnd::InsnOut { .. }, _) => { + let idx = match original_opnds[0] { + Opnd::InsnOut { idx, .. } => { + idx + }, + _ => panic!("nooooo") + }; + + // Our input must be from a previous instruction! + assert!(idx < index); + if live_ranges[idx] > index { (asm.load(opnds[0]), opnds[1]) } else {