[前][次][番号順一覧][スレッド一覧]

ruby-changes:73289

From: Kevin <ko1@a...>
Date: Tue, 30 Aug 2022 01:07:56 +0900 (JST)
Subject: [ruby-changes:73289] b735eb5ef3 (master): Instruction builders for backend IR (https://github.com/Shopify/ruby/pull/410)

https://git.ruby-lang.org/ruby.git/commit/?id=b735eb5ef3

From b735eb5ef39e73e2a0ea6bbdb6ff7ce41a998d63 Mon Sep 17 00:00:00 2001
From: Kevin Newton <kddnewton@g...>
Date: Wed, 17 Aug 2022 12:56:23 -0400
Subject: Instruction builders for backend IR
 (https://github.com/Shopify/ruby/pull/410)

Currently we use macros to define the shape of each of the
instruction building methods. This works while all of the
instructions share the same fields, but is really hard to get
working when they're an enum with different shapes. This is an
incremental step toward a bigger refactor of changing the Insn
from a struct to an enum.
---
 yjit/src/backend/arm64/mod.rs  |  10 +-
 yjit/src/backend/ir.rs         | 425 +++++++++++++++++++++++------------------
 yjit/src/backend/x86_64/mod.rs |   8 +-
 3 files changed, 246 insertions(+), 197 deletions(-)

diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs
index d92b4778e3..d2693fee32 100644
--- a/yjit/src/backend/arm64/mod.rs
+++ b/yjit/src/backend/arm64/mod.rs
@@ -228,17 +228,17 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L228
                 Op::And | Op::Or | Op::Xor => {
                     match (opnds[0], opnds[1]) {
                         (Opnd::Reg(_), Opnd::Reg(_)) => {
-                            asm.push_insn(insn.op, vec![opnds[0], opnds[1]], insn.target, insn.text, insn.pos_marker);
+                            asm.push_insn_parts(insn.op, vec![opnds[0], opnds[1]], insn.target, insn.text, insn.pos_marker);
                         },
                         (reg_opnd @ Opnd::Reg(_), other_opnd) |
                         (other_opnd, reg_opnd @ Opnd::Reg(_)) => {
                             let opnd1 = split_bitmask_immediate(asm, other_opnd);
-                            asm.push_insn(insn.op, vec![reg_opnd, opnd1], insn.target, insn.text, insn.pos_marker);
+                            asm.push_insn_parts(insn.op, vec![reg_opnd, opnd1], insn.target, insn.text, insn.pos_marker);
                         },
                         _ => {
                             let opnd0 = split_load_operand(asm, opnds[0]);
                             let opnd1 = split_bitmask_immediate(asm, opnds[1]);
-                            asm.push_insn(insn.op, vec![opnd0, opnd1], insn.target, insn.text, insn.pos_marker);
+                            asm.push_insn_parts(insn.op, vec![opnd0, opnd1], insn.target, insn.text, insn.pos_marker);
                         }
                     }
                 },
@@ -284,7 +284,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L284
                         }
                     }).collect();
 
-                    asm.push_insn(insn.op, new_opnds, insn.target, insn.text, insn.pos_marker);
+                    asm.push_insn_parts(insn.op, new_opnds, insn.target, insn.text, insn.pos_marker);
                 },
                 Op::IncrCounter => {
                     // We'll use LDADD later which only works with registers
@@ -403,7 +403,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L403
                     asm.test(opnd0, opnd1);
                 },
                 _ => {
-                    asm.push_insn(insn.op, opnds, insn.target, insn.text, insn.pos_marker);
+                    asm.push_insn_parts(insn.op, opnds, insn.target, insn.text, insn.pos_marker);
                 }
             };
 
diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index 952c8f7f10..481d447c5c 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -466,23 +466,15 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L466
         }
     }
 
-    /// Append an instruction to the list
-    pub(super) fn push_insn(
-        &mut self,
-        op: Op,
-        opnds: Vec<Opnd>,
-        target: Option<Target>,
-        text: Option<String>,
-        pos_marker: Option<PosMarkerFn>
-    ) -> Opnd
-    {
+    /// Append an instruction onto the current list of instructions.
+    pub(super) fn push_insn(&mut self, mut insn: Insn) -> Opnd {
         // Index of this instruction
         let insn_idx = self.insns.len();
 
         // If we find any InsnOut from previous instructions, we're going to
         // update the live range of the previous instruction to point to this
         // one.
-        for opnd in &opnds {
+        for opnd in &insn.opnds {
             match opnd {
                 Opnd::InsnOut{ idx, .. } => {
                     self.live_ranges[*idx] = insn_idx;
@@ -496,7 +488,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L488
 
         let mut out_num_bits: u8 = 0;
 
-        for opnd in &opnds {
+        for opnd in &insn.opnds {
             match *opnd {
                 Opnd::InsnOut{ num_bits, .. } |
                 Opnd::Mem(Mem { num_bits, .. }) |
@@ -518,15 +510,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L510
 
         // Operand for the output of this instruction
         let out_opnd = Opnd::InsnOut{ idx: insn_idx, num_bits: out_num_bits };
-
-        let insn = Insn {
-            op,
-            text,
-            opnds,
-            out: out_opnd,
-            target,
-            pos_marker,
-        };
+        insn.out = out_opnd;
 
         self.insns.push(insn);
         self.live_ranges.push(insn_idx);
@@ -535,40 +519,25 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L519
         out_opnd
     }
 
-    /// Add a comment at the current position
-    pub fn comment(&mut self, text: &str)
-    {
-        let insn = Insn {
-            op: Op::Comment,
-            text: Some(text.to_owned()),
-            opnds: vec![],
-            out: Opnd::None,
-            target: None,
-            pos_marker: None,
-        };
-        self.insns.push(insn);
-        self.live_ranges.push(self.insns.len());
-    }
-
-    /// Bake a string at the current position
-    pub fn bake_string(&mut self, text: &str)
+    /// Append an instruction to the list by creating a new instruction from the
+    /// component parts given to this function.
+    pub(super) fn push_insn_parts(
+        &mut self,
+        op: Op,
+        opnds: Vec<Opnd>,
+        target: Option<Target>,
+        text: Option<String>,
+        pos_marker: Option<PosMarkerFn>
+    ) -> Opnd
     {
-        let insn = Insn {
-            op: Op::BakeString,
-            text: Some(text.to_owned()),
-            opnds: vec![],
+        self.push_insn(Insn {
+            op,
+            text,
+            opnds,
             out: Opnd::None,
-            target: None,
-            pos_marker: None,
-        };
-        self.insns.push(insn);
-        self.live_ranges.push(self.insns.len());
-    }
-
-    /// Load an address relative to the given label.
-    #[must_use]
-    pub fn lea_label(&mut self, target: Target) -> Opnd {
-        self.push_insn(Op::LeaLabel, vec![], Some(target), None, None)
+            target,
+            pos_marker,
+        })
     }
 
     /// Create a new label instance that we can jump to
@@ -735,7 +704,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L704
                 }
             ).collect();
 
-            asm.push_insn(insn.op, reg_opnds, insn.target, insn.text, insn.pos_marker);
+            asm.push_insn_parts(insn.op, reg_opnds, insn.target, insn.text, insn.pos_marker);
 
             // Set the output register for this instruction
             let num_insns = asm.insns.len();
@@ -777,16 +746,6 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L746
     pub fn into_lookback_iter(self) -> AssemblerLookbackIterator {
         AssemblerLookbackIterator::new(self)
     }
-
-    pub fn ccall(&mut self, fptr: *const u8, opnds: Vec<Opnd>) -> Opnd {
-        let target = Target::FunPtr(fptr);
-        self.push_insn(Op::CCall, opnds, Some(target), None, None)
-    }
-
-    // pub fn pos_marker<F: FnMut(CodePtr)>(&mut self, marker_fn: F)
-    pub fn pos_marker(&mut self, marker_fn: impl Fn(CodePtr) + 'static) {
-        self.push_insn(Op::PosMarker, vec![], None, None, Some(Box::new(marker_fn)));
-    }
 }
 
 /// A struct that allows iterating through an assembler's instructions and
@@ -898,134 +857,224 @@ impl fmt::Debug for Assembler { https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L857
     }
 }
 
-macro_rules! def_push_jcc {
-    ($op_name:ident, $opcode:expr) => {
-        impl Assembler
-        {
-            pub fn $op_name(&mut self, target: Target)
-            {
-                self.push_insn($opcode, vec![], Some(target), None, None);
-            }
-        }
-    };
-}
+impl Assembler {
+    #[must_use]
+    pub fn add(&mut self, left: Opnd, right: Opnd) -> Opnd {
+        self.push_insn(Insn { op: Op::Add, opnds: vec![left, right], out: Opnd::None, text: None, target: None, pos_marker: None })
+    }
 
-macro_rules! def_push_0_opnd {
-    ($op_name:ident, $opcode:expr) => {
-        impl Assembler
-        {
-            #[must_use]
-            pub fn $op_name(&mut self) -> Opnd
-            {
-                self.push_insn($opcode, vec![], None, None, None)
-            }
-        }
-    };
-}
+    #[must_use]
+    pub fn and(&mut self, left: Opnd, right: Opnd) -> Opnd {
+        self.push_insn(Insn { op: Op::And, opnds: vec![left, right], out: Opnd::None, text: None, target: None, pos_marker: None })
+    }
 
-macro_rules! def_push_0_opnd_no_out {
-    ($op_name:ident, $opcode:expr) => {
-        impl Assembler
-        {
-            pub fn $op_name(&mut self)
-            {
-                self.push_insn($opcode, vec![], None, None, None);
-            }
-        }
-    };
-}
+    pub fn bake_string(&mut self, text: &str) {
+        self.push_insn(Insn { op: Op::BakeString, opnds: vec![], out: Opnd::None, text: Some(text.to_string()), target: None, pos_marker: None });
+     (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]