Remove BranchRange
This commit is contained in:
@@ -1,66 +0,0 @@
|
|||||||
//! Register constraints for instruction operands.
|
|
||||||
//!
|
|
||||||
//! An encoding recipe specifies how an instruction is encoded as binary machine code, but it only
|
|
||||||
//! works if the operands and results satisfy certain constraints. Constraints on immediate
|
|
||||||
//! operands are checked by instruction predicates when the recipe is chosen.
|
|
||||||
//!
|
|
||||||
//! It is the register allocator's job to make sure that the register constraints on value operands
|
|
||||||
//! are satisfied.
|
|
||||||
|
|
||||||
use crate::binemit::CodeOffset;
|
|
||||||
|
|
||||||
/// Constraints on the range of a branch instruction.
|
|
||||||
///
|
|
||||||
/// A branch instruction usually encodes its destination as a signed n-bit offset from an origin.
|
|
||||||
/// The origin depends on the ISA and the specific instruction:
|
|
||||||
///
|
|
||||||
/// - RISC-V and ARM Aarch64 use the address of the branch instruction, `origin = 0`.
|
|
||||||
/// - x86 uses the address of the instruction following the branch, `origin = 2` for a 2-byte
|
|
||||||
/// branch instruction.
|
|
||||||
/// - ARM's A32 encoding uses the address of the branch instruction + 8 bytes, `origin = 8`.
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub struct BranchRange {
|
|
||||||
/// Offset in bytes from the address of the branch instruction to the origin used for computing
|
|
||||||
/// the branch displacement. This is the destination of a branch that encodes a 0 displacement.
|
|
||||||
pub origin: u8,
|
|
||||||
|
|
||||||
/// Number of bits in the signed byte displacement encoded in the instruction. This does not
|
|
||||||
/// account for branches that can only target aligned addresses.
|
|
||||||
pub bits: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BranchRange {
|
|
||||||
/// Determine if this branch range can represent the range from `branch` to `dest`, where
|
|
||||||
/// `branch` is the code offset of the branch instruction itself and `dest` is the code offset
|
|
||||||
/// of the destination block header.
|
|
||||||
///
|
|
||||||
/// This method does not detect if the range is larger than 2 GB.
|
|
||||||
pub fn contains(self, branch: CodeOffset, dest: CodeOffset) -> bool {
|
|
||||||
let d = dest.wrapping_sub(branch + CodeOffset::from(self.origin)) as i32;
|
|
||||||
let s = 32 - self.bits;
|
|
||||||
d == d << s >> s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn branch_range() {
|
|
||||||
// ARM T1 branch.
|
|
||||||
let t1 = BranchRange { origin: 4, bits: 9 };
|
|
||||||
assert!(t1.contains(0, 0));
|
|
||||||
assert!(t1.contains(0, 2));
|
|
||||||
assert!(t1.contains(2, 0));
|
|
||||||
assert!(t1.contains(1000, 1000));
|
|
||||||
|
|
||||||
// Forward limit.
|
|
||||||
assert!(t1.contains(1000, 1258));
|
|
||||||
assert!(!t1.contains(1000, 1260));
|
|
||||||
|
|
||||||
// Backward limit
|
|
||||||
assert!(t1.contains(1000, 748));
|
|
||||||
assert!(!t1.contains(1000, 746));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -44,7 +44,6 @@
|
|||||||
//! concurrent function compilations.
|
//! concurrent function compilations.
|
||||||
|
|
||||||
pub use crate::isa::call_conv::CallConv;
|
pub use crate::isa::call_conv::CallConv;
|
||||||
pub use crate::isa::constraints::BranchRange;
|
|
||||||
|
|
||||||
use crate::flowgraph;
|
use crate::flowgraph;
|
||||||
use crate::ir;
|
use crate::ir;
|
||||||
@@ -76,7 +75,6 @@ mod s390x;
|
|||||||
pub mod unwind;
|
pub mod unwind;
|
||||||
|
|
||||||
mod call_conv;
|
mod call_conv;
|
||||||
mod constraints;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_utils;
|
mod test_utils;
|
||||||
|
|||||||
Reference in New Issue
Block a user