ruby-changes:73170
From: Alan <ko1@a...>
Date: Tue, 30 Aug 2022 00:57:59 +0900 (JST)
Subject: [ruby-changes:73170] d916328078 (master): Conscise IR disassembly (https://github.com/Shopify/ruby/pull/302)
https://git.ruby-lang.org/ruby.git/commit/?id=d916328078 From d9163280782086b57119abc9478580a6b3efd2c3 Mon Sep 17 00:00:00 2001 From: Alan Wu <XrXr@u...> Date: Tue, 21 Jun 2022 19:41:06 -0400 Subject: Conscise IR disassembly (https://github.com/Shopify/ruby/pull/302) The output from `dbg!` was too verbose. For `test_jo` the output went from 37 lines to 5 lines. The added index helps parsing InsnOut indicies. Samples: ``` test backend::tests::test_jo ... [src/backend/ir.rs:589] &self = Assembler 000 Load(Mem64[Reg(3) + 8]) -> Out64(0) 001 Sub(Out64(0), 1_i64) -> Out64(1) 002 Load(Out64(1)) -> Out64(2) 003 Add(Out64(2), Mem64[Reg(3)]) -> Out64(3) 004 Jo() target=CodePtr(CodePtr(0x5)) -> Out64(4) 005 Mov(Mem64[Reg(3)], Out64(3)) -> Out64(5) test backend::tests::test_reuse_reg ... [src/backend/ir.rs:589] &self = Assembler 000 Load(Mem64[Reg(3)]) -> Out64(0) 001 Add(Out64(0), 1_u64) -> Out64(1) 002 Load(Mem64[Reg(3) + 8]) -> Out64(2) 003 Add(Out64(2), 1_u64) -> Out64(3) 004 Add(Out64(1), 1_u64) -> Out64(4) 005 Add(Out64(1), Out64(4)) -> Out64(5) 006 Store(Mem64[Reg(3)], Out64(4)) -> Out64(6) 007 Store(Mem64[Reg(3) + 8], Out64(5)) -> Out64(7) ``` --- yjit/src/backend/ir.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs index 96b314e9cb..4e8ed0b8a4 100644 --- a/yjit/src/backend/ir.rs +++ b/yjit/src/backend/ir.rs @@ -121,7 +121,7 @@ pub enum MemBase https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L121 } // Memory location -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq)] pub struct Mem { // Base register number or instruction index @@ -134,8 +134,20 @@ pub struct Mem https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L134 pub(super) num_bits: u8, } +impl fmt::Debug for Mem { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "Mem{}[{:?}", self.num_bits, self.base)?; + if self.disp != 0 { + let sign = if self.disp > 0 { '+' } else { '-' }; + write!(fmt, " {sign} {}", self.disp)?; + } + + write!(fmt, "]") + } +} + /// Operand to an IR instruction -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq)] pub enum Opnd { None, // For insns with no output @@ -153,6 +165,22 @@ pub enum Opnd https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L165 Reg(Reg), // Machine register } +impl fmt::Debug for Opnd { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + use Opnd::*; + match self { + Self::None => write!(fmt, "None"), + Value(val) => write!(fmt, "Value({val:?})"), + InsnOut { idx, num_bits } => write!(fmt, "Out{num_bits}({idx})"), + Imm(signed) => write!(fmt, "{signed:x}_i64"), + UImm(unsigned) => write!(fmt, "{unsigned:x}_u64"), + // Say Mem and Reg only once + Mem(mem) => write!(fmt, "{mem:?}"), + Reg(reg) => write!(fmt, "{reg:?}"), + } + } +} + impl Opnd { /// Convenience constructor for memory operands @@ -263,7 +291,7 @@ impl From<CodePtr> for Target { https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L291 } /// YJIT IR instruction -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct Insn { // Opcode for the instruction @@ -286,6 +314,35 @@ pub struct Insn https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L314 pub(super) pos: Option<CodePtr>, } +impl fmt::Debug for Insn { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}(", self.op)?; + + // Print list of operands + let mut opnd_iter = self.opnds.iter(); + if let Some(first_opnd) = opnd_iter.next() { + write!(fmt, "{first_opnd:?}")?; + } + for opnd in opnd_iter { + write!(fmt, ", {opnd:?}")?; + } + write!(fmt, ")")?; + + // Print text, target, and pos if they are present + if let Some(text) = &self.text { + write!(fmt, " {text:?}")? + } + if let Some(target) = self.target { + write!(fmt, " target={target:?}")?; + } + if let Some(pos) = self.pos { + write!(fmt, " pos={pos:?}")?; + } + + write!(fmt, " -> {:?}", self.out) + } +} + /// Object into which we assemble instructions to be /// optimized and lowered pub struct Assembler @@ -687,7 +744,13 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L744 impl fmt::Debug for Assembler { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_list().entries(self.insns.iter()).finish() + write!(fmt, "Assembler\n")?; + + for (idx, insn) in self.insns.iter().enumerate() { + write!(fmt, " {idx:03} {insn:?}\n")?; + } + + Ok(()) } } -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/