AArch64: Migrate calls and returns to ISLE. (#4788)

This commit is contained in:
Chris Fallin
2022-08-26 16:26:39 -07:00
committed by GitHub
parent ca6d648e37
commit 8e8dfdf5f9
18 changed files with 282 additions and 329 deletions

View File

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

View File

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

View File

@@ -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 {
@@ -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()
@@ -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