diff options
Diffstat (limited to 'third_party/rust/naga/src/proc/terminator.rs')
-rw-r--r-- | third_party/rust/naga/src/proc/terminator.rs | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/third_party/rust/naga/src/proc/terminator.rs b/third_party/rust/naga/src/proc/terminator.rs new file mode 100644 index 0000000000..5915616cc5 --- /dev/null +++ b/third_party/rust/naga/src/proc/terminator.rs @@ -0,0 +1,42 @@ +/// Ensure that the given block has return statements +/// at the end of its control flow. +/// +/// Note: we don't want to blindly append a return statement +/// to the end, because it may be either redundant or invalid, +/// e.g. when the user already has returns in if/else branches. +pub fn ensure_block_returns(block: &mut crate::Block) { + use crate::Statement as S; + match block.last_mut() { + Some(&mut S::Block(ref mut b)) => { + ensure_block_returns(b); + } + Some(&mut S::If { + condition: _, + ref mut accept, + ref mut reject, + }) => { + ensure_block_returns(accept); + ensure_block_returns(reject); + } + Some(&mut S::Switch { + selector: _, + ref mut cases, + }) => { + for case in cases.iter_mut() { + if !case.fall_through { + ensure_block_returns(&mut case.body); + } + } + } + Some(&mut (S::Emit(_) | S::Break | S::Continue | S::Return { .. } | S::Kill)) => (), + Some( + &mut (S::Loop { .. } + | S::Store { .. } + | S::ImageStore { .. } + | S::Call { .. } + | S::Atomic { .. } + | S::Barrier(_)), + ) + | None => block.push(S::Return { value: None }, Default::default()), + } +} |