From 6eecea5dad8537524cbfff18fcea4611b77b08a5 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 24 Jun 2020 22:55:46 -0400 Subject: [PATCH] First bits of IR validation --- src/arena.rs | 12 +++++++++- src/proc/mod.rs | 2 ++ src/proc/validator.rs | 56 +++++++++++++++++++++++++++++++++++++++++++ tests/convert.rs | 3 +++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/proc/validator.rs diff --git a/src/arena.rs b/src/arena.rs index d84da77906..d9c760f908 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -1,4 +1,4 @@ -use std::{fmt, hash, marker::PhantomData, num::NonZeroU32}; +use std::{cmp::Ordering, fmt, hash, marker::PhantomData, num::NonZeroU32}; /// An unique index in the arena array that a handle points to. /// @@ -29,6 +29,16 @@ impl PartialEq for Handle { } } impl Eq for Handle {} +impl PartialOrd for Handle { + fn partial_cmp(&self, other: &Self) -> Option { + self.index.partial_cmp(&other.index) + } +} +impl Ord for Handle { + fn cmp(&self, other: &Self) -> Ordering { + self.index.cmp(&other.index) + } +} impl fmt::Debug for Handle { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "Handle({})", self.index) diff --git a/src/proc/mod.rs b/src/proc/mod.rs index e4b181a697..18362d183e 100644 --- a/src/proc/mod.rs +++ b/src/proc/mod.rs @@ -1,4 +1,6 @@ mod interface; mod typifier; +mod validator; pub use typifier::{check_constant_types, ResolveError, Typifier, UnexpectedConstantTypeError}; +pub use validator::{ValidationError, Validator}; diff --git a/src/proc/validator.rs b/src/proc/validator.rs new file mode 100644 index 0000000000..613357e550 --- /dev/null +++ b/src/proc/validator.rs @@ -0,0 +1,56 @@ +use crate::arena::Handle; + +pub struct Validator {} + +#[derive(Clone, Debug)] +pub enum ValidationError { + /// The type width is not supported. + InvalidTypeWidth(crate::ScalarKind, crate::Bytes), + /// A type handle can not be resolved. + UnresolvedType(Handle), + /// There are instructions after `return`/`break`/`continue`. + InvalidControlFlowExitTail, +} + +impl Validator { + pub fn new() -> Self { + Validator {} + } + + pub fn validate(&mut self, module: &crate::Module) -> Result<(), ValidationError> { + for (handle, ty) in module.types.iter() { + use crate::TypeInner as Ti; + match ty.inner { + Ti::Scalar { kind, width } + | Ti::Vector { kind, width, .. } + | Ti::Matrix { kind, width, .. } => { + if width != 32 { + return Err(ValidationError::InvalidTypeWidth(kind, width)); + } + } + Ti::Pointer { base, class: _ } => { + if base >= handle { + return Err(ValidationError::UnresolvedType(base)); + } + } + Ti::Array { base, .. } => { + if base >= handle { + return Err(ValidationError::UnresolvedType(base)); + } + } + Ti::Struct { ref members } => { + //TODO: check that offsets are not intersecting? + for member in members { + if member.ty >= handle { + return Err(ValidationError::UnresolvedType(member.ty)); + } + } + } + Ti::Image { .. } => {} + Ti::Sampler { comparison: _ } => {} + } + } + + Ok(()) + } +} diff --git a/tests/convert.rs b/tests/convert.rs index 1048b6a618..5a1ed8bd05 100644 --- a/tests/convert.rs +++ b/tests/convert.rs @@ -20,6 +20,7 @@ fn load_glsl(name: &str, entry: &str, exec: ExecutionModel) -> naga::Module { #[test] fn convert_quad() { let module = load_wgsl("quad.wgsl"); + naga::proc::Validator::new().validate(&module).unwrap(); { use naga::back::msl; let mut binding_map = msl::BindingMap::default(); @@ -51,6 +52,7 @@ fn convert_quad() { #[test] fn convert_boids() { let module = load_wgsl("boids.wgsl"); + naga::proc::Validator::new().validate(&module).unwrap(); { use naga::back::msl; let mut binding_map = msl::BindingMap::default(); @@ -93,6 +95,7 @@ fn convert_boids() { #[ignore] fn convert_phong_lighting() { let module = load_glsl("glsl_phong_lighting.frag", "main", ExecutionModel::Fragment); + naga::proc::Validator::new().validate(&module).unwrap(); let header = naga::Header { version: (1, 0, 0),