@@ -11,7 +11,10 @@ use rspirv::dr::Operand;
1111use  rspirv:: spirv:: { 
1212    Capability ,  Decoration ,  Dim ,  ExecutionModel ,  FunctionControl ,  StorageClass ,  Word , 
1313} ; 
14- use  rustc_codegen_ssa:: traits:: { BaseTypeCodegenMethods ,  BuilderMethods ,  MiscCodegenMethods  as  _} ; 
14+ use  rustc_codegen_ssa:: traits:: { 
15+     BaseTypeCodegenMethods ,  BuilderMethods ,  ConstCodegenMethods ,  LayoutTypeCodegenMethods , 
16+     MiscCodegenMethods  as  _, 
17+ } ; 
1518use  rustc_data_structures:: fx:: FxHashMap ; 
1619use  rustc_errors:: MultiSpan ; 
1720use  rustc_hir as  hir; 
@@ -87,21 +90,7 @@ impl<'tcx> CodegenCx<'tcx> {
8790        for  ( arg_abi,  hir_param)  in  fn_abi. args . iter ( ) . zip ( hir_params)  { 
8891            match  arg_abi. mode  { 
8992                PassMode :: Direct ( _)  => { } 
90-                 PassMode :: Pair ( ..)  => { 
91-                     // FIXME(eddyb) implement `ScalarPair` `Input`s, or change 
92-                     // the `FnAbi` readjustment to only use `PassMode::Pair` for 
93-                     // pointers to `!Sized` types, but not other `ScalarPair`s. 
94-                     if  !matches ! ( arg_abi. layout. ty. kind( ) ,  ty:: Ref ( ..) )  { 
95-                         self . tcx . dcx ( ) . span_err ( 
96-                             hir_param. ty_span , 
97-                             format ! ( 
98-                                 "entry point parameter type not yet supported \  
99- , 
100-                                 arg_abi. layout. ty
101-                             ) , 
102-                         ) ; 
103-                     } 
104-                 } 
93+                 PassMode :: Pair ( ..)  => { } 
10594                // FIXME(eddyb) support these (by just ignoring them) - if there 
10695                // is any validation concern, it should be done on the types. 
10796                PassMode :: Ignore  => self . tcx . dcx ( ) . span_fatal ( 
@@ -442,6 +431,36 @@ impl<'tcx> CodegenCx<'tcx> {
442431        }  = self . entry_param_deduce_from_rust_ref_or_value ( entry_arg_abi. layout ,  hir_param,  & attrs) ; 
443432        let  value_spirv_type = value_layout. spirv_type ( hir_param. ty_span ,  self ) ; 
444433
434+         // In compute shaders, user-provided data must come from buffers or push 
435+         // constants, i.e. by-reference parameters. 
436+         if  execution_model == ExecutionModel :: GLCompute 
437+             && matches ! ( entry_arg_abi. mode,  PassMode :: Direct ( _)  | PassMode :: Pair ( ..) ) 
438+             && !matches ! ( entry_arg_abi. layout. ty. kind( ) ,  ty:: Ref ( ..) ) 
439+             && attrs. builtin . is_none ( ) 
440+         { 
441+             let  param_name = if  let  hir:: PatKind :: Binding ( _,  _,  ident,  _)  = & hir_param. pat . kind  { 
442+                 ident. name . to_string ( ) 
443+             }  else  { 
444+                 "parameter" . to_string ( ) 
445+             } ; 
446+             self . tcx 
447+                 . dcx ( ) 
448+                 . struct_span_err ( 
449+                     hir_param. ty_span , 
450+                     format ! ( 
451+                         "compute entry parameter `{}` must be by-reference" , 
452+                         param_name
453+                     ) , 
454+                 ) 
455+                 . with_help ( format ! ( 
456+                     "consider changing the type to `&{}`" , 
457+                     entry_arg_abi. layout. ty
458+                 ) ) 
459+                 . emit ( ) ; 
460+             // Keep this a hard error to stop compilation after emitting help. 
461+             self . tcx . dcx ( ) . abort_if_errors ( ) ; 
462+         } 
463+ 
445464        let  ( var_id,  spec_const_id)  = match  storage_class { 
446465            // Pre-allocate the module-scoped `OpVariable` *Result* ID. 
447466            Ok ( _)  => ( 
@@ -491,14 +510,6 @@ impl<'tcx> CodegenCx<'tcx> {
491510\n {value_layout:#?}", 
492511            entry_arg_abi. layout. ty
493512        ) ; 
494-         if  is_pair && !is_unsized { 
495-             // If PassMode is Pair, then we need to fill in the second part of the pair with a 
496-             // value. We currently only do that with unsized types, so if a type is a pair for some 
497-             // other reason (e.g. a tuple), we bail. 
498-             self . tcx 
499-                 . dcx ( ) 
500-                 . span_fatal ( hir_param. ty_span ,  "pair type not supported yet" ) 
501-         } 
502513        // FIXME(eddyb) should this talk about "typed buffers" instead of "interface blocks"? 
503514        // FIXME(eddyb) should we talk about "descriptor indexing" or 
504515        // actually use more reasonable terms like "resource arrays"? 
@@ -621,8 +632,8 @@ impl<'tcx> CodegenCx<'tcx> {
621632                } 
622633            } 
623634
624-             let  value_len = if  is_pair { 
625-                 // We've already emitted an error, fill in a placeholder value  
635+             let  value_len = if  is_pair && is_unsized  { 
636+                 // For wide references (e.g., slices), the second component is a length.  
626637                Some ( bx. undef ( self . type_isize ( ) ) ) 
627638            }  else  { 
628639                None 
@@ -645,21 +656,54 @@ impl<'tcx> CodegenCx<'tcx> {
645656                _ => unreachable ! ( ) , 
646657            } 
647658        }  else  { 
648-             assert_matches ! ( entry_arg_abi. mode,  PassMode :: Direct ( _) ) ; 
649- 
650-             let  value = match  storage_class { 
651-                 Ok ( _)  => { 
659+             match  entry_arg_abi. mode  { 
660+                 PassMode :: Direct ( _)  => { 
661+                     let  value = match  storage_class { 
662+                         Ok ( _)  => { 
663+                             assert_eq ! ( storage_class,  Ok ( StorageClass :: Input ) ) ; 
664+                             bx. load ( 
665+                                 entry_arg_abi. layout . spirv_type ( hir_param. ty_span ,  bx) , 
666+                                 value_ptr. unwrap ( ) , 
667+                                 entry_arg_abi. layout . align . abi , 
668+                             ) 
669+                         } 
670+                         Err ( SpecConstant  {  .. } )  => { 
671+                             spec_const_id. unwrap ( ) . with_type ( value_spirv_type) 
672+                         } 
673+                     } ; 
674+                     call_args. push ( value) ; 
675+                     assert_eq ! ( value_len,  None ) ; 
676+                 } 
677+                 PassMode :: Pair ( ..)  => { 
678+                     // Load both elements of the scalar pair from the input variable. 
652679                    assert_eq ! ( storage_class,  Ok ( StorageClass :: Input ) ) ; 
653-                     bx. load ( 
654-                         entry_arg_abi. layout . spirv_type ( hir_param. ty_span ,  bx) , 
655-                         value_ptr. unwrap ( ) , 
656-                         entry_arg_abi. layout . align . abi , 
657-                     ) 
680+                     let  layout = entry_arg_abi. layout ; 
681+                     let  ( a,  b)  = match  layout. backend_repr  { 
682+                         rustc_abi:: BackendRepr :: ScalarPair ( a,  b)  => ( a,  b) , 
683+                         other => span_bug ! ( 
684+                             hir_param. ty_span, 
685+                             "ScalarPair expected for entry param, found {other:?}" 
686+                         ) , 
687+                     } ; 
688+                     let  b_offset = a
689+                         . primitive ( ) 
690+                         . size ( self ) 
691+                         . align_to ( b. primitive ( ) . align ( self ) . abi ) ; 
692+ 
693+                     let  elem0_ty = self . scalar_pair_element_backend_type ( layout,  0 ,  false ) ; 
694+                     let  elem1_ty = self . scalar_pair_element_backend_type ( layout,  1 ,  false ) ; 
695+ 
696+                     let  base_ptr = value_ptr. unwrap ( ) ; 
697+                     let  ptr1 = bx. inbounds_ptradd ( base_ptr,  self . const_usize ( b_offset. bytes ( ) ) ) ; 
698+ 
699+                     let  v0 = bx. load ( elem0_ty,  base_ptr,  layout. align . abi ) ; 
700+                     let  v1 = bx. load ( elem1_ty,  ptr1,  layout. align . restrict_for_offset ( b_offset) ) ; 
701+                     call_args. push ( v0) ; 
702+                     call_args. push ( v1) ; 
703+                     assert_eq ! ( value_len,  None ) ; 
658704                } 
659-                 Err ( SpecConstant  {  .. } )  => spec_const_id. unwrap ( ) . with_type ( value_spirv_type) , 
660-             } ; 
661-             call_args. push ( value) ; 
662-             assert_eq ! ( value_len,  None ) ; 
705+                 _ => unreachable ! ( ) , 
706+             } 
663707        } 
664708
665709        // FIXME(eddyb) check whether the storage class is compatible with the 
0 commit comments