Make cranelift-interpreter non-generic over value (#6178)

* Make cranelift-interpreter non-generic over value

Fixes #5793

* Review suggestion

Co-authored-by: Jamey Sharp <jamey@minilop.net>

* Fix fuzz target

* Update doc comments

---------

Co-authored-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
bjorn3
2023-04-11 13:13:29 +02:00
committed by GitHub
parent 3ff6e0fe03
commit 96a60aa26b
5 changed files with 441 additions and 449 deletions

View File

@@ -1,7 +1,6 @@
//! The [Value] trait describes what operations can be performed on interpreter values. The
//! interpreter usually executes using [DataValue]s so an implementation is provided here. The fact
//! that [Value] is a trait, however, allows interpretation of Cranelift IR on other kinds of
//! values.
//! The [DataValueExt] trait is an extension trait for [DataValue]. It provides a lot of functions
//! used by the rest of the interpreter.
use core::convert::TryFrom;
use core::fmt::{self, Display, Formatter};
use cranelift_codegen::data_value::{DataValue, DataValueCastFailure};
@@ -11,9 +10,8 @@ use thiserror::Error;
pub type ValueResult<T> = Result<T, ValueError>;
pub trait Value: Clone + From<DataValue> {
pub trait DataValueExt: Sized {
// Identity.
fn ty(&self) -> Type;
fn int(n: i128, ty: Type) -> ValueResult<Self>;
fn into_int(self) -> ValueResult<i128>;
fn float(n: u64, ty: Type) -> ValueResult<Self>;
@@ -34,17 +32,6 @@ pub trait Value: Clone + From<DataValue> {
fn min(self, other: Self) -> ValueResult<Self>;
// Comparison.
fn eq(&self, other: &Self) -> ValueResult<bool>;
fn gt(&self, other: &Self) -> ValueResult<bool>;
fn ge(&self, other: &Self) -> ValueResult<bool> {
Ok(self.eq(other)? || self.gt(other)?)
}
fn lt(&self, other: &Self) -> ValueResult<bool> {
other.gt(self)
}
fn le(&self, other: &Self) -> ValueResult<bool> {
Ok(other.eq(self)? || other.gt(self)?)
}
fn uno(&self, other: &Self) -> ValueResult<bool>;
// Arithmetic.
@@ -240,11 +227,7 @@ macro_rules! bitop {
};
}
impl Value for DataValue {
fn ty(&self) -> Type {
self.ty()
}
impl DataValueExt for DataValue {
fn int(n: i128, ty: Type) -> ValueResult<Self> {
if ty.is_int() && !ty.is_vector() {
DataValue::from_integer(n, ty).map_err(|_| ValueError::InvalidValue(ty))
@@ -507,7 +490,7 @@ impl Value for DataValue {
}
fn max(self, other: Self) -> ValueResult<Self> {
if Value::gt(&self, &other)? {
if self > other {
Ok(self)
} else {
Ok(other)
@@ -515,21 +498,13 @@ impl Value for DataValue {
}
fn min(self, other: Self) -> ValueResult<Self> {
if Value::lt(&self, &other)? {
if self < other {
Ok(self)
} else {
Ok(other)
}
}
fn eq(&self, other: &Self) -> ValueResult<bool> {
Ok(self == other)
}
fn gt(&self, other: &Self) -> ValueResult<bool> {
Ok(self > other)
}
fn uno(&self, other: &Self) -> ValueResult<bool> {
Ok(self.is_nan()? || other.is_nan()?)
}
@@ -566,7 +541,7 @@ impl Value for DataValue {
let denominator = other.clone().into_int()?;
// Check if we are dividing INT_MIN / -1. This causes an integer overflow trap.
let min = Value::int(1i128 << (self.ty().bits() - 1), self.ty())?;
let min = DataValueExt::int(1i128 << (self.ty().bits() - 1), self.ty())?;
if self == min && denominator == -1 {
return Err(ValueError::IntegerOverflow);
}
@@ -582,7 +557,7 @@ impl Value for DataValue {
let denominator = other.clone().into_int()?;
// Check if we are dividing INT_MIN / -1. This causes an integer overflow trap.
let min = Value::int(1i128 << (self.ty().bits() - 1), self.ty())?;
let min = DataValueExt::int(1i128 << (self.ty().bits() - 1), self.ty())?;
if self == min && denominator == -1 {
return Err(ValueError::IntegerOverflow);
}