Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AArch64: Migrate calls and returns to ISLE. #4788

Merged
merged 1 commit into from
Aug 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -1591,31 +1591,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 @@ -666,54 +667,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 @@ -1020,63 +973,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