From f0979af157741e32fb71e5720a5250e85a91d7ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Cabrera?= Date: Fri, 13 Jan 2023 14:46:25 -0500 Subject: [PATCH] cranelift-codegen: Prepare aarch64 for usage from Winch (#5570) This commit exposes the necessary aarch64 pieces to be used by Winch for binary emission. --- .../codegen/src/isa/aarch64/inst/args.rs | 63 +++++++++++++++++-- .../codegen/src/isa/aarch64/inst/emit.rs | 3 +- .../codegen/src/isa/aarch64/inst/imms.rs | 16 ++++- cranelift/codegen/src/isa/aarch64/inst/mod.rs | 26 ++++++-- .../isa/aarch64/lower/isle/generated_code.rs | 2 +- cranelift/codegen/src/isa/aarch64/mod.rs | 4 +- cranelift/codegen/src/isa/mod.rs | 2 +- 7 files changed, 98 insertions(+), 18 deletions(-) diff --git a/cranelift/codegen/src/isa/aarch64/inst/args.rs b/cranelift/codegen/src/isa/aarch64/inst/args.rs index 22a7d17acfea..69eb7e525185 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/args.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/args.rs @@ -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, diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index 15ed484dfef8..94ba0d55848e 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -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) } } diff --git a/cranelift/codegen/src/isa/aarch64/inst/imms.rs b/cranelift/codegen/src/isa/aarch64/inst/imms.rs index 47be7a449804..77c80d0e350c 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/imms.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/imms.rs @@ -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 { 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 { 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 { 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 { 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 } } diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index 06c1f26d8946..7ad3e1f0bdd0 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -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, + /// Default branch target. pub default_target: BranchTarget, } diff --git a/cranelift/codegen/src/isa/aarch64/lower/isle/generated_code.rs b/cranelift/codegen/src/isa/aarch64/lower/isle/generated_code.rs index 70a097f89763..f00fd2f86c16 100644 --- a/cranelift/codegen/src/isa/aarch64/lower/isle/generated_code.rs +++ b/cranelift/codegen/src/isa/aarch64/lower/isle/generated_code.rs @@ -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)] diff --git a/cranelift/codegen/src/isa/aarch64/mod.rs b/cranelift/codegen/src/isa/aarch64/mod.rs index b68fda1661df..e1e1d4f9e9d0 100644 --- a/cranelift/codegen/src/isa/aarch64/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/mod.rs @@ -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; diff --git a/cranelift/codegen/src/isa/mod.rs b/cranelift/codegen/src/isa/mod.rs index ec8edd1865b7..3d1e6f977ced 100644 --- a/cranelift/codegen/src/isa/mod.rs +++ b/cranelift/codegen/src/isa/mod.rs @@ -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;