mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[glsl-in] Fix void function calls
This commit is contained in:
committed by
Dzmitry Malyshau
parent
c526c85258
commit
4e95c46a9d
@@ -24,6 +24,8 @@ pub struct FunctionDeclaration {
|
||||
pub handle: Handle<Function>,
|
||||
/// Wheter this function was already defined or is just a prototype
|
||||
pub defined: bool,
|
||||
/// Wheter or not this function returns void (nothing)
|
||||
pub void: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -321,24 +323,46 @@ impl<'function> Context<'function> {
|
||||
self.scopes.pop();
|
||||
}
|
||||
|
||||
pub fn lower(
|
||||
pub fn lower_expect(
|
||||
&mut self,
|
||||
program: &mut Program,
|
||||
expr: Handle<HirExpr>,
|
||||
lhs: bool,
|
||||
body: &mut Block,
|
||||
) -> Result<(Handle<Expression>, SourceMetadata), ErrorKind> {
|
||||
let (maybe_expr, meta) = self.lower(program, expr, lhs, body)?;
|
||||
|
||||
let expr = match maybe_expr {
|
||||
Some(e) => e,
|
||||
None => {
|
||||
return Err(ErrorKind::SemanticError(
|
||||
meta,
|
||||
"Expression returns void".into(),
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Ok((expr, meta))
|
||||
}
|
||||
|
||||
pub fn lower(
|
||||
&mut self,
|
||||
program: &mut Program,
|
||||
expr: Handle<HirExpr>,
|
||||
lhs: bool,
|
||||
body: &mut Block,
|
||||
) -> Result<(Option<Handle<Expression>>, SourceMetadata), ErrorKind> {
|
||||
let HirExpr { kind, meta } = self.hir_exprs[expr].clone();
|
||||
|
||||
let handle = match kind {
|
||||
HirExprKind::Access { base, index } => {
|
||||
let base = self.lower(program, base, lhs, body)?.0;
|
||||
let index = self.lower(program, index, false, body)?.0;
|
||||
let base = self.lower_expect(program, base, lhs, body)?.0;
|
||||
let index = self.lower_expect(program, index, false, body)?.0;
|
||||
|
||||
self.add_expression(Expression::Access { base, index }, body)
|
||||
}
|
||||
HirExprKind::Select { base, field } => {
|
||||
let base = self.lower(program, base, lhs, body)?.0;
|
||||
let base = self.lower_expect(program, base, lhs, body)?.0;
|
||||
|
||||
program.field_selection(self, body, base, &field, meta)?
|
||||
}
|
||||
@@ -346,8 +370,8 @@ impl<'function> Context<'function> {
|
||||
self.add_expression(Expression::Constant(constant), body)
|
||||
}
|
||||
HirExprKind::Binary { left, op, right } if !lhs => {
|
||||
let (left, left_meta) = self.lower(program, left, false, body)?;
|
||||
let (right, right_meta) = self.lower(program, right, false, body)?;
|
||||
let (left, left_meta) = self.lower_expect(program, left, false, body)?;
|
||||
let (right, right_meta) = self.lower_expect(program, right, false, body)?;
|
||||
|
||||
if let BinaryOperator::Equal | BinaryOperator::NotEqual = op {
|
||||
let equals = op == BinaryOperator::Equal;
|
||||
@@ -386,7 +410,7 @@ impl<'function> Context<'function> {
|
||||
}
|
||||
}
|
||||
HirExprKind::Unary { op, expr } if !lhs => {
|
||||
let expr = self.lower(program, expr, false, body)?.0;
|
||||
let expr = self.lower_expect(program, expr, false, body)?.0;
|
||||
|
||||
self.add_expression(Expression::Unary { op, expr }, body)
|
||||
}
|
||||
@@ -405,16 +429,17 @@ impl<'function> Context<'function> {
|
||||
}
|
||||
}
|
||||
HirExprKind::Call(call) if !lhs => {
|
||||
program.function_call(self, body, call.kind, &call.args, meta)?
|
||||
let maybe_expr = program.function_call(self, body, call.kind, &call.args, meta)?;
|
||||
return Ok((maybe_expr, meta));
|
||||
}
|
||||
HirExprKind::Conditional {
|
||||
condition,
|
||||
accept,
|
||||
reject,
|
||||
} if !lhs => {
|
||||
let condition = self.lower(program, condition, false, body)?.0;
|
||||
let accept = self.lower(program, accept, false, body)?.0;
|
||||
let reject = self.lower(program, reject, false, body)?.0;
|
||||
let condition = self.lower_expect(program, condition, false, body)?.0;
|
||||
let accept = self.lower_expect(program, accept, false, body)?.0;
|
||||
let reject = self.lower_expect(program, reject, false, body)?.0;
|
||||
|
||||
self.add_expression(
|
||||
Expression::Select {
|
||||
@@ -426,8 +451,8 @@ impl<'function> Context<'function> {
|
||||
)
|
||||
}
|
||||
HirExprKind::Assign { tgt, value } if !lhs => {
|
||||
let pointer = self.lower(program, tgt, true, body)?.0;
|
||||
let value = self.lower(program, value, false, body)?.0;
|
||||
let pointer = self.lower_expect(program, tgt, true, body)?.0;
|
||||
let value = self.lower_expect(program, value, false, body)?.0;
|
||||
|
||||
self.emit_flush(body);
|
||||
self.emit_start();
|
||||
@@ -444,7 +469,7 @@ impl<'function> Context<'function> {
|
||||
}
|
||||
};
|
||||
|
||||
Ok((handle, meta))
|
||||
Ok((Some(handle), meta))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ impl Program<'_> {
|
||||
fc: FunctionCallKind,
|
||||
raw_args: &[Handle<HirExpr>],
|
||||
meta: SourceMetadata,
|
||||
) -> Result<Handle<Expression>, ErrorKind> {
|
||||
) -> Result<Option<Handle<Expression>>, ErrorKind> {
|
||||
let args: Vec<_> = raw_args
|
||||
.iter()
|
||||
.map(|e| ctx.lower(self, *e, false, body))
|
||||
.map(|e| ctx.lower_expect(self, *e, false, body))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
match fc {
|
||||
@@ -89,7 +89,7 @@ impl Program<'_> {
|
||||
)
|
||||
};
|
||||
|
||||
Ok(h)
|
||||
Ok(Some(h))
|
||||
}
|
||||
FunctionCallKind::Function(name) => {
|
||||
match name.as_str() {
|
||||
@@ -98,14 +98,14 @@ impl Program<'_> {
|
||||
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
|
||||
}
|
||||
ctx.samplers.insert(args[0].0, args[1].0);
|
||||
Ok(args[0].0)
|
||||
Ok(Some(args[0].0))
|
||||
}
|
||||
"texture" => {
|
||||
if args.len() != 2 {
|
||||
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
|
||||
}
|
||||
if let Some(sampler) = ctx.samplers.get(&args[0].0).copied() {
|
||||
Ok(ctx.add_expression(
|
||||
Ok(Some(ctx.add_expression(
|
||||
Expression::ImageSample {
|
||||
image: args[0].0,
|
||||
sampler,
|
||||
@@ -116,7 +116,7 @@ impl Program<'_> {
|
||||
depth_ref: None,
|
||||
},
|
||||
body,
|
||||
))
|
||||
)))
|
||||
} else {
|
||||
Err(ErrorKind::SemanticError(meta, "Bad call to texture".into()))
|
||||
}
|
||||
@@ -126,7 +126,7 @@ impl Program<'_> {
|
||||
return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta));
|
||||
}
|
||||
if let Some(sampler) = ctx.samplers.get(&args[0].0).copied() {
|
||||
Ok(ctx.add_expression(
|
||||
Ok(Some(ctx.add_expression(
|
||||
Expression::ImageSample {
|
||||
image: args[0].0,
|
||||
sampler,
|
||||
@@ -137,7 +137,7 @@ impl Program<'_> {
|
||||
depth_ref: None,
|
||||
},
|
||||
body,
|
||||
))
|
||||
)))
|
||||
} else {
|
||||
Err(ErrorKind::SemanticError(
|
||||
meta,
|
||||
@@ -151,7 +151,7 @@ impl Program<'_> {
|
||||
if args.len() != 1 {
|
||||
return Err(ErrorKind::wrong_function_args(name, 1, args.len(), meta));
|
||||
}
|
||||
Ok(ctx.add_expression(
|
||||
Ok(Some(ctx.add_expression(
|
||||
Expression::Math {
|
||||
fun: match name.as_str() {
|
||||
"ceil" => MathFunction::Ceil,
|
||||
@@ -176,13 +176,13 @@ impl Program<'_> {
|
||||
arg2: None,
|
||||
},
|
||||
body,
|
||||
))
|
||||
)))
|
||||
}
|
||||
"pow" | "dot" | "max" => {
|
||||
if args.len() != 2 {
|
||||
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
|
||||
}
|
||||
Ok(ctx.add_expression(
|
||||
Ok(Some(ctx.add_expression(
|
||||
Expression::Math {
|
||||
fun: match name.as_str() {
|
||||
"pow" => MathFunction::Pow,
|
||||
@@ -195,13 +195,13 @@ impl Program<'_> {
|
||||
arg2: None,
|
||||
},
|
||||
body,
|
||||
))
|
||||
)))
|
||||
}
|
||||
"mix" | "clamp" => {
|
||||
if args.len() != 3 {
|
||||
return Err(ErrorKind::wrong_function_args(name, 3, args.len(), meta));
|
||||
}
|
||||
Ok(ctx.add_expression(
|
||||
Ok(Some(ctx.add_expression(
|
||||
Expression::Math {
|
||||
fun: match name.as_str() {
|
||||
"mix" => MathFunction::Mix,
|
||||
@@ -213,14 +213,14 @@ impl Program<'_> {
|
||||
arg2: Some(args[2].0),
|
||||
},
|
||||
body,
|
||||
))
|
||||
)))
|
||||
}
|
||||
"lessThan" | "greaterThan" | "lessThanEqual" | "greaterThanEqual" | "equal"
|
||||
| "notEqual" => {
|
||||
if args.len() != 2 {
|
||||
return Err(ErrorKind::wrong_function_args(name, 2, args.len(), meta));
|
||||
}
|
||||
Ok(ctx.add_expression(
|
||||
Ok(Some(ctx.add_expression(
|
||||
Expression::Binary {
|
||||
op: match name.as_str() {
|
||||
"lessThan" => BinaryOperator::Less,
|
||||
@@ -235,7 +235,7 @@ impl Program<'_> {
|
||||
right: args[1].0,
|
||||
},
|
||||
body,
|
||||
))
|
||||
)))
|
||||
}
|
||||
"isinf" | "isnan" | "all" | "any" => {
|
||||
let fun = match name.as_str() {
|
||||
@@ -246,7 +246,9 @@ impl Program<'_> {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.parse_relational_fun(ctx, body, name, &args, fun, meta)
|
||||
Ok(Some(
|
||||
self.parse_relational_fun(ctx, body, name, &args, fun, meta)?,
|
||||
))
|
||||
}
|
||||
_ => {
|
||||
let mut parameters = Vec::new();
|
||||
@@ -273,22 +275,27 @@ impl Program<'_> {
|
||||
|
||||
let mut arguments = Vec::with_capacity(raw_args.len());
|
||||
for (qualifier, expr) in fun.parameters.iter().zip(raw_args.iter()) {
|
||||
let handle = ctx.lower(self, *expr, qualifier.is_lhs(), body)?.0;
|
||||
let handle = ctx.lower_expect(self, *expr, qualifier.is_lhs(), body)?.0;
|
||||
arguments.push(handle)
|
||||
}
|
||||
|
||||
ctx.emit_flush(body);
|
||||
|
||||
let expression = ctx.add_expression(Expression::Call(fun.handle), body);
|
||||
let result = if !fun.void {
|
||||
Some(ctx.add_expression(Expression::Call(fun.handle), body))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
body.push(crate::Statement::Call {
|
||||
function: fun.handle,
|
||||
arguments,
|
||||
result: Some(expression),
|
||||
result,
|
||||
});
|
||||
|
||||
ctx.emit_start();
|
||||
|
||||
Ok(expression)
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -351,6 +358,8 @@ impl Program<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
let void = function.result.is_none();
|
||||
|
||||
if let Some(decl) = self.lookup_function.get_mut(&sig) {
|
||||
if decl.defined {
|
||||
return Err(ErrorKind::SemanticError(
|
||||
@@ -369,6 +378,7 @@ impl Program<'_> {
|
||||
parameters,
|
||||
handle,
|
||||
defined: true,
|
||||
void,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -391,6 +401,7 @@ impl Program<'_> {
|
||||
name,
|
||||
parameters: function.arguments.iter().map(|p| p.ty).collect(),
|
||||
};
|
||||
let void = function.result.is_none();
|
||||
|
||||
for (arg, qualifier) in function.arguments.iter_mut().zip(parameters.iter()) {
|
||||
if qualifier.is_lhs() {
|
||||
@@ -412,6 +423,7 @@ impl Program<'_> {
|
||||
parameters,
|
||||
handle,
|
||||
defined: false,
|
||||
void,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
);
|
||||
|
||||
let expr = self.parse_conditional(&mut ctx, &mut block, None)?;
|
||||
let (root, meta) = ctx.lower(self.program, expr, false, &mut block)?;
|
||||
let (root, meta) = ctx.lower_expect(self.program, expr, false, &mut block)?;
|
||||
|
||||
Ok((self.program.solve_constant(&ctx, root, meta)?, meta))
|
||||
}
|
||||
@@ -434,7 +434,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
))
|
||||
} else {
|
||||
let expr = self.parse_assignment(ctx, body)?;
|
||||
Ok(ctx.lower(self.program, expr, false, body)?)
|
||||
Ok(ctx.lower_expect(self.program, expr, false, body)?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1183,7 +1183,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
_ => {
|
||||
let expr = self.parse_expression(ctx, body)?;
|
||||
self.expect(TokenValue::Semicolon)?;
|
||||
Some(ctx.lower(self.program, expr, false, body)?.0)
|
||||
Some(ctx.lower_expect(self.program, expr, false, body)?.0)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1203,7 +1203,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
self.expect(TokenValue::LeftParen)?;
|
||||
let condition = {
|
||||
let expr = self.parse_expression(ctx, body)?;
|
||||
ctx.lower(self.program, expr, false, body)?.0
|
||||
ctx.lower_expect(self.program, expr, false, body)?.0
|
||||
};
|
||||
self.expect(TokenValue::RightParen)?;
|
||||
|
||||
@@ -1230,7 +1230,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
self.expect(TokenValue::LeftParen)?;
|
||||
let selector = {
|
||||
let expr = self.parse_expression(ctx, body)?;
|
||||
ctx.lower(self.program, expr, false, body)?.0
|
||||
ctx.lower_expect(self.program, expr, false, body)?.0
|
||||
};
|
||||
self.expect(TokenValue::RightParen)?;
|
||||
|
||||
@@ -1247,7 +1247,8 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
self.bump()?;
|
||||
let value = {
|
||||
let expr = self.parse_expression(ctx, body)?;
|
||||
let (root, meta) = ctx.lower(self.program, expr, false, body)?;
|
||||
let (root, meta) =
|
||||
ctx.lower_expect(self.program, expr, false, body)?;
|
||||
let constant = self.program.solve_constant(&ctx, root, meta)?;
|
||||
|
||||
match self.program.module.constants[constant].inner {
|
||||
@@ -1332,7 +1333,9 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
let root = self.parse_expression(ctx, &mut loop_body)?;
|
||||
self.expect(TokenValue::RightParen)?;
|
||||
|
||||
let expr = ctx.lower(self.program, root, false, &mut loop_body)?.0;
|
||||
let expr = ctx
|
||||
.lower_expect(self.program, root, false, &mut loop_body)?
|
||||
.0;
|
||||
let condition = ctx.add_expression(
|
||||
Expression::Unary {
|
||||
op: UnaryOperator::Not,
|
||||
@@ -1368,7 +1371,9 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
let root = self.parse_expression(ctx, &mut loop_body)?;
|
||||
self.expect(TokenValue::RightParen)?;
|
||||
|
||||
let expr = ctx.lower(self.program, root, false, &mut loop_body)?.0;
|
||||
let expr = ctx
|
||||
.lower_expect(self.program, root, false, &mut loop_body)?
|
||||
.0;
|
||||
let condition = ctx.add_expression(
|
||||
Expression::Unary {
|
||||
op: UnaryOperator::Not,
|
||||
@@ -1439,7 +1444,7 @@ impl<'source, 'program, 'options> Parser<'source, 'program, 'options> {
|
||||
value
|
||||
} else {
|
||||
let root = self.parse_expression(ctx, &mut block)?;
|
||||
ctx.lower(self.program, root, false, &mut block)?.0
|
||||
ctx.lower_expect(self.program, root, false, &mut block)?.0
|
||||
};
|
||||
|
||||
let condition = ctx.add_expression(
|
||||
|
||||
Reference in New Issue
Block a user