@@ -655,6 +655,68 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
655655 // https://github.com/gpuweb/gpuweb/issues/33
656656 let ( & ptr_base_index, indices) = combined_indices. split_first ( ) . unwrap ( ) ;
657657
658+ // HACK(eddyb) this effectively removes any real support for GEPs with
659+ // any `indices` (beyond `ptr_base_index`), which should now be the case
660+ // across `rustc_codegen_ssa` (see also comment inside `inbounds_gep`).
661+ // FIXME(eddyb) are the warning + fallback path even work keeping?
662+ if !indices. is_empty ( ) {
663+ // HACK(eddyb) Cargo silences warnings in dependencies.
664+ let force_warn = |span, msg| -> rustc_errors:: Diag < ' _ , ( ) > {
665+ rustc_errors:: Diag :: new (
666+ self . tcx . dcx ( ) ,
667+ rustc_errors:: Level :: ForceWarning ( None ) ,
668+ msg,
669+ )
670+ . with_span ( span)
671+ } ;
672+ force_warn (
673+ self . span ( ) ,
674+ format ! (
675+ "[RUST-GPU BUG] `inbounds_gep` or `gep` called with \
676+ {} combined indices (expected only 1)",
677+ combined_indices. len( ) ,
678+ ) ,
679+ )
680+ . emit ( ) ;
681+
682+ let indexed_base_ptr = self . maybe_inbounds_gep ( ty, ptr, & [ ptr_base_index] , is_inbounds) ;
683+ let indexed_base_ptr_id = indexed_base_ptr. def ( self ) ;
684+ assert_ty_eq ! ( self , indexed_base_ptr. ty, self . type_ptr_to( ty) ) ;
685+
686+ let mut final_pointee = ty;
687+ for & index in indices {
688+ final_pointee = match self . lookup_type ( final_pointee) {
689+ SpirvType :: Adt { field_types, .. } => {
690+ field_types[ self
691+ . builder
692+ . lookup_const_scalar ( index)
693+ . expect ( "non-const struct index for GEP" )
694+ as usize ]
695+ }
696+ SpirvType :: Array { element, .. }
697+ | SpirvType :: RuntimeArray { element }
698+ | SpirvType :: Vector { element, .. }
699+ | SpirvType :: Matrix { element, .. } => element,
700+
701+ _ => self . fatal ( format ! (
702+ "GEP not implemented for indexing into type {}" ,
703+ self . debug_type( final_pointee)
704+ ) ) ,
705+ } ;
706+ }
707+ let final_spirv_ptr_type = self . type_ptr_to ( final_pointee) ;
708+
709+ let indices_ids: Vec < _ > = indices. iter ( ) . map ( |index| index. def ( self ) ) . collect ( ) ;
710+
711+ return self . emit_access_chain (
712+ final_spirv_ptr_type,
713+ indexed_base_ptr_id,
714+ None ,
715+ indices_ids,
716+ is_inbounds,
717+ ) ;
718+ }
719+
658720 // Determine if this GEP operation is effectively byte-level addressing.
659721 // This check is based on the *provided* input type `ty`. If `ty` is i8 or u8,
660722 // it suggests the caller intends to perform byte-offset calculations,
@@ -1972,6 +2034,21 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
19722034 ptr : Self :: Value ,
19732035 indices : & [ Self :: Value ] ,
19742036 ) -> Self :: Value {
2037+ // HACK(eddyb) effectively a backport of this `gep [0, i]` -> `gep [i]`
2038+ // PR: https://github.com/rust-lang/rust/pull/134117 to even earlier
2039+ // nightlies - and that PR happens to remove the last GEP that can be
2040+ // emitted with any "structured" (struct/array) indices, beyond the
2041+ // "first index" (which acts as `<*T>::offset` aka "pointer arithmetic").
2042+ if let & [ ptr_base_index, structured_index] = indices {
2043+ if self . builder . lookup_const_scalar ( ptr_base_index) == Some ( 0 ) {
2044+ if let SpirvType :: Array { element, .. } | SpirvType :: RuntimeArray { element, .. } =
2045+ self . lookup_type ( ty)
2046+ {
2047+ return self . maybe_inbounds_gep ( element, ptr, & [ structured_index] , true ) ;
2048+ }
2049+ }
2050+ }
2051+
19752052 self . maybe_inbounds_gep ( ty, ptr, indices, true )
19762053 }
19772054
0 commit comments