summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2022-05-24 16:30:18 -0400
committerTakashi Kokubun <takashikkbn@gmail.com>2022-08-29 08:46:54 -0700
commitefb45acb2932dd8ebd60853584370ca75653cdf8 (patch)
tree18cc71f5d7c20dee3965c8a3776113b6eb402b7a
parenta88fc48b3a61b63aa1c2f4b05981e0d8726e2b9e (diff)
Load GC Value operands into registers
-rw-r--r--yjit/src/backend/ir.rs32
1 files changed, 31 insertions, 1 deletions
diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index 9ed8f34c3e..63a0478984 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -219,7 +219,7 @@ pub enum Opnd
impl Opnd
{
- // Convenience constructor for memory operands
+ /// Convenience constructor for memory operands
pub fn mem(num_bits: u8, base: Opnd, disp: i32) -> Self {
match base {
Opnd::Reg(base_reg) => {
@@ -233,6 +233,11 @@ impl Opnd
_ => unreachable!()
}
}
+
+ /// Constant pointer operand
+ pub fn const_ptr(ptr: *const u8) -> Self {
+ Opnd::UImm(ptr as u64)
+ }
}
/// NOTE: this is useful during the port but can probably be removed once
@@ -436,7 +441,32 @@ impl Assembler
/// can.
pub(super) fn split_loads(self) -> Assembler
{
+ // Load operands that are GC values into a register
+ fn load_gc_opnds(op: Op, opnds: Vec<Opnd>, asm: &mut Assembler) -> Vec<Opnd>
+ {
+ if op == Op::Load || op == Op::Mov {
+ return opnds;
+ }
+
+ fn map_opnd(opnd: Opnd, asm: &mut Assembler) -> Opnd {
+ if let Opnd::Value(val) = opnd {
+ // If this is a heap object, load it into a register
+ if !val.special_const_p() {
+ asm.load(opnd);
+ }
+ }
+
+ opnd
+ }
+
+ opnds.into_iter().map(|opnd| map_opnd(opnd, asm)).collect()
+ }
+
self.transform_insns(|asm, _, op, opnds, target| {
+ // Load heap object operands into registers because most
+ // instructions can't directly work with 64-bit constants
+ let opnds = load_gc_opnds(op, opnds, asm);
+
match op {
// Check for Add, Sub, And, Mov, with two memory operands.
// Load one operand into memory.