Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make validation reject 64-bit floating-point literals. #2567

Merged
merged 3 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/proc/constant_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ impl<'a> ConstantEvaluator<'a> {
// expression at a time, `Compose` expressions can only refer to other
// expressions, and `ZeroValue` expressions are always okay.
if let Expression::Literal(literal) = expr {
crate::valid::validate_literal(literal)?;
crate::valid::check_literal_value(literal)?;
}

if let Some(FunctionLocalData {
Expand Down
19 changes: 16 additions & 3 deletions src/valid/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ pub enum ConstExpressionError {
Type(#[from] ResolveError),
#[error(transparent)]
Literal(#[from] LiteralError),
#[error(transparent)]
Width(#[from] super::r#type::WidthError),
}

#[derive(Clone, Debug, thiserror::Error)]
Expand All @@ -149,6 +151,8 @@ pub enum LiteralError {
NaN,
#[error("Float literal is infinite")]
Infinity,
#[error(transparent)]
Width(#[from] super::r#type::WidthError),
}

#[cfg(feature = "validate")]
Expand Down Expand Up @@ -188,7 +192,7 @@ impl super::Validator {

match gctx.const_expressions[handle] {
E::Literal(literal) => {
validate_literal(literal)?;
self.validate_literal(literal)?;
}
E::Constant(_) | E::ZeroValue(_) => {}
E::Compose { ref components, ty } => {
Expand Down Expand Up @@ -343,7 +347,7 @@ impl super::Validator {
ShaderStages::all()
}
E::Literal(literal) => {
validate_literal(literal)?;
self.validate_literal(literal)?;
ShaderStages::all()
}
E::Constant(_) | E::ZeroValue(_) => ShaderStages::all(),
Expand Down Expand Up @@ -1563,9 +1567,18 @@ impl super::Validator {
_ => Err(ExpressionError::ExpectedGlobalVariable),
}
}

pub fn validate_literal(&self, literal: crate::Literal) -> Result<(), LiteralError> {
let kind = literal.scalar_kind();
let width = literal.width();
self.check_width(kind, width)?;
check_literal_value(literal)?;

Ok(())
}
}

pub fn validate_literal(literal: crate::Literal) -> Result<(), LiteralError> {
pub fn check_literal_value(literal: crate::Literal) -> Result<(), LiteralError> {
let is_nan = match literal {
crate::Literal::F64(v) => v.is_nan(),
crate::Literal::F32(v) => v.is_nan(),
Expand Down
2 changes: 1 addition & 1 deletion src/valid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::ops;
use crate::span::{AddSpan as _, WithSpan};
pub use analyzer::{ExpressionInfo, FunctionInfo, GlobalUse, Uniformity, UniformityRequirements};
pub use compose::ComposeError;
pub use expression::{validate_literal, LiteralError};
pub use expression::{check_literal_value, LiteralError};
pub use expression::{ConstExpressionError, ExpressionError};
pub use function::{CallError, FunctionError, LocalVariableError};
pub use interface::{EntryPointError, GlobalVariableError, VaryingError};
Expand Down
32 changes: 26 additions & 6 deletions src/valid/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ pub enum Disalignment {
pub enum TypeError {
#[error("Capability {0:?} is required")]
MissingCapability(Capabilities),
#[error("The {0:?} scalar width {1} is not supported")]
InvalidWidth(crate::ScalarKind, crate::Bytes),
#[error("The {0:?} scalar width {1} is not supported for an atomic")]
InvalidAtomicWidth(crate::ScalarKind, crate::Bytes),
#[error("Invalid type for pointer target {0:?}")]
Expand Down Expand Up @@ -126,6 +124,23 @@ pub enum TypeError {
},
#[error("Structure types must have at least one member")]
EmptyStruct,
#[error(transparent)]
WidthError(#[from] WidthError),
}

#[derive(Clone, Debug, thiserror::Error)]
#[cfg_attr(test, derive(PartialEq))]
pub enum WidthError {
#[error("The {0:?} scalar width {1} is not supported")]
Invalid(crate::ScalarKind, crate::Bytes),
#[error("Using `{name}` values requires the `naga::valid::Capabilities::{flag}` flag")]
MissingCapability {
name: &'static str,
flag: &'static str,
},

#[error("64-bit integers are not yet supported")]
Unsupported64Bit,
}

// Only makes sense if `flags.contains(HOST_SHAREABLE)`
Expand Down Expand Up @@ -209,16 +224,21 @@ impl super::Validator {
}
}

pub(super) fn check_width(
pub(super) const fn check_width(
&self,
kind: crate::ScalarKind,
width: crate::Bytes,
) -> Result<(), TypeError> {
) -> Result<(), WidthError> {
let good = match kind {
crate::ScalarKind::Bool => width == crate::BOOL_WIDTH,
crate::ScalarKind::Float => {
if width == 8 {
self.require_type_capability(Capabilities::FLOAT64)?;
if !self.capabilities.contains(Capabilities::FLOAT64) {
return Err(WidthError::MissingCapability {
name: "f64",
flag: "FLOAT64",
});
}
true
} else {
width == 4
Expand All @@ -229,7 +249,7 @@ impl super::Validator {
if good {
Ok(())
} else {
Err(TypeError::InvalidWidth(kind, width))
Err(WidthError::Invalid(kind, width))
}
}

Expand Down