Skip to content
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
206 changes: 133 additions & 73 deletions cranelift/codegen/src/isa/x64/inst.isle

Large diffs are not rendered by default.

205 changes: 119 additions & 86 deletions cranelift/codegen/src/isa/x64/inst/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ macro_rules! newtype_of_reg {
$newtype_reg:ident,
$newtype_writable_reg:ident,
$newtype_option_writable_reg:ident,
$newtype_reg_mem:ident,
$newtype_reg_mem_imm:ident,
reg_mem: ($($newtype_reg_mem:ident $(aligned:$aligned:ident)?),*),
reg_mem_imm: ($($newtype_reg_mem_imm:ident $(aligned:$aligned_imm:ident)?),*),
$newtype_imm8_reg:ident,
|$check_reg:ident| $check:expr
) => {
Expand Down Expand Up @@ -102,108 +102,130 @@ macro_rules! newtype_of_reg {
}
}

/// A newtype wrapper around `RegMem` for general-purpose registers.
#[derive(Clone, Debug)]
pub struct $newtype_reg_mem(RegMem);
$(
/// A newtype wrapper around `RegMem` for general-purpose registers.
#[derive(Clone, Debug)]
pub struct $newtype_reg_mem(RegMem);

impl From<$newtype_reg_mem> for RegMem {
fn from(rm: $newtype_reg_mem) -> Self {
rm.0
impl From<$newtype_reg_mem> for RegMem {
fn from(rm: $newtype_reg_mem) -> Self {
rm.0
}
}
}

impl From<$newtype_reg> for $newtype_reg_mem {
fn from(r: $newtype_reg) -> Self {
$newtype_reg_mem(RegMem::reg(r.into()))
impl From<$newtype_reg> for $newtype_reg_mem {
fn from(r: $newtype_reg) -> Self {
$newtype_reg_mem(RegMem::reg(r.into()))
}
}
}

impl $newtype_reg_mem {
/// Construct a `RegMem` newtype from the given `RegMem`, or return
/// `None` if the `RegMem` is not a valid instance of this `RegMem`
/// newtype.
pub fn new(rm: RegMem) -> Option<Self> {
match rm {
RegMem::Mem { addr: _ } => Some(Self(rm)),
RegMem::Reg { reg: $check_reg } if $check => Some(Self(rm)),
RegMem::Reg { reg: _ } => None,
impl $newtype_reg_mem {
/// Construct a `RegMem` newtype from the given `RegMem`, or return
/// `None` if the `RegMem` is not a valid instance of this `RegMem`
/// newtype.
pub fn new(rm: RegMem) -> Option<Self> {
match rm {
RegMem::Mem { addr } => {
let mut _allow = true;
$(
if $aligned {
_allow = addr.aligned();
}
)?
if _allow {
Some(Self(RegMem::Mem { addr }))
} else {
None
}
}
RegMem::Reg { reg: $check_reg } if $check => Some(Self(rm)),
RegMem::Reg { reg: _ } => None,
}
}
}

/// Convert this newtype into its underlying `RegMem`.
pub fn to_reg_mem(self) -> RegMem {
self.0
}
/// Convert this newtype into its underlying `RegMem`.
pub fn to_reg_mem(self) -> RegMem {
self.0
}

#[allow(dead_code)] // Used by some newtypes and not others.
pub(crate) fn get_operands<F: Fn(VReg) -> VReg>(
&self,
collector: &mut OperandCollector<'_, F>,
) {
self.0.get_operands(collector);
#[allow(dead_code)] // Used by some newtypes and not others.
pub(crate) fn get_operands<F: Fn(VReg) -> VReg>(
&self,
collector: &mut OperandCollector<'_, F>,
) {
self.0.get_operands(collector);
}
}
}
impl PrettyPrint for $newtype_reg_mem {
fn pretty_print(&self, size: u8, allocs: &mut AllocationConsumer<'_>) -> String {
self.0.pretty_print(size, allocs)
impl PrettyPrint for $newtype_reg_mem {
fn pretty_print(&self, size: u8, allocs: &mut AllocationConsumer<'_>) -> String {
self.0.pretty_print(size, allocs)
}
}
}
)*

/// A newtype wrapper around `RegMemImm`.
#[derive(Clone, Debug)]
pub struct $newtype_reg_mem_imm(RegMemImm);
$(
/// A newtype wrapper around `RegMemImm`.
#[derive(Clone, Debug)]
pub struct $newtype_reg_mem_imm(RegMemImm);

impl From<$newtype_reg_mem_imm> for RegMemImm {
fn from(rmi: $newtype_reg_mem_imm) -> RegMemImm {
rmi.0
}
}

impl From<$newtype_reg> for $newtype_reg_mem_imm {
fn from(r: $newtype_reg) -> Self {
$newtype_reg_mem_imm(RegMemImm::reg(r.into()))
impl From<$newtype_reg_mem_imm> for RegMemImm {
fn from(rmi: $newtype_reg_mem_imm) -> RegMemImm {
rmi.0
}
}
}

impl From<$newtype_reg_mem> for $newtype_reg_mem_imm {
fn from(r: $newtype_reg_mem) -> Self {
$newtype_reg_mem_imm(r.0.into())
impl From<$newtype_reg> for $newtype_reg_mem_imm {
fn from(r: $newtype_reg) -> Self {
$newtype_reg_mem_imm(RegMemImm::reg(r.into()))
}
}
}

impl $newtype_reg_mem_imm {
/// Construct this newtype from the given `RegMemImm`, or return
/// `None` if the `RegMemImm` is not a valid instance of this
/// newtype.
pub fn new(rmi: RegMemImm) -> Option<Self> {
match rmi {
RegMemImm::Imm { .. } => Some(Self(rmi)),
RegMemImm::Mem { addr: _ } => Some(Self(rmi)),
RegMemImm::Reg { reg: $check_reg } if $check => Some(Self(rmi)),
RegMemImm::Reg { reg: _ } => None,
impl $newtype_reg_mem_imm {
/// Construct this newtype from the given `RegMemImm`, or return
/// `None` if the `RegMemImm` is not a valid instance of this
/// newtype.
pub fn new(rmi: RegMemImm) -> Option<Self> {
match rmi {
RegMemImm::Imm { .. } => Some(Self(rmi)),
RegMemImm::Mem { addr } => {
let mut _allow = true;
$(
if $aligned_imm {
_allow = addr.aligned();
}
)?
if _allow {
Some(Self(RegMemImm::Mem { addr }))
} else {
None
}
}
RegMemImm::Reg { reg: $check_reg } if $check => Some(Self(rmi)),
RegMemImm::Reg { reg: _ } => None,
}
}
}

/// Convert this newtype into its underlying `RegMemImm`.
#[allow(dead_code)] // Used by some newtypes and not others.
pub fn to_reg_mem_imm(self) -> RegMemImm {
self.0
}
/// Convert this newtype into its underlying `RegMemImm`.
#[allow(dead_code)] // Used by some newtypes and not others.
pub fn to_reg_mem_imm(self) -> RegMemImm {
self.0
}

#[allow(dead_code)] // Used by some newtypes and not others.
pub(crate) fn get_operands<F: Fn(VReg) -> VReg>(
&self,
collector: &mut OperandCollector<'_, F>,
) {
self.0.get_operands(collector);
#[allow(dead_code)] // Used by some newtypes and not others.
pub(crate) fn get_operands<F: Fn(VReg) -> VReg>(
&self,
collector: &mut OperandCollector<'_, F>,
) {
self.0.get_operands(collector);
}
}
}

impl PrettyPrint for $newtype_reg_mem_imm {
fn pretty_print(&self, size: u8, allocs: &mut AllocationConsumer<'_>) -> String {
self.0.pretty_print(size, allocs)
impl PrettyPrint for $newtype_reg_mem_imm {
fn pretty_print(&self, size: u8, allocs: &mut AllocationConsumer<'_>) -> String {
self.0.pretty_print(size, allocs)
}
}
}
)*

/// A newtype wrapper around `Imm8Reg`.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -242,8 +264,8 @@ newtype_of_reg!(
Gpr,
WritableGpr,
OptionWritableGpr,
GprMem,
GprMemImm,
reg_mem: (GprMem),
reg_mem_imm: (GprMemImm),
Imm8Gpr,
|reg| reg.class() == RegClass::Int
);
Expand All @@ -253,8 +275,8 @@ newtype_of_reg!(
Xmm,
WritableXmm,
OptionWritableXmm,
XmmMem,
XmmMemImm,
reg_mem: (XmmMem, XmmMemAligned aligned:true),
reg_mem_imm: (XmmMemImm, XmmMemAlignedImm aligned:true),
Imm8Xmm,
|reg| reg.class() == RegClass::Float
);
Expand Down Expand Up @@ -420,6 +442,10 @@ impl Amode {
}
ret
}

pub(crate) fn aligned(&self) -> bool {
self.get_flags().aligned()
}
}

impl PrettyPrint for Amode {
Expand Down Expand Up @@ -531,6 +557,13 @@ impl SyntheticAmode {
}
}
}

pub(crate) fn aligned(&self) -> bool {
match self {
SyntheticAmode::Real(addr) => addr.aligned(),
SyntheticAmode::NominalSPOffset { .. } | SyntheticAmode::ConstantOffset { .. } => true,
}
}
}

impl Into<SyntheticAmode> for Amode {
Expand Down
34 changes: 33 additions & 1 deletion cranelift/codegen/src/isa/x64/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1731,7 +1731,21 @@ pub(crate) fn emit(
sink.bind_label(else_label);
}

Inst::XmmUnaryRmR {
Inst::XmmUnaryRmR { op, src, dst } => {
emit(
&Inst::XmmUnaryRmRUnaligned {
op: *op,
src: XmmMem::new(src.clone().into()).unwrap(),
dst: *dst,
},
allocs,
sink,
info,
state,
);
}

Inst::XmmUnaryRmRUnaligned {
op,
src: src_e,
dst: reg_g,
Expand Down Expand Up @@ -1843,6 +1857,24 @@ pub(crate) fn emit(
}

Inst::XmmRmR {
op,
src1,
src2,
dst,
} => emit(
&Inst::XmmRmRUnaligned {
op: *op,
dst: *dst,
src1: *src1,
src2: XmmMem::new(src2.clone().to_reg_mem()).unwrap(),
},
allocs,
sink,
info,
state,
),

Inst::XmmRmRUnaligned {
op,
src1,
src2: src_e,
Expand Down
8 changes: 4 additions & 4 deletions cranelift/codegen/src/isa/x64/inst/emit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Inst {
debug_assert!(dst.to_reg().class() == RegClass::Float);
Inst::XmmUnaryRmRImm {
op,
src: XmmMem::new(src).unwrap(),
src: XmmMemAligned::new(src).unwrap(),
imm,
dst: WritableXmm::from_writable_reg(dst).unwrap(),
}
Expand All @@ -56,7 +56,7 @@ impl Inst {
Inst::XmmRmiReg {
opcode,
src1: Xmm::new(dst.to_reg()).unwrap(),
src2: XmmMemImm::new(src).unwrap(),
src2: XmmMemAlignedImm::new(src).unwrap(),
dst: WritableXmm::from_writable_reg(dst).unwrap(),
}
}
Expand Down Expand Up @@ -96,7 +96,7 @@ impl Inst {
debug_assert!(dst.to_reg().class() == RegClass::Float);
Inst::XmmUnaryRmR {
op,
src: XmmMem::new(src).unwrap(),
src: XmmMemAligned::new(src).unwrap(),
dst: WritableXmm::from_writable_reg(dst).unwrap(),
}
}
Expand Down Expand Up @@ -136,7 +136,7 @@ impl Inst {
Inst::XmmRmRBlend {
op,
src1: Xmm::new(dst.to_reg()).unwrap(),
src2: XmmMem::new(src2).unwrap(),
src2: XmmMemAligned::new(src2).unwrap(),
mask: Xmm::new(regs::xmm0()).unwrap(),
dst: WritableXmm::from_writable_reg(dst).unwrap(),
}
Expand Down
Loading