machinst x64: expand encoding names a bit;
This avoids one, two, and three letter structures names, which makes the code easier to read (while a bit more verbose).
This commit is contained in:
@@ -13,10 +13,10 @@ use super::regs::show_ireg_sized;
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum Addr {
|
||||
/// Immediate sign-extended and a Register.
|
||||
IR { simm32: u32, base: Reg },
|
||||
ImmReg { simm32: u32, base: Reg },
|
||||
|
||||
/// sign-extend-32-to-64(Immediate) + Register1 + (Register2 << Shift)
|
||||
IRRS {
|
||||
ImmRegRegShift {
|
||||
simm32: u32,
|
||||
base: Reg,
|
||||
index: Reg,
|
||||
@@ -25,18 +25,16 @@ pub(crate) enum Addr {
|
||||
}
|
||||
|
||||
impl Addr {
|
||||
// Constructors.
|
||||
|
||||
pub(crate) fn imm_reg(simm32: u32, base: Reg) -> Self {
|
||||
debug_assert!(base.get_class() == RegClass::I64);
|
||||
Self::IR { simm32, base }
|
||||
Self::ImmReg { simm32, base }
|
||||
}
|
||||
|
||||
pub(crate) fn imm_reg_reg_shift(simm32: u32, base: Reg, index: Reg, shift: u8) -> Self {
|
||||
debug_assert!(base.get_class() == RegClass::I64);
|
||||
debug_assert!(index.get_class() == RegClass::I64);
|
||||
debug_assert!(shift <= 3);
|
||||
Addr::IRRS {
|
||||
Self::ImmRegRegShift {
|
||||
simm32,
|
||||
base,
|
||||
index,
|
||||
@@ -47,10 +45,10 @@ impl Addr {
|
||||
/// Add the regs mentioned by `self` to `collector`.
|
||||
pub(crate) fn get_regs_as_uses(&self, collector: &mut RegUsageCollector) {
|
||||
match self {
|
||||
Addr::IR { simm32: _, base } => {
|
||||
Addr::ImmReg { simm32: _, base } => {
|
||||
collector.add_use(*base);
|
||||
}
|
||||
Addr::IRRS {
|
||||
Addr::ImmRegRegShift {
|
||||
simm32: _,
|
||||
base,
|
||||
index,
|
||||
@@ -66,8 +64,10 @@ impl Addr {
|
||||
impl ShowWithRRU for Addr {
|
||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
match self {
|
||||
Addr::IR { simm32, base } => format!("{}({})", *simm32 as i32, base.show_rru(mb_rru)),
|
||||
Addr::IRRS {
|
||||
Addr::ImmReg { simm32, base } => {
|
||||
format!("{}({})", *simm32 as i32, base.show_rru(mb_rru))
|
||||
}
|
||||
Addr::ImmRegRegShift {
|
||||
simm32,
|
||||
base,
|
||||
index,
|
||||
@@ -88,46 +88,44 @@ impl ShowWithRRU for Addr {
|
||||
/// the lower 8 or 16 bits of `simm32` is relevant. In the 64-bit case, the value denoted by
|
||||
/// `simm32` is its sign-extension out to 64 bits.
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum RMI {
|
||||
R { reg: Reg },
|
||||
M { addr: Addr },
|
||||
I { simm32: u32 },
|
||||
pub(crate) enum RegMemImm {
|
||||
Reg { reg: Reg },
|
||||
Mem { addr: Addr },
|
||||
Imm { simm32: u32 },
|
||||
}
|
||||
|
||||
impl RMI {
|
||||
// Constructors
|
||||
|
||||
pub(crate) fn reg(reg: Reg) -> RMI {
|
||||
impl RegMemImm {
|
||||
pub(crate) fn reg(reg: Reg) -> Self {
|
||||
debug_assert!(reg.get_class() == RegClass::I64);
|
||||
RMI::R { reg }
|
||||
Self::Reg { reg }
|
||||
}
|
||||
pub(crate) fn mem(addr: Addr) -> RMI {
|
||||
RMI::M { addr }
|
||||
pub(crate) fn mem(addr: Addr) -> Self {
|
||||
Self::Mem { addr }
|
||||
}
|
||||
pub(crate) fn imm(simm32: u32) -> RMI {
|
||||
RMI::I { simm32 }
|
||||
pub(crate) fn imm(simm32: u32) -> Self {
|
||||
Self::Imm { simm32 }
|
||||
}
|
||||
|
||||
/// Add the regs mentioned by `self` to `collector`.
|
||||
pub(crate) fn get_regs_as_uses(&self, collector: &mut RegUsageCollector) {
|
||||
match self {
|
||||
RMI::R { reg } => collector.add_use(*reg),
|
||||
RMI::M { addr } => addr.get_regs_as_uses(collector),
|
||||
RMI::I { simm32: _ } => {}
|
||||
Self::Reg { reg } => collector.add_use(*reg),
|
||||
Self::Mem { addr } => addr.get_regs_as_uses(collector),
|
||||
Self::Imm { simm32: _ } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowWithRRU for RMI {
|
||||
impl ShowWithRRU for RegMemImm {
|
||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
self.show_rru_sized(mb_rru, 8)
|
||||
}
|
||||
|
||||
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
|
||||
match self {
|
||||
RMI::R { reg } => show_ireg_sized(*reg, mb_rru, size),
|
||||
RMI::M { addr } => addr.show_rru(mb_rru),
|
||||
RMI::I { simm32 } => format!("${}", *simm32 as i32),
|
||||
Self::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
|
||||
Self::Mem { addr } => addr.show_rru(mb_rru),
|
||||
Self::Imm { simm32 } => format!("${}", *simm32 as i32),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,48 +133,45 @@ impl ShowWithRRU for RMI {
|
||||
/// An operand which is either an integer Register or a value in Memory. This can denote an 8, 16,
|
||||
/// 32 or 64 bit value.
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum RM {
|
||||
R { reg: Reg },
|
||||
M { addr: Addr },
|
||||
pub(crate) enum RegMem {
|
||||
Reg { reg: Reg },
|
||||
Mem { addr: Addr },
|
||||
}
|
||||
|
||||
impl RM {
|
||||
// Constructors.
|
||||
|
||||
impl RegMem {
|
||||
pub(crate) fn reg(reg: Reg) -> Self {
|
||||
debug_assert!(reg.get_class() == RegClass::I64 || reg.get_class() == RegClass::V128);
|
||||
RM::R { reg }
|
||||
Self::Reg { reg }
|
||||
}
|
||||
|
||||
pub(crate) fn mem(addr: Addr) -> Self {
|
||||
RM::M { addr }
|
||||
Self::Mem { addr }
|
||||
}
|
||||
|
||||
/// Add the regs mentioned by `self` to `collector`.
|
||||
pub(crate) fn get_regs_as_uses(&self, collector: &mut RegUsageCollector) {
|
||||
match self {
|
||||
RM::R { reg } => collector.add_use(*reg),
|
||||
RM::M { addr } => addr.get_regs_as_uses(collector),
|
||||
RegMem::Reg { reg } => collector.add_use(*reg),
|
||||
RegMem::Mem { addr } => addr.get_regs_as_uses(collector),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowWithRRU for RM {
|
||||
impl ShowWithRRU for RegMem {
|
||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
self.show_rru_sized(mb_rru, 8)
|
||||
}
|
||||
|
||||
fn show_rru_sized(&self, mb_rru: Option<&RealRegUniverse>, size: u8) -> String {
|
||||
match self {
|
||||
RM::R { reg } => show_ireg_sized(*reg, mb_rru, size),
|
||||
RM::M { addr } => addr.show_rru(mb_rru),
|
||||
RegMem::Reg { reg } => show_ireg_sized(*reg, mb_rru, size),
|
||||
RegMem::Mem { addr } => addr.show_rru(mb_rru),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Some basic ALU operations. TODO: maybe add Adc, Sbb.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum RMI_R_Op {
|
||||
pub enum AluRmiROpcode {
|
||||
Add,
|
||||
Sub,
|
||||
And,
|
||||
@@ -186,89 +181,185 @@ pub enum RMI_R_Op {
|
||||
Mul,
|
||||
}
|
||||
|
||||
impl RMI_R_Op {
|
||||
pub(crate) fn to_string(&self) -> String {
|
||||
impl fmt::Debug for AluRmiROpcode {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match self {
|
||||
AluRmiROpcode::Add => "add",
|
||||
AluRmiROpcode::Sub => "sub",
|
||||
AluRmiROpcode::And => "and",
|
||||
AluRmiROpcode::Or => "or",
|
||||
AluRmiROpcode::Xor => "xor",
|
||||
AluRmiROpcode::Mul => "imul",
|
||||
};
|
||||
write!(fmt, "{}", name)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for AluRmiROpcode {
|
||||
fn to_string(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum InstructionSet {
|
||||
SSE,
|
||||
SSE2,
|
||||
SSE41,
|
||||
}
|
||||
|
||||
/// Some scalar SSE operations requiring 2 operands r/m and r.
|
||||
/// TODO: Below only includes scalar operations. To be seen if packed will be added here.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum SseOpcode {
|
||||
Addss,
|
||||
Addsd,
|
||||
Comiss,
|
||||
Comisd,
|
||||
Cvtsd2ss,
|
||||
Cvtsd2si,
|
||||
Cvtsi2ss,
|
||||
Cvtsi2sd,
|
||||
Cvtss2si,
|
||||
Cvtss2sd,
|
||||
Cvttss2si,
|
||||
Cvttsd2si,
|
||||
Divss,
|
||||
Divsd,
|
||||
Maxss,
|
||||
Maxsd,
|
||||
Minss,
|
||||
Minsd,
|
||||
Movss,
|
||||
Movsd,
|
||||
Mulss,
|
||||
Mulsd,
|
||||
Rcpss,
|
||||
Roundss,
|
||||
Roundsd,
|
||||
Rsqrtss,
|
||||
Sqrtss,
|
||||
Sqrtsd,
|
||||
Subss,
|
||||
Subsd,
|
||||
Ucomiss,
|
||||
Ucomisd,
|
||||
}
|
||||
|
||||
impl SseOpcode {
|
||||
/// Which `InstructionSet` is the first supporting this opcode?
|
||||
pub(crate) fn available_from(&self) -> InstructionSet {
|
||||
use InstructionSet::*;
|
||||
match self {
|
||||
RMI_R_Op::Add => "add".to_string(),
|
||||
RMI_R_Op::Sub => "sub".to_string(),
|
||||
RMI_R_Op::And => "and".to_string(),
|
||||
RMI_R_Op::Or => "or".to_string(),
|
||||
RMI_R_Op::Xor => "xor".to_string(),
|
||||
RMI_R_Op::Mul => "imul".to_string(),
|
||||
SseOpcode::Addss
|
||||
| SseOpcode::Cvtsi2ss
|
||||
| SseOpcode::Cvtss2si
|
||||
| SseOpcode::Cvttss2si
|
||||
| SseOpcode::Divss
|
||||
| SseOpcode::Maxss
|
||||
| SseOpcode::Minss
|
||||
| SseOpcode::Movss
|
||||
| SseOpcode::Mulss
|
||||
| SseOpcode::Rcpss
|
||||
| SseOpcode::Rsqrtss
|
||||
| SseOpcode::Subss
|
||||
| SseOpcode::Ucomiss
|
||||
| SseOpcode::Sqrtss
|
||||
| SseOpcode::Comiss => SSE,
|
||||
|
||||
SseOpcode::Addsd
|
||||
| SseOpcode::Cvtsd2ss
|
||||
| SseOpcode::Cvtsd2si
|
||||
| SseOpcode::Cvtsi2sd
|
||||
| SseOpcode::Cvtss2sd
|
||||
| SseOpcode::Cvttsd2si
|
||||
| SseOpcode::Divsd
|
||||
| SseOpcode::Maxsd
|
||||
| SseOpcode::Minsd
|
||||
| SseOpcode::Movsd
|
||||
| SseOpcode::Mulsd
|
||||
| SseOpcode::Sqrtsd
|
||||
| SseOpcode::Subsd
|
||||
| SseOpcode::Ucomisd
|
||||
| SseOpcode::Comisd => SSE2,
|
||||
|
||||
SseOpcode::Roundss | SseOpcode::Roundsd => SSE41,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for RMI_R_Op {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Some scalar SSE operations requiring 2 operands r/m and r
|
||||
/// Each instruction is prefixed with the SSE version that introduced
|
||||
/// the particular instructions.
|
||||
/// TODO: Below only includes scalar operations. To be seen if packed will
|
||||
/// be added here.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum SSE_Op {
|
||||
SSE_Addss,
|
||||
SSE2_Addsd,
|
||||
SSE_Comiss,
|
||||
SSE2_Comisd,
|
||||
SSE2_Cvtsd2ss,
|
||||
SSE2_Cvtsd2si,
|
||||
SSE_Cvtsi2ss,
|
||||
SSE2_Cvtsi2sd,
|
||||
SSE_Cvtss2si,
|
||||
SSE2_Cvtss2sd,
|
||||
SSE_Cvttss2si,
|
||||
SSE2_Cvttsd2si,
|
||||
SSE_Divss,
|
||||
SSE2_Divsd,
|
||||
SSE_Maxss,
|
||||
SSE2_Maxsd,
|
||||
SSE_Minss,
|
||||
SSE2_Minsd,
|
||||
SSE_Movss,
|
||||
SSE2_Movsd,
|
||||
SSE_Mulss,
|
||||
SSE2_Mulsd,
|
||||
SSE_Rcpss,
|
||||
SSE41_Roundss,
|
||||
SSE41_Roundsd,
|
||||
SSE_Rsqrtss,
|
||||
SSE_Sqrtss,
|
||||
SSE2_Sqrtsd,
|
||||
SSE_Subss,
|
||||
SSE2_Subsd,
|
||||
SSE_Ucomiss,
|
||||
SSE2_Ucomisd,
|
||||
}
|
||||
|
||||
/// Some SSE operations requiring 3 operands i, r/m, and r
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum SSE_RMI_Op {
|
||||
SSE_Cmpss,
|
||||
SSE2_Cmpsd,
|
||||
SSE41_Insertps,
|
||||
}
|
||||
|
||||
impl SSE_Op {
|
||||
pub(crate) fn to_string(&self) -> String {
|
||||
match self {
|
||||
SSE_Op::SSE_Addss => "addss".to_string(),
|
||||
SSE_Op::SSE_Subss => "subss".to_string(),
|
||||
SSE_Op::SSE_Movss => "movss".to_string(),
|
||||
SSE_Op::SSE2_Movsd => "movsd".to_string(),
|
||||
SseOpcode::Addss => "addss".to_string(),
|
||||
SseOpcode::Subss => "subss".to_string(),
|
||||
SseOpcode::Movss => "movss".to_string(),
|
||||
SseOpcode::Movsd => "movsd".to_string(),
|
||||
_ => "unimplemented sse_op".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SSE_Op {
|
||||
impl fmt::Debug for SseOpcode {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.to_string())
|
||||
let name = match self {
|
||||
SseOpcode::Addss => "addss",
|
||||
SseOpcode::Addsd => "addsd",
|
||||
SseOpcode::Comiss => "comiss",
|
||||
SseOpcode::Comisd => "comisd",
|
||||
SseOpcode::Cvtsd2ss => "cvtsd2ss",
|
||||
SseOpcode::Cvtsd2si => "cvtsd2si",
|
||||
SseOpcode::Cvtsi2ss => "cvtsi2ss",
|
||||
SseOpcode::Cvtsi2sd => "cvtsi2sd",
|
||||
SseOpcode::Cvtss2si => "cvtss2si",
|
||||
SseOpcode::Cvtss2sd => "cvtss2sd",
|
||||
SseOpcode::Cvttss2si => "cvttss2si",
|
||||
SseOpcode::Cvttsd2si => "cvttsd2si",
|
||||
SseOpcode::Divss => "divss",
|
||||
SseOpcode::Divsd => "divsd",
|
||||
SseOpcode::Maxss => "maxss",
|
||||
SseOpcode::Maxsd => "maxsd",
|
||||
SseOpcode::Minss => "minss",
|
||||
SseOpcode::Minsd => "minsd",
|
||||
SseOpcode::Movss => "movss",
|
||||
SseOpcode::Movsd => "movsd",
|
||||
SseOpcode::Mulss => "mulss",
|
||||
SseOpcode::Mulsd => "mulsd",
|
||||
SseOpcode::Rcpss => "rcpss",
|
||||
SseOpcode::Roundss => "roundss",
|
||||
SseOpcode::Roundsd => "roundsd",
|
||||
SseOpcode::Rsqrtss => "rsqrtss",
|
||||
SseOpcode::Sqrtss => "srtqss",
|
||||
SseOpcode::Sqrtsd => "sqrtsd",
|
||||
SseOpcode::Subss => "subss",
|
||||
SseOpcode::Subsd => "subsd",
|
||||
SseOpcode::Ucomiss => "ucomiss",
|
||||
SseOpcode::Ucomisd => "ucomisd",
|
||||
};
|
||||
write!(fmt, "{}", name)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for SseOpcode {
|
||||
fn to_string(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Some SSE operations requiring 3 operands i, r/m, and r.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum SseRmiOpcode {
|
||||
Cmpss,
|
||||
Cmpsd,
|
||||
Insertps,
|
||||
}
|
||||
|
||||
impl SseRmiOpcode {
|
||||
/// Which `InstructionSet` is the first supporting this opcode?
|
||||
pub(crate) fn available_from(&self) -> InstructionSet {
|
||||
use InstructionSet::*;
|
||||
match self {
|
||||
SseRmiOpcode::Cmpss => SSE,
|
||||
SseRmiOpcode::Cmpsd => SSE2,
|
||||
SseRmiOpcode::Insertps => SSE41,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,30 +380,30 @@ pub enum ExtMode {
|
||||
}
|
||||
|
||||
impl ExtMode {
|
||||
pub(crate) fn to_string(&self) -> String {
|
||||
match self {
|
||||
ExtMode::BL => "bl".to_string(),
|
||||
ExtMode::BQ => "bq".to_string(),
|
||||
ExtMode::WL => "wl".to_string(),
|
||||
ExtMode::WQ => "wq".to_string(),
|
||||
ExtMode::LQ => "lq".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dst_size(&self) -> u8 {
|
||||
match self {
|
||||
ExtMode::BL => 4,
|
||||
ExtMode::BQ => 8,
|
||||
ExtMode::WL => 4,
|
||||
ExtMode::WQ => 8,
|
||||
ExtMode::LQ => 8,
|
||||
ExtMode::BL | ExtMode::WL => 4,
|
||||
ExtMode::BQ | ExtMode::WQ | ExtMode::LQ => 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ExtMode {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.to_string())
|
||||
let name = match self {
|
||||
ExtMode::BL => "bl",
|
||||
ExtMode::BQ => "bq",
|
||||
ExtMode::WL => "wl",
|
||||
ExtMode::WQ => "wq",
|
||||
ExtMode::LQ => "lq",
|
||||
};
|
||||
write!(fmt, "{}", name)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for ExtMode {
|
||||
fn to_string(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,19 +415,20 @@ pub enum ShiftKind {
|
||||
RightS,
|
||||
}
|
||||
|
||||
impl ShiftKind {
|
||||
pub(crate) fn to_string(&self) -> String {
|
||||
match self {
|
||||
ShiftKind::Left => "shl".to_string(),
|
||||
ShiftKind::RightZ => "shr".to_string(),
|
||||
ShiftKind::RightS => "sar".to_string(),
|
||||
}
|
||||
impl fmt::Debug for ShiftKind {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match self {
|
||||
ShiftKind::Left => "shl",
|
||||
ShiftKind::RightZ => "shr",
|
||||
ShiftKind::RightS => "sar",
|
||||
};
|
||||
write!(fmt, "{}", name)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ShiftKind {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.to_string())
|
||||
impl ToString for ShiftKind {
|
||||
fn to_string(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,25 +474,6 @@ pub enum CC {
|
||||
}
|
||||
|
||||
impl CC {
|
||||
pub(crate) fn to_string(&self) -> String {
|
||||
match self {
|
||||
CC::O => "o".to_string(),
|
||||
CC::NO => "no".to_string(),
|
||||
CC::B => "b".to_string(),
|
||||
CC::NB => "nb".to_string(),
|
||||
CC::Z => "z".to_string(),
|
||||
CC::NZ => "nz".to_string(),
|
||||
CC::BE => "be".to_string(),
|
||||
CC::NBE => "nbe".to_string(),
|
||||
CC::S => "s".to_string(),
|
||||
CC::NS => "ns".to_string(),
|
||||
CC::L => "l".to_string(),
|
||||
CC::NL => "nl".to_string(),
|
||||
CC::LE => "le".to_string(),
|
||||
CC::NLE => "nle".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn invert(&self) -> CC {
|
||||
match self {
|
||||
CC::O => CC::NO,
|
||||
@@ -433,7 +506,29 @@ impl CC {
|
||||
|
||||
impl fmt::Debug for CC {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.to_string())
|
||||
let name = match self {
|
||||
CC::O => "o",
|
||||
CC::NO => "no",
|
||||
CC::B => "b",
|
||||
CC::NB => "nb",
|
||||
CC::Z => "z",
|
||||
CC::NZ => "nz",
|
||||
CC::BE => "be",
|
||||
CC::NBE => "nbe",
|
||||
CC::S => "s",
|
||||
CC::NS => "ns",
|
||||
CC::L => "l",
|
||||
CC::NL => "nl",
|
||||
CC::LE => "le",
|
||||
CC::NLE => "nle",
|
||||
};
|
||||
write!(fmt, "{}", name)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for CC {
|
||||
fn to_string(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user