Skip to content

Commit

Permalink
pulley: Implement get_frame_pointer
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed Nov 26, 2024
1 parent 8e8ad73 commit 93a7c06
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 57 deletions.
23 changes: 16 additions & 7 deletions cranelift/codegen/src/isa/pulley_shared/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -371,11 +374,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)
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/pulley_shared/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ fn pulley_emit<P>(

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),

Expand Down
11 changes: 8 additions & 3 deletions cranelift/codegen/src/isa/pulley_shared/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 } => {
Expand Down
7 changes: 6 additions & 1 deletion cranelift/codegen/src/isa/pulley_shared/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -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` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Expand Down
9 changes: 9 additions & 0 deletions cranelift/codegen/src/isa/pulley_shared/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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.
Expand Down
18 changes: 0 additions & 18 deletions cranelift/filetests/filetests/isa/pulley32/get_stack_pointer.clif

This file was deleted.

70 changes: 70 additions & 0 deletions cranelift/filetests/filetests/isa/pulley32/special_regs.clif
Original file line number Diff line number Diff line change
@@ -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

18 changes: 0 additions & 18 deletions cranelift/filetests/filetests/isa/pulley64/get_stack_pointer.clif

This file was deleted.

70 changes: 70 additions & 0 deletions cranelift/filetests/filetests/isa/pulley64/special_regs.clif
Original file line number Diff line number Diff line change
@@ -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

1 change: 0 additions & 1 deletion pulley/fuzz/src/interp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ 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(),
ExtendedOp::CallIndirectHost(_) => false,
}
}
6 changes: 0 additions & 6 deletions pulley/src/interp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1239,12 +1239,6 @@ impl ExtendedOpVisitor for Interpreter<'_> {
ControlFlow::Break(Done::Trap(self.pc.as_ptr()))
}

fn get_sp(&mut self, dst: XReg) -> ControlFlow<Done> {
let sp = self.state[XReg::sp].get_u64();
self.state[dst].set_u64(sp);
ControlFlow::Continue(())
}

/// This instructions is sort of like a `call` instruction except that it
/// delegates to the host itself. That means that ABI details are baked in
/// here such as where various arguments are.
Expand Down
2 changes: 0 additions & 2 deletions pulley/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,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 };
/// A special opcode to use an indirect function call to reenter the
/// host from the interpreter.
///
Expand Down

0 comments on commit 93a7c06

Please sign in to comment.