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 fn vector_constructor(
359 &mut self,
360 ctx: &mut Context,
361 ty: Handle<Type>,
362 size: crate::VectorSize,
363 scalar: Scalar,
364 args: &[(Handle<Expression>, Span)],
365 meta: Span,
366 ) -> Result<Handle<Expression>> {
367 let mut components = Vec::with_capacity(size as usize);
368
369 for (mut arg, expr_meta) in args.iter().copied() {
370 ctx.forced_conversion(&mut arg, expr_meta, scalar)?;
371
372 if components.len() >= size as usize {
373 break;
374 }
375
376 match *ctx.resolve_type(arg, expr_meta)? {
377 TypeInner::Scalar { .. } => components.push(arg),
378 TypeInner::Matrix { rows, columns, .. } => {
379 components.reserve(rows as usize * columns as usize);
380 for c in 0..(columns as u32) {
381 let base = ctx.add_expression(
382 Expression::AccessIndex {
383 base: arg,
384 index: c,
385 },
386 expr_meta,
387 )?;
388 for r in 0..(rows as u32) {
389 components.push(ctx.add_expression(
390 Expression::AccessIndex { base, index: r },
391 expr_meta,
392 )?)
393 }
394 }
395 }
396 TypeInner::Vector { size: ori_size, .. } => {
397 components.reserve(ori_size as usize);
398 for index in 0..(ori_size as u32) {
399 components.push(ctx.add_expression(
400 Expression::AccessIndex { base: arg, index },
401 expr_meta,
402 )?)
403 }
404 }
405 _ => components.push(arg),
406 }
407 }
408
409 components.truncate(size as usize);
410
411 ctx.add_expression(Expression::Compose { ty, components }, meta)
412 }
413
414 fn constructor_many(
415 &mut self,
416 ctx: &mut Context,
417 ty: Handle<Type>,
418 args: Vec<(Handle<Expression>, Span)>,
419 meta: Span,
420 ) -> Result<Handle<Expression>> {
421 let mut components = Vec::with_capacity(args.len());
422
423 let struct_member_data = match ctx.module.types[ty].inner {
424 TypeInner::Matrix {
425 columns,
426 rows,
427 scalar: element_scalar,
428 } => {
429 let mut flattened = Vec::with_capacity(columns as usize * rows as usize);
430
431 for (mut arg, meta) in args.iter().copied() {
432 ctx.forced_conversion(&mut arg, meta, element_scalar)?;
433
434 match *ctx.resolve_type(arg, meta)? {
435 TypeInner::Vector { size, .. } => {
436 for i in 0..(size as u32) {
437 flattened.push(ctx.add_expression(
438 Expression::AccessIndex {
439 base: arg,
440 index: i,
441 },
442 meta,
443 )?)
444 }
445 }
446 _ => flattened.push(arg),
447 }
448 }
449
450 let ty = ctx.module.types.insert(
451 Type {
452 name: None,
453 inner: TypeInner::Vector {
454 size: rows,
455 scalar: element_scalar,
456 },
457 },
458 meta,
459 );
460
461 for chunk in flattened.chunks(rows as usize) {
462 components.push(ctx.add_expression(
463 Expression::Compose {
464 ty,
465 components: Vec::from(chunk),
466 },
467 meta,
468 )?)
469 }
470 None
471 }
472 TypeInner::Vector { size, scalar } => {
473 return self.vector_constructor(ctx, ty, size, scalar, &args, meta)
474 }
475 TypeInner::Array { base, .. } => {
476 for (mut arg, meta) in args.iter().copied() {
477 let scalar_components = scalar_components(&ctx.module.types[base].inner);
478 if let Some(scalar) = scalar_components {
479 ctx.implicit_conversion(&mut arg, meta, scalar)?;
480 }
481
482 components.push(arg)
483 }
484 None
485 }
486 TypeInner::Struct { ref members, .. } => Some(
487 members
488 .iter()
489 .map(|member| scalar_components(&ctx.module.types[member.ty].inner))
490 .collect::<Vec<_>>(),
491 ),
492 _ => {
493 return Err(Error {
494 kind: ErrorKind::SemanticError("Constructor: Too many arguments".into()),
495 meta,
496 })
497 }
498 };
499
500 if let Some(struct_member_data) = struct_member_data {
501 for ((mut arg, meta), scalar_components) in
502 args.iter().copied().zip(struct_member_data.iter().copied())
503 {
504 if let Some(scalar) = scalar_components {
505 ctx.implicit_conversion(&mut arg, meta, scalar)?;
506 }
507
508 components.push(arg)
509 }
510 }
511
512 ctx.add_expression(Expression::Compose { ty, components }, meta)
513 }
514
515 fn function_call(
516 &mut self,
517 ctx: &mut Context,
518 stmt: &StmtContext,
519 name: String,
520 args: Vec<(Handle<Expression>, Span)>,
521 raw_args: &[Handle<HirExpr>],
522 meta: Span,
523 ) -> Result<Option<Handle<Expression>>> {
524 for &(expr, span) in args.iter() {
527 ctx.typifier_grow(expr, span)?;
528 }
529
530 let mut variations =
532 builtin_required_variations(args.iter().map(|&(expr, _)| ctx.get_type(expr)));
533
534 let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| {
536 variations |= BuiltinVariations::STANDARD;
537 Default::default()
538 });
539 inject_builtin(declaration, ctx.module, &name, variations);
540
541 let declaration = self.lookup_function.get(&name).unwrap();
543
544 let mut maybe_overload = None;
546 let mut old_conversions = vec![Conversion::None; args.len()];
549 let mut ambiguous = false;
551
552 'outer: for (overload_idx, overload) in declaration.overloads.iter().enumerate() {
555 if args.len() != overload.parameters.len() {
558 continue;
559 }
560
561 log::trace!("Testing overload {overload_idx}");
562
563 let mut exact = true;
565 let mut superior = None;
570 let mut new_conversions = vec![Conversion::None; args.len()];
573
574 for (i, overload_parameter) in overload.parameters.iter().enumerate() {
577 let call_argument = &args[i];
578 let parameter_info = &overload.parameters_info[i];
579
580 if parameter_info.depth {
583 sampled_to_depth(ctx, call_argument.0, call_argument.1, &mut self.errors);
584 ctx.invalidate_expression(call_argument.0, call_argument.1)?
585 }
586
587 ctx.typifier_grow(call_argument.0, call_argument.1)?;
588
589 let overload_param_ty = &ctx.module.types[*overload_parameter].inner;
590 let call_arg_ty = ctx.get_type(call_argument.0);
591
592 log::trace!(
593 "Testing parameter {i}\n\tOverload = {overload_param_ty:?}\n\tCall = {call_arg_ty:?}"
594 );
595
596 if let (
600 &TypeInner::Image {
601 class:
602 crate::ImageClass::Storage {
603 format: overload_format,
604 access: overload_access,
605 },
606 dim: overload_dim,
607 arrayed: overload_arrayed,
608 },
609 &TypeInner::Image {
610 class:
611 crate::ImageClass::Storage {
612 format: call_format,
613 access: call_access,
614 },
615 dim: call_dim,
616 arrayed: call_arrayed,
617 },
618 ) = (overload_param_ty, call_arg_ty)
619 {
620 let good_size = call_dim == overload_dim && call_arrayed == overload_arrayed;
622 let good_format = overload_format == call_format
626 || (overload.internal
627 && Scalar::from(overload_format) == Scalar::from(call_format));
628 if !(good_size && good_format) {
629 continue 'outer;
630 }
631
632 if !call_access.contains(overload_access) {
636 self.errors.push(Error {
637 kind: ErrorKind::SemanticError(
638 format!(
639 "'{name}': image needs {overload_access:?} access but only {call_access:?} was provided"
640 )
641 .into(),
642 ),
643 meta,
644 });
645 }
646
647 new_conversions[i] = Conversion::Exact;
649 continue;
650 } else if overload_param_ty == call_arg_ty {
651 new_conversions[i] = Conversion::Exact;
653 continue;
654 }
655
656 if let ParameterQualifier::InOut = parameter_info.qualifier {
662 continue 'outer;
663 }
664
665 let maybe_conversion = if parameter_info.qualifier.is_lhs() {
676 conversion(call_arg_ty, overload_param_ty)
677 } else {
678 conversion(overload_param_ty, call_arg_ty)
679 };
680
681 let conversion = match maybe_conversion {
682 Some(info) => info,
683 None => continue 'outer,
684 };
685
686 exact = false;
689
690 let best_arg = match (conversion, old_conversions[i]) {
695 (_, Conversion::Exact) => false,
698 (_, Conversion::None) => true,
700 (Conversion::FloatToDouble, _) => true,
702 (_, Conversion::FloatToDouble) => false,
703 (Conversion::IntToFloat, Conversion::IntToDouble) => true,
706 (Conversion::IntToDouble, Conversion::IntToFloat) => false,
707 _ => continue,
710 };
711
712 match best_arg {
715 true => match superior {
716 Some(false) => ambiguous = true,
717 _ => {
718 superior = Some(true);
719 new_conversions[i] = conversion
720 }
721 },
722 false => match superior {
723 Some(true) => ambiguous = true,
724 _ => superior = Some(false),
725 },
726 }
727 }
728
729 if exact {
733 maybe_overload = Some(overload);
734 ambiguous = false;
735 break;
736 }
737
738 match superior {
739 Some(true) => {
741 maybe_overload = Some(overload);
742 old_conversions = new_conversions;
744 }
745 Some(false) => {}
747 None => {
751 ambiguous = true;
752 maybe_overload = Some(overload);
756 }
757 }
758 }
759
760 if ambiguous {
761 self.errors.push(Error {
762 kind: ErrorKind::SemanticError(
763 format!("Ambiguous best function for '{name}'").into(),
764 ),
765 meta,
766 })
767 }
768
769 let overload = maybe_overload.ok_or_else(|| Error {
770 kind: ErrorKind::SemanticError(format!("Unknown function '{name}'").into()),
771 meta,
772 })?;
773
774 let parameters_info = overload.parameters_info.clone();
775 let parameters = overload.parameters.clone();
776 let is_void = overload.void;
777 let kind = overload.kind;
778
779 let mut arguments = Vec::with_capacity(args.len());
780 let mut proxy_writes = Vec::new();
781
782 for (((parameter_info, call_argument), expr), parameter) in parameters_info
784 .iter()
785 .zip(&args)
786 .zip(raw_args)
787 .zip(¶meters)
788 {
789 if parameter_info.qualifier.is_lhs() {
790 let (handle, meta) = ctx.lower_expect_inner(stmt, self, *expr, ExprPos::Lhs)?;
792
793 self.process_lhs_argument(
794 ctx,
795 meta,
796 *parameter,
797 parameter_info,
798 handle,
799 call_argument,
800 &mut proxy_writes,
801 &mut arguments,
802 )?;
803
804 continue;
805 }
806
807 let (mut handle, meta) = *call_argument;
808
809 let scalar_comps = scalar_components(&ctx.module.types[*parameter].inner);
810
811 if let Some(scalar) = scalar_comps {
813 ctx.implicit_conversion(&mut handle, meta, scalar)?;
814 }
815
816 arguments.push(handle)
817 }
818
819 match kind {
820 FunctionKind::Call(function) => {
821 ctx.emit_end();
822
823 let result = if !is_void {
824 Some(ctx.add_expression(Expression::CallResult(function), meta)?)
825 } else {
826 None
827 };
828
829 ctx.body.push(
830 Statement::Call {
831 function,
832 arguments,
833 result,
834 },
835 meta,
836 );
837
838 ctx.emit_start();
839
840 for proxy_write in proxy_writes {
842 let mut value = ctx.add_expression(
843 Expression::Load {
844 pointer: proxy_write.value,
845 },
846 meta,
847 )?;
848
849 if let Some(scalar) = proxy_write.convert {
850 ctx.conversion(&mut value, meta, scalar)?;
851 }
852
853 ctx.emit_restart();
854
855 ctx.body.push(
856 Statement::Store {
857 pointer: proxy_write.target,
858 value,
859 },
860 meta,
861 );
862 }
863
864 Ok(result)
865 }
866 FunctionKind::Macro(builtin) => builtin.call(self, ctx, arguments.as_mut_slice(), meta),
867 }
868 }
869
870 #[allow(clippy::too_many_arguments)]
873 fn process_lhs_argument(
874 &mut self,
875 ctx: &mut Context,
876 meta: Span,
877 parameter_ty: Handle<Type>,
878 parameter_info: &ParameterInfo,
879 original: Handle<Expression>,
880 call_argument: &(Handle<Expression>, Span),
881 proxy_writes: &mut Vec<ProxyWrite>,
882 arguments: &mut Vec<Handle<Expression>>,
883 ) -> Result<()> {
884 let original_ty = ctx.resolve_type(original, meta)?;
885 let original_pointer_space = original_ty.pointer_space();
886
887 let mut maybe_ty = match *original_ty {
889 TypeInner::Vector { size, scalar } => Some(ctx.module.types.insert(
893 Type {
894 name: None,
895 inner: TypeInner::Vector { size, scalar },
896 },
897 Span::default(),
898 )),
899 TypeInner::Pointer { base, space } if space != AddressSpace::Function => Some(base),
903 TypeInner::ValuePointer {
904 size,
905 scalar,
906 space,
907 } if space != AddressSpace::Function => {
908 let inner = match size {
909 Some(size) => TypeInner::Vector { size, scalar },
910 None => TypeInner::Scalar(scalar),
911 };
912
913 Some(
914 ctx.module
915 .types
916 .insert(Type { name: None, inner }, Span::default()),
917 )
918 }
919 _ => None,
920 };
921
922 let value = if original_pointer_space.is_some() {
925 ctx.add_expression(Expression::Load { pointer: original }, Span::default())?
926 } else {
927 original
928 };
929
930 ctx.typifier_grow(call_argument.0, call_argument.1)?;
931
932 let overload_param_ty = &ctx.module.types[parameter_ty].inner;
933 let call_arg_ty = ctx.get_type(call_argument.0);
934 let needs_conversion = call_arg_ty != overload_param_ty;
935
936 let arg_scalar_comps = scalar_components(call_arg_ty);
937
938 if needs_conversion {
942 maybe_ty = Some(parameter_ty);
943 }
944
945 if let Some(ty) = maybe_ty {
946 let spill_var = ctx.locals.append(
948 LocalVariable {
949 name: None,
950 ty,
951 init: None,
952 },
953 Span::default(),
954 );
955 let spill_expr =
956 ctx.add_expression(Expression::LocalVariable(spill_var), Span::default())?;
957
958 if let ParameterQualifier::InOut = parameter_info.qualifier {
961 ctx.body.push(
962 Statement::Store {
963 pointer: spill_expr,
964 value,
965 },
966 Span::default(),
967 );
968 }
969
970 arguments.push(spill_expr);
972
973 let convert = if needs_conversion {
974 arg_scalar_comps
975 } else {
976 None
977 };
978
979 if let Expression::Swizzle {
982 size,
983 mut vector,
984 pattern,
985 } = ctx.expressions[original]
986 {
987 if let Expression::Load { pointer } = ctx.expressions[vector] {
988 vector = pointer;
989 }
990
991 for (i, component) in pattern.iter().take(size as usize).enumerate() {
992 let original = ctx.add_expression(
993 Expression::AccessIndex {
994 base: vector,
995 index: *component as u32,
996 },
997 Span::default(),
998 )?;
999
1000 let spill_component = ctx.add_expression(
1001 Expression::AccessIndex {
1002 base: spill_expr,
1003 index: i as u32,
1004 },
1005 Span::default(),
1006 )?;
1007
1008 proxy_writes.push(ProxyWrite {
1009 target: original,
1010 value: spill_component,
1011 convert,
1012 });
1013 }
1014 } else {
1015 proxy_writes.push(ProxyWrite {
1016 target: original,
1017 value: spill_expr,
1018 convert,
1019 });
1020 }
1021 } else {
1022 arguments.push(original);
1023 }
1024
1025 Ok(())
1026 }
1027
1028 pub(crate) fn add_function(
1029 &mut self,
1030 mut ctx: Context,
1031 name: String,
1032 result: Option<FunctionResult>,
1033 meta: Span,
1034 ) {
1035 ensure_block_returns(&mut ctx.body);
1036
1037 let void = result.is_none();
1038
1039 let mut variations = builtin_required_variations(
1041 ctx.parameters
1042 .iter()
1043 .map(|&arg| &ctx.module.types[arg].inner),
1044 );
1045
1046 let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| {
1048 variations |= BuiltinVariations::STANDARD;
1049 Default::default()
1050 });
1051 inject_builtin(declaration, ctx.module, &name, variations);
1052
1053 let Context {
1054 expressions,
1055 locals,
1056 arguments,
1057 parameters,
1058 parameters_info,
1059 body,
1060 module,
1061 ..
1062 } = ctx;
1063
1064 let function = Function {
1065 name: Some(name),
1066 arguments,
1067 result,
1068 local_variables: locals,
1069 expressions,
1070 named_expressions: crate::NamedExpressions::default(),
1071 body,
1072 diagnostic_filter_leaf: None,
1073 };
1074
1075 'outer: for decl in declaration.overloads.iter_mut() {
1076 if parameters.len() != decl.parameters.len() {
1077 continue;
1078 }
1079
1080 for (new_parameter, old_parameter) in parameters.iter().zip(decl.parameters.iter()) {
1081 let new_inner = &module.types[*new_parameter].inner;
1082 let old_inner = &module.types[*old_parameter].inner;
1083
1084 if new_inner != old_inner {
1085 continue 'outer;
1086 }
1087 }
1088
1089 if decl.defined {
1090 return self.errors.push(Error {
1091 kind: ErrorKind::SemanticError("Function already defined".into()),
1092 meta,
1093 });
1094 }
1095
1096 decl.defined = true;
1097 decl.parameters_info = parameters_info;
1098 match decl.kind {
1099 FunctionKind::Call(handle) => *module.functions.get_mut(handle) = function,
1100 FunctionKind::Macro(_) => {
1101 let handle = module.functions.append(function, meta);
1102 decl.kind = FunctionKind::Call(handle)
1103 }
1104 }
1105 return;
1106 }
1107
1108 let handle = module.functions.append(function, meta);
1109 declaration.overloads.push(Overload {
1110 parameters,
1111 parameters_info,
1112 kind: FunctionKind::Call(handle),
1113 defined: true,
1114 internal: false,
1115 void,
1116 });
1117 }
1118
1119 pub(crate) fn add_prototype(
1120 &mut self,
1121 ctx: Context,
1122 name: String,
1123 result: Option<FunctionResult>,
1124 meta: Span,
1125 ) {
1126 let void = result.is_none();
1127
1128 let mut variations = builtin_required_variations(
1130 ctx.parameters
1131 .iter()
1132 .map(|&arg| &ctx.module.types[arg].inner),
1133 );
1134
1135 let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| {
1137 variations |= BuiltinVariations::STANDARD;
1138 Default::default()
1139 });
1140 inject_builtin(declaration, ctx.module, &name, variations);
1141
1142 let Context {
1143 arguments,
1144 parameters,
1145 parameters_info,
1146 module,
1147 ..
1148 } = ctx;
1149
1150 let function = Function {
1151 name: Some(name),
1152 arguments,
1153 result,
1154 ..Default::default()
1155 };
1156
1157 'outer: for decl in declaration.overloads.iter() {
1158 if parameters.len() != decl.parameters.len() {
1159 continue;
1160 }
1161
1162 for (new_parameter, old_parameter) in parameters.iter().zip(decl.parameters.iter()) {
1163 let new_inner = &module.types[*new_parameter].inner;
1164 let old_inner = &module.types[*old_parameter].inner;
1165
1166 if new_inner != old_inner {
1167 continue 'outer;
1168 }
1169 }
1170
1171 return self.errors.push(Error {
1172 kind: ErrorKind::SemanticError("Prototype already defined".into()),
1173 meta,
1174 });
1175 }
1176
1177 let handle = module.functions.append(function, meta);
1178 declaration.overloads.push(Overload {
1179 parameters,
1180 parameters_info,
1181 kind: FunctionKind::Call(handle),
1182 defined: false,
1183 internal: false,
1184 void,
1185 });
1186 }
1187
1188 pub(crate) fn add_entry_point(
1219 &mut self,
1220 function: Handle<Function>,
1221 mut ctx: Context,
1222 ) -> Result<()> {
1223 let mut arguments = Vec::new();
1224
1225 let body = Block::with_capacity(
1226 ctx.body.len() +
1228 self.entry_args.len() * 2
1230 + 3,
1232 );
1233
1234 let global_init_body = core::mem::replace(&mut ctx.body, body);
1235
1236 for arg in self.entry_args.iter() {
1237 if arg.storage != StorageQualifier::Input {
1238 continue;
1239 }
1240
1241 let pointer = ctx
1242 .expressions
1243 .append(Expression::GlobalVariable(arg.handle), Default::default());
1244 ctx.local_expression_kind_tracker
1245 .insert(pointer, crate::proc::ExpressionKind::Runtime);
1246
1247 let ty = ctx.module.global_variables[arg.handle].ty;
1248
1249 ctx.arg_type_walker(
1250 arg.name.clone(),
1251 arg.binding.clone(),
1252 pointer,
1253 ty,
1254 &mut |ctx, name, pointer, ty, binding| {
1255 let idx = arguments.len() as u32;
1256
1257 arguments.push(FunctionArgument {
1258 name,
1259 ty,
1260 binding: Some(binding),
1261 });
1262
1263 let value = ctx
1264 .expressions
1265 .append(Expression::FunctionArgument(idx), Default::default());
1266 ctx.local_expression_kind_tracker
1267 .insert(value, crate::proc::ExpressionKind::Runtime);
1268 ctx.body
1269 .push(Statement::Store { pointer, value }, Default::default());
1270 },
1271 )?
1272 }
1273
1274 ctx.body.extend_block(global_init_body);
1275
1276 ctx.body.push(
1277 Statement::Call {
1278 function,
1279 arguments: Vec::new(),
1280 result: None,
1281 },
1282 Default::default(),
1283 );
1284
1285 let mut span = 0;
1286 let mut members = Vec::new();
1287 let mut components = Vec::new();
1288
1289 for arg in self.entry_args.iter() {
1290 if arg.storage != StorageQualifier::Output {
1291 continue;
1292 }
1293
1294 let pointer = ctx
1295 .expressions
1296 .append(Expression::GlobalVariable(arg.handle), Default::default());
1297 ctx.local_expression_kind_tracker
1298 .insert(pointer, crate::proc::ExpressionKind::Runtime);
1299
1300 let ty = ctx.module.global_variables[arg.handle].ty;
1301
1302 ctx.arg_type_walker(
1303 arg.name.clone(),
1304 arg.binding.clone(),
1305 pointer,
1306 ty,
1307 &mut |ctx, name, pointer, ty, binding| {
1308 members.push(StructMember {
1309 name,
1310 ty,
1311 binding: Some(binding),
1312 offset: span,
1313 });
1314
1315 span += ctx.module.types[ty].inner.size(ctx.module.to_ctx());
1316
1317 let len = ctx.expressions.len();
1318 let load = ctx
1319 .expressions
1320 .append(Expression::Load { pointer }, Default::default());
1321 ctx.local_expression_kind_tracker
1322 .insert(load, crate::proc::ExpressionKind::Runtime);
1323 ctx.body.push(
1324 Statement::Emit(ctx.expressions.range_from(len)),
1325 Default::default(),
1326 );
1327 components.push(load)
1328 },
1329 )?
1330 }
1331
1332 let (ty, value) = if !components.is_empty() {
1333 let ty = ctx.module.types.insert(
1334 Type {
1335 name: None,
1336 inner: TypeInner::Struct { members, span },
1337 },
1338 Default::default(),
1339 );
1340
1341 let len = ctx.expressions.len();
1342 let res = ctx
1343 .expressions
1344 .append(Expression::Compose { ty, components }, Default::default());
1345 ctx.local_expression_kind_tracker
1346 .insert(res, crate::proc::ExpressionKind::Runtime);
1347 ctx.body.push(
1348 Statement::Emit(ctx.expressions.range_from(len)),
1349 Default::default(),
1350 );
1351
1352 (Some(ty), Some(res))
1353 } else {
1354 (None, None)
1355 };
1356
1357 ctx.body
1358 .push(Statement::Return { value }, Default::default());
1359
1360 let Context {
1361 body, expressions, ..
1362 } = ctx;
1363
1364 ctx.module.entry_points.push(EntryPoint {
1365 name: "main".to_string(),
1366 stage: self.meta.stage,
1367 early_depth_test: Some(crate::EarlyDepthTest::Force)
1368 .filter(|_| self.meta.early_fragment_tests),
1369 workgroup_size: self.meta.workgroup_size,
1370 workgroup_size_overrides: None,
1371 function: Function {
1372 arguments,
1373 expressions,
1374 body,
1375 result: ty.map(|ty| FunctionResult { ty, binding: None }),
1376 ..Default::default()
1377 },
1378 mesh_info: None,
1379 task_payload: None,
1380 incoming_ray_payload: None,
1381 });
1382
1383 Ok(())
1384 }
1385}
1386
1387impl Context<'_> {
1388 fn arg_type_walker(
1400 &mut self,
1401 name: Option<String>,
1402 binding: crate::Binding,
1403 pointer: Handle<Expression>,
1404 ty: Handle<Type>,
1405 f: &mut impl FnMut(
1406 &mut Context,
1407 Option<String>,
1408 Handle<Expression>,
1409 Handle<Type>,
1410 crate::Binding,
1411 ),
1412 ) -> Result<()> {
1413 match self.module.types[ty].inner {
1414 TypeInner::Array {
1418 base,
1419 size: crate::ArraySize::Constant(size),
1420 ..
1421 } => {
1422 let mut location = match binding {
1423 crate::Binding::Location { location, .. } => location,
1424 crate::Binding::BuiltIn(_) => return Ok(()),
1425 };
1426
1427 let interpolation =
1428 self.module.types[base]
1429 .inner
1430 .scalar_kind()
1431 .map(|kind| match kind {
1432 ScalarKind::Float => crate::Interpolation::Perspective,
1433 _ => crate::Interpolation::Flat,
1434 });
1435
1436 for index in 0..size.get() {
1437 let member_pointer = self.add_expression(
1438 Expression::AccessIndex {
1439 base: pointer,
1440 index,
1441 },
1442 Span::default(),
1443 )?;
1444
1445 let binding = crate::Binding::Location {
1446 location,
1447 interpolation,
1448 sampling: None,
1449 blend_src: None,
1450 per_primitive: false,
1451 };
1452 location += 1;
1453
1454 self.arg_type_walker(name.clone(), binding, member_pointer, base, f)?
1455 }
1456 }
1457 TypeInner::Struct { ref members, .. } => {
1458 let mut location = match binding {
1459 crate::Binding::Location { location, .. } => location,
1460 crate::Binding::BuiltIn(_) => return Ok(()),
1461 };
1462
1463 for (i, member) in members.clone().into_iter().enumerate() {
1464 let member_pointer = self.add_expression(
1465 Expression::AccessIndex {
1466 base: pointer,
1467 index: i as u32,
1468 },
1469 Span::default(),
1470 )?;
1471
1472 let binding = match member.binding {
1473 Some(binding) => binding,
1474 None => {
1475 let interpolation = self.module.types[member.ty]
1476 .inner
1477 .scalar_kind()
1478 .map(|kind| match kind {
1479 ScalarKind::Float => crate::Interpolation::Perspective,
1480 _ => crate::Interpolation::Flat,
1481 });
1482 let binding = crate::Binding::Location {
1483 location,
1484 interpolation,
1485 sampling: None,
1486 blend_src: None,
1487 per_primitive: false,
1488 };
1489 location += 1;
1490 binding
1491 }
1492 };
1493
1494 self.arg_type_walker(member.name, binding, member_pointer, member.ty, f)?
1495 }
1496 }
1497 _ => f(self, name, pointer, ty, binding),
1498 }
1499
1500 Ok(())
1501 }
1502}
1503
1504#[derive(PartialEq, Eq, Clone, Copy, Debug)]
1506enum Conversion {
1507 Exact,
1509 FloatToDouble,
1511 IntToFloat,
1513 IntToDouble,
1515 Other,
1517 None,
1519}
1520
1521fn conversion(target: &TypeInner, source: &TypeInner) -> Option<Conversion> {
1524 use ScalarKind::*;
1525
1526 let (target_scalar, source_scalar) = match (target, source) {
1528 (&TypeInner::Scalar(tgt_scalar), &TypeInner::Scalar(src_scalar)) => {
1530 (tgt_scalar, src_scalar)
1531 }
1532 (
1534 &TypeInner::Vector {
1535 size: tgt_size,
1536 scalar: tgt_scalar,
1537 },
1538 &TypeInner::Vector {
1539 size: src_size,
1540 scalar: src_scalar,
1541 },
1542 ) if tgt_size == src_size => (tgt_scalar, src_scalar),
1543 (
1545 &TypeInner::Matrix {
1546 rows: tgt_rows,
1547 columns: tgt_cols,
1548 scalar: tgt_scalar,
1549 },
1550 &TypeInner::Matrix {
1551 rows: src_rows,
1552 columns: src_cols,
1553 scalar: src_scalar,
1554 },
1555 ) if tgt_cols == src_cols && tgt_rows == src_rows => (tgt_scalar, src_scalar),
1556 _ => return None,
1557 };
1558
1559 let target_power = type_power(target_scalar);
1562 let source_power = type_power(source_scalar);
1563 if target_power < source_power {
1564 return None;
1565 }
1566
1567 Some(match (target_scalar, source_scalar) {
1568 (Scalar::F64, Scalar::F32) => Conversion::FloatToDouble,
1570 (
1572 Scalar::F32,
1573 Scalar {
1574 kind: Sint | Uint,
1575 width: _,
1576 },
1577 ) => Conversion::IntToFloat,
1578 (
1580 Scalar::F64,
1581 Scalar {
1582 kind: Sint | Uint,
1583 width: _,
1584 },
1585 ) => Conversion::IntToDouble,
1586 _ => Conversion::Other,
1587 })
1588}
1589
1590fn builtin_required_variations<'a>(args: impl Iterator<Item = &'a TypeInner>) -> BuiltinVariations {
1593 let mut variations = BuiltinVariations::empty();
1594
1595 for ty in args {
1596 match *ty {
1597 TypeInner::ValuePointer { scalar, .. }
1598 | TypeInner::Scalar(scalar)
1599 | TypeInner::Vector { scalar, .. }
1600 | TypeInner::Matrix { scalar, .. } => {
1601 if scalar == Scalar::F64 {
1602 variations |= BuiltinVariations::DOUBLE
1603 }
1604 }
1605 TypeInner::Image {
1606 dim,
1607 arrayed,
1608 class,
1609 } => {
1610 if dim == crate::ImageDimension::Cube && arrayed {
1611 variations |= BuiltinVariations::CUBE_TEXTURES_ARRAY
1612 }
1613
1614 if dim == crate::ImageDimension::D2 && arrayed && class.is_multisampled() {
1615 variations |= BuiltinVariations::D2_MULTI_TEXTURES_ARRAY
1616 }
1617 }
1618 _ => {}
1619 }
1620 }
1621
1622 variations
1623}