Skip to content

Commit

Permalink
AArch64: Migrate calls and returns to ISLE. (#4788)
Browse files Browse the repository at this point in the history
  • Loading branch information
cfallin authored Aug 26, 2022
1 parent ca6d648 commit 8e8dfdf
Show file tree
Hide file tree
Showing 18 changed files with 280 additions and 327 deletions.
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/aarch64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,12 @@ impl ABIMachineSpec for AArch64MachineDeps {
slots: smallvec![
ABIArgSlot::Reg {
reg: lower_reg.to_real_reg().unwrap(),
ty: param.value_type,
ty: reg_types[0],
extension: param.extension,
},
ABIArgSlot::Reg {
reg: upper_reg.to_real_reg().unwrap(),
ty: param.value_type,
ty: reg_types[1],
extension: param.extension,
},
],
Expand Down
8 changes: 8 additions & 0 deletions cranelift/codegen/src/isa/aarch64/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -2818,3 +2818,11 @@
(let ((dst WritableReg (temp_writable_reg $I8X16))
(_ Unit (emit (MInst.IntToFpu op dst src))))
dst))

;;;; Helpers for Emitting Calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(decl gen_call (SigRef ExternalName RelocDistance ValueSlice) InstOutput)
(extern constructor gen_call gen_call)

(decl gen_call_indirect (SigRef Value ValueSlice) InstOutput)
(extern constructor gen_call_indirect gen_call_indirect)
14 changes: 14 additions & 0 deletions cranelift/codegen/src/isa/aarch64/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -2016,3 +2016,17 @@

(rule (lower (get_return_address))
(aarch64_link))

;;;; Rules for calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (call (func_ref_data sig_ref extname dist) inputs))
(gen_call sig_ref extname dist inputs))

(rule (lower (call_indirect sig_ref val inputs))
(gen_call_indirect sig_ref val inputs))

;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; N.B.: the Ret itself is generated by the ABI.
(rule (lower (return args))
(lower_return (range 0 (value_slice_len args)) args))
12 changes: 10 additions & 2 deletions cranelift/codegen/src/isa/aarch64/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// Pull in the ISLE generated code.
pub mod generated_code;
use generated_code::Context;

// Types that the generated ISLE code uses via `use super::*`.
use super::{
Expand All @@ -14,6 +15,7 @@ use super::{
use crate::isa::aarch64::inst::{FPULeftShiftImm, FPURightShiftImm};
use crate::isa::aarch64::lower::{lower_address, lower_splat_const};
use crate::isa::aarch64::settings::Flags as IsaFlags;
use crate::machinst::valueregs;
use crate::machinst::{isle::*, InputSourceInst};
use crate::settings::Flags;
use crate::{
Expand All @@ -22,10 +24,11 @@ use crate::{
immediates::*, types::*, AtomicRmwOp, ExternalName, Inst, InstructionData, MemFlags,
TrapCode, Value, ValueList,
},
isa::aarch64::abi::{AArch64Caller, AArch64MachineDeps},
isa::aarch64::inst::args::{ShiftOp, ShiftOpShiftImm},
isa::aarch64::lower::{writable_vreg, writable_xreg, xreg},
isa::unwind::UnwindInst,
machinst::{ty_bits, InsnOutput, Lower, VCodeConstant, VCodeConstantData},
machinst::{ty_bits, InsnOutput, Lower, MachInst, VCodeConstant, VCodeConstantData},
};
use regalloc2::PReg;
use std::boxed::Box;
Expand Down Expand Up @@ -69,8 +72,13 @@ pub struct SinkableAtomicLoad {
atomic_addr: Value,
}

impl generated_code::Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
impl IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
isle_prelude_method_helpers!(AArch64Caller);
}

impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
isle_prelude_methods!();
isle_prelude_caller_methods!(AArch64MachineDeps, AArch64Caller);

fn sign_return_address_disabled(&mut self) -> Option<()> {
if self.isa_flags.sign_return_address() {
Expand Down
72 changes: 2 additions & 70 deletions cranelift/codegen/src/isa/aarch64/lower_inst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::binemit::CodeOffset;
use crate::ir::types::*;
use crate::ir::Inst as IRInst;
use crate::ir::{InstructionData, Opcode};
use crate::isa::aarch64::abi::*;
use crate::isa::aarch64::inst::*;
use crate::isa::aarch64::settings as aarch64_settings;
use crate::machinst::lower::*;
Expand Down Expand Up @@ -469,29 +468,7 @@ pub(crate) fn lower_insn_to_regs(
}
}

Opcode::Return => {
for (i, input) in inputs.iter().enumerate() {
// N.B.: according to the AArch64 ABI, the top bits of a register
// (above the bits for the value's type) are undefined, so we
// need not extend the return values.
let src_regs = put_input_in_regs(ctx, *input);
let retval_regs = ctx.retval(i);

assert_eq!(src_regs.len(), retval_regs.len());
let ty = ctx.input_ty(insn, i);
let (_, tys) = Inst::rc_for_type(ty)?;

src_regs
.regs()
.iter()
.zip(retval_regs.regs().iter())
.zip(tys.iter())
.for_each(|((&src, &dst), &ty)| {
ctx.emit(Inst::gen_move(dst, src, ty));
});
}
// N.B.: the Ret itself is generated by the ABI.
}
Opcode::Return => implemented_in_isle(ctx),

Opcode::Ifcmp | Opcode::Ffcmp => {
// An Ifcmp/Ffcmp must always be seen as a use of a brif/brff or trueif/trueff
Expand Down Expand Up @@ -577,52 +554,7 @@ pub(crate) fn lower_insn_to_regs(

Opcode::SymbolValue => implemented_in_isle(ctx),

Opcode::Call | Opcode::CallIndirect => {
let caller_conv = ctx.abi().call_conv();
let (mut abi, inputs) = match op {
Opcode::Call => {
let (extname, dist) = ctx.call_target(insn).unwrap();
let extname = extname.clone();
let sig = ctx.call_sig(insn).unwrap();
assert!(inputs.len() == sig.params.len());
assert!(outputs.len() == sig.returns.len());
(
AArch64Caller::from_func(sig, &extname, dist, caller_conv, flags)?,
&inputs[..],
)
}
Opcode::CallIndirect => {
let ptr = put_input_in_reg(ctx, inputs[0], NarrowValueMode::ZeroExtend64);
let sig = ctx.call_sig(insn).unwrap();
assert!(inputs.len() - 1 == sig.params.len());
assert!(outputs.len() == sig.returns.len());
(
AArch64Caller::from_ptr(sig, ptr, op, caller_conv, flags)?,
&inputs[1..],
)
}
_ => unreachable!(),
};

abi.emit_stack_pre_adjust(ctx);
assert!(inputs.len() == abi.num_args());
let mut arg_regs = vec![];
for input in inputs {
arg_regs.push(put_input_in_regs(ctx, *input))
}
for (i, arg_regs) in arg_regs.iter().enumerate() {
abi.emit_copy_regs_to_buffer(ctx, i, *arg_regs);
}
for (i, arg_regs) in arg_regs.iter().enumerate() {
abi.emit_copy_regs_to_arg(ctx, i, *arg_regs);
}
abi.emit_call(ctx);
for (i, output) in outputs.iter().enumerate() {
let retval_regs = get_output_reg(ctx, *output);
abi.emit_copy_retval_to_regs(ctx, i, retval_regs);
}
abi.emit_stack_post_adjust(ctx);
}
Opcode::Call | Opcode::CallIndirect => implemented_in_isle(ctx),

Opcode::GetPinnedReg => {
let rd = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/s390x/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -2940,8 +2940,8 @@
(rule (abi_ext_ty (ArgumentExtension.Sext) _) $I64)

;; Copy a return value to a set of registers.
(decl copy_to_regs (WritableValueRegs Value) Unit)
(rule (copy_to_regs (only_writable_reg reg) val @ (value_type ty))
(decl s390x_copy_to_regs (WritableValueRegs Value) Unit)
(rule (s390x_copy_to_regs (only_writable_reg reg) val @ (value_type ty))
(emit_mov ty reg val))


Expand Down
12 changes: 6 additions & 6 deletions cranelift/codegen/src/isa/s390x/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -4047,13 +4047,13 @@
;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (return args))
(lower_return (range 0 (value_slice_len args)) args))
(s390x_lower_return (range 0 (value_slice_len args)) args))

(decl lower_return (Range ValueSlice) InstOutput)
(rule (lower_return (range_empty) _) (output_none))
(rule (lower_return (range_unwrap head tail) args)
(let ((_ Unit (copy_to_regs (retval head) (value_slice_get args head))))
(lower_return tail args)))
(decl s390x_lower_return (Range ValueSlice) InstOutput)
(rule (s390x_lower_return (range_empty) _) (output_none))
(rule (s390x_lower_return (range_unwrap head tail) args)
(let ((_ Unit (s390x_copy_to_regs (retval head) (value_slice_get args head))))
(s390x_lower_return tail args)))


;;;; Rules for `call` and `call_indirect` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/isa/s390x/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
isa::unwind::UnwindInst,
isa::CallConv,
machinst::abi_impl::ABIMachineSpec,
machinst::{InsnOutput, Lower, VCodeConstant, VCodeConstantData},
machinst::{InsnOutput, Lower, MachInst, VCodeConstant, VCodeConstantData},
};
use regalloc2::PReg;
use smallvec::{smallvec, SmallVec};
Expand Down
25 changes: 0 additions & 25 deletions cranelift/codegen/src/isa/x64/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -1596,31 +1596,6 @@

;;;; Helpers for Emitting Loads ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Generate a move between two registers.
(decl gen_move (Type WritableReg Reg) MInst)
(extern constructor gen_move gen_move)

;; Copy a return value to a set of registers.
(decl copy_to_regs (WritableValueRegs Value) Unit)
(rule (copy_to_regs dsts val @ (value_type ty))
(let ((srcs ValueRegs (put_in_regs val)))
(copy_to_regs_range ty (value_regs_range srcs) dsts srcs)))

;; Helper for `copy_to_regs` that uses a range to index into the reg/value
;; vectors. Fails for the empty range.
(decl copy_to_regs_range (Type Range WritableValueRegs ValueRegs) Unit)

(rule (copy_to_regs_range ty (range_singleton idx) dsts srcs)
(let ((dst WritableReg (writable_regs_get dsts idx))
(src Reg (value_regs_get srcs idx)))
(emit (gen_move ty dst src))))

(rule (copy_to_regs_range ty (range_unwrap head tail) dsts srcs)
(let ((dst WritableReg (writable_regs_get dsts head))
(src Reg (value_regs_get srcs head))
(_ Unit (emit (gen_move ty dst src))))
(copy_to_regs_range ty tail dsts srcs)))

;; Helper for constructing a LoadExtName instruction.
(decl load_ext_name (ExternalName i64) Reg)
(rule (load_ext_name extname offset)
Expand Down
7 changes: 0 additions & 7 deletions cranelift/codegen/src/isa/x64/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -1441,13 +1441,6 @@
(rule (lower (return args))
(lower_return (range 0 (value_slice_len args)) args))

(decl lower_return (Range ValueSlice) InstOutput)
(rule (lower_return (range_empty) _) (output_none))
(rule (lower_return (range_unwrap head tail) args)
(let ((_ Unit (copy_to_regs (retval head) (value_slice_get args head))))
(lower_return tail args)))


;;;; Rules for `icmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (icmp cc a @ (value_type (fits_in_64 ty)) b))
Expand Down
107 changes: 2 additions & 105 deletions cranelift/codegen/src/isa/x64/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub(crate) fn lower_branch(

impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
isle_prelude_methods!();
isle_prelude_caller_methods!(X64ABIMachineSpec, X64Caller);

#[inline]
fn operand_size_of_type_32_64(&mut self, ty: Type) -> OperandSize {
Expand Down Expand Up @@ -708,54 +709,6 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
MachAtomicRmwOp::from(*op)
}

#[inline]
fn gen_move(&mut self, ty: Type, dst: WritableReg, src: Reg) -> MInst {
MInst::gen_move(dst, src, ty)
}

fn gen_call(
&mut self,
sig_ref: SigRef,
extname: ExternalName,
dist: RelocDistance,
args @ (inputs, off): ValueSlice,
) -> InstOutput {
let caller_conv = self.lower_ctx.abi().call_conv();
let sig = &self.lower_ctx.dfg().signatures[sig_ref];
let num_rets = sig.returns.len();
let abi = ABISig::from_func_sig::<X64ABIMachineSpec>(sig, self.flags).unwrap();
let caller = X64Caller::from_func(sig, &extname, dist, caller_conv, self.flags).unwrap();

assert_eq!(
inputs.len(&self.lower_ctx.dfg().value_lists) - off,
sig.params.len()
);

self.gen_call_common(abi, num_rets, caller, args)
}

fn gen_call_indirect(
&mut self,
sig_ref: SigRef,
val: Value,
args @ (inputs, off): ValueSlice,
) -> InstOutput {
let caller_conv = self.lower_ctx.abi().call_conv();
let ptr = self.put_in_reg(val);
let sig = &self.lower_ctx.dfg().signatures[sig_ref];
let num_rets = sig.returns.len();
let abi = ABISig::from_func_sig::<X64ABIMachineSpec>(sig, self.flags).unwrap();
let caller =
X64Caller::from_ptr(sig, ptr, Opcode::CallIndirect, caller_conv, self.flags).unwrap();

assert_eq!(
inputs.len(&self.lower_ctx.dfg().value_lists) - off,
sig.params.len()
);

self.gen_call_common(abi, num_rets, caller, args)
}

#[inline]
fn preg_rbp(&mut self) -> PReg {
regs::rbp().to_real_reg().unwrap().into()
Expand Down Expand Up @@ -1062,63 +1015,7 @@ impl Context for IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
}

impl IsleContext<'_, '_, MInst, Flags, IsaFlags, 6> {
fn abi_arg_slot_regs(&mut self, arg: &ABIArg) -> Option<WritableValueRegs> {
match arg {
&ABIArg::Slots { ref slots, .. } => match slots.len() {
1 => {
let a = self.temp_writable_reg(slots[0].get_type());
Some(WritableValueRegs::one(a))
}
2 => {
let a = self.temp_writable_reg(slots[0].get_type());
let b = self.temp_writable_reg(slots[1].get_type());
Some(WritableValueRegs::two(a, b))
}
_ => panic!("Expected to see one or two slots only from {:?}", arg),
},
_ => None,
}
}

fn gen_call_common(
&mut self,
abi: ABISig,
num_rets: usize,
mut caller: X64Caller,
(inputs, off): ValueSlice,
) -> InstOutput {
caller.emit_stack_pre_adjust(self.lower_ctx);

assert_eq!(
inputs.len(&self.lower_ctx.dfg().value_lists) - off,
abi.num_args()
);
let mut arg_regs = vec![];
for i in 0..abi.num_args() {
let input = inputs
.get(off + i, &self.lower_ctx.dfg().value_lists)
.unwrap();
arg_regs.push(self.lower_ctx.put_value_in_regs(input));
}
for (i, arg_regs) in arg_regs.iter().enumerate() {
caller.emit_copy_regs_to_buffer(self.lower_ctx, i, *arg_regs);
}
for (i, arg_regs) in arg_regs.iter().enumerate() {
caller.emit_copy_regs_to_arg(self.lower_ctx, i, *arg_regs);
}
caller.emit_call(self.lower_ctx);

let mut outputs = InstOutput::new();
for i in 0..num_rets {
let ret = abi.get_ret(i);
let retval_regs = self.abi_arg_slot_regs(&ret).unwrap();
caller.emit_copy_retval_to_regs(self.lower_ctx, i, retval_regs.clone());
outputs.push(valueregs::non_writable_value_regs(retval_regs));
}
caller.emit_stack_post_adjust(self.lower_ctx);

outputs
}
isle_prelude_method_helpers!(X64Caller);
}

// Since x64 doesn't have 8x16 shifts and we must use a 16x8 shift instead, we
Expand Down
Loading

0 comments on commit 8e8dfdf

Please sign in to comment.