[meta] Remove Literal's kind field;
This commit is contained in:
@@ -8,7 +8,6 @@ use cranelift_entity::{entity_impl, PrimaryMap};
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Var(VarIndex),
|
Var(VarIndex),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
@@ -95,54 +94,37 @@ impl DefPool {
|
|||||||
pub struct DefIndex(u32);
|
pub struct DefIndex(u32);
|
||||||
entity_impl!(DefIndex);
|
entity_impl!(DefIndex);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug)]
|
||||||
enum LiteralValue {
|
pub enum Literal {
|
||||||
/// A value of an enumerated immediate operand.
|
/// A value of an enumerated immediate operand.
|
||||||
///
|
///
|
||||||
/// Some immediate operand kinds like `intcc` and `floatcc` have an enumerated range of values
|
/// Some immediate operand kinds like `intcc` and `floatcc` have an enumerated range of values
|
||||||
/// corresponding to a Rust enum type. An `Enumerator` object is an AST leaf node representing one
|
/// corresponding to a Rust enum type. An `Enumerator` object is an AST leaf node representing one
|
||||||
/// of the values.
|
/// of the values.
|
||||||
Enumerator(&'static str),
|
Enumerator {
|
||||||
|
rust_type: String,
|
||||||
|
value: &'static str,
|
||||||
|
},
|
||||||
|
|
||||||
/// A bitwise value of an immediate operand, used for bitwise exact floating point constants.
|
/// A bitwise value of an immediate operand, used for bitwise exact floating point constants.
|
||||||
Bits(u64),
|
Bits { rust_type: String, value: u64 },
|
||||||
|
|
||||||
/// A value of an integer immediate operand.
|
/// A value of an integer immediate operand.
|
||||||
Int(i64),
|
Int(i64),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Literal {
|
|
||||||
kind: OperandKind,
|
|
||||||
value: LiteralValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Literal {
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
||||||
write!(
|
|
||||||
fmt,
|
|
||||||
"Literal(kind={}, value={:?})",
|
|
||||||
self.kind.name, self.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Literal {
|
impl Literal {
|
||||||
pub fn enumerator_for(kind: &OperandKind, value: &'static str) -> Self {
|
pub fn enumerator_for(kind: &OperandKind, value: &'static str) -> Self {
|
||||||
if let OperandKindFields::ImmEnum(values) = &kind.fields {
|
let value = match &kind.fields {
|
||||||
assert!(
|
OperandKindFields::ImmEnum(values) => values.get(value).expect(&format!(
|
||||||
values.get(value).is_some(),
|
|
||||||
format!(
|
|
||||||
"nonexistent value '{}' in enumeration '{}'",
|
"nonexistent value '{}' in enumeration '{}'",
|
||||||
value, kind.name
|
value, kind.name
|
||||||
)
|
)),
|
||||||
);
|
_ => panic!("enumerator is for enum values"),
|
||||||
} else {
|
};
|
||||||
panic!("enumerator is for enum values");
|
Literal::Enumerator {
|
||||||
}
|
rust_type: kind.rust_type.clone(),
|
||||||
Self {
|
value,
|
||||||
kind: kind.clone(),
|
|
||||||
value: LiteralValue::Enumerator(value),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,36 +133,25 @@ impl Literal {
|
|||||||
OperandKindFields::ImmValue => {}
|
OperandKindFields::ImmValue => {}
|
||||||
_ => panic!("bits_of is for immediate scalar types"),
|
_ => panic!("bits_of is for immediate scalar types"),
|
||||||
}
|
}
|
||||||
Self {
|
Literal::Bits {
|
||||||
kind: kind.clone(),
|
rust_type: kind.rust_type.clone(),
|
||||||
value: LiteralValue::Bits(bits),
|
value: bits,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constant(kind: &OperandKind, value: i64) -> Self {
|
pub fn constant(kind: &OperandKind, value: i64) -> Self {
|
||||||
match kind.fields {
|
match kind.fields {
|
||||||
OperandKindFields::ImmValue => {}
|
OperandKindFields::ImmValue => {}
|
||||||
_ => panic!("bits_of is for immediate scalar types"),
|
_ => panic!("constant is for immediate scalar types"),
|
||||||
}
|
|
||||||
Self {
|
|
||||||
kind: kind.clone(),
|
|
||||||
value: LiteralValue::Int(value),
|
|
||||||
}
|
}
|
||||||
|
Literal::Int(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_rust_code(&self) -> String {
|
pub fn to_rust_code(&self) -> String {
|
||||||
let maybe_values = match &self.kind.fields {
|
match self {
|
||||||
OperandKindFields::ImmEnum(values) => Some(values),
|
Literal::Enumerator { rust_type, value } => format!("{}::{}", rust_type, value),
|
||||||
OperandKindFields::ImmValue => None,
|
Literal::Bits { rust_type, value } => format!("{}::with_bits({:#x})", rust_type, value),
|
||||||
_ => panic!("impossible per construction"),
|
Literal::Int(val) => val.to_string(),
|
||||||
};
|
|
||||||
|
|
||||||
match self.value {
|
|
||||||
LiteralValue::Enumerator(value) => {
|
|
||||||
format!("{}::{}", self.kind.rust_type, maybe_values.unwrap()[value])
|
|
||||||
}
|
|
||||||
LiteralValue::Bits(bits) => format!("{}::with_bits({:#x})", self.kind.rust_type, bits),
|
|
||||||
LiteralValue::Int(val) => val.to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,7 +335,6 @@ impl VarPool {
|
|||||||
///
|
///
|
||||||
/// An `Apply` AST expression is created by using function call syntax on instructions. This
|
/// An `Apply` AST expression is created by using function call syntax on instructions. This
|
||||||
/// applies to both bound and unbound polymorphic instructions.
|
/// applies to both bound and unbound polymorphic instructions.
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Apply {
|
pub struct Apply {
|
||||||
pub inst: Instruction,
|
pub inst: Instruction,
|
||||||
pub args: Vec<Expr>,
|
pub args: Vec<Expr>,
|
||||||
@@ -395,13 +365,38 @@ impl Apply {
|
|||||||
let arg = &args[imm_index];
|
let arg = &args[imm_index];
|
||||||
if let Some(literal) = arg.maybe_literal() {
|
if let Some(literal) = arg.maybe_literal() {
|
||||||
let op = &inst.operands_in[imm_index];
|
let op = &inst.operands_in[imm_index];
|
||||||
|
match &op.kind.fields {
|
||||||
|
OperandKindFields::ImmEnum(values) => {
|
||||||
|
if let Literal::Enumerator { value, .. } = literal {
|
||||||
assert!(
|
assert!(
|
||||||
op.kind.name == literal.kind.name,
|
values.iter().any(|(_key, v)| v == value),
|
||||||
format!(
|
"Nonexistent enum value '{}' passed to field of kind '{}' -- \
|
||||||
"Passing literal of kind {} to field of wrong kind {}",
|
did you use the right enum?",
|
||||||
literal.kind.name, op.kind.name
|
value,
|
||||||
)
|
op.kind.name
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"Passed non-enum field value {:?} to field of kind {}",
|
||||||
|
literal, op.kind.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OperandKindFields::ImmValue => match &literal {
|
||||||
|
Literal::Enumerator { value, .. } => panic!(
|
||||||
|
"Expected immediate value in immediate field of kind '{}', \
|
||||||
|
obtained enum value '{}'",
|
||||||
|
op.kind.name, value
|
||||||
|
),
|
||||||
|
Literal::Bits { .. } | Literal::Int(_) => {}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
panic!(
|
||||||
|
"Literal passed to non-literal field of kind {}",
|
||||||
|
op.kind.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user