From 22c4033cb3dab5d0d3315ddb386faead710d18c6 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Thu, 10 Apr 2025 09:48:38 -0700 Subject: [PATCH] [naga] Properly evaluate `abs(most negative abstract int)`. Have constant evaluator use `wrapping_abs` instead of `abs` when applying `MathFunction::Abs` to AbstractInt values. WGSL says that applying `abs` to the most negative AbstractInt value must return it unchanged, which is what Rust's `i64::wrapping_abs` does. --- naga/src/proc/constant_evaluator.rs | 2 +- naga/tests/naga/wgsl_errors.rs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/naga/src/proc/constant_evaluator.rs b/naga/src/proc/constant_evaluator.rs index f0085a32e..0edb0ee52 100644 --- a/naga/src/proc/constant_evaluator.rs +++ b/naga/src/proc/constant_evaluator.rs @@ -1080,7 +1080,7 @@ impl<'a> ConstantEvaluator<'a> { Scalar::AbstractFloat([e]) => Ok(Scalar::AbstractFloat([e.abs()])), Scalar::F32([e]) => Ok(Scalar::F32([e.abs()])), Scalar::F16([e]) => Ok(Scalar::F16([e.abs()])), - Scalar::AbstractInt([e]) => Ok(Scalar::AbstractInt([e.abs()])), + Scalar::AbstractInt([e]) => Ok(Scalar::AbstractInt([e.wrapping_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()])), diff --git a/naga/tests/naga/wgsl_errors.rs b/naga/tests/naga/wgsl_errors.rs index 800cba25f..61953e49b 100644 --- a/naga/tests/naga/wgsl_errors.rs +++ b/naga/tests/naga/wgsl_errors.rs @@ -3572,3 +3572,24 @@ fn struct_names_in_init_errors() { assert!(variant("1.0").is_err()); assert!(variant("A()").is_err()); } + +/// Constant evaluation with interesting values. +#[test] +fn const_eval_value_errors() { + #[track_caller] + fn variant(expr: &str) -> Result { + let input = format!( + r#" + fn f() {{ _ = {expr}; }} + "# + ); + naga::front::wgsl::parse_str(&input) + } + + assert!(variant("1/1").is_ok()); + assert!(variant("1/0").is_err()); + + assert!(variant("f32(abs(1))").is_ok()); + assert!(variant("f32(abs(-9223372036854775807))").is_ok()); + assert!(variant("f32(abs(-9223372036854775807 - 1))").is_ok()); +}