naga/proc/
terminator.rs

1/// Ensure that the given block has return statements
2/// at the end of its control flow.
3///
4/// Note: we don't want to blindly append a return statement
5/// to the end, because it may be either redundant or invalid,
6/// e.g. when the user already has returns in if/else branches.
7pub fn ensure_block_returns(block: &mut crate::Block) {
8    use crate::Statement as S;
9    match block.last_mut() {
10        Some(&mut S::Block(ref mut b)) => {
11            ensure_block_returns(b);
12        }
13        Some(&mut S::If {
14            condition: _,
15            ref mut accept,
16            ref mut reject,
17        }) => {
18            ensure_block_returns(accept);
19            ensure_block_returns(reject);
20        }
21        Some(&mut S::Switch {
22            selector: _,
23            ref mut cases,
24        }) => {
25            for case in cases.iter_mut() {
26                if !case.fall_through {
27                    ensure_block_returns(&mut case.body);
28                }
29            }
30        }
31        Some(&mut (S::Emit(_) | S::Break | S::Continue | S::Return { .. } | S::Kill)) => (),
32        Some(
33            &mut (S::Loop { .. }
34            | S::Store { .. }
35            | S::ImageStore { .. }
36            | S::Call { .. }
37            | S::RayQuery { .. }
38            | S::Atomic { .. }
39            | S::WorkGroupUniformLoad { .. }
40            | S::SubgroupBallot { .. }
41            | S::SubgroupCollectiveOperation { .. }
42            | S::SubgroupGather { .. }
43            | S::Barrier(_)),
44        )
45        | None => block.push(S::Return { value: None }, Default::default()),
46    }
47}