@@ -290,7 +290,7 @@ pub(crate) fn provide(providers: &mut Providers) {
290290 let trivial_struct = match tcx. hir_node_by_def_id ( def_id) {
291291 rustc_hir:: Node :: Item ( item) => match item. kind {
292292 rustc_hir:: ItemKind :: Struct (
293- .. ,
293+ _ ,
294294 & rustc_hir:: Generics {
295295 params :
296296 & [ ]
@@ -309,6 +309,7 @@ pub(crate) fn provide(providers: &mut Providers) {
309309 where_clause_span : _,
310310 span : _,
311311 } ,
312+ _,
312313 ) => Some ( tcx. adt_def ( def_id) ) ,
313314 _ => None ,
314315 } ,
@@ -792,10 +793,11 @@ fn dig_scalar_pointee<'tcx>(
792793// the type is really more "Layout with Ty" (`.ty` field + `Deref`s to `Layout`).
793794fn trans_aggregate < ' tcx > ( cx : & CodegenCx < ' tcx > , span : Span , ty : TyAndLayout < ' tcx > ) -> Word {
794795 fn create_zst < ' tcx > ( cx : & CodegenCx < ' tcx > , span : Span , ty : TyAndLayout < ' tcx > ) -> Word {
796+ assert_eq ! ( ty. size, Size :: ZERO ) ;
795797 SpirvType :: Adt {
796798 def_id : def_id_for_spirv_type_adt ( ty) ,
797799 size : Some ( Size :: ZERO ) ,
798- align : Align :: from_bytes ( 0 ) . unwrap ( ) ,
800+ align : ty . align . abi ,
799801 field_types : & [ ] ,
800802 field_offsets : & [ ] ,
801803 field_names : None ,
@@ -817,14 +819,18 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>
817819 // NOTE(eddyb) even if long-term this may become a byte array, that
818820 // only works for "data types" and not "opaque handles" (images etc.).
819821 let largest_case = ( 0 ..ty. fields . count ( ) )
820- . map ( |i| ty. field ( cx, i) )
821- . max_by_key ( |case| case. size ) ;
822+ . map ( |i| ( FieldIdx :: from_usize ( i ) , ty. field ( cx, i) ) )
823+ . max_by_key ( |( _ , case) | case. size ) ;
822824
823- if let Some ( case) = largest_case {
824- assert_eq ! ( ty. size, case. size) ;
825- case. spirv_type ( span, cx)
825+ if let Some ( ( case_idx, case) ) = largest_case {
826+ if ty. align != case. align {
827+ // HACK(eddyb) mismatched alignment requires a wrapper `struct`.
828+ trans_struct_or_union ( cx, span, ty, Some ( case_idx) )
829+ } else {
830+ assert_eq ! ( ty. size, case. size) ;
831+ case. spirv_type ( span, cx)
832+ }
826833 } else {
827- assert_eq ! ( ty. size, Size :: ZERO ) ;
828834 create_zst ( cx, span, ty)
829835 }
830836 }
@@ -859,7 +865,7 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>
859865 FieldsShape :: Arbitrary {
860866 offsets : _,
861867 memory_index : _,
862- } => trans_struct ( cx, span, ty) ,
868+ } => trans_struct_or_union ( cx, span, ty, None ) ,
863869 }
864870}
865871
@@ -890,14 +896,25 @@ pub fn auto_struct_layout(
890896}
891897
892898// see struct_llfields in librustc_codegen_llvm for implementation hints
893- fn trans_struct < ' tcx > ( cx : & CodegenCx < ' tcx > , span : Span , ty : TyAndLayout < ' tcx > ) -> Word {
899+ fn trans_struct_or_union < ' tcx > (
900+ cx : & CodegenCx < ' tcx > ,
901+ span : Span ,
902+ ty : TyAndLayout < ' tcx > ,
903+ union_case : Option < FieldIdx > ,
904+ ) -> Word {
894905 let size = if ty. is_unsized ( ) { None } else { Some ( ty. size ) } ;
895906 let align = ty. align . abi ;
896907 // FIXME(eddyb) use `AccumulateVec`s just like `rustc` itself does.
897908 let mut field_types = Vec :: new ( ) ;
898909 let mut field_offsets = Vec :: new ( ) ;
899910 let mut field_names = Vec :: new ( ) ;
900911 for i in ty. fields . index_by_increasing_offset ( ) {
912+ if let Some ( expected_field_idx) = union_case {
913+ if i != expected_field_idx. as_usize ( ) {
914+ continue ;
915+ }
916+ }
917+
901918 let field_ty = ty. field ( cx, i) ;
902919 field_types. push ( field_ty. spirv_type ( span, cx) ) ;
903920 let offset = ty. fields . offset ( i) ;
0 commit comments