machinst x64: remove dead code and allow(dead_code) annotation;
The BranchTarget is always used as a label, so just use a plain MachLabel in this case.
This commit is contained in:
@@ -276,11 +276,11 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gen_ret() -> Self::I {
|
fn gen_ret() -> Self::I {
|
||||||
Inst::Ret
|
Inst::ret()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_epilogue_placeholder() -> Self::I {
|
fn gen_epilogue_placeholder() -> Self::I {
|
||||||
Inst::EpiloguePlaceholder
|
Inst::epilogue_placeholder()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_add_imm(into_reg: Writable<Reg>, from_reg: Reg, imm: u32) -> SmallVec<[Self::I; 4]> {
|
fn gen_add_imm(into_reg: Writable<Reg>, from_reg: Reg, imm: u32) -> SmallVec<[Self::I; 4]> {
|
||||||
|
|||||||
@@ -4,13 +4,12 @@ use super::regs::{self, show_ireg_sized};
|
|||||||
use super::EmitState;
|
use super::EmitState;
|
||||||
use crate::ir::condcodes::{FloatCC, IntCC};
|
use crate::ir::condcodes::{FloatCC, IntCC};
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
use core::fmt::Debug;
|
|
||||||
use regalloc::{
|
use regalloc::{
|
||||||
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
|
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
|
||||||
RegUsageMapper, Writable,
|
RegUsageMapper, Writable,
|
||||||
};
|
};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::string::{String, ToString};
|
use std::string::String;
|
||||||
|
|
||||||
/// A possible addressing mode (amode) that can be used in instructions.
|
/// A possible addressing mode (amode) that can be used in instructions.
|
||||||
/// These denote a 64-bit value only.
|
/// These denote a 64-bit value only.
|
||||||
@@ -29,7 +28,7 @@ pub enum Amode {
|
|||||||
|
|
||||||
/// sign-extend-32-to-64(Immediate) + RIP (instruction pointer).
|
/// sign-extend-32-to-64(Immediate) + RIP (instruction pointer).
|
||||||
/// To wit: not supported in 32-bits mode.
|
/// To wit: not supported in 32-bits mode.
|
||||||
RipRelative { target: BranchTarget },
|
RipRelative { target: MachLabel },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Amode {
|
impl Amode {
|
||||||
@@ -50,7 +49,7 @@ impl Amode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn rip_relative(target: BranchTarget) -> Self {
|
pub(crate) fn rip_relative(target: MachLabel) -> Self {
|
||||||
Self::RipRelative { target }
|
Self::RipRelative { target }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,13 +88,7 @@ impl PrettyPrint for Amode {
|
|||||||
index.show_rru(mb_rru),
|
index.show_rru(mb_rru),
|
||||||
1 << shift
|
1 << shift
|
||||||
),
|
),
|
||||||
Amode::RipRelative { ref target } => format!(
|
Amode::RipRelative { ref target } => format!("label{}(%rip)", target.get()),
|
||||||
"{}(%rip)",
|
|
||||||
match target {
|
|
||||||
BranchTarget::Label(label) => format!("label{}", label.get()),
|
|
||||||
BranchTarget::ResolvedOffset(offset) => offset.to_string(),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1094,55 +1087,6 @@ impl From<FloatCC> for FcmpImm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A branch target. Either unresolved (basic-block index) or resolved (offset
|
|
||||||
/// from end of current instruction).
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub enum BranchTarget {
|
|
||||||
/// An unresolved reference to a MachLabel.
|
|
||||||
Label(MachLabel),
|
|
||||||
|
|
||||||
/// A resolved reference to another instruction, in bytes.
|
|
||||||
ResolvedOffset(isize),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PrettyPrint for BranchTarget {
|
|
||||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
|
||||||
match self {
|
|
||||||
BranchTarget::Label(l) => format!("{:?}", l),
|
|
||||||
BranchTarget::ResolvedOffset(offs) => format!("(offset {})", offs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BranchTarget {
|
|
||||||
/// Get the label.
|
|
||||||
pub fn as_label(&self) -> Option<MachLabel> {
|
|
||||||
match self {
|
|
||||||
&BranchTarget::Label(l) => Some(l),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the offset as a signed 32 bit byte offset. This returns the
|
|
||||||
/// offset in bytes between the first byte of the source and the first
|
|
||||||
/// byte of the target. It does not take into account the Intel-specific
|
|
||||||
/// rule that a branch offset is encoded as relative to the start of the
|
|
||||||
/// following instruction. That is a problem for the emitter to deal
|
|
||||||
/// with. If a label, returns zero.
|
|
||||||
pub fn as_offset32_or_zero(&self) -> i32 {
|
|
||||||
match self {
|
|
||||||
&BranchTarget::ResolvedOffset(off) => {
|
|
||||||
// Leave a bit of slack so that the emitter is guaranteed to
|
|
||||||
// be able to add the length of the jump instruction encoding
|
|
||||||
// to this value and still have a value in signed-32 range.
|
|
||||||
assert!(off >= -0x7FFF_FF00 && off <= 0x7FFF_FF00);
|
|
||||||
off as i32
|
|
||||||
}
|
|
||||||
_ => 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An operand's size in bits.
|
/// An operand's size in bits.
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum OperandSize {
|
pub enum OperandSize {
|
||||||
@@ -1176,6 +1120,7 @@ impl OperandSize {
|
|||||||
|
|
||||||
/// An x64 memory fence kind.
|
/// An x64 memory fence kind.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub enum FenceKind {
|
pub enum FenceKind {
|
||||||
/// `mfence` instruction ("Memory Fence")
|
/// `mfence` instruction ("Memory Fence")
|
||||||
MFence,
|
MFence,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use crate::machinst::{inst_common, MachBuffer, MachInstEmit, MachLabel};
|
|||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use regalloc::{Reg, RegClass, Writable};
|
use regalloc::{Reg, RegClass, Writable};
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
fn low8_will_sign_extend_to_64(x: u32) -> bool {
|
fn low8_will_sign_extend_to_64(x: u32) -> bool {
|
||||||
let xs = (x as i32) as i64;
|
let xs = (x as i32) as i64;
|
||||||
@@ -296,18 +295,9 @@ fn emit_std_enc_mem(
|
|||||||
// RIP-relative is mod=00, rm=101.
|
// RIP-relative is mod=00, rm=101.
|
||||||
sink.put1(encode_modrm(0, enc_g & 7, 0b101));
|
sink.put1(encode_modrm(0, enc_g & 7, 0b101));
|
||||||
|
|
||||||
match *target {
|
let offset = sink.cur_offset();
|
||||||
BranchTarget::Label(label) => {
|
sink.use_label_at_offset(offset, *target, LabelUse::JmpRel32);
|
||||||
let offset = sink.cur_offset();
|
sink.put4(0);
|
||||||
sink.use_label_at_offset(offset, label, LabelUse::JmpRel32);
|
|
||||||
sink.put4(0);
|
|
||||||
}
|
|
||||||
BranchTarget::ResolvedOffset(offset) => {
|
|
||||||
let offset =
|
|
||||||
u32::try_from(offset).expect("rip-relative can't hold >= U32_MAX values");
|
|
||||||
sink.put4(offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -808,7 +798,7 @@ pub(crate) fn emit(
|
|||||||
);
|
);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::jmp_known(BranchTarget::Label(done_label));
|
let inst = Inst::jmp_known(done_label);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
(Some(do_op), Some(done_label))
|
(Some(do_op), Some(done_label))
|
||||||
@@ -1503,30 +1493,26 @@ pub(crate) fn emit(
|
|||||||
let br_start = sink.cur_offset();
|
let br_start = sink.cur_offset();
|
||||||
let br_disp_off = br_start + 1;
|
let br_disp_off = br_start + 1;
|
||||||
let br_end = br_start + 5;
|
let br_end = br_start + 5;
|
||||||
if let Some(l) = dst.as_label() {
|
|
||||||
sink.use_label_at_offset(br_disp_off, l, LabelUse::JmpRel32);
|
|
||||||
sink.add_uncond_branch(br_start, br_end, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
let disp = dst.as_offset32_or_zero();
|
sink.use_label_at_offset(br_disp_off, *dst, LabelUse::JmpRel32);
|
||||||
let disp = disp as u32;
|
sink.add_uncond_branch(br_start, br_end, *dst);
|
||||||
|
|
||||||
sink.put1(0xE9);
|
sink.put1(0xE9);
|
||||||
sink.put4(disp);
|
// Placeholder for the label value.
|
||||||
|
sink.put4(0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::JmpIf { cc, taken } => {
|
Inst::JmpIf { cc, taken } => {
|
||||||
let cond_start = sink.cur_offset();
|
let cond_start = sink.cur_offset();
|
||||||
let cond_disp_off = cond_start + 2;
|
let cond_disp_off = cond_start + 2;
|
||||||
if let Some(l) = taken.as_label() {
|
|
||||||
sink.use_label_at_offset(cond_disp_off, l, LabelUse::JmpRel32);
|
|
||||||
// Since this is not a terminator, don't enroll in the branch inversion mechanism.
|
|
||||||
}
|
|
||||||
|
|
||||||
let taken_disp = taken.as_offset32_or_zero();
|
sink.use_label_at_offset(cond_disp_off, *taken, LabelUse::JmpRel32);
|
||||||
let taken_disp = taken_disp as u32;
|
// Since this is not a terminator, don't enroll in the branch inversion mechanism.
|
||||||
|
|
||||||
sink.put1(0x0F);
|
sink.put1(0x0F);
|
||||||
sink.put1(0x80 + cc.get_enc());
|
sink.put1(0x80 + cc.get_enc());
|
||||||
sink.put4(taken_disp);
|
// Placeholder for the label value.
|
||||||
|
sink.put4(0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::JmpCond {
|
Inst::JmpCond {
|
||||||
@@ -1538,32 +1524,27 @@ pub(crate) fn emit(
|
|||||||
let cond_start = sink.cur_offset();
|
let cond_start = sink.cur_offset();
|
||||||
let cond_disp_off = cond_start + 2;
|
let cond_disp_off = cond_start + 2;
|
||||||
let cond_end = cond_start + 6;
|
let cond_end = cond_start + 6;
|
||||||
if let Some(l) = taken.as_label() {
|
|
||||||
sink.use_label_at_offset(cond_disp_off, l, LabelUse::JmpRel32);
|
|
||||||
let inverted: [u8; 6] =
|
|
||||||
[0x0F, 0x80 + (cc.invert().get_enc()), 0x00, 0x00, 0x00, 0x00];
|
|
||||||
sink.add_cond_branch(cond_start, cond_end, l, &inverted[..]);
|
|
||||||
}
|
|
||||||
|
|
||||||
let taken_disp = taken.as_offset32_or_zero();
|
sink.use_label_at_offset(cond_disp_off, *taken, LabelUse::JmpRel32);
|
||||||
let taken_disp = taken_disp as u32;
|
let inverted: [u8; 6] = [0x0F, 0x80 + (cc.invert().get_enc()), 0x00, 0x00, 0x00, 0x00];
|
||||||
|
sink.add_cond_branch(cond_start, cond_end, *taken, &inverted[..]);
|
||||||
|
|
||||||
sink.put1(0x0F);
|
sink.put1(0x0F);
|
||||||
sink.put1(0x80 + cc.get_enc());
|
sink.put1(0x80 + cc.get_enc());
|
||||||
sink.put4(taken_disp);
|
// Placeholder for the label value.
|
||||||
|
sink.put4(0x0);
|
||||||
|
|
||||||
// If not taken.
|
// If not taken.
|
||||||
let uncond_start = sink.cur_offset();
|
let uncond_start = sink.cur_offset();
|
||||||
let uncond_disp_off = uncond_start + 1;
|
let uncond_disp_off = uncond_start + 1;
|
||||||
let uncond_end = uncond_start + 5;
|
let uncond_end = uncond_start + 5;
|
||||||
if let Some(l) = not_taken.as_label() {
|
|
||||||
sink.use_label_at_offset(uncond_disp_off, l, LabelUse::JmpRel32);
|
|
||||||
sink.add_uncond_branch(uncond_start, uncond_end, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
let nt_disp = not_taken.as_offset32_or_zero();
|
sink.use_label_at_offset(uncond_disp_off, *not_taken, LabelUse::JmpRel32);
|
||||||
let nt_disp = nt_disp as u32;
|
sink.add_uncond_branch(uncond_start, uncond_end, *not_taken);
|
||||||
|
|
||||||
sink.put1(0xE9);
|
sink.put1(0xE9);
|
||||||
sink.put4(nt_disp);
|
// Placeholder for the label value.
|
||||||
|
sink.put4(0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::JmpUnknown { target } => {
|
Inst::JmpUnknown { target } => {
|
||||||
@@ -1625,11 +1606,7 @@ pub(crate) fn emit(
|
|||||||
// j *%tmp1
|
// j *%tmp1
|
||||||
// $start_of_jump_table:
|
// $start_of_jump_table:
|
||||||
// -- jump table entries
|
// -- jump table entries
|
||||||
let default_label = match default_target {
|
one_way_jmp(sink, CC::NB, *default_target); // idx unsigned >= jmp table size
|
||||||
BranchTarget::Label(label) => label,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
one_way_jmp(sink, CC::NB, *default_label); // idx unsigned >= jmp table size
|
|
||||||
|
|
||||||
// Copy the index (and make sure to clear the high 32-bits lane of tmp2).
|
// Copy the index (and make sure to clear the high 32-bits lane of tmp2).
|
||||||
let inst = Inst::movzx_rm_r(ExtMode::LQ, RegMem::reg(*idx), *tmp2, None);
|
let inst = Inst::movzx_rm_r(ExtMode::LQ, RegMem::reg(*idx), *tmp2, None);
|
||||||
@@ -1637,10 +1614,7 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
// Load base address of jump table.
|
// Load base address of jump table.
|
||||||
let start_of_jumptable = sink.get_label();
|
let start_of_jumptable = sink.get_label();
|
||||||
let inst = Inst::lea(
|
let inst = Inst::lea(Amode::rip_relative(start_of_jumptable), *tmp1);
|
||||||
Amode::rip_relative(BranchTarget::Label(start_of_jumptable)),
|
|
||||||
*tmp1,
|
|
||||||
);
|
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
// Load value out of the jump table. It's a relative offset to the target block, so it
|
// Load value out of the jump table. It's a relative offset to the target block, so it
|
||||||
@@ -1676,7 +1650,7 @@ pub(crate) fn emit(
|
|||||||
// with the extra addend, it'll be relative to the jump table's start, after
|
// with the extra addend, it'll be relative to the jump table's start, after
|
||||||
// patching.
|
// patching.
|
||||||
let off_into_table = word_off - jt_off;
|
let off_into_table = word_off - jt_off;
|
||||||
sink.use_label_at_offset(word_off, target.as_label().unwrap(), LabelUse::PCRel32);
|
sink.use_label_at_offset(word_off, target, LabelUse::PCRel32);
|
||||||
sink.put4(off_into_table);
|
sink.put4(off_into_table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1912,7 +1886,7 @@ pub(crate) fn emit(
|
|||||||
let inst = Inst::xmm_rm_r(op, RegMem::reg(*lhs), *rhs_dst);
|
let inst = Inst::xmm_rm_r(op, RegMem::reg(*lhs), *rhs_dst);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
let inst = Inst::jmp_known(done);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
// x86's min/max are not symmetric; if either operand is a NaN, they return the
|
// x86's min/max are not symmetric; if either operand is a NaN, they return the
|
||||||
@@ -1994,14 +1968,13 @@ pub(crate) fn emit(
|
|||||||
|
|
||||||
// Load the inline constant.
|
// Load the inline constant.
|
||||||
let constant_start_label = sink.get_label();
|
let constant_start_label = sink.get_label();
|
||||||
let load_offset = Amode::rip_relative(BranchTarget::Label(constant_start_label));
|
let load_offset = Amode::rip_relative(constant_start_label);
|
||||||
let load = Inst::load(*ty, load_offset, *dst, ExtKind::None, None);
|
let load = Inst::load(*ty, load_offset, *dst, ExtKind::None, None);
|
||||||
load.emit(sink, info, state);
|
load.emit(sink, info, state);
|
||||||
|
|
||||||
// Jump over the constant.
|
// Jump over the constant.
|
||||||
let constant_end_label = sink.get_label();
|
let constant_end_label = sink.get_label();
|
||||||
let continue_at_offset = BranchTarget::Label(constant_end_label);
|
let jump = Inst::jmp_known(constant_end_label);
|
||||||
let jump = Inst::jmp_known(continue_at_offset);
|
|
||||||
jump.emit(sink, info, state);
|
jump.emit(sink, info, state);
|
||||||
|
|
||||||
// Emit the constant.
|
// Emit the constant.
|
||||||
@@ -2169,7 +2142,7 @@ pub(crate) fn emit(
|
|||||||
// right thing.
|
// right thing.
|
||||||
emit_signed_cvt(sink, info, state, src.to_reg(), *dst, *to_f64);
|
emit_signed_cvt(sink, info, state, src.to_reg(), *dst, *to_f64);
|
||||||
|
|
||||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
let inst = Inst::jmp_known(done);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
sink.bind_label(handle_negative);
|
sink.bind_label(handle_negative);
|
||||||
@@ -2308,7 +2281,7 @@ pub(crate) fn emit(
|
|||||||
);
|
);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
let inst = Inst::jmp_known(done);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
sink.bind_label(not_nan);
|
sink.bind_label(not_nan);
|
||||||
@@ -2499,7 +2472,7 @@ pub(crate) fn emit(
|
|||||||
);
|
);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
let inst = Inst::jmp_known(done);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
} else {
|
} else {
|
||||||
// Trap.
|
// Trap.
|
||||||
@@ -2531,7 +2504,7 @@ pub(crate) fn emit(
|
|||||||
);
|
);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
let inst = Inst::jmp_known(done);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
} else {
|
} else {
|
||||||
// Trap.
|
// Trap.
|
||||||
@@ -2569,7 +2542,7 @@ pub(crate) fn emit(
|
|||||||
);
|
);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
|
|
||||||
let inst = Inst::jmp_known(BranchTarget::Label(done));
|
let inst = Inst::jmp_known(done);
|
||||||
inst.emit(sink, info, state);
|
inst.emit(sink, info, state);
|
||||||
} else {
|
} else {
|
||||||
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
let inst = Inst::trap(*srcloc, TrapCode::IntegerOverflow);
|
||||||
@@ -2746,7 +2719,15 @@ pub(crate) fn emit(
|
|||||||
state.virtual_sp_offset += offset;
|
state.virtual_sp_offset += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::Nop { .. } | Inst::EpiloguePlaceholder => {
|
Inst::Nop { len } => {
|
||||||
|
if *len == 0 {
|
||||||
|
// Nothing to emit.
|
||||||
|
} else {
|
||||||
|
unimplemented!("non-zero nop opcodes.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Inst::EpiloguePlaceholder => {
|
||||||
// Generate no code.
|
// Generate no code.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1766,17 +1766,9 @@ fn test_x64_emit() {
|
|||||||
"lea 179(%r10,%r9,1), %r8",
|
"lea 179(%r10,%r9,1), %r8",
|
||||||
));
|
));
|
||||||
insns.push((
|
insns.push((
|
||||||
Inst::lea(Amode::rip_relative(BranchTarget::ResolvedOffset(0)), w_rdi),
|
Inst::lea(Amode::rip_relative(MachLabel::from_block(0)), w_rdi),
|
||||||
"488D3D00000000",
|
"488D3D00000000",
|
||||||
"lea 0(%rip), %rdi",
|
"lea label0(%rip), %rdi",
|
||||||
));
|
|
||||||
insns.push((
|
|
||||||
Inst::lea(
|
|
||||||
Amode::rip_relative(BranchTarget::ResolvedOffset(1337)),
|
|
||||||
w_r15,
|
|
||||||
),
|
|
||||||
"4C8D3D39050000",
|
|
||||||
"lea 1337(%rip), %r15",
|
|
||||||
));
|
));
|
||||||
|
|
||||||
// ========================================================
|
// ========================================================
|
||||||
@@ -3676,7 +3668,13 @@ fn test_x64_emit() {
|
|||||||
assert_eq!(expected_printing, actual_printing);
|
assert_eq!(expected_printing, actual_printing);
|
||||||
let mut sink = test_utils::TestCodeSink::new();
|
let mut sink = test_utils::TestCodeSink::new();
|
||||||
let mut buffer = MachBuffer::new();
|
let mut buffer = MachBuffer::new();
|
||||||
|
|
||||||
insn.emit(&mut buffer, &emit_info, &mut Default::default());
|
insn.emit(&mut buffer, &emit_info, &mut Default::default());
|
||||||
|
|
||||||
|
// Allow one label just after the instruction (so the offset is 0).
|
||||||
|
let label = buffer.get_label();
|
||||||
|
buffer.bind_label(label);
|
||||||
|
|
||||||
let buffer = buffer.finish();
|
let buffer = buffer.finish();
|
||||||
buffer.emit(&mut sink);
|
buffer.emit(&mut sink);
|
||||||
let actual_encoding = &sink.stringify();
|
let actual_encoding = &sink.stringify();
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
//! This module defines x86_64-specific machine instruction types.
|
//! This module defines x86_64-specific machine instruction types.
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
use crate::binemit::{CodeOffset, StackMap};
|
use crate::binemit::{CodeOffset, StackMap};
|
||||||
use crate::ir::{types, ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
use crate::ir::{types, ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
||||||
@@ -369,7 +368,7 @@ pub enum Inst {
|
|||||||
EpiloguePlaceholder,
|
EpiloguePlaceholder,
|
||||||
|
|
||||||
/// Jump to a known target: jmp simm32.
|
/// Jump to a known target: jmp simm32.
|
||||||
JmpKnown { dst: BranchTarget },
|
JmpKnown { dst: MachLabel },
|
||||||
|
|
||||||
/// One-way conditional branch: jcond cond target.
|
/// One-way conditional branch: jcond cond target.
|
||||||
///
|
///
|
||||||
@@ -379,14 +378,14 @@ pub enum Inst {
|
|||||||
/// A note of caution: in contexts where the branch target is another block, this has to be the
|
/// A note of caution: in contexts where the branch target is another block, this has to be the
|
||||||
/// same successor as the one specified in the terminator branch of the current block.
|
/// same successor as the one specified in the terminator branch of the current block.
|
||||||
/// Otherwise, this might confuse register allocation by creating new invisible edges.
|
/// Otherwise, this might confuse register allocation by creating new invisible edges.
|
||||||
JmpIf { cc: CC, taken: BranchTarget },
|
JmpIf { cc: CC, taken: MachLabel },
|
||||||
|
|
||||||
/// Two-way conditional branch: jcond cond target target.
|
/// Two-way conditional branch: jcond cond target target.
|
||||||
/// Emitted as a compound sequence; the MachBuffer will shrink it as appropriate.
|
/// Emitted as a compound sequence; the MachBuffer will shrink it as appropriate.
|
||||||
JmpCond {
|
JmpCond {
|
||||||
cc: CC,
|
cc: CC,
|
||||||
taken: BranchTarget,
|
taken: MachLabel,
|
||||||
not_taken: BranchTarget,
|
not_taken: MachLabel,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Jump-table sequence, as one compound instruction (see note in lower.rs for rationale).
|
/// Jump-table sequence, as one compound instruction (see note in lower.rs for rationale).
|
||||||
@@ -397,8 +396,8 @@ pub enum Inst {
|
|||||||
idx: Reg,
|
idx: Reg,
|
||||||
tmp1: Writable<Reg>,
|
tmp1: Writable<Reg>,
|
||||||
tmp2: Writable<Reg>,
|
tmp2: Writable<Reg>,
|
||||||
default_target: BranchTarget,
|
default_target: MachLabel,
|
||||||
targets: Vec<BranchTarget>,
|
targets: Vec<MachLabel>,
|
||||||
targets_for_term: Vec<MachLabel>,
|
targets_for_term: Vec<MachLabel>,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1077,15 +1076,15 @@ impl Inst {
|
|||||||
Inst::EpiloguePlaceholder
|
Inst::EpiloguePlaceholder
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn jmp_known(dst: BranchTarget) -> Inst {
|
pub(crate) fn jmp_known(dst: MachLabel) -> Inst {
|
||||||
Inst::JmpKnown { dst }
|
Inst::JmpKnown { dst }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn jmp_if(cc: CC, taken: BranchTarget) -> Inst {
|
pub(crate) fn jmp_if(cc: CC, taken: MachLabel) -> Inst {
|
||||||
Inst::JmpIf { cc, taken }
|
Inst::JmpIf { cc, taken }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn jmp_cond(cc: CC, taken: BranchTarget, not_taken: BranchTarget) -> Inst {
|
pub(crate) fn jmp_cond(cc: CC, taken: MachLabel, not_taken: MachLabel) -> Inst {
|
||||||
Inst::JmpCond {
|
Inst::JmpCond {
|
||||||
cc,
|
cc,
|
||||||
taken,
|
taken,
|
||||||
@@ -1679,13 +1678,13 @@ impl PrettyPrint for Inst {
|
|||||||
Inst::EpiloguePlaceholder => "epilogue placeholder".to_string(),
|
Inst::EpiloguePlaceholder => "epilogue placeholder".to_string(),
|
||||||
|
|
||||||
Inst::JmpKnown { dst } => {
|
Inst::JmpKnown { dst } => {
|
||||||
format!("{} {}", ljustify("jmp".to_string()), dst.show_rru(mb_rru))
|
format!("{} {}", ljustify("jmp".to_string()), dst.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst::JmpIf { cc, taken } => format!(
|
Inst::JmpIf { cc, taken } => format!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
ljustify2("j".to_string(), cc.to_string()),
|
ljustify2("j".to_string(), cc.to_string()),
|
||||||
taken.show_rru(mb_rru),
|
taken.to_string(),
|
||||||
),
|
),
|
||||||
|
|
||||||
Inst::JmpCond {
|
Inst::JmpCond {
|
||||||
@@ -1695,8 +1694,8 @@ impl PrettyPrint for Inst {
|
|||||||
} => format!(
|
} => format!(
|
||||||
"{} {}; j {}",
|
"{} {}; j {}",
|
||||||
ljustify2("j".to_string(), cc.to_string()),
|
ljustify2("j".to_string(), cc.to_string()),
|
||||||
taken.show_rru(mb_rru),
|
taken.to_string(),
|
||||||
not_taken.show_rru(mb_rru)
|
not_taken.to_string()
|
||||||
),
|
),
|
||||||
|
|
||||||
Inst::JmpTableSeq { idx, .. } => {
|
Inst::JmpTableSeq { idx, .. } => {
|
||||||
@@ -2446,10 +2445,10 @@ impl MachInst for Inst {
|
|||||||
match self {
|
match self {
|
||||||
// Interesting cases.
|
// Interesting cases.
|
||||||
&Self::Ret | &Self::EpiloguePlaceholder => MachTerminator::Ret,
|
&Self::Ret | &Self::EpiloguePlaceholder => MachTerminator::Ret,
|
||||||
&Self::JmpKnown { dst } => MachTerminator::Uncond(dst.as_label().unwrap()),
|
&Self::JmpKnown { dst } => MachTerminator::Uncond(dst),
|
||||||
&Self::JmpCond {
|
&Self::JmpCond {
|
||||||
taken, not_taken, ..
|
taken, not_taken, ..
|
||||||
} => MachTerminator::Cond(taken.as_label().unwrap(), not_taken.as_label().unwrap()),
|
} => MachTerminator::Cond(taken, not_taken),
|
||||||
&Self::JmpTableSeq {
|
&Self::JmpTableSeq {
|
||||||
ref targets_for_term,
|
ref targets_for_term,
|
||||||
..
|
..
|
||||||
@@ -2487,8 +2486,8 @@ impl MachInst for Inst {
|
|||||||
Inst::Nop { len: 0 }
|
Inst::Nop { len: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_nop(_preferred_size: usize) -> Inst {
|
fn gen_nop(preferred_size: usize) -> Inst {
|
||||||
unimplemented!()
|
Inst::nop(preferred_size as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_direct_reload(&self, _reg: VirtualReg, _slot: SpillSlot) -> Option<Inst> {
|
fn maybe_direct_reload(&self, _reg: VirtualReg, _slot: SpillSlot) -> Option<Inst> {
|
||||||
@@ -2519,7 +2518,7 @@ impl MachInst for Inst {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gen_jump(label: MachLabel) -> Inst {
|
fn gen_jump(label: MachLabel) -> Inst {
|
||||||
Inst::jmp_known(BranchTarget::Label(label))
|
Inst::jmp_known(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_constant<F: FnMut(RegClass, Type) -> Writable<Reg>>(
|
fn gen_constant<F: FnMut(RegClass, Type) -> Writable<Reg>>(
|
||||||
|
|||||||
@@ -3315,10 +3315,10 @@ impl LowerBackend for X64Backend {
|
|||||||
);
|
);
|
||||||
assert!(op1 == Opcode::Jump || op1 == Opcode::Fallthrough);
|
assert!(op1 == Opcode::Jump || op1 == Opcode::Fallthrough);
|
||||||
|
|
||||||
let taken = BranchTarget::Label(targets[0]);
|
let taken = targets[0];
|
||||||
let not_taken = match op1 {
|
let not_taken = match op1 {
|
||||||
Opcode::Jump => BranchTarget::Label(targets[1]),
|
Opcode::Jump => targets[1],
|
||||||
Opcode::Fallthrough => BranchTarget::Label(fallthrough.unwrap()),
|
Opcode::Fallthrough => fallthrough.unwrap(),
|
||||||
_ => unreachable!(), // assert above.
|
_ => unreachable!(), // assert above.
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3422,7 +3422,7 @@ impl LowerBackend for X64Backend {
|
|||||||
let op = ctx.data(branches[0]).opcode();
|
let op = ctx.data(branches[0]).opcode();
|
||||||
match op {
|
match op {
|
||||||
Opcode::Jump | Opcode::Fallthrough => {
|
Opcode::Jump | Opcode::Fallthrough => {
|
||||||
ctx.emit(Inst::jmp_known(BranchTarget::Label(targets[0])));
|
ctx.emit(Inst::jmp_known(targets[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::BrTable => {
|
Opcode::BrTable => {
|
||||||
@@ -3465,13 +3465,9 @@ impl LowerBackend for X64Backend {
|
|||||||
let tmp2 = ctx.alloc_tmp(RegClass::I64, types::I64);
|
let tmp2 = ctx.alloc_tmp(RegClass::I64, types::I64);
|
||||||
|
|
||||||
let targets_for_term: Vec<MachLabel> = targets.to_vec();
|
let targets_for_term: Vec<MachLabel> = targets.to_vec();
|
||||||
let default_target = BranchTarget::Label(targets[0]);
|
let default_target = targets[0];
|
||||||
|
|
||||||
let jt_targets: Vec<BranchTarget> = targets
|
let jt_targets: Vec<MachLabel> = targets.iter().skip(1).cloned().collect();
|
||||||
.iter()
|
|
||||||
.skip(1)
|
|
||||||
.map(|bix| BranchTarget::Label(*bix))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
ctx.emit(Inst::JmpTableSeq {
|
ctx.emit(Inst::JmpTableSeq {
|
||||||
idx,
|
idx,
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ use crate::timing;
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::string::String;
|
||||||
|
|
||||||
/// A buffer of output to be produced, fixed up, and then emitted to a CodeSink
|
/// A buffer of output to be produced, fixed up, and then emitted to a CodeSink
|
||||||
/// in bulk.
|
/// in bulk.
|
||||||
@@ -259,6 +260,11 @@ impl MachLabel {
|
|||||||
pub fn get(self) -> u32 {
|
pub fn get(self) -> u32 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a string representing this label, for convenience.
|
||||||
|
pub fn to_string(&self) -> String {
|
||||||
|
format!("label{}", self.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A stack map extent, when creating a stack map.
|
/// A stack map extent, when creating a stack map.
|
||||||
|
|||||||
Reference in New Issue
Block a user