cranelift-codegen: Prepare aarch64 for usage from Winch (#5570)
This commit exposes the necessary aarch64 pieces to be used by Winch for binary emission.
This commit is contained in:
@@ -14,12 +14,13 @@ use std::string::String;
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(u8)]
|
||||
pub enum ShiftOp {
|
||||
/// Logical shift left.
|
||||
LSL = 0b00,
|
||||
#[allow(dead_code)]
|
||||
/// Logical shift right.
|
||||
LSR = 0b01,
|
||||
#[allow(dead_code)]
|
||||
/// Arithmentic shift right.
|
||||
ASR = 0b10,
|
||||
#[allow(dead_code)]
|
||||
/// Rotate right.
|
||||
ROR = 0b11,
|
||||
}
|
||||
|
||||
@@ -61,11 +62,14 @@ impl ShiftOpShiftImm {
|
||||
/// A shift operator with an amount, guaranteed to be within range.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ShiftOpAndAmt {
|
||||
/// The shift operator.
|
||||
op: ShiftOp,
|
||||
/// The shift operator amount.
|
||||
shift: ShiftOpShiftImm,
|
||||
}
|
||||
|
||||
impl ShiftOpAndAmt {
|
||||
/// Create a new shift operator with an amount.
|
||||
pub fn new(op: ShiftOp, shift: ShiftOpShiftImm) -> ShiftOpAndAmt {
|
||||
ShiftOpAndAmt { op, shift }
|
||||
}
|
||||
@@ -85,14 +89,21 @@ impl ShiftOpAndAmt {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(u8)]
|
||||
pub enum ExtendOp {
|
||||
/// Unsigned extend byte.
|
||||
UXTB = 0b000,
|
||||
/// Unsigned extend halfword.
|
||||
UXTH = 0b001,
|
||||
/// Unsigned extend word.
|
||||
UXTW = 0b010,
|
||||
/// Unsigned extend doubleword.
|
||||
UXTX = 0b011,
|
||||
/// Signed extend byte.
|
||||
SXTB = 0b100,
|
||||
/// Signed extend halfword.
|
||||
SXTH = 0b101,
|
||||
/// Signed extend word.
|
||||
SXTW = 0b110,
|
||||
#[allow(dead_code)]
|
||||
/// Signed extend doubleword.
|
||||
SXTX = 0b111,
|
||||
}
|
||||
|
||||
@@ -137,7 +148,7 @@ impl AMode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_allocs(&self, allocs: &mut AllocationConsumer<'_>) -> Self {
|
||||
pub(crate) fn with_allocs(&self, allocs: &mut AllocationConsumer<'_>) -> Self {
|
||||
// This should match `memarg_operands()`.
|
||||
match self {
|
||||
&AMode::Unscaled { rn, simm9 } => AMode::Unscaled {
|
||||
@@ -191,13 +202,16 @@ impl AMode {
|
||||
/// A memory argument to a load/store-pair.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PairAMode {
|
||||
/// Signed, scaled 7-bit offset from a register.
|
||||
SignedOffset(Reg, SImm7Scaled),
|
||||
/// Pre-increment register before address computation.
|
||||
SPPreIndexed(SImm7Scaled),
|
||||
/// Post-increment register after address computation.
|
||||
SPPostIndexed(SImm7Scaled),
|
||||
}
|
||||
|
||||
impl PairAMode {
|
||||
pub fn with_allocs(&self, allocs: &mut AllocationConsumer<'_>) -> Self {
|
||||
pub(crate) fn with_allocs(&self, allocs: &mut AllocationConsumer<'_>) -> Self {
|
||||
// Should match `pairmemarg_operands()`.
|
||||
match self {
|
||||
&PairAMode::SignedOffset(reg, simm7scaled) => {
|
||||
@@ -216,21 +230,37 @@ impl PairAMode {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum Cond {
|
||||
/// Equal.
|
||||
Eq = 0,
|
||||
/// Not equal.
|
||||
Ne = 1,
|
||||
/// Unsigned greater than or equal to.
|
||||
Hs = 2,
|
||||
/// Unsigned less than.
|
||||
Lo = 3,
|
||||
/// Minus, negative.
|
||||
Mi = 4,
|
||||
/// Positive or zero.
|
||||
Pl = 5,
|
||||
/// Signed overflow.
|
||||
Vs = 6,
|
||||
/// No signed overflow.
|
||||
Vc = 7,
|
||||
/// Unsigned greater than.
|
||||
Hi = 8,
|
||||
/// Unsigned less than or equal to.
|
||||
Ls = 9,
|
||||
/// Signed greater or equal to.
|
||||
Ge = 10,
|
||||
/// Signed less than.
|
||||
Lt = 11,
|
||||
/// Signed greater than.
|
||||
Gt = 12,
|
||||
/// Signed less than or equal.
|
||||
Le = 13,
|
||||
/// Always executed.
|
||||
Al = 14,
|
||||
/// Always executed.
|
||||
Nv = 15,
|
||||
}
|
||||
|
||||
@@ -491,7 +521,9 @@ impl PrettyPrint for BranchTarget {
|
||||
/// 64-bit variants of many instructions (and integer registers).
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum OperandSize {
|
||||
/// 32-bit.
|
||||
Size32,
|
||||
/// 64-bit.
|
||||
Size64,
|
||||
}
|
||||
|
||||
@@ -517,6 +549,7 @@ impl OperandSize {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the operand size in bits.
|
||||
pub fn bits(&self) -> u8 {
|
||||
match self {
|
||||
OperandSize::Size32 => 32,
|
||||
@@ -539,6 +572,9 @@ impl OperandSize {
|
||||
}
|
||||
}
|
||||
|
||||
/// Register interpretation bit.
|
||||
/// When 0, the register is interpreted as the 32-bit version.
|
||||
/// When 1, the register is interpreted as the 64-bit version.
|
||||
pub fn sf_bit(&self) -> u32 {
|
||||
match self {
|
||||
OperandSize::Size32 => 0,
|
||||
@@ -550,10 +586,15 @@ impl OperandSize {
|
||||
/// Type used to communicate the size of a scalar SIMD & FP operand.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ScalarSize {
|
||||
/// 8-bit.
|
||||
Size8,
|
||||
/// 16-bit.
|
||||
Size16,
|
||||
/// 32-bit.
|
||||
Size32,
|
||||
/// 64-bit.
|
||||
Size64,
|
||||
/// 128-bit.
|
||||
Size128,
|
||||
}
|
||||
|
||||
@@ -578,6 +619,7 @@ impl ScalarSize {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the widened version of the scalar size.
|
||||
pub fn widen(&self) -> ScalarSize {
|
||||
match self {
|
||||
ScalarSize::Size8 => ScalarSize::Size16,
|
||||
@@ -588,6 +630,7 @@ impl ScalarSize {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the narrowed version of the scalar size.
|
||||
pub fn narrow(&self) -> ScalarSize {
|
||||
match self {
|
||||
ScalarSize::Size8 => panic!("can't narrow 8-bits"),
|
||||
@@ -602,12 +645,19 @@ impl ScalarSize {
|
||||
/// Type used to communicate the size of a vector operand.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum VectorSize {
|
||||
/// 8-bit, 8 lanes.
|
||||
Size8x8,
|
||||
/// 8 bit, 16 lanes.
|
||||
Size8x16,
|
||||
/// 16-bit, 4 lanes.
|
||||
Size16x4,
|
||||
/// 16-bit, 8 lanes.
|
||||
Size16x8,
|
||||
/// 32-bit, 2 lanes.
|
||||
Size32x2,
|
||||
/// 32-bit, 4 lanes.
|
||||
Size32x4,
|
||||
/// 64-bit, 2 lanes.
|
||||
Size64x2,
|
||||
}
|
||||
|
||||
@@ -644,6 +694,7 @@ impl VectorSize {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the VectorSize is 128-bits.
|
||||
pub fn is_128bits(&self) -> bool {
|
||||
match self {
|
||||
VectorSize::Size8x8 => false,
|
||||
|
||||
@@ -675,7 +675,8 @@ impl EmitState {
|
||||
pub struct EmitInfo(settings::Flags);
|
||||
|
||||
impl EmitInfo {
|
||||
pub(crate) fn new(flags: settings::Flags) -> Self {
|
||||
/// Create a constant state for emission of instructions.
|
||||
pub fn new(flags: settings::Flags) -> Self {
|
||||
Self(flags)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
//! AArch64 ISA definitions: immediate constants.
|
||||
|
||||
// Some variants are never constructed, but we still want them as options in the future.
|
||||
#[allow(dead_code)]
|
||||
use crate::ir::types::*;
|
||||
use crate::ir::Type;
|
||||
use crate::isa::aarch64::inst::{OperandSize, ScalarSize};
|
||||
@@ -24,6 +22,7 @@ pub struct NZCV {
|
||||
}
|
||||
|
||||
impl NZCV {
|
||||
/// Create a new NZCV flags representation.
|
||||
pub fn new(n: bool, z: bool, c: bool, v: bool) -> NZCV {
|
||||
NZCV { n, z, c, v }
|
||||
}
|
||||
@@ -45,6 +44,7 @@ pub struct UImm5 {
|
||||
}
|
||||
|
||||
impl UImm5 {
|
||||
/// Create an unsigned 5-bit immediate from u8.
|
||||
pub fn maybe_from_u8(value: u8) -> Option<UImm5> {
|
||||
if value < 32 {
|
||||
Some(UImm5 { value })
|
||||
@@ -99,13 +99,17 @@ impl SImm7Scaled {
|
||||
}
|
||||
}
|
||||
|
||||
/// Floating-point unit immediate left shift.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct FPULeftShiftImm {
|
||||
/// Shift amount.
|
||||
pub amount: u8,
|
||||
/// Lane size in bits.
|
||||
pub lane_size_in_bits: u8,
|
||||
}
|
||||
|
||||
impl FPULeftShiftImm {
|
||||
/// Create a floating-point unit immediate left shift from u8.
|
||||
pub fn maybe_from_u8(amount: u8, lane_size_in_bits: u8) -> Option<Self> {
|
||||
debug_assert!(lane_size_in_bits == 32 || lane_size_in_bits == 64);
|
||||
if amount < lane_size_in_bits {
|
||||
@@ -118,6 +122,7 @@ impl FPULeftShiftImm {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the encoding of the immediate.
|
||||
pub fn enc(&self) -> u32 {
|
||||
debug_assert!(self.lane_size_in_bits.is_power_of_two());
|
||||
debug_assert!(self.lane_size_in_bits > self.amount);
|
||||
@@ -139,13 +144,17 @@ impl FPULeftShiftImm {
|
||||
}
|
||||
}
|
||||
|
||||
/// Floating-point unit immediate right shift.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct FPURightShiftImm {
|
||||
/// Shift amount.
|
||||
pub amount: u8,
|
||||
/// Lane size in bits.
|
||||
pub lane_size_in_bits: u8,
|
||||
}
|
||||
|
||||
impl FPURightShiftImm {
|
||||
/// Create a floating-point unit immediate right shift from u8.
|
||||
pub fn maybe_from_u8(amount: u8, lane_size_in_bits: u8) -> Option<Self> {
|
||||
debug_assert!(lane_size_in_bits == 32 || lane_size_in_bits == 64);
|
||||
if amount > 0 && amount <= lane_size_in_bits {
|
||||
@@ -158,6 +167,7 @@ impl FPURightShiftImm {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns encoding of the immediate.
|
||||
pub fn enc(&self) -> u32 {
|
||||
debug_assert_ne!(0, self.amount);
|
||||
// The encoding of the immediate follows the table below,
|
||||
@@ -596,6 +606,7 @@ impl MoveWideConst {
|
||||
None
|
||||
}
|
||||
|
||||
/// Create a `MoveWideCosnt` from a given shift, if possible.
|
||||
pub fn maybe_with_shift(imm: u16, shift: u8) -> Option<MoveWideConst> {
|
||||
let shift_enc = shift / 16;
|
||||
if shift_enc > 3 {
|
||||
@@ -608,6 +619,7 @@ impl MoveWideConst {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a zero immediate of this format.
|
||||
pub fn zero() -> MoveWideConst {
|
||||
MoveWideConst { bits: 0, shift: 0 }
|
||||
}
|
||||
|
||||
@@ -15,17 +15,17 @@ use regalloc2::{PRegSet, VReg};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::string::{String, ToString};
|
||||
|
||||
pub mod regs;
|
||||
pub use self::regs::*;
|
||||
pub(crate) mod regs;
|
||||
pub(crate) use self::regs::*;
|
||||
pub mod imms;
|
||||
pub use self::imms::*;
|
||||
pub mod args;
|
||||
pub use self::args::*;
|
||||
pub mod emit;
|
||||
pub use self::emit::*;
|
||||
pub(crate) mod emit;
|
||||
pub(crate) use self::emit::*;
|
||||
use crate::isa::aarch64::abi::AArch64MachineDeps;
|
||||
|
||||
pub mod unwind;
|
||||
pub(crate) mod unwind;
|
||||
|
||||
#[cfg(test)]
|
||||
mod emit_tests;
|
||||
@@ -78,12 +78,19 @@ impl BitOp {
|
||||
/// the Inst enum.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CallInfo {
|
||||
/// Call destination.
|
||||
pub dest: ExternalName,
|
||||
/// Arguments to the call instruction.
|
||||
pub uses: CallArgList,
|
||||
/// Return values from the call instruction.
|
||||
pub defs: CallRetList,
|
||||
/// Clobbers register set.
|
||||
pub clobbers: PRegSet,
|
||||
/// Instruction opcode.
|
||||
pub opcode: Opcode,
|
||||
/// Caller calling convention.
|
||||
pub caller_callconv: CallConv,
|
||||
/// Callee calling convention.
|
||||
pub callee_callconv: CallConv,
|
||||
}
|
||||
|
||||
@@ -91,12 +98,19 @@ pub struct CallInfo {
|
||||
/// enum.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CallIndInfo {
|
||||
/// Function pointer for indirect call.
|
||||
pub rn: Reg,
|
||||
/// Arguments to the call instruction.
|
||||
pub uses: SmallVec<[CallArgPair; 8]>,
|
||||
/// Return values from the call instruction.
|
||||
pub defs: SmallVec<[CallRetPair; 8]>,
|
||||
/// Clobbers register set.
|
||||
pub clobbers: PRegSet,
|
||||
/// Instruction opcode.
|
||||
pub opcode: Opcode,
|
||||
/// Caller calling convention.
|
||||
pub caller_callconv: CallConv,
|
||||
/// Callee calling convention.
|
||||
pub callee_callconv: CallConv,
|
||||
}
|
||||
|
||||
@@ -104,7 +118,9 @@ pub struct CallIndInfo {
|
||||
/// enum.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct JTSequenceInfo {
|
||||
/// Possible branch targets.
|
||||
pub targets: Vec<BranchTarget>,
|
||||
/// Default branch target.
|
||||
pub default_target: BranchTarget,
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// the generated ISLE source below because we include!() it. We must include!() it because its path
|
||||
// depends on an environment variable; and also because of this, we can't do the `#[path = "..."]
|
||||
// mod generated_code;` trick either.
|
||||
#![allow(dead_code, unreachable_code, unreachable_patterns)]
|
||||
#![allow(missing_docs, dead_code, unreachable_code, unreachable_patterns)]
|
||||
#![allow(unused_imports, unused_variables, non_snake_case, unused_mut)]
|
||||
#![allow(irrefutable_let_patterns, unused_assignments, non_camel_case_types)]
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ use target_lexicon::{Aarch64Architecture, Architecture, OperatingSystem, Triple}
|
||||
|
||||
// New backend:
|
||||
mod abi;
|
||||
pub(crate) mod inst;
|
||||
pub mod inst;
|
||||
mod lower;
|
||||
mod settings;
|
||||
pub mod settings;
|
||||
|
||||
use inst::create_reg_env;
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ use target_lexicon::{triple, Architecture, PointerWidth, Triple};
|
||||
pub mod x64;
|
||||
|
||||
#[cfg(feature = "arm64")]
|
||||
pub(crate) mod aarch64;
|
||||
pub mod aarch64;
|
||||
|
||||
#[cfg(feature = "riscv64")]
|
||||
pub mod riscv64;
|
||||
|
||||
Reference in New Issue
Block a user