mach backend: reduce the size of the Inst enum down to 32 bytes;
This commit is contained in:
@@ -1276,33 +1276,39 @@ impl ABICall for AArch64ABICall {
|
|||||||
);
|
);
|
||||||
match &self.dest {
|
match &self.dest {
|
||||||
&CallDest::ExtName(ref name, RelocDistance::Near) => ctx.emit(Inst::Call {
|
&CallDest::ExtName(ref name, RelocDistance::Near) => ctx.emit(Inst::Call {
|
||||||
dest: Box::new(name.clone()),
|
info: Box::new(CallInfo {
|
||||||
uses: uses.into_boxed_slice(),
|
dest: name.clone(),
|
||||||
defs: defs.into_boxed_slice(),
|
uses,
|
||||||
loc: self.loc,
|
defs,
|
||||||
opcode: self.opcode,
|
loc: self.loc,
|
||||||
|
opcode: self.opcode,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
&CallDest::ExtName(ref name, RelocDistance::Far) => {
|
&CallDest::ExtName(ref name, RelocDistance::Far) => {
|
||||||
ctx.emit(Inst::LoadExtName {
|
ctx.emit(Inst::LoadExtName {
|
||||||
rd: writable_spilltmp_reg(),
|
rd: writable_spilltmp_reg(),
|
||||||
name: name.clone(),
|
name: Box::new(name.clone()),
|
||||||
offset: 0,
|
offset: 0,
|
||||||
srcloc: self.loc,
|
srcloc: self.loc,
|
||||||
});
|
});
|
||||||
ctx.emit(Inst::CallInd {
|
ctx.emit(Inst::CallInd {
|
||||||
rn: spilltmp_reg(),
|
info: Box::new(CallIndInfo {
|
||||||
uses: uses.into_boxed_slice(),
|
rn: spilltmp_reg(),
|
||||||
defs: defs.into_boxed_slice(),
|
uses,
|
||||||
loc: self.loc,
|
defs,
|
||||||
opcode: self.opcode,
|
loc: self.loc,
|
||||||
|
opcode: self.opcode,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
&CallDest::Reg(reg) => ctx.emit(Inst::CallInd {
|
&CallDest::Reg(reg) => ctx.emit(Inst::CallInd {
|
||||||
rn: reg,
|
info: Box::new(CallIndInfo {
|
||||||
uses: uses.into_boxed_slice(),
|
rn: reg,
|
||||||
defs: defs.into_boxed_slice(),
|
uses,
|
||||||
loc: self.loc,
|
defs,
|
||||||
opcode: self.opcode,
|
loc: self.loc,
|
||||||
|
opcode: self.opcode,
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ pub enum BranchTarget {
|
|||||||
/// `lower_branch_group()`.
|
/// `lower_branch_group()`.
|
||||||
Label(MachLabel),
|
Label(MachLabel),
|
||||||
/// A fixed PC offset.
|
/// A fixed PC offset.
|
||||||
ResolvedOffset(isize),
|
ResolvedOffset(i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BranchTarget {
|
impl BranchTarget {
|
||||||
|
|||||||
@@ -1239,24 +1239,17 @@ impl MachInstEmit for Inst {
|
|||||||
&Inst::EpiloguePlaceholder => {
|
&Inst::EpiloguePlaceholder => {
|
||||||
// Noop; this is just a placeholder for epilogues.
|
// Noop; this is just a placeholder for epilogues.
|
||||||
}
|
}
|
||||||
&Inst::Call {
|
&Inst::Call { ref info } => {
|
||||||
ref dest,
|
sink.add_reloc(info.loc, Reloc::Arm64Call, &info.dest, 0);
|
||||||
loc,
|
|
||||||
opcode,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
sink.add_reloc(loc, Reloc::Arm64Call, dest, 0);
|
|
||||||
sink.put4(enc_jump26(0b100101, 0));
|
sink.put4(enc_jump26(0b100101, 0));
|
||||||
if opcode.is_call() {
|
if info.opcode.is_call() {
|
||||||
sink.add_call_site(loc, opcode);
|
sink.add_call_site(info.loc, info.opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Inst::CallInd {
|
&Inst::CallInd { ref info } => {
|
||||||
rn, loc, opcode, ..
|
sink.put4(0b1101011_0001_11111_000000_00000_00000 | (machreg_to_gpr(info.rn) << 5));
|
||||||
} => {
|
if info.opcode.is_call() {
|
||||||
sink.put4(0b1101011_0001_11111_000000_00000_00000 | (machreg_to_gpr(rn) << 5));
|
sink.add_call_site(info.loc, info.opcode);
|
||||||
if opcode.is_call() {
|
|
||||||
sink.add_call_site(loc, opcode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Inst::CondBr {
|
&Inst::CondBr {
|
||||||
@@ -1318,7 +1311,7 @@ impl MachInstEmit for Inst {
|
|||||||
ridx,
|
ridx,
|
||||||
rtmp1,
|
rtmp1,
|
||||||
rtmp2,
|
rtmp2,
|
||||||
ref targets,
|
ref info,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
// This sequence is *one* instruction in the vcode, and is expanded only here at
|
// This sequence is *one* instruction in the vcode, and is expanded only here at
|
||||||
@@ -1361,7 +1354,7 @@ impl MachInstEmit for Inst {
|
|||||||
inst.emit(sink, flags, state);
|
inst.emit(sink, flags, state);
|
||||||
// Emit jump table (table of 32-bit offsets).
|
// Emit jump table (table of 32-bit offsets).
|
||||||
let jt_off = sink.cur_offset();
|
let jt_off = sink.cur_offset();
|
||||||
for &target in targets.iter() {
|
for &target in info.targets.iter() {
|
||||||
let word_off = sink.cur_offset();
|
let word_off = sink.cur_offset();
|
||||||
let off_into_table = word_off - jt_off;
|
let off_into_table = word_off - jt_off;
|
||||||
sink.use_label_at_offset(
|
sink.use_label_at_offset(
|
||||||
|
|||||||
@@ -2113,11 +2113,13 @@ fn test_aarch64_binemit() {
|
|||||||
|
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::Call {
|
Inst::Call {
|
||||||
dest: Box::new(ExternalName::testcase("test0")),
|
info: Box::new(CallInfo {
|
||||||
uses: Vec::new().into_boxed_slice(),
|
dest: ExternalName::testcase("test0"),
|
||||||
defs: Vec::new().into_boxed_slice(),
|
uses: Vec::new(),
|
||||||
loc: SourceLoc::default(),
|
defs: Vec::new(),
|
||||||
opcode: Opcode::Call,
|
loc: SourceLoc::default(),
|
||||||
|
opcode: Opcode::Call,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
"00000094",
|
"00000094",
|
||||||
"bl 0",
|
"bl 0",
|
||||||
@@ -2125,11 +2127,13 @@ fn test_aarch64_binemit() {
|
|||||||
|
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::CallInd {
|
Inst::CallInd {
|
||||||
rn: xreg(10),
|
info: Box::new(CallIndInfo {
|
||||||
uses: Vec::new().into_boxed_slice(),
|
rn: xreg(10),
|
||||||
defs: Vec::new().into_boxed_slice(),
|
uses: Vec::new(),
|
||||||
loc: SourceLoc::default(),
|
defs: Vec::new(),
|
||||||
opcode: Opcode::CallIndirect,
|
loc: SourceLoc::default(),
|
||||||
|
opcode: Opcode::CallIndirect,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
"40013FD6",
|
"40013FD6",
|
||||||
"blr x10",
|
"blr x10",
|
||||||
|
|||||||
@@ -247,6 +247,36 @@ impl From<(Opcode, Type)> for BitOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Additional information for (direct) Call instructions, left out of line to lower the size of
|
||||||
|
/// the Inst enum.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct CallInfo {
|
||||||
|
pub dest: ExternalName,
|
||||||
|
pub uses: Vec<Reg>,
|
||||||
|
pub defs: Vec<Writable<Reg>>,
|
||||||
|
pub loc: SourceLoc,
|
||||||
|
pub opcode: Opcode,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Additional information for CallInd instructions, left out of line to lower the size of the Inst
|
||||||
|
/// enum.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct CallIndInfo {
|
||||||
|
pub rn: Reg,
|
||||||
|
pub uses: Vec<Reg>,
|
||||||
|
pub defs: Vec<Writable<Reg>>,
|
||||||
|
pub loc: SourceLoc,
|
||||||
|
pub opcode: Opcode,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Additional information for JTSequence instructions, left out of line to lower the size of the Inst
|
||||||
|
/// enum.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct JTSequenceInfo {
|
||||||
|
pub targets: Vec<BranchTarget>,
|
||||||
|
pub targets_for_term: Vec<MachLabel>, // needed for MachTerminator.
|
||||||
|
}
|
||||||
|
|
||||||
/// Instruction formats.
|
/// Instruction formats.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Inst {
|
pub enum Inst {
|
||||||
@@ -649,19 +679,11 @@ pub enum Inst {
|
|||||||
/// code should use a `LoadExtName` / `CallInd` sequence instead, allowing an arbitrary 64-bit
|
/// code should use a `LoadExtName` / `CallInd` sequence instead, allowing an arbitrary 64-bit
|
||||||
/// target.
|
/// target.
|
||||||
Call {
|
Call {
|
||||||
dest: Box<ExternalName>,
|
info: Box<CallInfo>,
|
||||||
uses: Box<[Reg]>,
|
|
||||||
defs: Box<[Writable<Reg>]>,
|
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: Opcode,
|
|
||||||
},
|
},
|
||||||
/// A machine indirect-call instruction.
|
/// A machine indirect-call instruction.
|
||||||
CallInd {
|
CallInd {
|
||||||
rn: Reg,
|
info: Box<CallIndInfo>,
|
||||||
uses: Box<[Reg]>,
|
|
||||||
defs: Box<[Writable<Reg>]>,
|
|
||||||
loc: SourceLoc,
|
|
||||||
opcode: Opcode,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---- branches (exactly one must appear at end of BB) ----
|
// ---- branches (exactly one must appear at end of BB) ----
|
||||||
@@ -742,8 +764,7 @@ pub enum Inst {
|
|||||||
/// Jump-table sequence, as one compound instruction (see note in lower.rs
|
/// Jump-table sequence, as one compound instruction (see note in lower.rs
|
||||||
/// for rationale).
|
/// for rationale).
|
||||||
JTSequence {
|
JTSequence {
|
||||||
targets: Box<[BranchTarget]>,
|
info: Box<JTSequenceInfo>,
|
||||||
targets_for_term: Box<[MachLabel]>, // needed for MachTerminator.
|
|
||||||
ridx: Reg,
|
ridx: Reg,
|
||||||
rtmp1: Writable<Reg>,
|
rtmp1: Writable<Reg>,
|
||||||
rtmp2: Writable<Reg>,
|
rtmp2: Writable<Reg>,
|
||||||
@@ -758,7 +779,7 @@ pub enum Inst {
|
|||||||
/// Load an inline symbol reference.
|
/// Load an inline symbol reference.
|
||||||
LoadExtName {
|
LoadExtName {
|
||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
name: ExternalName,
|
name: Box<ExternalName>,
|
||||||
srcloc: SourceLoc,
|
srcloc: SourceLoc,
|
||||||
offset: i64,
|
offset: i64,
|
||||||
},
|
},
|
||||||
@@ -817,7 +838,7 @@ fn count_zero_half_words(mut value: u64) -> usize {
|
|||||||
fn inst_size_test() {
|
fn inst_size_test() {
|
||||||
// This test will help with unintentionally growing the size
|
// This test will help with unintentionally growing the size
|
||||||
// of the Inst enum.
|
// of the Inst enum.
|
||||||
assert_eq!(48, std::mem::size_of::<Inst>());
|
assert_eq!(32, std::mem::size_of::<Inst>());
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inst {
|
impl Inst {
|
||||||
@@ -1173,21 +1194,14 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
|
|||||||
collector.add_use(rn);
|
collector.add_use(rn);
|
||||||
}
|
}
|
||||||
&Inst::Jump { .. } | &Inst::Ret | &Inst::EpiloguePlaceholder => {}
|
&Inst::Jump { .. } | &Inst::Ret | &Inst::EpiloguePlaceholder => {}
|
||||||
&Inst::Call {
|
&Inst::Call { ref info } => {
|
||||||
ref uses, ref defs, ..
|
collector.add_uses(&*info.uses);
|
||||||
} => {
|
collector.add_defs(&*info.defs);
|
||||||
collector.add_uses(&*uses);
|
|
||||||
collector.add_defs(&*defs);
|
|
||||||
}
|
}
|
||||||
&Inst::CallInd {
|
&Inst::CallInd { ref info } => {
|
||||||
ref uses,
|
collector.add_uses(&*info.uses);
|
||||||
ref defs,
|
collector.add_defs(&*info.defs);
|
||||||
rn,
|
collector.add_use(info.rn);
|
||||||
..
|
|
||||||
} => {
|
|
||||||
collector.add_uses(&*uses);
|
|
||||||
collector.add_defs(&*defs);
|
|
||||||
collector.add_use(rn);
|
|
||||||
}
|
}
|
||||||
&Inst::CondBr { ref kind, .. } | &Inst::OneWayCondBr { ref kind, .. } => match kind {
|
&Inst::CondBr { ref kind, .. } | &Inst::OneWayCondBr { ref kind, .. } => match kind {
|
||||||
CondBrKind::Zero(rt) | CondBrKind::NotZero(rt) => {
|
CondBrKind::Zero(rt) | CondBrKind::NotZero(rt) => {
|
||||||
@@ -1724,32 +1738,23 @@ fn aarch64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
|
|||||||
map_use(mapper, rn);
|
map_use(mapper, rn);
|
||||||
}
|
}
|
||||||
&mut Inst::Jump { .. } => {}
|
&mut Inst::Jump { .. } => {}
|
||||||
&mut Inst::Call {
|
&mut Inst::Call { ref mut info } => {
|
||||||
ref mut uses,
|
for r in info.uses.iter_mut() {
|
||||||
ref mut defs,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
for r in uses.iter_mut() {
|
|
||||||
map_use(mapper, r);
|
map_use(mapper, r);
|
||||||
}
|
}
|
||||||
for r in defs.iter_mut() {
|
for r in info.defs.iter_mut() {
|
||||||
map_def(mapper, r);
|
map_def(mapper, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&mut Inst::Ret | &mut Inst::EpiloguePlaceholder => {}
|
&mut Inst::Ret | &mut Inst::EpiloguePlaceholder => {}
|
||||||
&mut Inst::CallInd {
|
&mut Inst::CallInd { ref mut info, .. } => {
|
||||||
ref mut uses,
|
for r in info.uses.iter_mut() {
|
||||||
ref mut defs,
|
|
||||||
ref mut rn,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
for r in uses.iter_mut() {
|
|
||||||
map_use(mapper, r);
|
map_use(mapper, r);
|
||||||
}
|
}
|
||||||
for r in defs.iter_mut() {
|
for r in info.defs.iter_mut() {
|
||||||
map_def(mapper, r);
|
map_def(mapper, r);
|
||||||
}
|
}
|
||||||
map_use(mapper, rn);
|
map_use(mapper, &mut info.rn);
|
||||||
}
|
}
|
||||||
&mut Inst::CondBr { ref mut kind, .. } | &mut Inst::OneWayCondBr { ref mut kind, .. } => {
|
&mut Inst::CondBr { ref mut kind, .. } | &mut Inst::OneWayCondBr { ref mut kind, .. } => {
|
||||||
map_br(mapper, kind);
|
map_br(mapper, kind);
|
||||||
@@ -1833,10 +1838,9 @@ impl MachInst for Inst {
|
|||||||
MachTerminator::None
|
MachTerminator::None
|
||||||
}
|
}
|
||||||
&Inst::IndirectBr { ref targets, .. } => MachTerminator::Indirect(&targets[..]),
|
&Inst::IndirectBr { ref targets, .. } => MachTerminator::Indirect(&targets[..]),
|
||||||
&Inst::JTSequence {
|
&Inst::JTSequence { ref info, .. } => {
|
||||||
ref targets_for_term,
|
MachTerminator::Indirect(&info.targets_for_term[..])
|
||||||
..
|
}
|
||||||
} => MachTerminator::Indirect(&targets_for_term[..]),
|
|
||||||
_ => MachTerminator::None,
|
_ => MachTerminator::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2554,9 +2558,9 @@ impl ShowWithRRU for Inst {
|
|||||||
&Inst::Extend { .. } => {
|
&Inst::Extend { .. } => {
|
||||||
panic!("Unsupported Extend case");
|
panic!("Unsupported Extend case");
|
||||||
}
|
}
|
||||||
&Inst::Call { dest: _, .. } => format!("bl 0"),
|
&Inst::Call { .. } => format!("bl 0"),
|
||||||
&Inst::CallInd { rn, .. } => {
|
&Inst::CallInd { ref info, .. } => {
|
||||||
let rn = rn.show_rru(mb_rru);
|
let rn = info.rn.show_rru(mb_rru);
|
||||||
format!("blr {}", rn)
|
format!("blr {}", rn)
|
||||||
}
|
}
|
||||||
&Inst::Ret => "ret".to_string(),
|
&Inst::Ret => "ret".to_string(),
|
||||||
@@ -2620,7 +2624,7 @@ impl ShowWithRRU for Inst {
|
|||||||
&Inst::Word4 { data } => format!("data.i32 {}", data),
|
&Inst::Word4 { data } => format!("data.i32 {}", data),
|
||||||
&Inst::Word8 { data } => format!("data.i64 {}", data),
|
&Inst::Word8 { data } => format!("data.i64 {}", data),
|
||||||
&Inst::JTSequence {
|
&Inst::JTSequence {
|
||||||
ref targets,
|
ref info,
|
||||||
ridx,
|
ridx,
|
||||||
rtmp1,
|
rtmp1,
|
||||||
rtmp2,
|
rtmp2,
|
||||||
@@ -2637,7 +2641,7 @@ impl ShowWithRRU for Inst {
|
|||||||
"br {} ; ",
|
"br {} ; ",
|
||||||
"jt_entries {:?}"
|
"jt_entries {:?}"
|
||||||
),
|
),
|
||||||
rtmp1, rtmp2, rtmp1, ridx, rtmp1, rtmp1, rtmp2, rtmp1, targets
|
rtmp1, rtmp2, rtmp1, ridx, rtmp1, rtmp1, rtmp2, rtmp1, info.targets
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
&Inst::LoadConst64 { rd, const_data } => {
|
&Inst::LoadConst64 { rd, const_data } => {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use crate::isa::aarch64::inst::*;
|
|||||||
|
|
||||||
use regalloc::RegClass;
|
use regalloc::RegClass;
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
@@ -1245,7 +1246,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let loc = ctx.srcloc(insn);
|
let loc = ctx.srcloc(insn);
|
||||||
ctx.emit(Inst::LoadExtName {
|
ctx.emit(Inst::LoadExtName {
|
||||||
rd,
|
rd,
|
||||||
name: extname,
|
name: Box::new(extname),
|
||||||
srcloc: loc,
|
srcloc: loc,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
});
|
});
|
||||||
@@ -1262,7 +1263,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
let loc = ctx.srcloc(insn);
|
let loc = ctx.srcloc(insn);
|
||||||
ctx.emit(Inst::LoadExtName {
|
ctx.emit(Inst::LoadExtName {
|
||||||
rd,
|
rd,
|
||||||
name: extname,
|
name: Box::new(extname),
|
||||||
srcloc: loc,
|
srcloc: loc,
|
||||||
offset,
|
offset,
|
||||||
});
|
});
|
||||||
@@ -2140,8 +2141,10 @@ pub(crate) fn lower_branch<C: LowerCtx<I = Inst>>(
|
|||||||
ridx,
|
ridx,
|
||||||
rtmp1,
|
rtmp1,
|
||||||
rtmp2,
|
rtmp2,
|
||||||
targets: jt_targets.into_boxed_slice(),
|
info: Box::new(JTSequenceInfo {
|
||||||
targets_for_term: targets_for_term.into_boxed_slice(),
|
targets: jt_targets,
|
||||||
|
targets_for_term: targets_for_term,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user