From 35a07613553471bd553a2f9e57a84c97c18b3072 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Nov 2024 15:35:01 -0800 Subject: [PATCH] pulley: Implement `get_frame_pointer` This commit implements the CLIF `get_frame_pointer` instruction which will be needed by trampolines in Wasmtime. This is implemented by generalizing the preexisting `GetSp` `MInst` into a "get special". This the additionally removes the extended `get_sp` opcode in Pulley as it's not necessary as `xmov` can operate on this register. --- .../codegen/src/isa/pulley_shared/inst.isle | 23 ++++-- .../src/isa/pulley_shared/inst/emit.rs | 2 +- .../codegen/src/isa/pulley_shared/inst/mod.rs | 11 ++- .../codegen/src/isa/pulley_shared/lower.isle | 7 +- .../src/isa/pulley_shared/lower/isle.rs | 9 +++ .../isa/pulley32/get_stack_pointer.clif | 18 ----- .../filetests/isa/pulley32/special_regs.clif | 70 +++++++++++++++++++ .../isa/pulley64/get_stack_pointer.clif | 18 ----- .../filetests/isa/pulley64/special_regs.clif | 70 +++++++++++++++++++ pulley/fuzz/src/interp.rs | 1 - pulley/src/interp.rs | 6 -- pulley/src/lib.rs | 3 - 12 files changed, 180 insertions(+), 58 deletions(-) delete mode 100644 cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif create mode 100644 cranelift/filetests/filetests/isa/pulley32/special_regs.clif delete mode 100644 cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif create mode 100644 cranelift/filetests/filetests/isa/pulley64/special_regs.clif diff --git a/cranelift/codegen/src/isa/pulley_shared/inst.isle b/cranelift/codegen/src/isa/pulley_shared/inst.isle index bdce4929d95e..5326f193b162 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst.isle +++ b/cranelift/codegen/src/isa/pulley_shared/inst.isle @@ -32,8 +32,11 @@ ;; Nothing. (Nop) - ;; Get the stack pointer. - (GetSp (dst WritableXReg)) + ;; Move a special register (e.g. sp, fp, lr, etc) in to a general-purpose + ;; register + (GetSpecial + (dst WritableXReg) + (reg XReg)) ;; Return. (Ret) @@ -367,11 +370,17 @@ (rule (pulley_trap_if cond size src1 src2 code) (SideEffectNoResult.Inst (MInst.TrapIf cond size src1 src2 code))) -(decl pulley_get_sp () XReg) -(rule (pulley_get_sp) - (let ((reg WritableXReg (temp_writable_xreg)) - (_ Unit (emit (MInst.GetSp reg)))) - reg)) +(decl sp_reg () XReg) +(extern constructor sp_reg sp_reg) + +(decl fp_reg () XReg) +(extern constructor fp_reg fp_reg) + +(decl pulley_get_special (XReg) XReg) +(rule (pulley_get_special reg) + (let ((dst WritableXReg (temp_writable_xreg)) + (_ Unit (emit (MInst.GetSpecial dst reg)))) + dst)) (decl pulley_xconst8 (i8) XReg) (rule (pulley_xconst8 x) diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs index 3772c127955b..4552a624e5c0 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/emit.rs @@ -188,7 +188,7 @@ fn pulley_emit

( Inst::Nop => todo!(), - Inst::GetSp { dst } => enc::get_sp(sink, dst), + Inst::GetSpecial { dst, reg } => enc::xmov(sink, dst, reg), Inst::Ret => enc::ret(sink), diff --git a/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs b/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs index 0e8d3f346ce4..06034170efd8 100644 --- a/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs +++ b/cranelift/codegen/src/isa/pulley_shared/inst/mod.rs @@ -79,8 +79,12 @@ fn pulley_get_operands(inst: &mut Inst, collector: &mut impl OperandVisitor) { collector.reg_use(src2); } - Inst::GetSp { dst } => { + Inst::GetSpecial { dst, reg } => { collector.reg_def(dst); + // Note that this is explicitly ignored as this is only used for + // special register that don't participate in register allocation + // such as the stack pointer, frame pointer, etc. + let _ = reg; } Inst::LoadExtName { @@ -563,9 +567,10 @@ impl Inst { Inst::Ret => format!("ret"), - Inst::GetSp { dst } => { + Inst::GetSpecial { dst, reg } => { let dst = format_reg(*dst.to_reg()); - format!("{dst} = get_sp") + let reg = format_reg(**reg); + format!("xmov {dst}, {reg}") } Inst::LoadExtName { dst, name, offset } => { diff --git a/cranelift/codegen/src/isa/pulley_shared/lower.isle b/cranelift/codegen/src/isa/pulley_shared/lower.isle index 5659ccca3887..60471df1f979 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower.isle +++ b/cranelift/codegen/src/isa/pulley_shared/lower.isle @@ -116,7 +116,12 @@ ;;;; Rules for `get_stack_pointer` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule (lower (get_stack_pointer)) - (pulley_get_sp)) + (pulley_get_special (sp_reg))) + +;;;; Rules for `get_frame_pointer` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(rule (lower (get_frame_pointer)) + (pulley_get_special (fp_reg))) ;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs index e1c57bd73bc1..bf96f08eb1c3 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs +++ b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs @@ -10,6 +10,7 @@ use crate::ir::{condcodes::*, immediates::*, types::*, *}; use crate::isa::pulley_shared::{ abi::*, inst::{FReg, OperandSize, VReg, WritableFReg, WritableVReg, WritableXReg, XReg}, + lower::regs, *, }; use crate::machinst::{ @@ -105,6 +106,14 @@ where fn emit(&mut self, arg0: &MInst) -> Unit { self.lower_ctx.emit(arg0.clone().into()); } + + fn sp_reg(&mut self) -> XReg { + XReg::new(regs::stack_reg()).unwrap() + } + + fn fp_reg(&mut self) -> XReg { + XReg::new(regs::fp_reg()).unwrap() + } } /// The main entry point for lowering with ISLE. diff --git a/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif b/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif deleted file mode 100644 index f269efa92e36..000000000000 --- a/cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif +++ /dev/null @@ -1,18 +0,0 @@ -test compile precise-output -target pulley32 - -function %get_stack_pointer() -> i32 { -block0: - v0 = get_stack_pointer.i32 - return v0 -} - -; VCode: -; block0: -; x0 = get_sp -; ret -; -; Disassembled: -; get_sp x0 -; ret - diff --git a/cranelift/filetests/filetests/isa/pulley32/special_regs.clif b/cranelift/filetests/filetests/isa/pulley32/special_regs.clif new file mode 100644 index 000000000000..d46e04c741f5 --- /dev/null +++ b/cranelift/filetests/filetests/isa/pulley32/special_regs.clif @@ -0,0 +1,70 @@ +test compile precise-output +set preserve_frame_pointers +target pulley32 + +function %get_stack_pointer() -> i32 { +block0: + v0 = get_stack_pointer.i32 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x27 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, sp +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + +function %get_frame_pointer() -> i32 { +block0: + v0 = get_frame_pointer.i32 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x29 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, fp +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + diff --git a/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif b/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif deleted file mode 100644 index e3df1187e779..000000000000 --- a/cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif +++ /dev/null @@ -1,18 +0,0 @@ -test compile precise-output -target pulley64 - -function %get_stack_pointer() -> i64 { -block0: - v0 = get_stack_pointer.i64 - return v0 -} - -; VCode: -; block0: -; x0 = get_sp -; ret -; -; Disassembled: -; get_sp x0 -; ret - diff --git a/cranelift/filetests/filetests/isa/pulley64/special_regs.clif b/cranelift/filetests/filetests/isa/pulley64/special_regs.clif new file mode 100644 index 000000000000..ad0dcac017b5 --- /dev/null +++ b/cranelift/filetests/filetests/isa/pulley64/special_regs.clif @@ -0,0 +1,70 @@ +test compile precise-output +set preserve_frame_pointers +target pulley64 + +function %get_stack_pointer() -> i64 { +block0: + v0 = get_stack_pointer.i64 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x27 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, sp +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + +function %get_frame_pointer() -> i64 { +block0: + v0 = get_frame_pointer.i64 + return v0 +} + +; VCode: +; x30 = xconst8 -16 +; x27 = xadd32 x27, x30 +; store64 sp+8, x28 // flags = notrap aligned +; store64 sp+0, x29 // flags = notrap aligned +; x29 = xmov x27 +; block0: +; xmov x0, x29 +; x28 = load64_u sp+8 // flags = notrap aligned +; x29 = load64_u sp+0 // flags = notrap aligned +; x30 = xconst8 16 +; x27 = xadd32 x27, x30 +; ret +; +; Disassembled: +; xconst8 spilltmp0, -16 +; xadd32 sp, sp, spilltmp0 +; store64_offset8 sp, 8, lr +; store64 sp, fp +; xmov fp, sp +; xmov x0, fp +; load64_offset8 lr, sp, 8 +; load64 fp, sp +; xconst8 spilltmp0, 16 +; xadd32 sp, sp, spilltmp0 +; ret + diff --git a/pulley/fuzz/src/interp.rs b/pulley/fuzz/src/interp.rs index 5fd70b082c16..0925cb27f35d 100644 --- a/pulley/fuzz/src/interp.rs +++ b/pulley/fuzz/src/interp.rs @@ -123,6 +123,5 @@ fn extended_op_is_safe_for_fuzzing(op: &ExtendedOp) -> bool { match op { ExtendedOp::Trap(_) => true, ExtendedOp::Nop(_) => true, - ExtendedOp::GetSp(GetSp { dst, .. }) => !dst.is_special(), } } diff --git a/pulley/src/interp.rs b/pulley/src/interp.rs index c0817f454144..702af4d7e40e 100644 --- a/pulley/src/interp.rs +++ b/pulley/src/interp.rs @@ -1171,10 +1171,4 @@ impl ExtendedOpVisitor for Interpreter<'_> { fn trap(&mut self) -> ControlFlow { ControlFlow::Break(Done::Trap(self.pc.as_ptr())) } - - fn get_sp(&mut self, dst: XReg) -> ControlFlow { - let sp = self.state[XReg::sp].get_u64(); - self.state[dst].set_u64(sp); - ControlFlow::Continue(()) - } } diff --git a/pulley/src/lib.rs b/pulley/src/lib.rs index b80a5646ec9b..8c21fe224ffc 100644 --- a/pulley/src/lib.rs +++ b/pulley/src/lib.rs @@ -189,9 +189,6 @@ macro_rules! for_each_extended_op { /// Do nothing. nop = Nop; - - /// Copy the special `sp` stack pointer register into an `x` register. - get_sp = GetSp { dst: XReg }; } }; }