From 04e2ccede4e992a6e0d18ed506d76625ee7da8a3 Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Mon, 6 Jun 2022 15:54:22 -0400 Subject: Change codegen.rs to use backend Assembler directly --- yjit/src/backend/ir.rs | 17 ++++++ yjit/src/backend/x86_64/mod.rs | 6 +- yjit/src/codegen.rs | 126 +++++++++++------------------------------ yjit/src/lib.rs | 7 +++ 4 files changed, 62 insertions(+), 94 deletions(-) diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs index a578564afb..fa8a7b8e2b 100644 --- a/yjit/src/backend/ir.rs +++ b/yjit/src/backend/ir.rs @@ -84,6 +84,9 @@ pub enum Op // C function call with N arguments (variadic) CCall, + // C function return + CRet, + /* // The following are conditional jump instructions. They all accept as their // first operand an EIR_LABEL_NAME, which is used as the target of the jump. @@ -661,6 +664,18 @@ macro_rules! def_push_1_opnd { }; } +macro_rules! def_push_1_opnd_no_out { + ($op_name:ident, $opcode:expr) => { + impl Assembler + { + pub fn $op_name(&mut self, opnd0: Opnd) + { + self.push_insn($opcode, vec![opnd0], None); + } + } + }; +} + macro_rules! def_push_2_opnd { ($op_name:ident, $opcode:expr) => { impl Assembler @@ -688,7 +703,9 @@ macro_rules! def_push_2_opnd_no_out { def_push_2_opnd!(add, Op::Add); def_push_2_opnd!(sub, Op::Sub); def_push_2_opnd!(and, Op::And); +def_push_1_opnd_no_out!(cret, Op::CRet); def_push_1_opnd!(load, Op::Load); +def_push_2_opnd_no_out!(store, Op::Store); def_push_2_opnd_no_out!(mov, Op::Mov); def_push_2_opnd_no_out!(lea, Op::Lea); def_push_2_opnd_no_out!(cmp, Op::Cmp); diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs index f6ebcc5643..eb54ced2bf 100644 --- a/yjit/src/backend/x86_64/mod.rs +++ b/yjit/src/backend/x86_64/mod.rs @@ -109,8 +109,7 @@ impl Assembler add(cb, insn.opnds[0].into(), insn.opnds[1].into()) }, - //TODO: - //Store + Op::Store => mov(cb, insn.opnds[0].into(), insn.opnds[1].into()), Op::Load => { mov(cb, insn.out.into(), insn.opnds[0].into()); @@ -127,6 +126,9 @@ impl Assembler Op::Mov => mov(cb, insn.opnds[0].into(), insn.opnds[1].into()), + // Load effective address + Op::Lea => lea(cb, insn.opnds[0].into(), insn.opnds[1].into()), + // Test and set flags Op::Test => test(cb, insn.opnds[0].into(), insn.opnds[1].into()), diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index a94eeb62ca..955d87eb68 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -54,7 +54,7 @@ enum CodegenStatus { type InsnGenFn = fn( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, ocb: &mut OutlinedCb, ) -> CodegenStatus; @@ -778,6 +778,9 @@ pub fn gen_single_block( // Mark the start position of the block blockref.borrow_mut().set_start_addr(cb.get_write_ptr()); + // Create a backend assembler instance + let mut asm = Assembler::new(); + // For each instruction to compile // NOTE: could rewrite this loop with a std::iter::Iterator while insn_idx < iseq_size { @@ -832,7 +835,7 @@ pub fn gen_single_block( } // Call the code generation function - status = gen_fn(&mut jit, &mut ctx, cb, ocb); + status = gen_fn(&mut jit, &mut ctx, &mut asm, ocb); } // If we can't compile this instruction @@ -869,6 +872,9 @@ pub fn gen_single_block( // Finish filling out the block { + // Compile code into the code block + asm.compile(&mut jit, cb); + let mut block = jit.block.borrow_mut(); // Mark the end position of the block @@ -887,19 +893,6 @@ pub fn gen_single_block( return Err(()); } - // TODO: we may want a feature for this called dump_insns? Can leave commented for now - /* - if (YJIT_DUMP_MODE >= 2) { - // Dump list of compiled instrutions - fprintf(stderr, "Compiled the following for iseq=%p:\n", (void *)iseq); - for (uint32_t idx = block->blockid.idx; idx < insn_idx; ) { - int opcode = yjit_opcode_at_pc(iseq, yjit_iseq_pc_at_idx(iseq, idx)); - fprintf(stderr, " %04d %s\n", idx, insn_name(opcode)); - idx += insn_len(opcode); - } - } - */ - // Block compiled successfully Ok(blockref) } @@ -907,7 +900,7 @@ pub fn gen_single_block( fn gen_nop( _jit: &mut JITState, _ctx: &mut Context, - _cb: &mut CodeBlock, + _asm: &mut Assembler, _ocb: &mut OutlinedCb, ) -> CodegenStatus { // Do nothing @@ -917,7 +910,7 @@ fn gen_nop( fn gen_pop( _jit: &mut JITState, ctx: &mut Context, - _cb: &mut CodeBlock, + _asm: &mut Assembler, _ocb: &mut OutlinedCb, ) -> CodegenStatus { // Decrement SP @@ -925,90 +918,27 @@ fn gen_pop( KeepCompiling } - - - -/* -fn gen_dup( - _jit: &mut JITState, - ctx: &mut Context, - cb: &mut CodeBlock, - _ocb: &mut OutlinedCb, -) -> CodegenStatus { - let dup_val = ctx.stack_pop(0); - let (mapping, tmp_type) = ctx.get_opnd_mapping(StackOpnd(0)); - - let loc0 = ctx.stack_push_mapping((mapping, tmp_type)); - mov(cb, REG0, dup_val); - mov(cb, loc0, REG0); - - KeepCompiling -} -*/ - -#[allow(dead_code)] fn gen_dup( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, _ocb: &mut OutlinedCb, ) -> CodegenStatus { - let mut asm = Assembler::new(); - let dup_val = ctx.ir_stack_pop(0); let (mapping, tmp_type) = ctx.get_opnd_mapping(StackOpnd(0)); let loc0 = ctx.ir_stack_push_mapping((mapping, tmp_type)); asm.mov(loc0, dup_val); - asm.compile(jit, cb); - - KeepCompiling -} - - - - -/* -// duplicate stack top n elements -fn gen_dupn( - jit: &mut JITState, - ctx: &mut Context, - cb: &mut CodeBlock, - _ocb: &mut OutlinedCb, -) -> CodegenStatus { - let nval: VALUE = jit_get_arg(jit, 0); - let VALUE(n) = nval; - - // In practice, seems to be only used for n==2 - if n != 2 { - return CantCompile; - } - - let opnd1: X86Opnd = ctx.stack_opnd(1); - let opnd0: X86Opnd = ctx.stack_opnd(0); - - let mapping1 = ctx.get_opnd_mapping(StackOpnd(1)); - let mapping0 = ctx.get_opnd_mapping(StackOpnd(0)); - - let dst1: X86Opnd = ctx.stack_push_mapping(mapping1); - mov(cb, REG0, opnd1); - mov(cb, dst1, REG0); - - let dst0: X86Opnd = ctx.stack_push_mapping(mapping0); - mov(cb, REG0, opnd0); - mov(cb, dst0, REG0); - KeepCompiling } -*/ // duplicate stack top n elements fn gen_dupn( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, _ocb: &mut OutlinedCb, ) -> CodegenStatus { @@ -1034,8 +964,6 @@ fn gen_dupn( let dst0: Opnd = ctx.ir_stack_push_mapping(mapping0); asm.mov(dst0, opnd0); - asm.compile(jit, cb); - KeepCompiling } @@ -1043,24 +971,22 @@ fn gen_dupn( fn gen_swap( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, _ocb: &mut OutlinedCb, ) -> CodegenStatus { - stack_swap(jit, ctx, cb, 0, 1, REG0, REG1); + stack_swap(jit, ctx, asm, 0, 1, REG0, REG1); KeepCompiling } fn stack_swap( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, offset0: u16, offset1: u16, _reg0: X86Opnd, _reg1: X86Opnd, ) { - let mut asm = Assembler::new(); - let stack0_mem = ctx.ir_stack_opnd(offset0 as i32); let stack1_mem = ctx.ir_stack_opnd(offset1 as i32); @@ -1074,10 +1000,18 @@ fn stack_swap( ctx.set_opnd_mapping(StackOpnd(offset0), mapping1); ctx.set_opnd_mapping(StackOpnd(offset1), mapping0); - - asm.compile(jit, cb); } + + + + + + + + + +/* fn gen_putnil( jit: &mut JITState, ctx: &mut Context, @@ -6069,6 +6003,7 @@ fn gen_opt_invokebuiltin_delegate( KeepCompiling } +*/ /// Maps a YARV opcode to a code generation function (if supported) fn get_gen_fn(opcode: VALUE) -> Option { @@ -6078,10 +6013,12 @@ fn get_gen_fn(opcode: VALUE) -> Option { match opcode { YARVINSN_nop => Some(gen_nop), - YARVINSN_pop => Some(gen_pop), + //YARVINSN_pop => Some(gen_pop), YARVINSN_dup => Some(gen_dup), YARVINSN_dupn => Some(gen_dupn), YARVINSN_swap => Some(gen_swap), + + /* YARVINSN_putnil => Some(gen_putnil), YARVINSN_putobject => Some(gen_putobject), YARVINSN_putobject_INT2FIX_0_ => Some(gen_putobject_int2fix), @@ -6163,6 +6100,7 @@ fn get_gen_fn(opcode: VALUE) -> Option { YARVINSN_getspecial => Some(gen_getspecial), YARVINSN_getclassvariable => Some(gen_getclassvariable), YARVINSN_setclassvariable => Some(gen_setclassvariable), + */ // Unimplemented opcode, YJIT won't generate code for this yet _ => None, @@ -6350,6 +6288,7 @@ impl CodegenGlobals { /// Register codegen functions for some Ruby core methods fn reg_method_codegen_fns(&mut self) { + /* unsafe { // Specialization for C methods. See yjit_reg_method() for details. self.yjit_reg_method(rb_cBasicObject, "!", jit_rb_obj_not); @@ -6378,6 +6317,7 @@ impl CodegenGlobals { jit_thread_s_current, ); } + */ } /// Get a mutable reference to the codegen globals instance @@ -6442,6 +6382,7 @@ impl CodegenGlobals { } } +/* #[cfg(test)] mod tests { use super::*; @@ -6704,3 +6645,4 @@ mod tests { gen_leave(&mut jit, &mut context, &mut cb, &mut ocb); } } +*/ \ No newline at end of file diff --git a/yjit/src/lib.rs b/yjit/src/lib.rs index 752b7872c1..e92186da7d 100644 --- a/yjit/src/lib.rs +++ b/yjit/src/lib.rs @@ -3,6 +3,13 @@ #![allow(clippy::too_many_arguments)] // :shrug: #![allow(clippy::identity_op)] // Sometimes we do it for style + +// Temporary while switching to the new backend +#![allow(dead_code)] +#![allow(unused)] + + + mod asm; mod backend; mod codegen; -- cgit v1.2.3