diff --git a/cranelift/codegen/src/data_value.rs b/cranelift/codegen/src/data_value.rs index 05379196d4..4568923bfc 100644 --- a/cranelift/codegen/src/data_value.rs +++ b/cranelift/codegen/src/data_value.rs @@ -1,6 +1,6 @@ //! This module gives users to instantiate values that Cranelift understands. These values are used, //! for example, during interpretation and for wrapping immediates. -use crate::ir::immediates::{Ieee32, Ieee64, Imm64}; +use crate::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32}; use crate::ir::{types, ConstantData, Type}; use core::convert::TryInto; use core::fmt::{self, Display, Formatter}; @@ -100,6 +100,21 @@ build_conversion_impl!(i64, I64, I64); build_conversion_impl!(f32, F32, F32); build_conversion_impl!(f64, F64, F64); build_conversion_impl!([u8; 16], V128, I8X16); +impl From for DataValue { + fn from(f: Ieee64) -> Self { + DataValue::from(f64::from_bits(f.bits())) + } +} +impl From for DataValue { + fn from(f: Ieee32) -> Self { + DataValue::from(f32::from_bits(f.bits())) + } +} +impl From for DataValue { + fn from(o: Offset32) -> Self { + DataValue::from(Into::::into(o)) + } +} impl Display for DataValue { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { diff --git a/cranelift/codegen/src/ir/instructions.rs b/cranelift/codegen/src/ir/instructions.rs index 48334b1837..4a14b77f33 100644 --- a/cranelift/codegen/src/ir/instructions.rs +++ b/cranelift/codegen/src/ir/instructions.rs @@ -17,6 +17,7 @@ use crate::ir::{self, trapcode::TrapCode, types, Block, FuncRef, JumpTable, SigR use crate::isa; use crate::bitset::BitSet; +use crate::data_value::DataValue; use crate::entity; use ir::condcodes::{FloatCC, IntCC}; @@ -284,6 +285,41 @@ impl InstructionData { } } + /// Return the value of an immediate if the instruction has one or `None` otherwise. Only + /// immediate values are considered, not global values, constant handles, condition codes, etc. + pub fn imm_value(&self) -> Option { + match self { + &InstructionData::UnaryBool { imm, .. } => Some(DataValue::from(imm)), + // 8-bit. + &InstructionData::BinaryImm8 { imm, .. } + | &InstructionData::BranchTableEntry { imm, .. } => Some(DataValue::from(imm as i8)), // Note the switch from unsigned to signed. + // 32-bit + &InstructionData::UnaryIeee32 { imm, .. } => Some(DataValue::from(imm)), + &InstructionData::HeapAddr { imm, .. } => { + let imm: u32 = imm.into(); + Some(DataValue::from(imm as i32)) // Note the switch from unsigned to signed. + } + &InstructionData::Load { offset, .. } + | &InstructionData::LoadComplex { offset, .. } + | &InstructionData::Store { offset, .. } + | &InstructionData::StoreComplex { offset, .. } + | &InstructionData::StackLoad { offset, .. } + | &InstructionData::StackStore { offset, .. } + | &InstructionData::TableAddr { offset, .. } => Some(DataValue::from(offset)), + // 64-bit. + &InstructionData::UnaryImm { imm, .. } + | &InstructionData::BinaryImm64 { imm, .. } + | &InstructionData::IntCompareImm { imm, .. } => Some(DataValue::from(imm.bits())), + &InstructionData::UnaryIeee64 { imm, .. } => Some(DataValue::from(imm)), + // 128-bit; though these immediates are present logically in the IR they are not + // included in the `InstructionData` for memory-size reasons. This case, returning + // `None`, is left here to alert users of this method that they should retrieve the + // value using the `DataFlowGraph`. + &InstructionData::Shuffle { mask: _, .. } => None, + _ => None, + } + } + /// If this is a trapping instruction, get its trap code. Otherwise, return /// `None`. pub fn trap_code(&self) -> Option {