Skip to content

Commit

Permalink
Cranelift: Add instructions for getting the current stack/frame point…
Browse files Browse the repository at this point in the history
…ers and return address

This is the initial part of bytecodealliance#4535
  • Loading branch information
fitzgen committed Aug 2, 2022
1 parent c77bec4 commit 9cd12ca
Show file tree
Hide file tree
Showing 28 changed files with 485 additions and 24 deletions.
26 changes: 26 additions & 0 deletions cranelift/codegen/meta/src/shared/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,32 @@ pub(crate) fn define(
.other_side_effects(true),
);

ig.push(Inst::new(
"get_frame_pointer",
r#"
Get the address in the frame pointer register.
Usage of this instruction requires setting `preserve_frame_pointers` to `true`.
"#,
&formats.nullary
).operands_out(vec![addr]));

ig.push(Inst::new(
"get_stack_pointer",
r#"
Get the address in the stack pointer register.
"#,
&formats.nullary
).operands_out(vec![addr]));

ig.push(Inst::new(
"get_return_address",
r#"
Get the PC where this function will transfer control to when it returns.
"#,
&formats.nullary
).operands_out(vec![addr]));

let TableOffset = &TypeVar::new(
"TableOffset",
"An unsigned table offset",
Expand Down
34 changes: 34 additions & 0 deletions cranelift/codegen/src/isa/aarch64/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@
(rd WritableReg)
(rm Reg))

;; Like `Move` but with a particular `PReg` source (for implementing CLIF
;; instructions like `get_stack_pointer`).
(MovPReg
(rd WritableReg)
(rm PReg))

;; A MOV[Z,N,K] with a 16-bit immediate.
(MovWide
(op MoveWideOp)
Expand Down Expand Up @@ -2426,3 +2432,31 @@
;; And finally, copy the preordained AtomicCASLoop output reg to its destination.
;; Also, x24 and x28 are trashed.
(mov64_from_real 27)))

;; Helper for emitting `MInst.MovPReg` instructions.
(decl mov_preg (PReg) Reg)
(rule (mov_preg src)
(let ((dst WritableReg (temp_writable_reg $I64))
(_ Unit (emit (MInst.MovPReg dst src))))
dst))

(decl preg_sp () PReg)
(extern constructor preg_sp preg_sp)

(decl preg_fp () PReg)
(extern constructor preg_fp preg_fp)

(decl preg_link () PReg)
(extern constructor preg_link preg_link)

(decl aarch64_sp () Reg)
(rule (aarch64_sp)
(mov_preg (preg_sp)))

(decl aarch64_fp () Reg)
(rule (aarch64_fp)
(mov_preg (preg_fp)))

(decl aarch64_link () Reg)
(rule (aarch64_link)
(mov_preg (preg_link)))
9 changes: 9 additions & 0 deletions cranelift/codegen/src/isa/aarch64/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,15 @@ impl MachInstEmit for Inst {
}
}
}
&Inst::MovPReg { rd, rm } => {
let rd = allocs.next_writable(rd);
let rm: Reg = rm.into();
debug_assert!([regs::fp_reg(), regs::stack_reg(), regs::link_reg()].contains(&rm));
assert!(rm.class() == RegClass::Int);
assert!(rd.to_reg().class() == rm.class());
let size = OperandSize::Size64;
Inst::Mov { size, rd, rm }.emit(&[], sink, emit_info, state);
}
&Inst::MovWide { op, rd, imm, size } => {
let rd = allocs.next_writable(rd);
sink.put4(enc_move_wide(op, rd, imm, size));
Expand Down
12 changes: 12 additions & 0 deletions cranelift/codegen/src/isa/aarch64/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,13 @@ fn aarch64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut Operan
collector.reg_def(rd);
collector.reg_use(rm);
}
&Inst::MovPReg { rd, rm } => {
debug_assert!(
[regs::fp_reg(), regs::stack_reg(), regs::link_reg()].contains(&rm.into())
);
debug_assert!(rd.to_reg().is_virtual());
collector.reg_def(rd);
}
&Inst::MovWide { op, rd, .. } => match op {
MoveWideOp::MovK => collector.reg_mod(rd),
_ => collector.reg_def(rd),
Expand Down Expand Up @@ -1482,6 +1489,11 @@ impl Inst {
let rm = pretty_print_ireg(rm, size, allocs);
format!("mov {}, {}", rd, rm)
}
&Inst::MovPReg { rd, rm } => {
let rd = pretty_print_ireg(rd.to_reg(), OperandSize::Size64, allocs);
let rm = show_ireg_sized(rm.into(), OperandSize::Size64);
format!("mov {}, {}", rd, rm)
}
&Inst::MovWide {
op,
rd,
Expand Down
12 changes: 12 additions & 0 deletions cranelift/codegen/src/isa/aarch64/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,7 @@


;;;; Rules for `uunarrow` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type (ty_vec128_int ty) (uunarrow x y)))
(if (zero_value y))
(uqxtn x (lane_size ty)))
Expand Down Expand Up @@ -1723,3 +1724,14 @@

(rule (lower (debugtrap))
(side_effect (brk)))

;;; Rules for `get_{frame,stack}_pointer` and `get_return_address` ;;;;;;;;;;;;;

(rule (lower (get_frame_pointer))
(aarch64_fp))

(rule (lower (get_stack_pointer))
(aarch64_sp))

(rule (lower (get_return_address))
(aarch64_link))
13 changes: 13 additions & 0 deletions cranelift/codegen/src/isa/aarch64/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::{
isa::unwind::UnwindInst,
machinst::{ty_bits, InsnOutput, LowerCtx, VCodeConstant, VCodeConstantData},
};
use regalloc2::PReg;
use std::boxed::Box;
use std::convert::TryFrom;
use std::vec::Vec;
Expand Down Expand Up @@ -466,4 +467,16 @@ where

rd.to_reg()
}

fn preg_sp(&mut self) -> PReg {
super::regs::stack_reg().to_real_reg().unwrap().into()
}

fn preg_fp(&mut self) -> PReg {
super::regs::fp_reg().to_real_reg().unwrap().into()
}

fn preg_link(&mut self) -> PReg {
super::regs::link_reg().to_real_reg().unwrap().into()
}
}
4 changes: 4 additions & 0 deletions cranelift/codegen/src/isa/aarch64/lower_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
point, as constants are rematerialized at use-sites"
),

Opcode::GetFramePointer | Opcode::GetStackPointer | Opcode::GetReturnAddress => {
implemented_in_isle(ctx)
}

Opcode::Iadd => implemented_in_isle(ctx),
Opcode::Isub => implemented_in_isle(ctx),
Opcode::UaddSat | Opcode::SaddSat | Opcode::UsubSat | Opcode::SsubSat => {
Expand Down
25 changes: 25 additions & 0 deletions cranelift/codegen/src/isa/s390x/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,11 @@
(rd WritableReg)
(rm Reg))

;; Like `Mov64` but with a particular physical register source.
(MovPReg
(rd WritableReg)
(rm PReg))

;; A 32-bit move instruction with a full 32-bit immediate.
(Mov32Imm
(rd WritableReg)
Expand Down Expand Up @@ -2473,6 +2478,26 @@
(rule (emit_load $I64 dst addr)
(emit (MInst.Load64 dst addr)))

;; Helper for creating `MInst.MovPReg` instructions.
(decl mov_preg (PReg) Reg)
(rule (mov_preg src)
(let ((dst WritableReg (temp_writable_reg $I64))
(_ Unit (emit (MInst.MovPReg dst src))))
dst))

(decl preg_r14 () PReg)
(extern constructor preg_r14 preg_r14)

(decl preg_r15 () PReg)
(extern constructor preg_r15 preg_r15)

(decl r14 () Reg)
(rule (r14)
(mov_preg (preg_r14)))

(decl r15 () Reg)
(rule (r15)
(mov_preg (preg_r15)))

;; Helpers for accessing argument / return value slots ;;;;;;;;;;;;;;;;;;;;;;;;;

Expand Down
6 changes: 6 additions & 0 deletions cranelift/codegen/src/isa/s390x/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,12 @@ impl MachInstEmit for Inst {
let opcode = 0xb904; // LGR
put(sink, &enc_rre(opcode, rd.to_reg(), rm));
}
&Inst::MovPReg { rd, rm } => {
let rm: Reg = rm.into();
debug_assert!([regs::gpr(14), regs::gpr(15)].contains(&rm));
let rd = allocs.next_writable(rd);
Inst::Mov64 { rd, rm }.emit(&[], sink, emit_info, state);
}
&Inst::Mov32 { rd, rm } => {
let rd = allocs.next_writable(rd);
let rm = allocs.next(rm);
Expand Down
11 changes: 11 additions & 0 deletions cranelift/codegen/src/isa/s390x/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ impl Inst {
| Inst::StoreMultiple64 { .. }
| Inst::Mov32 { .. }
| Inst::Mov64 { .. }
| Inst::MovPReg { .. }
| Inst::Mov32Imm { .. }
| Inst::Mov32SImm16 { .. }
| Inst::Mov64SImm16 { .. }
Expand Down Expand Up @@ -624,6 +625,11 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
collector.reg_def(rd);
collector.reg_use(rm);
}
&Inst::MovPReg { rd, rm } => {
debug_assert!([regs::gpr(14), regs::gpr(15)].contains(&rm.into()));
debug_assert!(rd.to_reg().is_virtual());
collector.reg_def(rd);
}
&Inst::Mov32 { rd, rm } => {
collector.reg_def(rd);
collector.reg_use(rm);
Expand Down Expand Up @@ -1787,6 +1793,11 @@ impl Inst {
let rm = pretty_print_reg(rm, allocs);
format!("lgr {}, {}", rd, rm)
}
&Inst::MovPReg { rd, rm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
let rm = show_reg(rm.into());
format!("lgr {}, {}", rd, rm)
}
&Inst::Mov32 { rd, rm } => {
let rd = pretty_print_reg(rd.to_reg(), allocs);
let rm = pretty_print_reg(rm, allocs);
Expand Down
10 changes: 10 additions & 0 deletions cranelift/codegen/src/isa/s390x/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -3619,3 +3619,13 @@
(_ Unit (output_builder_push builder ret)))
(lower_call_rets abi tail builder)))

;;;; Rules for `get_{frame,stack}_pointer` and `get_return_address` ;;;;;;;;;;;;

(rule (lower (get_stack_pointer))
(r15))

(rule (lower (get_frame_pointer))
(load64 (memarg_stack_off 0 0)))

(rule (lower (get_return_address))
(r14))
5 changes: 4 additions & 1 deletion cranelift/codegen/src/isa/s390x/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ impl LowerBackend for S390xBackend {
| Opcode::Return
| Opcode::StackAddr
| Opcode::FuncAddr
| Opcode::SymbolValue => {
| Opcode::SymbolValue
| Opcode::GetFramePointer
| Opcode::GetStackPointer
| Opcode::GetReturnAddress => {
unreachable!(
"implemented in ISLE: inst = `{}`, type = `{:?}`",
ctx.dfg().display_inst(ir_inst),
Expand Down
15 changes: 13 additions & 2 deletions cranelift/codegen/src/isa/s390x/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pub mod generated_code;
// Types that the generated ISLE code uses via `use super::*`.
use crate::isa::s390x::abi::S390xMachineDeps;
use crate::isa::s390x::inst::{
stack_reg, writable_gpr, zero_reg, CallIndInfo, CallInfo, Cond, Inst as MInst, MemArg, UImm12,
UImm16Shifted, UImm32Shifted,
regs, stack_reg, writable_gpr, zero_reg, CallIndInfo, CallInfo, Cond, Inst as MInst, MemArg,
UImm12, UImm16Shifted, UImm32Shifted,
};
use crate::isa::s390x::settings::Flags as IsaFlags;
use crate::machinst::isle::*;
Expand All @@ -21,6 +21,7 @@ use crate::{
isa::unwind::UnwindInst,
machinst::{InsnOutput, LowerCtx, VCodeConstant, VCodeConstantData},
};
use regalloc2::PReg;
use std::boxed::Box;
use std::cell::Cell;
use std::convert::TryFrom;
Expand Down Expand Up @@ -670,6 +671,16 @@ where
fn emit(&mut self, inst: &MInst) -> Unit {
self.lower_ctx.emit(inst.clone());
}

#[inline]
fn preg_r14(&mut self) -> PReg {
regs::gpr(14).to_real_reg().unwrap().into()
}

#[inline]
fn preg_r15(&mut self) -> PReg {
stack_reg().to_real_reg().unwrap().into()
}
}

/// Zero-extend the low `from_bits` bits of `value` to a full u64.
Expand Down
Loading

0 comments on commit 9cd12ca

Please sign in to comment.