Make DataValue, not Ieee32/64, respect IEEE754 (#4860)

* cranelift-codegen: Remove all uses of DataValue

This type is only used by the interpreter, cranelift-fuzzgen, and
filetests. I haven't found another convenient crate for those to all
depend on where this type can live instead, but this small refactor at
least makes it obvious that code generation does not in any way depend
on the implementation of this type.

* Make DataValue, not Ieee32/64, respect IEEE754

This fixes #4857 by partially reverting #4849.

It turns out that Ieee32 and Ieee64 need bitwise equality semantics so
they can be used as hash-table keys.

Moving the IEEE754 semantics up a layer to DataValue makes sense in
conjunction with #4855, where we introduced a DataValue::bitwise_eq
alternative implementation of equality for those cases where users of
DataValue still want the bitwise equality semantics.

* cranelift-interpreter: Use eq/ord from DataValue

This fixes #4828, again, now that the comparison operators on DataValue
have the right IEEE754 semantics.

* Add regression test from issue #4857
This commit is contained in:
Jamey Sharp
2022-09-02 17:26:14 -07:00
committed by GitHub
parent 7e45cff459
commit 9856664f1f
7 changed files with 81 additions and 61 deletions

View File

@@ -17,7 +17,6 @@ use core::str::FromStr;
use serde::{Deserialize, Serialize};
use crate::bitset::BitSet;
use crate::data_value::DataValue;
use crate::entity;
use crate::ir::{
self,
@@ -289,39 +288,6 @@ 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<DataValue> {
match self {
&InstructionData::UnaryBool { imm, .. } => Some(DataValue::from(imm)),
// 8-bit.
&InstructionData::BinaryImm8 { imm, .. }
| &InstructionData::TernaryImm8 { 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::Store { 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 { imm: _, .. } => None,
_ => None,
}
}
/// If this is a trapping instruction, get its trap code. Otherwise, return
/// `None`.
pub fn trap_code(&self) -> Option<TrapCode> {