Skip to content

ZJIT: GetLocal or SetLocal causes backend panic #614

Closed
ruby/ruby
#14270

Description

@tekknolagi
def test
          l3 = 3
          1.times do |l2|
            _ = l3
            1
          end
end

test
test
thread '<unnamed>' panicked at zjit/src/backend/arm64/mod.rs:73:34:
attempted to lower an Opnd::VReg

../build-dev/miniruby --zjit --zjit-disable-hir-opt --zjit-dump-hir=all testmatch.rb on macOS ARM

Activity

  1. k0kubun commented on Jul 2, 2025

    @k0kubun
    Member

    I can't reproduce the issue.

    $ cat ~/tmp/c.rb
    def test
      l3 = 3
      1.times do |l2|
        _ = l3
        1
      end
    end
    
    test
    test
    
    $ .ruby/miniruby --zjit -v ~/tmp/c.rb
    ruby 3.5.0dev (2025-07-02T20:01:24Z master d5f5a56bf2) +ZJIT dev_nodebug +PRISM [arm64-darwin24]
    
  2. tekknolagi commented on Jul 3, 2025

    @tekknolagi
    Author

    Sorry, this has to be with my patch that removes GetLocal reverted: ruby#13750

    Try git revert e54a242bdf35d4bd90dd8628af411a848946d4f1 beforehand

  3. tekknolagi commented on Aug 19, 2025

    @tekknolagi
    Author

    This repros if you disable the HIR optimizer (original description edited).

  4. tekknolagi commented on Aug 19, 2025

    @tekknolagi
    Author

    Two LIR snippets, pre-alloc and post-alloc:

    LIR:
    fn block in test:
    Assembler
        000 Label() target=Label(Label(0)) -> None
        001 FrameSetup() -> None
        002 LiveReg(A64Reg { num_bits: 64, reg_no: 0 }) -> VReg(0)
        003 LiveReg(A64Reg { num_bits: 64, reg_no: 1 }) -> VReg(1)
        004 Load(Mem64[Reg(19) + 32]) -> VReg(2)
        005 Load(Mem64[VReg(2) - 8]) -> VReg(3)
        006 And(VReg(3), fffffffffffffffc_i64) -> VReg(4)
        007 Load(Mem64[VReg(4) - 24]) -> VReg(5)
        008 Add(A64Reg { num_bits: 64, reg_no: 19 }, 38_u64) -> VReg(6)
        009 Mov(A64Reg { num_bits: 64, reg_no: 19 }, VReg(6)) -> None
        010 Mov(Mem64[Reg(20) + 16], A64Reg { num_bits: 64, reg_no: 19 }) -> None
        011 LoadInto(A64Reg { num_bits: 64, reg_no: 0 }, Value(VALUE(3))) -> None
        012 FrameTeardown() -> None
        013 CRet(A64Reg { num_bits: 64, reg_no: 0 }) -> None
        014 PadPatchPoint() -> None
    
    LIR:
    fn:
    Assembler
        000 Label() target=Label(Label(0)) -> None
        001 FrameSetup() -> None
        002 LiveReg(A64Reg { num_bits: 64, reg_no: 0 }) -> VReg(0)
        003 LiveReg(A64Reg { num_bits: 64, reg_no: 1 }) -> VReg(1)
        004 Load(Mem64[Reg(19) + 32]) -> A64Reg { num_bits: 64, reg_no: 0 }
        005 Load(Mem64[Reg(0) - 8]) -> A64Reg { num_bits: 64, reg_no: 0 }
        006 And(A64Reg { num_bits: 64, reg_no: 0 }, fffffffffffffffc_u64) -> A64Reg { num_bits: 64, reg_no: 0 }
        007 Load(Mem64[Reg(0) - 24]) -> VReg(5)
        008 Add(A64Reg { num_bits: 64, reg_no: 19 }, 38_u64) -> A64Reg { num_bits: 64, reg_no: 19 }
        009 Store(Mem64[Reg(20) + 16], A64Reg { num_bits: 64, reg_no: 19 }) -> None
        010 LoadInto(A64Reg { num_bits: 64, reg_no: 0 }, 3_u64) -> None
        011 FrameTeardown() -> None
        012 CRet(A64Reg { num_bits: 64, reg_no: 0 }) -> None
        013 PadPatchPoint() -> None
    

    Looks like 007 Load output Vreg(5) is not getting allocated a physical register

  5. tekknolagi commented on Aug 19, 2025

    @tekknolagi
    Author

    Maybe we should add something like

                if let Some(idx) = vreg_idx {
                    if live_ranges[idx].end() == index {
                        if let Some(reg) = reg_mapping[idx] {
                            pool.dealloc_reg(&reg);
                        } else {
                            unreachable!("no register allocated for insn {:?}", insn);
                        }
                    }
                }

    before pushing the insn in alloc_regs because VReg(5) starts and ends life at idx 7

  6. self-assigned this
    on Aug 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions