Skip to content

Commit

Permalink
cranelift-codegen: Prepare aarch64 for usage from Winch (#5570)
Browse files Browse the repository at this point in the history
This commit exposes the necessary aarch64 pieces to be used by Winch for binary emission.
  • Loading branch information
saulecabrera authored Jan 13, 2023
1 parent 7682a40 commit f0979af
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 18 deletions.
63 changes: 57 additions & 6 deletions cranelift/codegen/src/isa/aarch64/inst/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down Expand Up @@ -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 }
}
Expand All @@ -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,
}

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) => {
Expand All @@ -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,
}

Expand Down Expand Up @@ -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,
}

Expand All @@ -517,6 +549,7 @@ impl OperandSize {
}
}

/// Return the operand size in bits.
pub fn bits(&self) -> u8 {
match self {
OperandSize::Size32 => 32,
Expand All @@ -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,
Expand All @@ -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,
}

Expand All @@ -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,
Expand All @@ -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"),
Expand All @@ -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,
}

Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion cranelift/codegen/src/isa/aarch64/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
16 changes: 14 additions & 2 deletions cranelift/codegen/src/isa/aarch64/inst/imms.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -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 }
}
Expand All @@ -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 })
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand All @@ -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 {
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand All @@ -608,6 +619,7 @@ impl MoveWideConst {
}
}

/// Create a zero immediate of this format.
pub fn zero() -> MoveWideConst {
MoveWideConst { bits: 0, shift: 0 }
}
Expand Down
26 changes: 21 additions & 5 deletions cranelift/codegen/src/isa/aarch64/inst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -78,33 +78,49 @@ 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,
}

/// Additional information for CallInd instructions, left out of line to lower the size of the Inst
/// 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,
}

/// Additional information for JTSequence instructions, left out of line to lower the size of the Inst
/// enum.
#[derive(Clone, Debug)]
pub struct JTSequenceInfo {
/// Possible branch targets.
pub targets: Vec<BranchTarget>,
/// Default branch target.
pub default_target: BranchTarget,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)]

Expand Down
Loading

0 comments on commit f0979af

Please sign in to comment.