mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-26 16:53:48 +00:00
Terminator processor, used in WGSL and GLSL frontends
This commit is contained in:
parent
f18443a79d
commit
5fe9429a63
@ -5,10 +5,15 @@ pomelo! {
|
||||
//%verbose;
|
||||
%include {
|
||||
use super::super::{error::ErrorKind, token::*, ast::*};
|
||||
use crate::{proc::Typifier, Arena, BinaryOperator, Binding, Block, Constant,
|
||||
ConstantInner, EntryPoint, Expression, FallThrough, FastHashMap, Function, GlobalVariable, Handle, Interpolation,
|
||||
LocalVariable, MemberOrigin, SampleLevel, ScalarKind, Statement, StorageAccess,
|
||||
StorageClass, StructMember, Type, TypeInner, UnaryOperator};
|
||||
use crate::{
|
||||
proc::{ensure_block_returns, Typifier},
|
||||
Arena, BinaryOperator, Binding, Block, Constant,
|
||||
ConstantInner, EntryPoint, Expression, FallThrough,
|
||||
FastHashMap, Function, GlobalVariable, Handle, Interpolation,
|
||||
LocalVariable, MemberOrigin, SampleLevel, ScalarKind,
|
||||
Statement, StorageAccess,
|
||||
StorageClass, StructMember, Type, TypeInner, UnaryOperator,
|
||||
};
|
||||
}
|
||||
%token #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] pub enum Token {};
|
||||
%parser pub struct Parser<'a> {};
|
||||
@ -1117,11 +1122,7 @@ pomelo! {
|
||||
extra.context.clear_scopes();
|
||||
extra.context.lookup_global_var_exps.clear();
|
||||
extra.context.typifier = Typifier::new();
|
||||
// make sure function ends with return
|
||||
match cs.last() {
|
||||
Some(Statement::Return {..}) => {}
|
||||
_ => {cs.push(Statement::Return { value:None });}
|
||||
}
|
||||
ensure_block_returns(&mut cs);
|
||||
f.body = cs;
|
||||
f.fill_global_use(&extra.module.global_variables);
|
||||
f
|
||||
|
@ -7,7 +7,7 @@ mod lexer;
|
||||
|
||||
use crate::{
|
||||
arena::{Arena, Handle},
|
||||
proc::{ResolveContext, ResolveError, Typifier},
|
||||
proc::{ensure_block_returns, ResolveContext, ResolveError, Typifier},
|
||||
FastHashMap,
|
||||
};
|
||||
|
||||
@ -1594,6 +1594,8 @@ impl Parser {
|
||||
arguments: &fun.arguments,
|
||||
},
|
||||
)?;
|
||||
// fixup the IR
|
||||
ensure_block_returns(&mut fun.body);
|
||||
// done
|
||||
fun.fill_global_use(&module.global_variables);
|
||||
self.scopes.pop();
|
||||
|
@ -4,6 +4,7 @@
|
||||
mod call_graph;
|
||||
mod interface;
|
||||
mod namer;
|
||||
mod terminator;
|
||||
mod typifier;
|
||||
mod validator;
|
||||
|
||||
@ -11,6 +12,7 @@ mod validator;
|
||||
pub use call_graph::{CallGraph, CallGraphBuilder};
|
||||
pub use interface::{Interface, Visitor};
|
||||
pub use namer::{EntryPointIndex, NameKey, Namer};
|
||||
pub use terminator::ensure_block_returns;
|
||||
pub use typifier::{check_constant_type, ResolveContext, ResolveError, Typifier};
|
||||
pub use validator::{ValidationError, Validator};
|
||||
|
||||
|
40
src/proc/terminator.rs
Normal file
40
src/proc/terminator.rs
Normal file
@ -0,0 +1,40 @@
|
||||
/// 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) {
|
||||
match block.last_mut() {
|
||||
Some(&mut crate::Statement::Block(ref mut b)) => {
|
||||
ensure_block_returns(b);
|
||||
}
|
||||
Some(&mut crate::Statement::If {
|
||||
condition: _,
|
||||
ref mut accept,
|
||||
ref mut reject,
|
||||
}) => {
|
||||
ensure_block_returns(accept);
|
||||
ensure_block_returns(reject);
|
||||
}
|
||||
Some(&mut crate::Statement::Switch {
|
||||
selector: _,
|
||||
ref mut cases,
|
||||
ref mut default,
|
||||
}) => {
|
||||
for case in cases.values_mut() {
|
||||
if let (ref mut b, None) = *case {
|
||||
ensure_block_returns(b);
|
||||
}
|
||||
}
|
||||
ensure_block_returns(default);
|
||||
}
|
||||
Some(&mut crate::Statement::Break)
|
||||
| Some(&mut crate::Statement::Continue)
|
||||
| Some(&mut crate::Statement::Return { .. })
|
||||
| Some(&mut crate::Statement::Kill) => (),
|
||||
Some(&mut crate::Statement::Loop { .. })
|
||||
| Some(&mut crate::Statement::Store { .. })
|
||||
| None => block.push(crate::Statement::Return { value: None }),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user