1use alloc::{
2 format,
3 string::{String, ToString},
4 vec,
5 vec::Vec,
6};
7use core::iter;
8
9use super::{
10 ast::*,
11 builtins::{inject_builtin, sampled_to_depth},
12 context::{Context, ExprPos, StmtContext},
13 error::{Error, ErrorKind},
14 types::scalar_components,
15 Frontend, Result,
16};
17use crate::{
18 front::glsl::types::type_power, proc::ensure_block_returns, AddressSpace, Block, EntryPoint,
19 Expression, Function, FunctionArgument, FunctionResult, Handle, Literal, LocalVariable, Scalar,
20 ScalarKind, Span, Statement, StructMember, Type, TypeInner,
21};
22
23struct ProxyWrite {
25 target: Handle<Expression>,
27 value: Handle<Expression>,
29 convert: Option<Scalar>,
31}
32
33impl Frontend {
34 pub(crate) fn function_or_constructor_call(
35 &mut self,
36 ctx: &mut Context,
37 stmt: &StmtContext,
38 fc: FunctionCallKind,
39 raw_args: &[Handle<HirExpr>],
40 meta: Span,
41 ) -> Result<Option<Handle<Expression>>> {
42 let args: Vec<_> = raw_args
43 .iter()
44 .map(|e| ctx.lower_expect_inner(stmt, self, *e, ExprPos::Rhs))
45 .collect::<Result<_>>()?;
46
47 match fc {
48 FunctionCallKind::TypeConstructor(ty) => {
49 if args.len() == 1 {
50 self.constructor_single(ctx, ty, args[0], meta).map(Some)
51 } else {
52 self.constructor_many(ctx, ty, args, meta).map(Some)
53 }
54 }
55 FunctionCallKind::Function(name) => {
56 self.function_call(ctx, stmt, name, args, raw_args, meta)
57 }
58 }
59 }
60
61 fn constructor_single(
62 &mut self,
63 ctx: &mut Context,
64 ty: Handle<Type>,
65 (mut value, expr_meta): (Handle<Expression>, Span),
66 meta: Span,
67 ) -> Result<Handle<Expression>> {
68 let expr_type = ctx.resolve_type(value, expr_meta)?;
69
70 let vector_size = match *expr_type {
71 TypeInner::Vector { size, .. } => Some(size),
72 _ => None,
73 };
74
75 let expr_is_bool = expr_type.scalar_kind() == Some(ScalarKind::Bool);
76
77 match ctx.module.types[ty].inner.scalar() {
79 Some(result_scalar) if expr_is_bool && result_scalar.kind != ScalarKind::Bool => {
80 let result_scalar = Scalar {
81 width: 4,
82 ..result_scalar
83 };
84 let l0 = Literal::zero(result_scalar).unwrap();
85 let l1 = Literal::one(result_scalar).unwrap();
86 let mut reject = ctx.add_expression(Expression::Literal(l0), expr_meta)?;
87 let mut accept = ctx.add_expression(Expression::Literal(l1), expr_meta)?;
88
89 ctx.implicit_splat(&mut reject, meta, vector_size)?;
90 ctx.implicit_splat(&mut accept, meta, vector_size)?;
91
92 let h = ctx.add_expression(
93 Expression::Select {
94 accept,
95 reject,
96 condition: value,
97 },
98 expr_meta,
99 )?;
100
101 return Ok(h);
102 }
103 _ => {}
104 }
105
106 Ok(match ctx.module.types[ty].inner {
107 TypeInner::Vector { size, scalar } if vector_size.is_none() => {
108 ctx.forced_conversion(&mut value, expr_meta, scalar)?;
109
110 if let TypeInner::Scalar { .. } = *ctx.resolve_type(value, expr_meta)? {
111 ctx.add_expression(Expression::Splat { size, value }, meta)?
112 } else {
113 self.vector_constructor(ctx, ty, size, scalar, &[(value, expr_meta)], meta)?
114 }
115 }
116 TypeInner::Scalar(scalar) => {
117 let mut expr = value;
118 if let TypeInner::Vector { .. } | TypeInner::Matrix { .. } =
119 *ctx.resolve_type(value, expr_meta)?
120 {
121 expr = ctx.add_expression(
122 Expression::AccessIndex {
123 base: expr,
124 index: 0,
125 },
126 meta,
127 )?;
128 }
129
130 if let TypeInner::Matrix { .. } = *ctx.resolve_type(value, expr_meta)? {
131 expr = ctx.add_expression(
132 Expression::AccessIndex {
133 base: expr,
134 index: 0,
135 },
136 meta,
137 )?;
138 }
139
140 ctx.add_expression(
141 Expression::As {
142 kind: scalar.kind,
143 expr,
144 convert: Some(scalar.width),
145 },
146 meta,
147 )?
148 }
149 TypeInner::Vector { size, scalar } => {
150 if vector_size != Some(size) {
151 value = ctx.vector_resize(size, value, expr_meta)?;
152 }
153
154 ctx.add_expression(
155 Expression::As {
156 kind: scalar.kind,
157 expr: value,
158 convert: Some(scalar.width),
159 },
160 meta,
161 )?
162 }
163 TypeInner::Matrix {
164 columns,
165 rows,
166 scalar,
167 } => self.matrix_one_arg(ctx, ty, columns, rows, scalar, (value, expr_meta), meta)?,
168 TypeInner::Struct { ref members, .. } => {
169 let scalar_components = members
170 .first()
171 .and_then(|member| scalar_components(&ctx.module.types[member.ty].inner));
172 if let Some(scalar) = scalar_components {
173 ctx.implicit_conversion(&mut value, expr_meta, scalar)?;
174 }
175
176 ctx.add_expression(
177 Expression::Compose {
178 ty,
179 components: vec![value],
180 },
181 meta,
182 )?
183 }
184
185 TypeInner::Array { base, .. } => {
186 let scalar_components = scalar_components(&ctx.module.types[base].inner);
187 if let Some(scalar) = scalar_components {
188 ctx.implicit_conversion(&mut value, expr_meta, scalar)?;
189 }
190
191 ctx.add_expression(
192 Expression::Compose {
193 ty,
194 components: vec![value],
195 },
196 meta,
197 )?
198 }
199 _ => {
200 self.errors.push(Error {
201 kind: ErrorKind::SemanticError("Bad type constructor".into()),
202 meta,
203 });
204
205 value
206 }
207 })
208 }
209
210 #[allow(clippy::too_many_arguments)]
211 fn matrix_one_arg(
212 &mut self,
213 ctx: &mut Context,
214 ty: Handle<Type>,
215 columns: crate::VectorSize,
216 rows: crate::VectorSize,
217 element_scalar: Scalar,
218 (mut value, expr_meta): (Handle<Expression>, Span),
219 meta: Span,
220 ) -> Result<Handle<Expression>> {
221 let mut components = Vec::with_capacity(columns as usize);
222 ctx.forced_conversion(&mut value, expr_meta, element_scalar)?;
227 match *ctx.resolve_type(value, expr_meta)? {
228 TypeInner::Scalar(_) => {
229 let vector_ty = ctx.module.types.insert(
233 Type {
234 name: None,
235 inner: TypeInner::Vector {
236 size: rows,
237 scalar: element_scalar,
238 },
239 },
240 meta,
241 );
242
243 let zero_literal = Literal::zero(element_scalar).unwrap();
244 let zero = ctx.add_expression(Expression::Literal(zero_literal), meta)?;
245
246 for i in 0..columns as u32 {
247 components.push(
248 ctx.add_expression(
249 Expression::Compose {
250 ty: vector_ty,
251 components: (0..rows as u32)
252 .map(|r| match r == i {
253 true => value,
254 false => zero,
255 })
256 .collect(),
257 },
258 meta,
259 )?,
260 )
261 }
262 }
263 TypeInner::Matrix {
264 rows: ori_rows,
265 columns: ori_cols,
266 ..
267 } => {
268 let zero_literal = Literal::zero(element_scalar).unwrap();
274 let one_literal = Literal::one(element_scalar).unwrap();
275
276 let zero = ctx.add_expression(Expression::Literal(zero_literal), meta)?;
277 let one = ctx.add_expression(Expression::Literal(one_literal), meta)?;
278
279 let vector_ty = ctx.module.types.insert(
280 Type {
281 name: None,
282 inner: TypeInner::Vector {
283 size: rows,
284 scalar: element_scalar,
285 },
286 },
287 meta,
288 );
289
290 for i in 0..columns as u32 {
291 if i < ori_cols as u32 {
292 use core::cmp::Ordering;
293
294 let vector = ctx.add_expression(
295 Expression::AccessIndex {
296 base: value,
297 index: i,
298 },
299 meta,
300 )?;
301
302 components.push(match ori_rows.cmp(&rows) {
303 Ordering::Less => {
304 let components = (0..rows as u32)
305 .map(|r| {
306 if r < ori_rows as u32 {
307 ctx.add_expression(
308 Expression::AccessIndex {
309 base: vector,
310 index: r,
311 },
312 meta,
313 )
314 } else if r == i {
315 Ok(one)
316 } else {
317 Ok(zero)
318 }
319 })
320 .collect::<Result<_>>()?;
321
322 ctx.add_expression(
323 Expression::Compose {
324 ty: vector_ty,
325 components,
326 },
327 meta,
328 )?
329 }
330 Ordering::Equal => vector,
331 Ordering::Greater => ctx.vector_resize(rows, vector, meta)?,
332 })
333 } else {
334 let compose_expr = Expression::Compose {
335 ty: vector_ty,
336 components: (0..rows as u32)
337 .map(|r| match r == i {
338 true => one,
339 false => zero,
340 })
341 .collect(),
342 };
343
344 let vec = ctx.add_expression(compose_expr, meta)?;
345
346 components.push(vec)
347 }
348 }
349 }
350 _ => {
351 components = iter::repeat_n(value, columns as usize).collect();
352 }
353 }
354
355 ctx.add_expression(Expression::Compose { ty, components }, meta)
356 }
357
358 #[allow(clippy::too_many_arguments)]
359 fn vector_constructor(
360 &mut self,
361 ctx: &mut Context,
362 ty: Handle<Type>,
363 size: crate::VectorSize,
364 scalar: Scalar,
365 args: &[(Handle<Expression>, Span)],
366 meta: Span,
367 ) -> Result<Handle<Expression>> {
368 let mut components = Vec::with_capacity(size as usize);
369
370 for (mut arg, expr_meta) in args.iter().copied() {
371 ctx.forced_conversion(&mut arg, expr_meta, scalar)?;
372
373 if components.len() >= size as usize {
374 break;
375 }
376
377 match *ctx.resolve_type(arg, expr_meta)? {
378 TypeInner::Scalar { .. } => components.push(arg),
379 TypeInner::Matrix { rows, columns, .. } => {
380 components.reserve(rows as usize * columns as usize);
381 for c in 0..(columns as u32) {
382 let base = ctx.add_expression(
383 Expression::AccessIndex {
384 base: arg,
385 index: c,
386 },
387 expr_meta,
388 )?;
389 for r in 0..(rows as u32) {
390 components.push(ctx.add_expression(
391 Expression::AccessIndex { base, index: r },
392 expr_meta,
393 )?)
394 }
395 }
396 }
397 TypeInner::Vector { size: ori_size, .. } => {
398 components.reserve(ori_size as usize);
399 for index in 0..(ori_size as u32) {
400 components.push(ctx.add_expression(
401 Expression::AccessIndex { base: arg, index },
402 expr_meta,
403 )?)
404 }
405 }
406 _ => components.push(arg),
407 }
408 }
409
410 components.truncate(size as usize);
411
412 ctx.add_expression(Expression::Compose { ty, components }, meta)
413 }
414
415 fn constructor_many(
416 &mut self,
417 ctx: &mut Context,
418 ty: Handle<Type>,
419 args: Vec<(Handle<Expression>, Span)>,
420 meta: Span,
421 ) -> Result<Handle<Expression>> {
422 let mut components = Vec::with_capacity(args.len());
423
424 let struct_member_data = match ctx.module.types[ty].inner {
425 TypeInner::Matrix {
426 columns,
427 rows,
428 scalar: element_scalar,
429 } => {
430 let mut flattened = Vec::with_capacity(columns as usize * rows as usize);
431
432 for (mut arg, meta) in args.iter().copied() {
433 ctx.forced_conversion(&mut arg, meta, element_scalar)?;
434
435 match *ctx.resolve_type(arg, meta)? {
436 TypeInner::Vector { size, .. } => {
437 for i in 0..(size as u32) {
438 flattened.push(ctx.add_expression(
439 Expression::AccessIndex {
440 base: arg,
441 index: i,
442 },
443 meta,
444 )?)
445 }
446 }
447 _ => flattened.push(arg),
448 }
449 }
450
451 let ty = ctx.module.types.insert(
452 Type {
453 name: None,
454 inner: TypeInner::Vector {
455 size: rows,
456 scalar: element_scalar,
457 },
458 },
459 meta,
460 );
461
462 for chunk in flattened.chunks(rows as usize) {
463 components.push(ctx.add_expression(
464 Expression::Compose {
465 ty,
466 components: Vec::from(chunk),
467 },
468 meta,
469 )?)
470 }
471 None
472 }
473 TypeInner::Vector { size, scalar } => {
474 return self.vector_constructor(ctx, ty, size, scalar, &args, meta)
475 }
476 TypeInner::Array { base, .. } => {
477 for (mut arg, meta) in args.iter().copied() {
478 let scalar_components = scalar_components(&ctx.module.types[base].inner);
479 if let Some(scalar) = scalar_components {
480 ctx.implicit_conversion(&mut arg, meta, scalar)?;
481 }
482
483 components.push(arg)
484 }
485 None
486 }
487 TypeInner::Struct { ref members, .. } => Some(
488 members
489 .iter()
490 .map(|member| scalar_components(&ctx.module.types[member.ty].inner))
491 .collect::<Vec<_>>(),
492 ),
493 _ => {
494 return Err(Error {
495 kind: ErrorKind::SemanticError("Constructor: Too many arguments".into()),
496 meta,
497 })
498 }
499 };
500
501 if let Some(struct_member_data) = struct_member_data {
502 for ((mut arg, meta), scalar_components) in
503 args.iter().copied().zip(struct_member_data.iter().copied())
504 {
505 if let Some(scalar) = scalar_components {
506 ctx.implicit_conversion(&mut arg, meta, scalar)?;
507 }
508
509 components.push(arg)
510 }
511 }
512
513 ctx.add_expression(Expression::Compose { ty, components }, meta)
514 }
515
516 #[allow(clippy::too_many_arguments)]
517 fn function_call(
518 &mut self,
519 ctx: &mut Context,
520 stmt: &StmtContext,
521 name: String,
522 args: Vec<(Handle<Expression>, Span)>,
523 raw_args: &[Handle<HirExpr>],
524 meta: Span,
525 ) -> Result<Option<Handle<Expression>>> {
526 for &(expr, span) in args.iter() {
529 ctx.typifier_grow(expr, span)?;
530 }
531
532 let mut variations =
534 builtin_required_variations(args.iter().map(|&(expr, _)| ctx.get_type(expr)));
535
536 let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| {
538 variations |= BuiltinVariations::STANDARD;
539 Default::default()
540 });
541 inject_builtin(declaration, ctx.module, &name, variations);
542
543 let declaration = self.lookup_function.get(&name).unwrap();
545
546 let mut maybe_overload = None;
548 let mut old_conversions = vec![Conversion::None; args.len()];
551 let mut ambiguous = false;
553
554 'outer: for (overload_idx, overload) in declaration.overloads.iter().enumerate() {
557 if args.len() != overload.parameters.len() {
560 continue;
561 }
562
563 log::trace!("Testing overload {overload_idx}");
564
565 let mut exact = true;
567 let mut superior = None;
572 let mut new_conversions = vec![Conversion::None; args.len()];
575
576 for (i, overload_parameter) in overload.parameters.iter().enumerate() {
579 let call_argument = &args[i];
580 let parameter_info = &overload.parameters_info[i];
581
582 if parameter_info.depth {
585 sampled_to_depth(ctx, call_argument.0, call_argument.1, &mut self.errors);
586 ctx.invalidate_expression(call_argument.0, call_argument.1)?
587 }
588
589 ctx.typifier_grow(call_argument.0, call_argument.1)?;
590
591 let overload_param_ty = &ctx.module.types[*overload_parameter].inner;
592 let call_arg_ty = ctx.get_type(call_argument.0);
593
594 log::trace!(
595 "Testing parameter {i}\n\tOverload = {overload_param_ty:?}\n\tCall = {call_arg_ty:?}"
596 );
597
598 if let (
602 &TypeInner::Image {
603 class:
604 crate::ImageClass::Storage {
605 format: overload_format,
606 access: overload_access,
607 },
608 dim: overload_dim,
609 arrayed: overload_arrayed,
610 },
611 &TypeInner::Image {
612 class:
613 crate::ImageClass::Storage {
614 format: call_format,
615 access: call_access,
616 },
617 dim: call_dim,
618 arrayed: call_arrayed,
619 },
620 ) = (overload_param_ty, call_arg_ty)
621 {
622 let good_size = call_dim == overload_dim && call_arrayed == overload_arrayed;
624 let good_format = overload_format == call_format
628 || (overload.internal
629 && Scalar::from(overload_format) == Scalar::from(call_format));
630 if !(good_size && good_format) {
631 continue 'outer;
632 }
633
634 if !call_access.contains(overload_access) {
638 self.errors.push(Error {
639 kind: ErrorKind::SemanticError(
640 format!(
641 "'{name}': image needs {overload_access:?} access but only {call_access:?} was provided"
642 )
643 .into(),
644 ),
645 meta,
646 });
647 }
648
649 new_conversions[i] = Conversion::Exact;
651 continue;
652 } else if overload_param_ty == call_arg_ty {
653 new_conversions[i] = Conversion::Exact;
655 continue;
656 }
657
658 if let ParameterQualifier::InOut = parameter_info.qualifier {
664 continue 'outer;
665 }
666
667 let maybe_conversion = if parameter_info.qualifier.is_lhs() {
678 conversion(call_arg_ty, overload_param_ty)
679 } else {
680 conversion(overload_param_ty, call_arg_ty)
681 };
682
683 let conversion = match maybe_conversion {
684 Some(info) => info,
685 None => continue 'outer,
686 };
687
688 exact = false;
691
692 let best_arg = match (conversion, old_conversions[i]) {
697 (_, Conversion::Exact) => false,
700 (_, Conversion::None) => true,
702 (Conversion::FloatToDouble, _) => true,
704 (_, Conversion::FloatToDouble) => false,
705 (Conversion::IntToFloat, Conversion::IntToDouble) => true,
708 (Conversion::IntToDouble, Conversion::IntToFloat) => false,
709 _ => continue,
712 };
713
714 match best_arg {
717 true => match superior {
718 Some(false) => ambiguous = true,
719 _ => {
720 superior = Some(true);
721 new_conversions[i] = conversion
722 }
723 },
724 false => match superior {
725 Some(true) => ambiguous = true,
726 _ => superior = Some(false),
727 },
728 }
729 }
730
731 if exact {
735 maybe_overload = Some(overload);
736 ambiguous = false;
737 break;
738 }
739
740 match superior {
741 Some(true) => {
743 maybe_overload = Some(overload);
744 old_conversions = new_conversions;
746 }
747 Some(false) => {}
749 None => {
753 ambiguous = true;
754 maybe_overload = Some(overload);
758 }
759 }
760 }
761
762 if ambiguous {
763 self.errors.push(Error {
764 kind: ErrorKind::SemanticError(
765 format!("Ambiguous best function for '{name}'").into(),
766 ),
767 meta,
768 })
769 }
770
771 let overload = maybe_overload.ok_or_else(|| Error {
772 kind: ErrorKind::SemanticError(format!("Unknown function '{name}'").into()),
773 meta,
774 })?;
775
776 let parameters_info = overload.parameters_info.clone();
777 let parameters = overload.parameters.clone();
778 let is_void = overload.void;
779 let kind = overload.kind;
780
781 let mut arguments = Vec::with_capacity(args.len());
782 let mut proxy_writes = Vec::new();
783
784 for (((parameter_info, call_argument), expr), parameter) in parameters_info
786 .iter()
787 .zip(&args)
788 .zip(raw_args)
789 .zip(¶meters)
790 {
791 if parameter_info.qualifier.is_lhs() {
792 let (handle, meta) = ctx.lower_expect_inner(stmt, self, *expr, ExprPos::Lhs)?;
794
795 self.process_lhs_argument(
796 ctx,
797 meta,
798 *parameter,
799 parameter_info,
800 handle,
801 call_argument,
802 &mut proxy_writes,
803 &mut arguments,
804 )?;
805
806 continue;
807 }
808
809 let (mut handle, meta) = *call_argument;
810
811 let scalar_comps = scalar_components(&ctx.module.types[*parameter].inner);
812
813 if let Some(scalar) = scalar_comps {
815 ctx.implicit_conversion(&mut handle, meta, scalar)?;
816 }
817
818 arguments.push(handle)
819 }
820
821 match kind {
822 FunctionKind::Call(function) => {
823 ctx.emit_end();
824
825 let result = if !is_void {
826 Some(ctx.add_expression(Expression::CallResult(function), meta)?)
827 } else {
828 None
829 };
830
831 ctx.body.push(
832 Statement::Call {
833 function,
834 arguments,
835 result,
836 },
837 meta,
838 );
839
840 ctx.emit_start();
841
842 for proxy_write in proxy_writes {
844 let mut value = ctx.add_expression(
845 Expression::Load {
846 pointer: proxy_write.value,
847 },
848 meta,
849 )?;
850
851 if let Some(scalar) = proxy_write.convert {
852 ctx.conversion(&mut value, meta, scalar)?;
853 }
854
855 ctx.emit_restart();
856
857 ctx.body.push(
858 Statement::Store {
859 pointer: proxy_write.target,
860 value,
861 },
862 meta,
863 );
864 }
865
866 Ok(result)
867 }
868 FunctionKind::Macro(builtin) => builtin.call(self, ctx, arguments.as_mut_slice(), meta),
869 }
870 }
871
872 #[allow(clippy::too_many_arguments)]
875 fn process_lhs_argument(
876 &mut self,
877 ctx: &mut Context,
878 meta: Span,
879 parameter_ty: Handle<Type>,
880 parameter_info: &ParameterInfo,
881 original: Handle<Expression>,
882 call_argument: &(Handle<Expression>, Span),
883 proxy_writes: &mut Vec<ProxyWrite>,
884 arguments: &mut Vec<Handle<Expression>>,
885 ) -> Result<()> {
886 let original_ty = ctx.resolve_type(original, meta)?;
887 let original_pointer_space = original_ty.pointer_space();
888
889 let mut maybe_ty = match *original_ty {
891 TypeInner::Vector { size, scalar } => Some(ctx.module.types.insert(
895 Type {
896 name: None,
897 inner: TypeInner::Vector { size, scalar },
898 },
899 Span::default(),
900 )),
901 TypeInner::Pointer { base, space } if space != AddressSpace::Function => Some(base),
905 TypeInner::ValuePointer {
906 size,
907 scalar,
908 space,
909 } if space != AddressSpace::Function => {
910 let inner = match size {
911 Some(size) => TypeInner::Vector { size, scalar },
912 None => TypeInner::Scalar(scalar),
913 };
914
915 Some(
916 ctx.module
917 .types
918 .insert(Type { name: None, inner }, Span::default()),
919 )
920 }
921 _ => None,
922 };
923
924 let value = if original_pointer_space.is_some() {
927 ctx.add_expression(Expression::Load { pointer: original }, Span::default())?
928 } else {
929 original
930 };
931
932 ctx.typifier_grow(call_argument.0, call_argument.1)?;
933
934 let overload_param_ty = &ctx.module.types[parameter_ty].inner;
935 let call_arg_ty = ctx.get_type(call_argument.0);
936 let needs_conversion = call_arg_ty != overload_param_ty;
937
938 let arg_scalar_comps = scalar_components(call_arg_ty);
939
940 if needs_conversion {
944 maybe_ty = Some(parameter_ty);
945 }
946
947 if let Some(ty) = maybe_ty {
948 let spill_var = ctx.locals.append(
950 LocalVariable {
951 name: None,
952 ty,
953 init: None,
954 },
955 Span::default(),
956 );
957 let spill_expr =
958 ctx.add_expression(Expression::LocalVariable(spill_var), Span::default())?;
959
960 if let ParameterQualifier::InOut = parameter_info.qualifier {
963 ctx.body.push(
964 Statement::Store {
965 pointer: spill_expr,
966 value,
967 },
968 Span::default(),
969 );
970 }
971
972 arguments.push(spill_expr);
974
975 let convert = if needs_conversion {
976 arg_scalar_comps
977 } else {
978 None
979 };
980
981 if let Expression::Swizzle {
984 size,
985 mut vector,
986 pattern,
987 } = ctx.expressions[original]
988 {
989 if let Expression::Load { pointer } = ctx.expressions[vector] {
990 vector = pointer;
991 }
992
993 for (i, component) in pattern.iter().take(size as usize).enumerate() {
994 let original = ctx.add_expression(
995 Expression::AccessIndex {
996 base: vector,
997 index: *component as u32,
998 },
999 Span::default(),
1000 )?;
1001
1002 let spill_component = ctx.add_expression(
1003 Expression::AccessIndex {
1004 base: spill_expr,
1005 index: i as u32,
1006 },
1007 Span::default(),
1008 )?;
1009
1010 proxy_writes.push(ProxyWrite {
1011 target: original,
1012 value: spill_component,
1013 convert,
1014 });
1015 }
1016 } else {
1017 proxy_writes.push(ProxyWrite {
1018 target: original,
1019 value: spill_expr,
1020 convert,
1021 });
1022 }
1023 } else {
1024 arguments.push(original);
1025 }
1026
1027 Ok(())
1028 }
1029
1030 pub(crate) fn add_function(
1031 &mut self,
1032 mut ctx: Context,
1033 name: String,
1034 result: Option<FunctionResult>,
1035 meta: Span,
1036 ) {
1037 ensure_block_returns(&mut ctx.body);
1038
1039 let void = result.is_none();
1040
1041 let mut variations = builtin_required_variations(
1043 ctx.parameters
1044 .iter()
1045 .map(|&arg| &ctx.module.types[arg].inner),
1046 );
1047
1048 let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| {
1050 variations |= BuiltinVariations::STANDARD;
1051 Default::default()
1052 });
1053 inject_builtin(declaration, ctx.module, &name, variations);
1054
1055 let Context {
1056 expressions,
1057 locals,
1058 arguments,
1059 parameters,
1060 parameters_info,
1061 body,
1062 module,
1063 ..
1064 } = ctx;
1065
1066 let function = Function {
1067 name: Some(name),
1068 arguments,
1069 result,
1070 local_variables: locals,
1071 expressions,
1072 named_expressions: crate::NamedExpressions::default(),
1073 body,
1074 diagnostic_filter_leaf: None,
1075 };
1076
1077 'outer: for decl in declaration.overloads.iter_mut() {
1078 if parameters.len() != decl.parameters.len() {
1079 continue;
1080 }
1081
1082 for (new_parameter, old_parameter) in parameters.iter().zip(decl.parameters.iter()) {
1083 let new_inner = &module.types[*new_parameter].inner;
1084 let old_inner = &module.types[*old_parameter].inner;
1085
1086 if new_inner != old_inner {
1087 continue 'outer;
1088 }
1089 }
1090
1091 if decl.defined {
1092 return self.errors.push(Error {
1093 kind: ErrorKind::SemanticError("Function already defined".into()),
1094 meta,
1095 });
1096 }
1097
1098 decl.defined = true;
1099 decl.parameters_info = parameters_info;
1100 match decl.kind {
1101 FunctionKind::Call(handle) => *module.functions.get_mut(handle) = function,
1102 FunctionKind::Macro(_) => {
1103 let handle = module.functions.append(function, meta);
1104 decl.kind = FunctionKind::Call(handle)
1105 }
1106 }
1107 return;
1108 }
1109
1110 let handle = module.functions.append(function, meta);
1111 declaration.overloads.push(Overload {
1112 parameters,
1113 parameters_info,
1114 kind: FunctionKind::Call(handle),
1115 defined: true,
1116 internal: false,
1117 void,
1118 });
1119 }
1120
1121 pub(crate) fn add_prototype(
1122 &mut self,
1123 ctx: Context,
1124 name: String,
1125 result: Option<FunctionResult>,
1126 meta: Span,
1127 ) {
1128 let void = result.is_none();
1129
1130 let mut variations = builtin_required_variations(
1132 ctx.parameters
1133 .iter()
1134 .map(|&arg| &ctx.module.types[arg].inner),
1135 );
1136
1137 let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| {
1139 variations |= BuiltinVariations::STANDARD;
1140 Default::default()
1141 });
1142 inject_builtin(declaration, ctx.module, &name, variations);
1143
1144 let Context {
1145 arguments,
1146 parameters,
1147 parameters_info,
1148 module,
1149 ..
1150 } = ctx;
1151
1152 let function = Function {
1153 name: Some(name),
1154 arguments,
1155 result,
1156 ..Default::default()
1157 };
1158
1159 'outer: for decl in declaration.overloads.iter() {
1160 if parameters.len() != decl.parameters.len() {
1161 continue;
1162 }
1163
1164 for (new_parameter, old_parameter) in parameters.iter().zip(decl.parameters.iter()) {
1165 let new_inner = &module.types[*new_parameter].inner;
1166 let old_inner = &module.types[*old_parameter].inner;
1167
1168 if new_inner != old_inner {
1169 continue 'outer;
1170 }
1171 }
1172
1173 return self.errors.push(Error {
1174 kind: ErrorKind::SemanticError("Prototype already defined".into()),
1175 meta,
1176 });
1177 }
1178
1179 let handle = module.functions.append(function, meta);
1180 declaration.overloads.push(Overload {
1181 parameters,
1182 parameters_info,
1183 kind: FunctionKind::Call(handle),
1184 defined: false,
1185 internal: false,
1186 void,
1187 });
1188 }
1189
1190 pub(crate) fn add_entry_point(
1221 &mut self,
1222 function: Handle<Function>,
1223 mut ctx: Context,
1224 ) -> Result<()> {
1225 let mut arguments = Vec::new();
1226
1227 let body = Block::with_capacity(
1228 ctx.body.len() +
1230 self.entry_args.len() * 2
1232 + 3,
1234 );
1235
1236 let global_init_body = core::mem::replace(&mut ctx.body, body);
1237
1238 for arg in self.entry_args.iter() {
1239 if arg.storage != StorageQualifier::Input {
1240 continue;
1241 }
1242
1243 let pointer = ctx
1244 .expressions
1245 .append(Expression::GlobalVariable(arg.handle), Default::default());
1246 ctx.local_expression_kind_tracker
1247 .insert(pointer, crate::proc::ExpressionKind::Runtime);
1248
1249 let ty = ctx.module.global_variables[arg.handle].ty;
1250
1251 ctx.arg_type_walker(
1252 arg.name.clone(),
1253 arg.binding.clone(),
1254 pointer,
1255 ty,
1256 &mut |ctx, name, pointer, ty, binding| {
1257 let idx = arguments.len() as u32;
1258
1259 arguments.push(FunctionArgument {
1260 name,
1261 ty,
1262 binding: Some(binding),
1263 });
1264
1265 let value = ctx
1266 .expressions
1267 .append(Expression::FunctionArgument(idx), Default::default());
1268 ctx.local_expression_kind_tracker
1269 .insert(value, crate::proc::ExpressionKind::Runtime);
1270 ctx.body
1271 .push(Statement::Store { pointer, value }, Default::default());
1272 },
1273 )?
1274 }
1275
1276 ctx.body.extend_block(global_init_body);
1277
1278 ctx.body.push(
1279 Statement::Call {
1280 function,
1281 arguments: Vec::new(),
1282 result: None,
1283 },
1284 Default::default(),
1285 );
1286
1287 let mut span = 0;
1288 let mut members = Vec::new();
1289 let mut components = Vec::new();
1290
1291 for arg in self.entry_args.iter() {
1292 if arg.storage != StorageQualifier::Output {
1293 continue;
1294 }
1295
1296 let pointer = ctx
1297 .expressions
1298 .append(Expression::GlobalVariable(arg.handle), Default::default());
1299 ctx.local_expression_kind_tracker
1300 .insert(pointer, crate::proc::ExpressionKind::Runtime);
1301
1302 let ty = ctx.module.global_variables[arg.handle].ty;
1303
1304 ctx.arg_type_walker(
1305 arg.name.clone(),
1306 arg.binding.clone(),
1307 pointer,
1308 ty,
1309 &mut |ctx, name, pointer, ty, binding| {
1310 members.push(StructMember {
1311 name,
1312 ty,
1313 binding: Some(binding),
1314 offset: span,
1315 });
1316
1317 span += ctx.module.types[ty].inner.size(ctx.module.to_ctx());
1318
1319 let len = ctx.expressions.len();
1320 let load = ctx
1321 .expressions
1322 .append(Expression::Load { pointer }, Default::default());
1323 ctx.local_expression_kind_tracker
1324 .insert(load, crate::proc::ExpressionKind::Runtime);
1325 ctx.body.push(
1326 Statement::Emit(ctx.expressions.range_from(len)),
1327 Default::default(),
1328 );
1329 components.push(load)
1330 },
1331 )?
1332 }
1333
1334 let (ty, value) = if !components.is_empty() {
1335 let ty = ctx.module.types.insert(
1336 Type {
1337 name: None,
1338 inner: TypeInner::Struct { members, span },
1339 },
1340 Default::default(),
1341 );
1342
1343 let len = ctx.expressions.len();
1344 let res = ctx
1345 .expressions
1346 .append(Expression::Compose { ty, components }, Default::default());
1347 ctx.local_expression_kind_tracker
1348 .insert(res, crate::proc::ExpressionKind::Runtime);
1349 ctx.body.push(
1350 Statement::Emit(ctx.expressions.range_from(len)),
1351 Default::default(),
1352 );
1353
1354 (Some(ty), Some(res))
1355 } else {
1356 (None, None)
1357 };
1358
1359 ctx.body
1360 .push(Statement::Return { value }, Default::default());
1361
1362 let Context {
1363 body, expressions, ..
1364 } = ctx;
1365
1366 ctx.module.entry_points.push(EntryPoint {
1367 name: "main".to_string(),
1368 stage: self.meta.stage,
1369 early_depth_test: Some(crate::EarlyDepthTest::Force)
1370 .filter(|_| self.meta.early_fragment_tests),
1371 workgroup_size: self.meta.workgroup_size,
1372 workgroup_size_overrides: None,
1373 function: Function {
1374 arguments,
1375 expressions,
1376 body,
1377 result: ty.map(|ty| FunctionResult { ty, binding: None }),
1378 ..Default::default()
1379 },
1380 });
1381
1382 Ok(())
1383 }
1384}
1385
1386impl Context<'_> {
1387 fn arg_type_walker(
1399 &mut self,
1400 name: Option<String>,
1401 binding: crate::Binding,
1402 pointer: Handle<Expression>,
1403 ty: Handle<Type>,
1404 f: &mut impl FnMut(
1405 &mut Context,
1406 Option<String>,
1407 Handle<Expression>,
1408 Handle<Type>,
1409 crate::Binding,
1410 ),
1411 ) -> Result<()> {
1412 match self.module.types[ty].inner {
1413 TypeInner::Array {
1417 base,
1418 size: crate::ArraySize::Constant(size),
1419 ..
1420 } => {
1421 let mut location = match binding {
1422 crate::Binding::Location { location, .. } => location,
1423 crate::Binding::BuiltIn(_) => return Ok(()),
1424 };
1425
1426 let interpolation =
1427 self.module.types[base]
1428 .inner
1429 .scalar_kind()
1430 .map(|kind| match kind {
1431 ScalarKind::Float => crate::Interpolation::Perspective,
1432 _ => crate::Interpolation::Flat,
1433 });
1434
1435 for index in 0..size.get() {
1436 let member_pointer = self.add_expression(
1437 Expression::AccessIndex {
1438 base: pointer,
1439 index,
1440 },
1441 Span::default(),
1442 )?;
1443
1444 let binding = crate::Binding::Location {
1445 location,
1446 interpolation,
1447 sampling: None,
1448 blend_src: None,
1449 };
1450 location += 1;
1451
1452 self.arg_type_walker(name.clone(), binding, member_pointer, base, f)?
1453 }
1454 }
1455 TypeInner::Struct { ref members, .. } => {
1456 let mut location = match binding {
1457 crate::Binding::Location { location, .. } => location,
1458 crate::Binding::BuiltIn(_) => return Ok(()),
1459 };
1460
1461 for (i, member) in members.clone().into_iter().enumerate() {
1462 let member_pointer = self.add_expression(
1463 Expression::AccessIndex {
1464 base: pointer,
1465 index: i as u32,
1466 },
1467 Span::default(),
1468 )?;
1469
1470 let binding = match member.binding {
1471 Some(binding) => binding,
1472 None => {
1473 let interpolation = self.module.types[member.ty]
1474 .inner
1475 .scalar_kind()
1476 .map(|kind| match kind {
1477 ScalarKind::Float => crate::Interpolation::Perspective,
1478 _ => crate::Interpolation::Flat,
1479 });
1480 let binding = crate::Binding::Location {
1481 location,
1482 interpolation,
1483 sampling: None,
1484 blend_src: None,
1485 };
1486 location += 1;
1487 binding
1488 }
1489 };
1490
1491 self.arg_type_walker(member.name, binding, member_pointer, member.ty, f)?
1492 }
1493 }
1494 _ => f(self, name, pointer, ty, binding),
1495 }
1496
1497 Ok(())
1498 }
1499}
1500
1501#[derive(PartialEq, Eq, Clone, Copy, Debug)]
1503enum Conversion {
1504 Exact,
1506 FloatToDouble,
1508 IntToFloat,
1510 IntToDouble,
1512 Other,
1514 None,
1516}
1517
1518fn conversion(target: &TypeInner, source: &TypeInner) -> Option<Conversion> {
1521 use ScalarKind::*;
1522
1523 let (target_scalar, source_scalar) = match (target, source) {
1525 (&TypeInner::Scalar(tgt_scalar), &TypeInner::Scalar(src_scalar)) => {
1527 (tgt_scalar, src_scalar)
1528 }
1529 (
1531 &TypeInner::Vector {
1532 size: tgt_size,
1533 scalar: tgt_scalar,
1534 },
1535 &TypeInner::Vector {
1536 size: src_size,
1537 scalar: src_scalar,
1538 },
1539 ) if tgt_size == src_size => (tgt_scalar, src_scalar),
1540 (
1542 &TypeInner::Matrix {
1543 rows: tgt_rows,
1544 columns: tgt_cols,
1545 scalar: tgt_scalar,
1546 },
1547 &TypeInner::Matrix {
1548 rows: src_rows,
1549 columns: src_cols,
1550 scalar: src_scalar,
1551 },
1552 ) if tgt_cols == src_cols && tgt_rows == src_rows => (tgt_scalar, src_scalar),
1553 _ => return None,
1554 };
1555
1556 let target_power = type_power(target_scalar);
1559 let source_power = type_power(source_scalar);
1560 if target_power < source_power {
1561 return None;
1562 }
1563
1564 Some(match (target_scalar, source_scalar) {
1565 (Scalar::F64, Scalar::F32) => Conversion::FloatToDouble,
1567 (
1569 Scalar::F32,
1570 Scalar {
1571 kind: Sint | Uint,
1572 width: _,
1573 },
1574 ) => Conversion::IntToFloat,
1575 (
1577 Scalar::F64,
1578 Scalar {
1579 kind: Sint | Uint,
1580 width: _,
1581 },
1582 ) => Conversion::IntToDouble,
1583 _ => Conversion::Other,
1584 })
1585}
1586
1587fn builtin_required_variations<'a>(args: impl Iterator<Item = &'a TypeInner>) -> BuiltinVariations {
1590 let mut variations = BuiltinVariations::empty();
1591
1592 for ty in args {
1593 match *ty {
1594 TypeInner::ValuePointer { scalar, .. }
1595 | TypeInner::Scalar(scalar)
1596 | TypeInner::Vector { scalar, .. }
1597 | TypeInner::Matrix { scalar, .. } => {
1598 if scalar == Scalar::F64 {
1599 variations |= BuiltinVariations::DOUBLE
1600 }
1601 }
1602 TypeInner::Image {
1603 dim,
1604 arrayed,
1605 class,
1606 } => {
1607 if dim == crate::ImageDimension::Cube && arrayed {
1608 variations |= BuiltinVariations::CUBE_TEXTURES_ARRAY
1609 }
1610
1611 if dim == crate::ImageDimension::D2 && arrayed && class.is_multisampled() {
1612 variations |= BuiltinVariations::D2_MULTI_TEXTURES_ARRAY
1613 }
1614 }
1615 _ => {}
1616 }
1617 }
1618
1619 variations
1620}