Change Option<DataSize> to DataSize

This commit is contained in:
Minseong Jang
2022-01-25 17:21:41 +09:00
parent 1fb7e85d37
commit a843992e8f
2 changed files with 61 additions and 80 deletions

View File

@@ -168,31 +168,23 @@ pub enum Instruction {
Pseudo(Pseudo), Pseudo(Pseudo),
} }
/// If the enum variant contains `Option<DataSize>`,
/// it means that the instructions used may vary according to `DataSize`.
/// Use 'Some' if RISC-V ISA provides instruction to support a specific 'DataSize',
/// if not, 'None' which means to use default instruction.
/// Because KECC uses RV64 (RISC-V ISA for 64-bit architecture),
/// KECC uses `Some` if `DataSize` is `Word`, if not, use `None`.
/// https://riscv.org/specifications/isa-spec-pdf/ (35p)
///
/// If the enum variant contains `bool`, /// If the enum variant contains `bool`,
/// It means that different instructions exist /// It means that different instructions exist
/// depending on whether the operand is signed or not. /// depending on whether the operand is signed or not.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum RType { pub enum RType {
Add(Option<DataSize>), Add(DataSize),
Sub(Option<DataSize>), Sub(DataSize),
Sll(Option<DataSize>), Sll(DataSize),
Srl(Option<DataSize>), Srl(DataSize),
Sra(Option<DataSize>), Sra(DataSize),
Mul(Option<DataSize>), Mul(DataSize),
Div { Div {
data_size: Option<DataSize>, data_size: DataSize,
is_signed: bool, is_signed: bool,
}, },
Rem { Rem {
data_size: Option<DataSize>, data_size: DataSize,
is_signed: bool, is_signed: bool,
}, },
Slt { Slt {
@@ -218,7 +210,7 @@ pub enum RType {
/// fcvt.s.l(u) or fcvt.d.l(u) /// fcvt.s.l(u) or fcvt.d.l(u)
/// fcvt.s.w(u) or fcvt.d.w(u) /// fcvt.s.w(u) or fcvt.d.w(u)
FcvtIntToFloat { FcvtIntToFloat {
int_data_size: Option<DataSize>, int_data_size: DataSize,
float_data_size: DataSize, float_data_size: DataSize,
is_signed: bool, is_signed: bool,
}, },
@@ -226,7 +218,7 @@ pub enum RType {
/// fcvt.w(u).s or fcvt.w(u).d /// fcvt.w(u).s or fcvt.w(u).d
FcvtFloatToInt { FcvtFloatToInt {
float_data_size: DataSize, float_data_size: DataSize,
int_data_size: Option<DataSize>, int_data_size: DataSize,
is_signed: bool, is_signed: bool,
}, },
/// fcvt.s.d or fcvt.d.s /// fcvt.s.d or fcvt.d.s
@@ -240,58 +232,58 @@ impl RType {
pub fn add(dtype: ir::Dtype) -> Self { pub fn add(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Add(data_size.word()) Self::Add(data_size)
} }
pub fn sub(dtype: ir::Dtype) -> Self { pub fn sub(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Sub(data_size.word()) Self::Sub(data_size)
} }
pub fn sll(dtype: ir::Dtype) -> Self { pub fn sll(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Sll(data_size.word()) Self::Sll(data_size)
} }
pub fn srl(dtype: ir::Dtype) -> Self { pub fn srl(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Srl(data_size.word()) Self::Srl(data_size)
} }
pub fn sra(dtype: ir::Dtype) -> Self { pub fn sra(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Sra(data_size.word()) Self::Sra(data_size)
} }
pub fn mul(dtype: ir::Dtype) -> Self { pub fn mul(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Mul(data_size.word()) Self::Mul(data_size)
} }
pub fn div(dtype: ir::Dtype, is_signed: bool) -> Self { pub fn div(dtype: ir::Dtype, is_signed: bool) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Div { Self::Div {
data_size: data_size.word(), data_size,
is_signed, is_signed,
} }
} }
@@ -299,10 +291,10 @@ impl RType {
pub fn rem(dtype: ir::Dtype, is_signed: bool) -> Self { pub fn rem(dtype: ir::Dtype, is_signed: bool) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Rem { Self::Rem {
data_size: data_size.word(), data_size,
is_signed, is_signed,
} }
} }
@@ -375,14 +367,14 @@ impl RType {
let is_signed = from.is_int_signed(); let is_signed = from.is_int_signed();
let int_data_size = let int_data_size =
DataSize::try_from(from).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(from).expect("`data_size` must be derived from `dtype`");
assert!(int_data_size.is_integer()); assert!(matches!(int_data_size, DataSize::Word | DataSize::Double));
let float_data_size = let float_data_size =
DataSize::try_from(to).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(to).expect("`data_size` must be derived from `dtype`");
assert!(float_data_size.is_floating_point()); assert!(float_data_size.is_floating_point());
Self::FcvtIntToFloat { Self::FcvtIntToFloat {
int_data_size: int_data_size.word(), int_data_size,
float_data_size, float_data_size,
is_signed, is_signed,
} }
@@ -396,36 +388,29 @@ impl RType {
let is_signed = to.is_int_signed(); let is_signed = to.is_int_signed();
let int_data_size = let int_data_size =
DataSize::try_from(to).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(to).expect("`data_size` must be derived from `dtype`");
assert!(int_data_size.is_integer()); assert!(matches!(int_data_size, DataSize::Word | DataSize::Double));
Self::FcvtFloatToInt { Self::FcvtFloatToInt {
float_data_size, float_data_size,
int_data_size: int_data_size.word(), int_data_size,
is_signed, is_signed,
} }
} }
} }
/// If the enum variant contains `Option<DataSize>`,
/// it means that the instructions used may vary according to `DataSize`.
/// Use 'Some' if RISC-V ISA provides instruction to support a specific 'DataSize',
/// if not, 'None' which means to use default instruction.
/// Because KECC uses RV64 (RISC-V ISA for 64-bit architecture),
/// KECC uses `Some` if `DataSize` is `Word`, if not, use `None`.
/// https://riscv.org/specifications/isa-spec-pdf/ (35p)
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum IType { pub enum IType {
Load { Load {
data_size: DataSize, data_size: DataSize,
is_signed: bool, is_signed: bool,
}, },
Addi(Option<DataSize>), Addi(DataSize),
Xori, Xori,
Ori, Ori,
Andi, Andi,
Slli(Option<DataSize>), Slli(DataSize),
Srli(Option<DataSize>), Srli(DataSize),
Srai(Option<DataSize>), Srai(DataSize),
Slti { Slti {
is_signed: bool, is_signed: bool,
}, },
@@ -440,7 +425,7 @@ impl IType {
data_size: DataSize::Double, data_size: DataSize::Double,
is_signed: true, is_signed: true,
}; };
pub const ADDI: Self = Self::Addi(None); pub const ADDI: Self = Self::Addi(DataSize::Double);
pub fn load(dtype: ir::Dtype) -> Self { pub fn load(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
@@ -467,25 +452,25 @@ impl IType {
pub fn slli(dtype: ir::Dtype) -> Self { pub fn slli(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Slli(data_size.word()) Self::Slli(data_size)
} }
pub fn srli(dtype: ir::Dtype) -> Self { pub fn srli(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Srli(data_size.word()) Self::Srli(data_size)
} }
pub fn srai(dtype: ir::Dtype) -> Self { pub fn srai(dtype: ir::Dtype) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
assert!(data_size.is_integer()); assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Self::Srai(data_size.word()) Self::Srai(data_size)
} }
} }
@@ -543,7 +528,7 @@ pub enum Pseudo {
}, },
/// neg(w) rd, rs /// neg(w) rd, rs
Neg { Neg {
data_size: Option<DataSize>, data_size: DataSize,
rd: Register, rd: Register,
rs: Register, rs: Register,
}, },
@@ -575,11 +560,7 @@ impl Pseudo {
pub fn neg(dtype: ir::Dtype, rd: Register, rs: Register) -> Self { pub fn neg(dtype: ir::Dtype, rd: Register, rs: Register) -> Self {
let data_size = let data_size =
DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`"); DataSize::try_from(dtype).expect("`data_size` must be derived from `dtype`");
let data_size = if data_size == DataSize::Word { assert!(matches!(data_size, DataSize::Word | DataSize::Double));
Some(data_size)
} else {
None
};
Self::Neg { data_size, rd, rs } Self::Neg { data_size, rd, rs }
} }
@@ -633,7 +614,7 @@ impl Label {
} }
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum DataSize { pub enum DataSize {
Byte, Byte,
Half, Half,

View File

@@ -205,19 +205,19 @@ impl WriteString for Instruction {
impl WriteString for RType { impl WriteString for RType {
fn write_string(&self) -> String { fn write_string(&self) -> String {
match self { match self {
Self::Add(data_size) => format!("add{}", data_size.write_string()), Self::Add(data_size) => format!("add{}", data_size.word().write_string()),
Self::Sub(data_size) => format!("sub{}", data_size.write_string()), Self::Sub(data_size) => format!("sub{}", data_size.word().write_string()),
Self::Sll(data_size) => format!("sll{}", data_size.write_string()), Self::Sll(data_size) => format!("sll{}", data_size.word().write_string()),
Self::Srl(data_size) => format!("srl{}", data_size.write_string()), Self::Srl(data_size) => format!("srl{}", data_size.word().write_string()),
Self::Sra(data_size) => format!("sra{}", data_size.write_string()), Self::Sra(data_size) => format!("sra{}", data_size.word().write_string()),
Self::Mul(data_size) => format!("mul{}", data_size.write_string()), Self::Mul(data_size) => format!("mul{}", data_size.word().write_string()),
Self::Div { Self::Div {
data_size, data_size,
is_signed, is_signed,
} => format!( } => format!(
"div{}{}", "div{}{}",
if *is_signed { "" } else { "u" }, if *is_signed { "" } else { "u" },
data_size.write_string() data_size.word().write_string()
), ),
Self::Rem { Self::Rem {
data_size, data_size,
@@ -225,7 +225,7 @@ impl WriteString for RType {
} => format!( } => format!(
"rem{}{}", "rem{}{}",
if *is_signed { "" } else { "u" }, if *is_signed { "" } else { "u" },
data_size.write_string() data_size.word().write_string()
), ),
Self::Slt { is_signed } => format!("slt{}", if *is_signed { "" } else { "u" }), Self::Slt { is_signed } => format!("slt{}", if *is_signed { "" } else { "u" }),
Self::Xor => "xor".to_string(), Self::Xor => "xor".to_string(),
@@ -265,10 +265,10 @@ impl WriteString for RType {
is_signed, is_signed,
} => { } => {
assert!(float_data_size.is_floating_point()); assert!(float_data_size.is_floating_point());
assert!(matches!(int_data_size, DataSize::Word | DataSize::Double));
format!( format!(
"fcvt.{}{}.{}", "fcvt.{}{}.{}",
if let Some(int_data_size) = int_data_size { if matches!(int_data_size, DataSize::Word) {
assert_eq!(*int_data_size, DataSize::Word);
"w" "w"
} else { } else {
"l" "l"
@@ -284,11 +284,11 @@ impl WriteString for RType {
is_signed, is_signed,
} => { } => {
assert!(float_data_size.is_floating_point()); assert!(float_data_size.is_floating_point());
assert!(matches!(int_data_size, DataSize::Word | DataSize::Double));
format!( format!(
"fcvt.{}.{}{}", "fcvt.{}.{}{}",
float_data_size.write_string(), float_data_size.write_string(),
if let Some(int_data_size) = int_data_size { if matches!(int_data_size, DataSize::Word) {
assert_eq!(*int_data_size, DataSize::Word);
"w" "w"
} else { } else {
"l" "l"
@@ -330,13 +330,13 @@ impl WriteString for IType {
) )
} }
} }
Self::Addi(data_size) => format!("addi{}", data_size.write_string()), Self::Addi(data_size) => format!("addi{}", data_size.word().write_string()),
Self::Xori => "xori".to_string(), Self::Xori => "xori".to_string(),
Self::Ori => "ori".to_string(), Self::Ori => "ori".to_string(),
Self::Andi => "andi".to_string(), Self::Andi => "andi".to_string(),
Self::Slli(data_size) => format!("slli{}", data_size.write_string()), Self::Slli(data_size) => format!("slli{}", data_size.word().write_string()),
Self::Srli(data_size) => format!("srli{}", data_size.write_string()), Self::Srli(data_size) => format!("srli{}", data_size.word().write_string()),
Self::Srai(data_size) => format!("srai{}", data_size.write_string()), Self::Srai(data_size) => format!("srai{}", data_size.word().write_string()),
Self::Slti { is_signed } => format!("slti{}", if *is_signed { "" } else { "u" }), Self::Slti { is_signed } => format!("slti{}", if *is_signed { "" } else { "u" }),
} }
} }
@@ -396,7 +396,7 @@ impl WriteString for Pseudo {
), ),
Self::Neg { data_size, rd, rs } => format!( Self::Neg { data_size, rd, rs } => format!(
"neg{}\t{},{}", "neg{}\t{},{}",
data_size.write_string(), data_size.word().write_string(),
rd.write_string(), rd.write_string(),
rs.write_string() rs.write_string()
), ),