summaryrefslogtreecommitdiffstats
path: root/third_party/rust/naga/src/proc/constant_evaluator.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/naga/src/proc/constant_evaluator.rs')
-rw-r--r--third_party/rust/naga/src/proc/constant_evaluator.rs242
1 files changed, 148 insertions, 94 deletions
diff --git a/third_party/rust/naga/src/proc/constant_evaluator.rs b/third_party/rust/naga/src/proc/constant_evaluator.rs
index b3884b04b1..983af3718c 100644
--- a/third_party/rust/naga/src/proc/constant_evaluator.rs
+++ b/third_party/rust/naga/src/proc/constant_evaluator.rs
@@ -31,7 +31,7 @@ macro_rules! gen_component_wise_extractor {
$(
#[doc = concat!(
"Maps to [`Literal::",
- stringify!($mapping),
+ stringify!($literal),
"`]",
)]
$mapping([$ty; N]),
@@ -200,6 +200,8 @@ gen_component_wise_extractor! {
AbstractInt => AbstractInt: i64,
U32 => U32: u32,
I32 => I32: i32,
+ U64 => U64: u64,
+ I64 => I64: i64,
],
scalar_kinds: [
Float,
@@ -847,6 +849,8 @@ impl<'a> ConstantEvaluator<'a> {
Scalar::AbstractInt([e]) => Ok(Scalar::AbstractInt([e.abs()])),
Scalar::I32([e]) => Ok(Scalar::I32([e.wrapping_abs()])),
Scalar::U32([e]) => Ok(Scalar::U32([e])), // TODO: just re-use the expression, ezpz
+ Scalar::I64([e]) => Ok(Scalar::I64([e.wrapping_abs()])),
+ Scalar::U64([e]) => Ok(Scalar::U64([e])),
})
}
crate::MathFunction::Min => {
@@ -1280,7 +1284,7 @@ impl<'a> ConstantEvaluator<'a> {
Literal::U32(v) => v as i32,
Literal::F32(v) => v as i32,
Literal::Bool(v) => v as i32,
- Literal::F64(_) | Literal::I64(_) => {
+ Literal::F64(_) | Literal::I64(_) | Literal::U64(_) => {
return make_error();
}
Literal::AbstractInt(v) => i32::try_from_abstract(v)?,
@@ -1291,18 +1295,40 @@ impl<'a> ConstantEvaluator<'a> {
Literal::U32(v) => v,
Literal::F32(v) => v as u32,
Literal::Bool(v) => v as u32,
- Literal::F64(_) | Literal::I64(_) => {
+ Literal::F64(_) | Literal::I64(_) | Literal::U64(_) => {
return make_error();
}
Literal::AbstractInt(v) => u32::try_from_abstract(v)?,
Literal::AbstractFloat(v) => u32::try_from_abstract(v)?,
}),
+ Sc::I64 => Literal::I64(match literal {
+ Literal::I32(v) => v as i64,
+ Literal::U32(v) => v as i64,
+ Literal::F32(v) => v as i64,
+ Literal::Bool(v) => v as i64,
+ Literal::F64(v) => v as i64,
+ Literal::I64(v) => v,
+ Literal::U64(v) => v as i64,
+ Literal::AbstractInt(v) => i64::try_from_abstract(v)?,
+ Literal::AbstractFloat(v) => i64::try_from_abstract(v)?,
+ }),
+ Sc::U64 => Literal::U64(match literal {
+ Literal::I32(v) => v as u64,
+ Literal::U32(v) => v as u64,
+ Literal::F32(v) => v as u64,
+ Literal::Bool(v) => v as u64,
+ Literal::F64(v) => v as u64,
+ Literal::I64(v) => v as u64,
+ Literal::U64(v) => v,
+ Literal::AbstractInt(v) => u64::try_from_abstract(v)?,
+ Literal::AbstractFloat(v) => u64::try_from_abstract(v)?,
+ }),
Sc::F32 => Literal::F32(match literal {
Literal::I32(v) => v as f32,
Literal::U32(v) => v as f32,
Literal::F32(v) => v,
Literal::Bool(v) => v as u32 as f32,
- Literal::F64(_) | Literal::I64(_) => {
+ Literal::F64(_) | Literal::I64(_) | Literal::U64(_) => {
return make_error();
}
Literal::AbstractInt(v) => f32::try_from_abstract(v)?,
@@ -1314,7 +1340,7 @@ impl<'a> ConstantEvaluator<'a> {
Literal::F32(v) => v as f64,
Literal::F64(v) => v,
Literal::Bool(v) => v as u32 as f64,
- Literal::I64(_) => return make_error(),
+ Literal::I64(_) | Literal::U64(_) => return make_error(),
Literal::AbstractInt(v) => f64::try_from_abstract(v)?,
Literal::AbstractFloat(v) => f64::try_from_abstract(v)?,
}),
@@ -1325,6 +1351,7 @@ impl<'a> ConstantEvaluator<'a> {
Literal::Bool(v) => v,
Literal::F64(_)
| Literal::I64(_)
+ | Literal::U64(_)
| Literal::AbstractInt(_)
| Literal::AbstractFloat(_) => {
return make_error();
@@ -1877,6 +1904,122 @@ impl<'a> ConstantEvaluator<'a> {
}
}
+/// Trait for conversions of abstract values to concrete types.
+trait TryFromAbstract<T>: Sized {
+ /// Convert an abstract literal `value` to `Self`.
+ ///
+ /// Since Naga's `AbstractInt` and `AbstractFloat` exist to support
+ /// WGSL, we follow WGSL's conversion rules here:
+ ///
+ /// - WGSL §6.1.2. Conversion Rank says that automatic conversions
+ /// to integers are either lossless or an error.
+ ///
+ /// - WGSL §14.6.4 Floating Point Conversion says that conversions
+ /// to floating point in constant expressions and override
+ /// expressions are errors if the value is out of range for the
+ /// destination type, but rounding is okay.
+ ///
+ /// [`AbstractInt`]: crate::Literal::AbstractInt
+ /// [`Float`]: crate::Literal::Float
+ fn try_from_abstract(value: T) -> Result<Self, ConstantEvaluatorError>;
+}
+
+impl TryFromAbstract<i64> for i32 {
+ fn try_from_abstract(value: i64) -> Result<i32, ConstantEvaluatorError> {
+ i32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
+ value: format!("{value:?}"),
+ to_type: "i32",
+ })
+ }
+}
+
+impl TryFromAbstract<i64> for u32 {
+ fn try_from_abstract(value: i64) -> Result<u32, ConstantEvaluatorError> {
+ u32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
+ value: format!("{value:?}"),
+ to_type: "u32",
+ })
+ }
+}
+
+impl TryFromAbstract<i64> for u64 {
+ fn try_from_abstract(value: i64) -> Result<u64, ConstantEvaluatorError> {
+ u64::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
+ value: format!("{value:?}"),
+ to_type: "u64",
+ })
+ }
+}
+
+impl TryFromAbstract<i64> for i64 {
+ fn try_from_abstract(value: i64) -> Result<i64, ConstantEvaluatorError> {
+ Ok(value)
+ }
+}
+
+impl TryFromAbstract<i64> for f32 {
+ fn try_from_abstract(value: i64) -> Result<Self, ConstantEvaluatorError> {
+ let f = value as f32;
+ // The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of
+ // `f32` is roughly ±3.4 × 10³⁸, so there's no opportunity for
+ // overflow here.
+ Ok(f)
+ }
+}
+
+impl TryFromAbstract<f64> for f32 {
+ fn try_from_abstract(value: f64) -> Result<f32, ConstantEvaluatorError> {
+ let f = value as f32;
+ if f.is_infinite() {
+ return Err(ConstantEvaluatorError::AutomaticConversionLossy {
+ value: format!("{value:?}"),
+ to_type: "f32",
+ });
+ }
+ Ok(f)
+ }
+}
+
+impl TryFromAbstract<i64> for f64 {
+ fn try_from_abstract(value: i64) -> Result<Self, ConstantEvaluatorError> {
+ let f = value as f64;
+ // The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of
+ // `f64` is roughly ±1.8 × 10³⁰⁸, so there's no opportunity for
+ // overflow here.
+ Ok(f)
+ }
+}
+
+impl TryFromAbstract<f64> for f64 {
+ fn try_from_abstract(value: f64) -> Result<f64, ConstantEvaluatorError> {
+ Ok(value)
+ }
+}
+
+impl TryFromAbstract<f64> for i32 {
+ fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
+ Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "i32" })
+ }
+}
+
+impl TryFromAbstract<f64> for u32 {
+ fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
+ Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "u32" })
+ }
+}
+
+impl TryFromAbstract<f64> for i64 {
+ fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
+ Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "i64" })
+ }
+}
+
+impl TryFromAbstract<f64> for u64 {
+ fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
+ Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "u64" })
+ }
+}
+
#[cfg(test)]
mod tests {
use std::vec;
@@ -2384,92 +2527,3 @@ mod tests {
}
}
}
-
-/// Trait for conversions of abstract values to concrete types.
-trait TryFromAbstract<T>: Sized {
- /// Convert an abstract literal `value` to `Self`.
- ///
- /// Since Naga's `AbstractInt` and `AbstractFloat` exist to support
- /// WGSL, we follow WGSL's conversion rules here:
- ///
- /// - WGSL §6.1.2. Conversion Rank says that automatic conversions
- /// to integers are either lossless or an error.
- ///
- /// - WGSL §14.6.4 Floating Point Conversion says that conversions
- /// to floating point in constant expressions and override
- /// expressions are errors if the value is out of range for the
- /// destination type, but rounding is okay.
- ///
- /// [`AbstractInt`]: crate::Literal::AbstractInt
- /// [`Float`]: crate::Literal::Float
- fn try_from_abstract(value: T) -> Result<Self, ConstantEvaluatorError>;
-}
-
-impl TryFromAbstract<i64> for i32 {
- fn try_from_abstract(value: i64) -> Result<i32, ConstantEvaluatorError> {
- i32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
- value: format!("{value:?}"),
- to_type: "i32",
- })
- }
-}
-
-impl TryFromAbstract<i64> for u32 {
- fn try_from_abstract(value: i64) -> Result<u32, ConstantEvaluatorError> {
- u32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy {
- value: format!("{value:?}"),
- to_type: "u32",
- })
- }
-}
-
-impl TryFromAbstract<i64> for f32 {
- fn try_from_abstract(value: i64) -> Result<Self, ConstantEvaluatorError> {
- let f = value as f32;
- // The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of
- // `f32` is roughly ±3.4 × 10³⁸, so there's no opportunity for
- // overflow here.
- Ok(f)
- }
-}
-
-impl TryFromAbstract<f64> for f32 {
- fn try_from_abstract(value: f64) -> Result<f32, ConstantEvaluatorError> {
- let f = value as f32;
- if f.is_infinite() {
- return Err(ConstantEvaluatorError::AutomaticConversionLossy {
- value: format!("{value:?}"),
- to_type: "f32",
- });
- }
- Ok(f)
- }
-}
-
-impl TryFromAbstract<i64> for f64 {
- fn try_from_abstract(value: i64) -> Result<Self, ConstantEvaluatorError> {
- let f = value as f64;
- // The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of
- // `f64` is roughly ±1.8 × 10³⁰⁸, so there's no opportunity for
- // overflow here.
- Ok(f)
- }
-}
-
-impl TryFromAbstract<f64> for f64 {
- fn try_from_abstract(value: f64) -> Result<f64, ConstantEvaluatorError> {
- Ok(value)
- }
-}
-
-impl TryFromAbstract<f64> for i32 {
- fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
- Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "i32" })
- }
-}
-
-impl TryFromAbstract<f64> for u32 {
- fn try_from_abstract(_: f64) -> Result<Self, ConstantEvaluatorError> {
- Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "u32" })
- }
-}