[machinst x64]: allow addressing of constants

This commit is contained in:
Andrew Brown
2020-11-11 09:46:47 -08:00
parent 01b7d88641
commit 8131b15921
2 changed files with 34 additions and 24 deletions

View File

@@ -3,6 +3,7 @@
use super::regs::{self, show_ireg_sized}; 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::isa::x64::inst::Inst;
use crate::machinst::*; use crate::machinst::*;
use regalloc::{ use regalloc::{
PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector, PrettyPrint, PrettyPrintSized, RealRegUniverse, Reg, RegClass, RegUsageCollector,
@@ -104,6 +105,9 @@ pub enum SyntheticAmode {
/// A (virtual) offset to the "nominal SP" value, which will be recomputed as we push and pop /// A (virtual) offset to the "nominal SP" value, which will be recomputed as we push and pop
/// within the function. /// within the function.
NominalSPOffset { simm32: u32 }, NominalSPOffset { simm32: u32 },
/// A virtual offset to a constant that will be emitted in the constant section of the buffer.
ConstantOffset(VCodeConstant),
} }
impl SyntheticAmode { impl SyntheticAmode {
@@ -118,6 +122,7 @@ impl SyntheticAmode {
SyntheticAmode::NominalSPOffset { .. } => { SyntheticAmode::NominalSPOffset { .. } => {
// Nothing to do; the base is SP and isn't involved in regalloc. // Nothing to do; the base is SP and isn't involved in regalloc.
} }
SyntheticAmode::ConstantOffset(_) => {}
} }
} }
@@ -127,10 +132,11 @@ impl SyntheticAmode {
SyntheticAmode::NominalSPOffset { .. } => { SyntheticAmode::NominalSPOffset { .. } => {
// Nothing to do. // Nothing to do.
} }
SyntheticAmode::ConstantOffset(_) => {}
} }
} }
pub(crate) fn finalize(&self, state: &mut EmitState) -> Amode { pub(crate) fn finalize(&self, state: &mut EmitState, buffer: &MachBuffer<Inst>) -> Amode {
match self { match self {
SyntheticAmode::Real(addr) => addr.clone(), SyntheticAmode::Real(addr) => addr.clone(),
SyntheticAmode::NominalSPOffset { simm32 } => { SyntheticAmode::NominalSPOffset { simm32 } => {
@@ -142,6 +148,9 @@ impl SyntheticAmode {
); );
Amode::imm_reg(off as u32, regs::rsp()) Amode::imm_reg(off as u32, regs::rsp())
} }
SyntheticAmode::ConstantOffset(c) => {
Amode::rip_relative(buffer.get_label_for_constant(*c))
}
} }
} }
} }
@@ -159,6 +168,7 @@ impl PrettyPrint for SyntheticAmode {
SyntheticAmode::NominalSPOffset { simm32 } => { SyntheticAmode::NominalSPOffset { simm32 } => {
format!("rsp({} + virtual offset)", *simm32 as i32) format!("rsp({} + virtual offset)", *simm32 as i32)
} }
SyntheticAmode::ConstantOffset(c) => format!("const({:?})", c),
} }
} }
} }

View File

@@ -533,7 +533,7 @@ pub(crate) fn emit(
} }
RegMemImm::Mem { addr } => { RegMemImm::Mem { addr } => {
let amode = addr.finalize(state); let amode = addr.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
state, state,
@@ -592,7 +592,7 @@ pub(crate) fn emit(
RegMemImm::Mem { addr } => { RegMemImm::Mem { addr } => {
// Here we revert to the "normal" G-E ordering. // Here we revert to the "normal" G-E ordering.
let amode = addr.finalize(state); let amode = addr.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
state, state,
@@ -649,7 +649,7 @@ pub(crate) fn emit(
rex_flags, rex_flags,
), ),
RegMem::Mem { addr: src } => { RegMem::Mem { addr: src } => {
let amode = src.finalize(state); let amode = src.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
state, state,
@@ -715,7 +715,7 @@ pub(crate) fn emit(
emit_std_enc_enc(sink, prefix, opcode, 1, subopcode, src, rex_flags) emit_std_enc_enc(sink, prefix, opcode, 1, subopcode, src, rex_flags)
} }
RegMem::Mem { addr: src } => { RegMem::Mem { addr: src } => {
let amode = src.finalize(state); let amode = src.finalize(state, sink);
emit_std_enc_mem(sink, state, prefix, opcode, 1, subopcode, &amode, rex_flags); emit_std_enc_mem(sink, state, prefix, opcode, 1, subopcode, &amode, rex_flags);
} }
} }
@@ -736,7 +736,7 @@ pub(crate) fn emit(
emit_std_enc_enc(sink, prefix, 0xF7, 1, subopcode, src, rex_flags) emit_std_enc_enc(sink, prefix, 0xF7, 1, subopcode, src, rex_flags)
} }
RegMem::Mem { addr: src } => { RegMem::Mem { addr: src } => {
let amode = src.finalize(state); let amode = src.finalize(state, sink);
emit_std_enc_mem(sink, state, prefix, 0xF7, 1, subopcode, &amode, rex_flags); emit_std_enc_mem(sink, state, prefix, 0xF7, 1, subopcode, &amode, rex_flags);
} }
} }
@@ -981,7 +981,7 @@ pub(crate) fn emit(
} }
RegMem::Mem { addr: src } => { RegMem::Mem { addr: src } => {
let src = &src.finalize(state); let src = &src.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
@@ -998,7 +998,7 @@ pub(crate) fn emit(
} }
Inst::Mov64MR { src, dst } => { Inst::Mov64MR { src, dst } => {
let src = &src.finalize(state); let src = &src.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
@@ -1013,7 +1013,7 @@ pub(crate) fn emit(
} }
Inst::LoadEffectiveAddress { addr, dst } => { Inst::LoadEffectiveAddress { addr, dst } => {
let amode = addr.finalize(state); let amode = addr.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
@@ -1075,7 +1075,7 @@ pub(crate) fn emit(
} }
RegMem::Mem { addr: src } => { RegMem::Mem { addr: src } => {
let src = &src.finalize(state); let src = &src.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
@@ -1092,7 +1092,7 @@ pub(crate) fn emit(
} }
Inst::MovRM { size, src, dst } => { Inst::MovRM { size, src, dst } => {
let dst = &dst.finalize(state); let dst = &dst.finalize(state, sink);
match size { match size {
1 => { 1 => {
@@ -1248,7 +1248,7 @@ pub(crate) fn emit(
emit_std_reg_reg(sink, prefix, opcode_bytes, 2, dst.to_reg(), *reg, rex); emit_std_reg_reg(sink, prefix, opcode_bytes, 2, dst.to_reg(), *reg, rex);
} }
RegMemImm::Mem { addr } => { RegMemImm::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
state, state,
@@ -1307,7 +1307,7 @@ pub(crate) fn emit(
} }
RegMemImm::Mem { addr } => { RegMemImm::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
// Whereas here we revert to the "normal" G-E ordering. // Whereas here we revert to the "normal" G-E ordering.
let opcode = if *size == 1 { 0x3A } else { 0x3B }; let opcode = if *size == 1 { 0x3A } else { 0x3B };
emit_std_reg_mem(sink, state, prefix, opcode, 1, *reg_g, addr, rex); emit_std_reg_mem(sink, state, prefix, opcode, 1, *reg_g, addr, rex);
@@ -1367,7 +1367,7 @@ pub(crate) fn emit(
emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex_flags); emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex_flags);
} }
RegMem::Mem { addr } => { RegMem::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
state, state,
@@ -1418,7 +1418,7 @@ pub(crate) fn emit(
} }
RegMemImm::Mem { addr } => { RegMemImm::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_enc_mem( emit_std_enc_mem(
sink, sink,
state, state,
@@ -1484,7 +1484,7 @@ pub(crate) fn emit(
} }
RegMem::Mem { addr } => { RegMem::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_enc_mem( emit_std_enc_mem(
sink, sink,
state, state,
@@ -1582,7 +1582,7 @@ pub(crate) fn emit(
} }
RegMem::Mem { addr } => { RegMem::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_enc_mem( emit_std_enc_mem(
sink, sink,
state, state,
@@ -1728,7 +1728,7 @@ pub(crate) fn emit(
); );
} }
RegMem::Mem { addr } => { RegMem::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
state, state,
@@ -1841,7 +1841,7 @@ pub(crate) fn emit(
emit_std_reg_reg(sink, prefix, opcode, length, reg_g.to_reg(), *reg_e, rex); emit_std_reg_reg(sink, prefix, opcode, length, reg_g.to_reg(), *reg_e, rex);
} }
RegMem::Mem { addr } => { RegMem::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
state, state,
@@ -1986,7 +1986,7 @@ pub(crate) fn emit(
} }
} }
RegMem::Mem { addr } => { RegMem::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
assert!( assert!(
!regs_swapped, !regs_swapped,
"No existing way to encode a mem argument in the ModRM r/m field." "No existing way to encode a mem argument in the ModRM r/m field."
@@ -2020,7 +2020,7 @@ pub(crate) fn emit(
SseOpcode::Movupd => (LegacyPrefixes::_66, 0x0F11), SseOpcode::Movupd => (LegacyPrefixes::_66, 0x0F11),
_ => unimplemented!("Opcode {:?} not implemented", op), _ => unimplemented!("Opcode {:?} not implemented", op),
}; };
let dst = &dst.finalize(state); let dst = &dst.finalize(state, sink);
emit_std_reg_mem( emit_std_reg_mem(
sink, sink,
state, state,
@@ -2087,7 +2087,7 @@ pub(crate) fn emit(
emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex); emit_std_reg_reg(sink, prefix, opcode, 2, reg_g.to_reg(), *reg_e, rex);
} }
RegMem::Mem { addr } => { RegMem::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_reg_mem(sink, state, prefix, opcode, 2, reg_g.to_reg(), addr, rex); emit_std_reg_mem(sink, state, prefix, opcode, 2, reg_g.to_reg(), addr, rex);
} }
} }
@@ -2107,7 +2107,7 @@ pub(crate) fn emit(
emit_std_reg_reg(sink, prefix, opcode, len, *dst, *reg, rex); emit_std_reg_reg(sink, prefix, opcode, len, *dst, *reg, rex);
} }
RegMem::Mem { addr } => { RegMem::Mem { addr } => {
let addr = &addr.finalize(state); let addr = &addr.finalize(state, sink);
emit_std_reg_mem(sink, state, prefix, opcode, len, *dst, addr, rex); emit_std_reg_mem(sink, state, prefix, opcode, len, *dst, addr, rex);
} }
} }
@@ -2621,7 +2621,7 @@ pub(crate) fn emit(
types::I64 => (LegacyPrefixes::_F0, RexFlags::set_w(), 0x0FB1), types::I64 => (LegacyPrefixes::_F0, RexFlags::set_w(), 0x0FB1),
_ => unreachable!(), _ => unreachable!(),
}; };
let amode = dst.finalize(state); let amode = dst.finalize(state, sink);
emit_std_reg_mem(sink, state, prefix, opcodes, 2, *src, &amode, rex); emit_std_reg_mem(sink, state, prefix, opcodes, 2, *src, &amode, rex);
} }