diff options
-rw-r--r-- | yjit/src/asm/arm64/arg/shifted_imm.rs | 18 | ||||
-rw-r--r-- | yjit/src/backend/tests.rs | 17 | ||||
-rw-r--r-- | yjit/src/backend/x86_64/mod.rs | 24 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 71 |
4 files changed, 78 insertions, 52 deletions
diff --git a/yjit/src/asm/arm64/arg/shifted_imm.rs b/yjit/src/asm/arm64/arg/shifted_imm.rs index 0dd7af25b5..4602ac64ab 100644 --- a/yjit/src/asm/arm64/arg/shifted_imm.rs +++ b/yjit/src/asm/arm64/arg/shifted_imm.rs @@ -46,18 +46,24 @@ mod tests { #[test] fn test_no_shift() { - let value = 256; - let result = ShiftedImmediate::try_from(value); + let expected_value = 256; + let result = ShiftedImmediate::try_from(expected_value); - assert!(matches!(result, Ok(ShiftedImmediate { shift: Shift::LSL0, value }))); + match result { + Ok(ShiftedImmediate { shift: Shift::LSL0, value }) => assert_eq!(value as u64, expected_value), + _ => panic!("Unexpected shift value") + } } #[test] fn test_maximum_no_shift() { - let value = (1 << 12) - 1; - let result = ShiftedImmediate::try_from(value); + let expected_value = (1 << 12) - 1; + let result = ShiftedImmediate::try_from(expected_value); - assert!(matches!(result, Ok(ShiftedImmediate { shift: Shift::LSL0, value }))); + match result { + Ok(ShiftedImmediate { shift: Shift::LSL0, value }) => assert_eq!(value as u64, expected_value), + _ => panic!("Unexpected shift value") + } } #[test] diff --git a/yjit/src/backend/tests.rs b/yjit/src/backend/tests.rs index 1df726c468..1bad8642a2 100644 --- a/yjit/src/backend/tests.rs +++ b/yjit/src/backend/tests.rs @@ -44,9 +44,20 @@ fn test_alloc_regs() { let reg0 = regs[0]; let reg1 = regs[1]; - assert!(matches!(result.insns[0].out_opnd(), Some(Opnd::Reg(reg0)))); - assert!(matches!(result.insns[2].out_opnd(), Some(Opnd::Reg(reg1)))); - assert!(matches!(result.insns[5].out_opnd(), Some(Opnd::Reg(reg0)))); + match result.insns[0].out_opnd() { + Some(Opnd::Reg(value)) => assert_eq!(value, ®0), + val => panic!("Unexpected register value {:?}", val), + } + + match result.insns[2].out_opnd() { + Some(Opnd::Reg(value)) => assert_eq!(value, ®1), + val => panic!("Unexpected register value {:?}", val), + } + + match result.insns[5].out_opnd() { + Some(Opnd::Reg(value)) => assert_eq!(value, ®0), + val => panic!("Unexpected register value {:?}", val), + } } fn setup_asm() -> (Assembler, CodeBlock) { diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs index 2f770c2eac..f6bd822727 100644 --- a/yjit/src/backend/x86_64/mod.rs +++ b/yjit/src/backend/x86_64/mod.rs @@ -152,6 +152,9 @@ impl Assembler } } + // We are replacing instructions here so we know they are already + // being used. It is okay not to use their output here. + #[allow(unused_must_use)] match &mut insn { Insn::Add { left, right, out } | Insn::Sub { left, right, out } | @@ -660,6 +663,7 @@ impl Assembler // we feed to the backend could get lowered into other // instructions. So it's possible that some of our backend // instructions can never make it to the emit stage. + #[allow(unreachable_patterns)] _ => panic!("unsupported instruction passed to x86 backend: {:?}", insn) }; } @@ -700,7 +704,7 @@ mod tests { fn test_emit_add_lt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.add(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); + let _ = asm.add(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c04881c0ff000000"); @@ -710,7 +714,7 @@ mod tests { fn test_emit_add_gt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.add(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); + let _ = asm.add(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c049bbffffffffffff00004c01d8"); @@ -720,7 +724,7 @@ mod tests { fn test_emit_and_lt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.and(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); + let _ = asm.and(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c04881e0ff000000"); @@ -730,7 +734,7 @@ mod tests { fn test_emit_and_gt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.and(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); + let _ = asm.and(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c049bbffffffffffff00004c21d8"); @@ -760,7 +764,7 @@ mod tests { fn test_emit_or_lt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.or(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); + let _ = asm.or(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c04881c8ff000000"); @@ -770,7 +774,7 @@ mod tests { fn test_emit_or_gt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.or(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); + let _ = asm.or(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c049bbffffffffffff00004c09d8"); @@ -780,7 +784,7 @@ mod tests { fn test_emit_sub_lt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.sub(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); + let _ = asm.sub(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c04881e8ff000000"); @@ -790,7 +794,7 @@ mod tests { fn test_emit_sub_gt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.sub(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); + let _ = asm.sub(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c049bbffffffffffff00004c29d8"); @@ -820,7 +824,7 @@ mod tests { fn test_emit_xor_lt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.xor(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); + let _ = asm.xor(Opnd::Reg(RAX_REG), Opnd::UImm(0xFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c04881f0ff000000"); @@ -830,7 +834,7 @@ mod tests { fn test_emit_xor_gt_32_bits() { let (mut asm, mut cb) = setup_asm(); - asm.xor(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); + let _ = asm.xor(Opnd::Reg(RAX_REG), Opnd::UImm(0xFFFF_FFFF_FFFF)); asm.compile_with_num_regs(&mut cb, 1); assert_eq!(format!("{:x}", cb), "4889c049bbffffffffffff00004c31d8"); diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index f8379a7159..88b51674cf 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1923,7 +1923,7 @@ fn gen_set_ivar( jit: &mut JITState, ctx: &mut Context, asm: &mut Assembler, - recv: VALUE, + _recv: VALUE, ivar_name: ID, flags: u32, argc: i32, @@ -1947,7 +1947,7 @@ fn gen_set_ivar( rb_vm_set_ivar_id as *const u8, vec![ recv_opnd, - Opnd::UImm(ivar_name.into()), + Opnd::UImm(ivar_name), val_opnd, ], ); @@ -2077,41 +2077,46 @@ fn gen_get_ivar( side_exit, ); - // If there is no IVAR index, then the ivar was undefined - // when we entered the compiler. That means we can just return - // nil for this shape + iv name - if ivar_index.is_none() { - let out_opnd = ctx.stack_push(Type::Nil); - asm.mov(out_opnd, Qnil.into()); - } else if embed_test_result { - // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h - - // Load the variable - let offs = ROBJECT_OFFSET_AS_ARY + (ivar_index.unwrap() * SIZEOF_VALUE) as i32; - let ivar_opnd = Opnd::mem(64, recv, offs); - - // Push the ivar on the stack - let out_opnd = ctx.stack_push(Type::Unknown); - asm.mov(out_opnd, ivar_opnd); - } else { - // Compile time value is *not* embedded. - - if USE_RVARGC == 0 { - // Check that the extended table is big enough - // Check that the slot is inside the extended table (num_slots > index) - let num_slots = Opnd::mem(32, recv, ROBJECT_OFFSET_NUMIV); - asm.cmp(num_slots, Opnd::UImm(ivar_index.unwrap() as u64)); - asm.jbe(counted_exit!(ocb, side_exit, getivar_idx_out_of_range).into()); + match ivar_index { + // If there is no IVAR index, then the ivar was undefined + // when we entered the compiler. That means we can just return + // nil for this shape + iv name + None => { + let out_opnd = ctx.stack_push(Type::Nil); + asm.mov(out_opnd, Qnil.into()); } + Some(ivar_index) => { + if embed_test_result { + // See ROBJECT_IVPTR() from include/ruby/internal/core/robject.h + + // Load the variable + let offs = ROBJECT_OFFSET_AS_ARY + (ivar_index * SIZEOF_VALUE) as i32; + let ivar_opnd = Opnd::mem(64, recv, offs); + + // Push the ivar on the stack + let out_opnd = ctx.stack_push(Type::Unknown); + asm.mov(out_opnd, ivar_opnd); + } else { + // Compile time value is *not* embedded. + + if USE_RVARGC == 0 { + // Check that the extended table is big enough + // Check that the slot is inside the extended table (num_slots > index) + let num_slots = Opnd::mem(32, recv, ROBJECT_OFFSET_NUMIV); + asm.cmp(num_slots, Opnd::UImm(ivar_index as u64)); + asm.jbe(counted_exit!(ocb, side_exit, getivar_idx_out_of_range).into()); + } - // Get a pointer to the extended table - let tbl_opnd = asm.load(Opnd::mem(64, recv, ROBJECT_OFFSET_AS_HEAP_IVPTR)); + // Get a pointer to the extended table + let tbl_opnd = asm.load(Opnd::mem(64, recv, ROBJECT_OFFSET_AS_HEAP_IVPTR)); - // Read the ivar from the extended table - let ivar_opnd = Opnd::mem(64, tbl_opnd, (SIZEOF_VALUE * ivar_index.unwrap()) as i32); + // Read the ivar from the extended table + let ivar_opnd = Opnd::mem(64, tbl_opnd, (SIZEOF_VALUE * ivar_index) as i32); - let out_opnd = ctx.stack_push(Type::Unknown); - asm.mov(out_opnd, ivar_opnd); + let out_opnd = ctx.stack_push(Type::Unknown); + asm.mov(out_opnd, ivar_opnd); + } + } } // Jump to next instruction. This allows guard chains to share the same successor. |