@@ -655,6 +655,68 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
655
655
// https://github.com/gpuweb/gpuweb/issues/33
656
656
let ( & ptr_base_index, indices) = combined_indices. split_first ( ) . unwrap ( ) ;
657
657
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
+
658
720
// Determine if this GEP operation is effectively byte-level addressing.
659
721
// This check is based on the *provided* input type `ty`. If `ty` is i8 or u8,
660
722
// it suggests the caller intends to perform byte-offset calculations,
@@ -1972,6 +2034,21 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
1972
2034
ptr : Self :: Value ,
1973
2035
indices : & [ Self :: Value ] ,
1974
2036
) -> 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
+
1975
2052
self . maybe_inbounds_gep ( ty, ptr, indices, true )
1976
2053
}
1977
2054
0 commit comments