From 7adf3cacc50a10512e001552aa5b9d84ab238cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Cabrera?= Date: Mon, 12 Dec 2022 12:01:06 -0500 Subject: [PATCH] cranelift-codegen: Prepare cranelift codegen for usage from Winch (#5413) This commit prepares the x64 pieces from cranelift codegen to be consumed by Winch for binary emission. This change doesn't introduce or modifies functionality it makes the necessary pieces for binary emission public. This change also improves documentation where applicable. --- cranelift/codegen/src/isa/x64/inst/args.rs | 124 +++++++++++++++--- cranelift/codegen/src/isa/x64/inst/mod.rs | 3 +- .../src/isa/x64/lower/isle/generated_code.rs | 7 +- cranelift/codegen/src/isa/x64/mod.rs | 2 +- cranelift/codegen/src/lib.rs | 5 +- 5 files changed, 119 insertions(+), 22 deletions(-) diff --git a/cranelift/codegen/src/isa/x64/inst/args.rs b/cranelift/codegen/src/isa/x64/inst/args.rs index b792e528a1..0d202082c7 100644 --- a/cranelift/codegen/src/isa/x64/inst/args.rs +++ b/cranelift/codegen/src/isa/x64/inst/args.rs @@ -14,11 +14,13 @@ use std::string::String; /// An extenstion trait for converting `Writable{Xmm,Gpr}` to `Writable`. pub trait ToWritableReg { + /// Convert `Writable{Xmm,Gpr}` to `Writable`. fn to_writable_reg(&self) -> Writable; } /// An extension trait for converting `Writable` to `Writable{Xmm,Gpr}`. pub trait FromWritableReg: Sized { + /// Convert `Writable` to `Writable{Xmm,Gpr}`. fn from_writable_reg(w: Writable) -> Option; } @@ -81,9 +83,11 @@ macro_rules! newtype_of_reg { } } + /// Writable Gpr. pub type $newtype_writable_reg = Writable<$newtype_reg>; #[allow(dead_code)] // Used by some newtypes and not others. + /// Optional writable Gpr. pub type $newtype_option_writable_reg = Option>; impl ToWritableReg for $newtype_writable_reg { @@ -132,7 +136,7 @@ macro_rules! newtype_of_reg { } #[allow(dead_code)] // Used by some newtypes and not others. - pub fn get_operands VReg>( + pub(crate) fn get_operands VReg>( &self, collector: &mut OperandCollector<'_, F>, ) { @@ -181,7 +185,7 @@ macro_rules! newtype_of_reg { } #[allow(dead_code)] // Used by some newtypes and not others. - pub fn get_operands VReg>( + pub(crate) fn get_operands VReg>( &self, collector: &mut OperandCollector<'_, F>, ) { @@ -256,7 +260,8 @@ newtype_of_reg!( pub use crate::isa::x64::lower::isle::generated_code::Amode; impl Amode { - pub(crate) fn imm_reg(simm32: u32, base: Reg) -> Self { + /// Create an immediate sign-extended and register addressing mode. + pub fn imm_reg(simm32: u32, base: Reg) -> Self { debug_assert!(base.class() == RegClass::Int); Self::ImmReg { simm32, @@ -265,7 +270,8 @@ impl Amode { } } - pub(crate) fn imm_reg_reg_shift(simm32: u32, base: Gpr, index: Gpr, shift: u8) -> Self { + /// Create a sign-extended-32-to-64 with register and shift addressing mode. + pub fn imm_reg_reg_shift(simm32: u32, base: Gpr, index: Gpr, shift: u8) -> Self { debug_assert!(base.class() == RegClass::Int); debug_assert!(index.class() == RegClass::Int); debug_assert!(shift <= 3); @@ -446,13 +452,21 @@ pub enum SyntheticAmode { /// A (virtual) offset to the "nominal SP" value, which will be recomputed as we push and pop /// within the function. - NominalSPOffset { simm32: u32 }, + NominalSPOffset { + /// The nominal stack pointer value. + simm32: u32, + }, /// A virtual offset to a constant that will be emitted in the constant section of the buffer. ConstantOffset(VCodeConstant), } impl SyntheticAmode { + /// Create a real addressing mode. + pub fn real(amode: Amode) -> Self { + Self::Real(amode) + } + pub(crate) fn nominal_sp_offset(simm32: u32) -> Self { SyntheticAmode::NominalSPOffset { simm32 } } @@ -544,20 +558,37 @@ impl PrettyPrint for SyntheticAmode { /// `simm32` is its sign-extension out to 64 bits. #[derive(Clone, Debug)] pub enum RegMemImm { - Reg { reg: Reg }, - Mem { addr: SyntheticAmode }, - Imm { simm32: u32 }, + /// A register operand. + Reg { + /// The underlying register. + reg: Reg, + }, + /// A memory operand. + Mem { + /// The memory address. + addr: SyntheticAmode, + }, + /// An immediate operand. + Imm { + /// The immediate value. + simm32: u32, + }, } impl RegMemImm { - pub(crate) fn reg(reg: Reg) -> Self { + /// Create a register operand. + pub fn reg(reg: Reg) -> Self { debug_assert!(reg.class() == RegClass::Int || reg.class() == RegClass::Float); Self::Reg { reg } } - pub(crate) fn mem(addr: impl Into) -> Self { + + /// Create a memory operand. + pub fn mem(addr: impl Into) -> Self { Self::Mem { addr: addr.into() } } - pub(crate) fn imm(simm32: u32) -> Self { + + /// Create an immediate operand. + pub fn imm(simm32: u32) -> Self { Self::Imm { simm32 } } @@ -613,8 +644,16 @@ impl PrettyPrint for RegMemImm { /// An operand which is either an 8-bit integer immediate or a register. #[derive(Clone, Debug)] pub enum Imm8Reg { - Imm8 { imm: u8 }, - Reg { reg: Reg }, + /// 8-bit immediate operand. + Imm8 { + /// The 8-bit immediate value. + imm: u8, + }, + /// A register operand. + Reg { + /// The underlying register. + reg: Reg, + }, } impl From for Imm8Reg { @@ -633,16 +672,27 @@ impl From for Imm8Reg { /// 32, 64, or 128 bit value. #[derive(Clone, Debug)] pub enum RegMem { - Reg { reg: Reg }, - Mem { addr: SyntheticAmode }, + /// A register operand. + Reg { + /// The underlying register. + reg: Reg, + }, + /// A memory operand. + Mem { + /// The memory address. + addr: SyntheticAmode, + }, } impl RegMem { - pub(crate) fn reg(reg: Reg) -> Self { + /// Create a register operand. + pub fn reg(reg: Reg) -> Self { debug_assert!(reg.class() == RegClass::Int || reg.class() == RegClass::Float); Self::Reg { reg } } - pub(crate) fn mem(addr: impl Into) -> Self { + + /// Create a memory operand. + pub fn mem(addr: impl Into) -> Self { Self::Mem { addr: addr.into() } } /// Asserts that in register mode, the reg class is the one that's expected. @@ -698,12 +748,19 @@ impl PrettyPrint for RegMem { /// Some basic ALU operations. TODO: maybe add Adc, Sbb. #[derive(Copy, Clone, PartialEq)] pub enum AluRmiROpcode { + /// Add operation. Add, + /// Add with carry. Adc, + /// Integer subtraction. Sub, + /// Integer subtraction with borrow. Sbb, + /// Bitwise AND operation. And, + /// Bitwise inclusive OR. Or, + /// Bitwise exclusive OR. Xor, /// The signless, non-extending (N x N -> N, for N in {32,64}) variant. Mul, @@ -732,6 +789,7 @@ impl fmt::Display for AluRmiROpcode { } #[derive(Clone, PartialEq)] +/// Unary operations requiring register or memory and register operands. pub enum UnaryRmROpcode { /// Bit-scan reverse. Bsr, @@ -775,6 +833,7 @@ impl fmt::Display for UnaryRmROpcode { } #[derive(Clone, Copy, PartialEq)] +/// Comparison operations. pub enum CmpOpcode { /// CMP instruction: compute `a - b` and set flags from result. Cmp, @@ -805,6 +864,7 @@ pub(crate) enum InstructionSet { /// Some SSE operations requiring 2 operands r/m and r. #[derive(Clone, Copy, PartialEq)] #[allow(dead_code)] // some variants here aren't used just yet +#[allow(missing_docs)] pub enum SseOpcode { Addps, Addpd, @@ -1388,6 +1448,7 @@ impl fmt::Display for SseOpcode { } #[derive(Clone, PartialEq)] +#[allow(missing_docs)] pub enum AvxOpcode { Vfmadd213ss, Vfmadd213sd, @@ -1426,6 +1487,7 @@ impl fmt::Display for AvxOpcode { } #[derive(Clone, PartialEq)] +#[allow(missing_docs)] pub enum Avx512Opcode { Vcvtudq2ps, Vpabsq, @@ -1478,8 +1540,11 @@ impl fmt::Display for Avx512Opcode { #[allow(dead_code)] #[derive(Clone, PartialEq)] pub enum ExtKind { + /// No extension. None, + /// Sign-extend. SignExtend, + /// Zero-extend. ZeroExtend, } @@ -1552,12 +1617,15 @@ impl fmt::Display for ExtMode { /// These indicate the form of a scalar shift/rotate: left, signed right, unsigned right. #[derive(Clone, Copy)] pub enum ShiftKind { + /// Left shift. ShiftLeft, /// Inserts zeros in the most significant bits. ShiftRightLogical, /// Replicates the sign bit in the most significant bits. ShiftRightArithmetic, + /// Left rotation. RotateLeft, + /// Right rotation. RotateRight, } @@ -1580,12 +1648,16 @@ impl fmt::Display for ShiftKind { } } -/// What kind of division or remainer instruction this is? +/// What kind of division or remainder instruction this is? #[derive(Clone, Eq, PartialEq)] pub enum DivOrRemKind { + /// Signed division. SignedDiv, + /// Unsigned division. UnsignedDiv, + /// Signed remainder. SignedRem, + /// Unsigned remainder. UnsignedRem, } @@ -1736,13 +1808,21 @@ impl fmt::Display for CC { /// whereas [FcmpImm] is used as an immediate. #[derive(Clone, Copy)] pub enum FcmpImm { + /// Equal comparison. Equal = 0x00, + /// Less than comparison. LessThan = 0x01, + /// Less than or equal comparison. LessThanOrEqual = 0x02, + /// Unordered. Unordered = 0x03, + /// Not equal comparison. NotEqual = 0x04, + /// Unordered of greater than or equal comparison. UnorderedOrGreaterThanOrEqual = 0x05, + /// Unordered or greater than comparison. UnorderedOrGreaterThan = 0x06, + /// Ordered. Ordered = 0x07, } @@ -1776,9 +1856,13 @@ impl From for FcmpImm { /// These two bits are not defined here and are implictly set to zero when encoded. #[derive(Clone, Copy)] pub enum RoundImm { + /// Round to nearest mode. RoundNearest = 0x00, + /// Round down mode. RoundDown = 0x01, + /// Round up mode. RoundUp = 0x02, + /// Round to zero mode. RoundZero = 0x03, } @@ -1791,9 +1875,13 @@ impl RoundImm { /// An operand's size in bits. #[derive(Clone, Copy, PartialEq)] pub enum OperandSize { + /// 8-bit. Size8, + /// 16-bit. Size16, + /// 32-bit. Size32, + /// 64-bit. Size64, } diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index a510789446..0357d81ac9 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -2486,7 +2486,8 @@ pub struct EmitInfo { } impl EmitInfo { - pub(crate) fn new(flags: settings::Flags, isa_flags: x64_settings::Flags) -> Self { + /// Create a constant state for emission of instructions. + pub fn new(flags: settings::Flags, isa_flags: x64_settings::Flags) -> Self { Self { flags, isa_flags } } } diff --git a/cranelift/codegen/src/isa/x64/lower/isle/generated_code.rs b/cranelift/codegen/src/isa/x64/lower/isle/generated_code.rs index dc85f2916b..a03aed0a56 100644 --- a/cranelift/codegen/src/isa/x64/lower/isle/generated_code.rs +++ b/cranelift/codegen/src/isa/x64/lower/isle/generated_code.rs @@ -4,6 +4,11 @@ // mod generated_code;` trick either. #![allow(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)] +#![allow( + irrefutable_let_patterns, + unused_assignments, + non_camel_case_types, + missing_docs +)] include!(concat!(env!("ISLE_DIR"), "/isle_x64.rs")); diff --git a/cranelift/codegen/src/isa/x64/mod.rs b/cranelift/codegen/src/isa/x64/mod.rs index a947e00f07..fae8a90b52 100644 --- a/cranelift/codegen/src/isa/x64/mod.rs +++ b/cranelift/codegen/src/isa/x64/mod.rs @@ -1,6 +1,6 @@ //! X86_64-bit Instruction Set Architecture. -use self::inst::EmitInfo; +pub use self::inst::{args, EmitInfo, EmitState, Inst}; use super::TargetIsa; use crate::ir::{condcodes::IntCC, Function, Type}; diff --git a/cranelift/codegen/src/lib.rs b/cranelift/codegen/src/lib.rs index 621b9b572f..e8687114c3 100644 --- a/cranelift/codegen/src/lib.rs +++ b/cranelift/codegen/src/lib.rs @@ -89,7 +89,10 @@ pub mod write; pub use crate::entity::packed_option; pub use crate::machinst::buffer::{MachCallSite, MachReloc, MachSrcLoc, MachStackMap, MachTrap}; -pub use crate::machinst::{CompiledCode, TextSectionBuilder}; +pub use crate::machinst::{ + CompiledCode, Final, MachBuffer, MachBufferFinalized, MachInst, MachInstEmit, Reg, + TextSectionBuilder, Writable, +}; mod alias_analysis; mod bitset;