* Rename size to base_size and introduce a compute_size function; * Add infra to inspect in/outs registers when computing the size of an instruction; * Remove the GPR_SAFE_DEREF and GPR_ZERO_DEREF_SAFE register classes on x86 (fixes #335);
This commit is contained in:
committed by
Dan Gohman
parent
c2069762ef
commit
9d6821d6d9
@@ -1,7 +1,9 @@
|
||||
//! The `Encoding` struct.
|
||||
|
||||
use binemit::CodeOffset;
|
||||
use ir::{Function, Inst};
|
||||
use isa::constraints::{BranchRange, RecipeConstraints};
|
||||
use regalloc::RegDiversions;
|
||||
use std::fmt;
|
||||
|
||||
/// Bits needed to encode an instruction as binary machine code.
|
||||
@@ -78,12 +80,24 @@ impl fmt::Display for DisplayEncoding {
|
||||
}
|
||||
}
|
||||
|
||||
type SizeCalculatorFn = fn(&RecipeSizing, Inst, &RegDiversions, &Function) -> u8;
|
||||
|
||||
/// Returns the base size of the Recipe, assuming it's fixed. This is the default for most
|
||||
/// encodings; others can be variable and longer than this base size, depending on the registers
|
||||
/// they're using and use a different function, specific per platform.
|
||||
pub fn base_size(sizing: &RecipeSizing, _: Inst, _2: &RegDiversions, _3: &Function) -> u8 {
|
||||
sizing.base_size
|
||||
}
|
||||
|
||||
/// Code size information for an encoding recipe.
|
||||
///
|
||||
/// All encoding recipes correspond to an exact instruction size.
|
||||
pub struct RecipeSizing {
|
||||
/// Size in bytes of instructions encoded with this recipe.
|
||||
pub bytes: u8,
|
||||
pub base_size: u8,
|
||||
|
||||
/// Method computing the real instruction's size, given inputs and outputs.
|
||||
pub compute_size: SizeCalculatorFn,
|
||||
|
||||
/// Allowed branch range in this recipe, if any.
|
||||
///
|
||||
@@ -118,13 +132,20 @@ impl EncInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the exact size in bytes of instructions encoded with `enc`.
|
||||
/// Get the precise size in bytes of instructions encoded with `enc`.
|
||||
///
|
||||
/// Returns 0 for illegal encodings.
|
||||
pub fn bytes(&self, enc: Encoding) -> CodeOffset {
|
||||
self.sizing
|
||||
.get(enc.recipe())
|
||||
.map_or(0, |s| CodeOffset::from(s.bytes))
|
||||
pub fn byte_size(
|
||||
&self,
|
||||
enc: Encoding,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> CodeOffset {
|
||||
self.sizing.get(enc.recipe()).map_or(0, |s| {
|
||||
let compute_size = s.compute_size;
|
||||
CodeOffset::from(compute_size(&s, inst, divert, func))
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the branch range that is supported by `enc`, if any.
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
//! concurrent function compilations.
|
||||
|
||||
pub use isa::constraints::{BranchRange, ConstraintKind, OperandConstraint, RecipeConstraints};
|
||||
pub use isa::encoding::{EncInfo, Encoding};
|
||||
pub use isa::encoding::{base_size, EncInfo, Encoding};
|
||||
pub use isa::registers::{regs_overlap, RegClass, RegClassIndex, RegInfo, RegUnit};
|
||||
pub use isa::stack::{StackBase, StackBaseMask, StackRef};
|
||||
|
||||
@@ -204,7 +204,7 @@ pub trait TargetIsa: fmt::Display {
|
||||
/// Get a data structure describing the registers in this ISA.
|
||||
fn register_info(&self) -> RegInfo;
|
||||
|
||||
/// Returns an iterartor over legal encodings for the instruction.
|
||||
/// Returns an iterator over legal encodings for the instruction.
|
||||
fn legal_encodings<'a>(
|
||||
&'a self,
|
||||
func: &'a ir::Function,
|
||||
|
||||
@@ -5,7 +5,7 @@ use ir;
|
||||
use isa;
|
||||
use isa::constraints::*;
|
||||
use isa::enc_tables::*;
|
||||
use isa::encoding::RecipeSizing;
|
||||
use isa::encoding::{base_size, RecipeSizing};
|
||||
|
||||
// Include the generated encoding tables:
|
||||
// - `LEVEL1_RV32`
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//! Emitting binary x86 machine code.
|
||||
|
||||
use super::enc_tables::{needs_offset, needs_sib_byte};
|
||||
use super::registers::RU;
|
||||
use binemit::{bad_encoding, CodeSink, Reloc};
|
||||
use ir::condcodes::{CondCode, FloatCC, IntCC};
|
||||
|
||||
@@ -5,15 +5,73 @@ use bitset::BitSet;
|
||||
use cursor::{Cursor, FuncCursor};
|
||||
use flowgraph::ControlFlowGraph;
|
||||
use ir::condcodes::IntCC;
|
||||
use ir::{self, InstBuilder};
|
||||
use ir::{self, Function, Inst, InstBuilder};
|
||||
use isa;
|
||||
use isa::constraints::*;
|
||||
use isa::enc_tables::*;
|
||||
use isa::encoding::base_size;
|
||||
use isa::encoding::RecipeSizing;
|
||||
use isa::RegUnit;
|
||||
use regalloc::RegDiversions;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/encoding-x86.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/legalize-x86.rs"));
|
||||
|
||||
pub fn needs_sib_byte(reg: RegUnit) -> bool {
|
||||
reg == RU::r12 as RegUnit || reg == RU::rsp as RegUnit
|
||||
}
|
||||
pub fn needs_offset(reg: RegUnit) -> bool {
|
||||
reg == RU::r13 as RegUnit || reg == RU::rbp as RegUnit
|
||||
}
|
||||
|
||||
fn additional_size_if(
|
||||
op_index: usize,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
condition_func: fn(RegUnit) -> bool,
|
||||
) -> u8 {
|
||||
let addr_reg = divert.reg(func.dfg.inst_args(inst)[op_index], &func.locations);
|
||||
if condition_func(addr_reg) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn size_plus_maybe_offset_for_in_reg_0(
|
||||
sizing: &RecipeSizing,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
sizing.base_size + additional_size_if(0, inst, divert, func, needs_offset)
|
||||
}
|
||||
fn size_plus_maybe_offset_for_in_reg_1(
|
||||
sizing: &RecipeSizing,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
sizing.base_size + additional_size_if(1, inst, divert, func, needs_offset)
|
||||
}
|
||||
fn size_plus_maybe_sib_for_in_reg_0(
|
||||
sizing: &RecipeSizing,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
sizing.base_size + additional_size_if(0, inst, divert, func, needs_sib_byte)
|
||||
}
|
||||
fn size_plus_maybe_sib_for_in_reg_1(
|
||||
sizing: &RecipeSizing,
|
||||
inst: Inst,
|
||||
divert: &RegDiversions,
|
||||
func: &Function,
|
||||
) -> u8 {
|
||||
sizing.base_size + additional_size_if(1, inst, divert, func, needs_sib_byte)
|
||||
}
|
||||
|
||||
/// Expand the `sdiv` and `srem` instructions using `x86_sdivmodx`.
|
||||
fn expand_sdivrem(
|
||||
inst: ir::Inst,
|
||||
|
||||
Reference in New Issue
Block a user