@@ -358,19 +358,33 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
358
358
let field = self . layout . field ( bx. cx ( ) , i) ;
359
359
let offset = self . layout . fields . offset ( i) ;
360
360
361
- let val = if field. is_zst ( ) {
362
- OperandValue :: ZeroSized
363
- } else if field. size == self . layout . size {
364
- assert_eq ! ( offset. bytes( ) , 0 ) ;
365
- if let Some ( field_val) = fx. codegen_transmute_operand ( bx, * self , field) {
366
- field_val
367
- } else {
368
- // we have to go through memory for things like
361
+ if !bx. is_backend_ref ( self . layout ) && bx. is_backend_ref ( field) {
362
+ if let BackendRepr :: Vector { count, .. } = self . layout . backend_repr
363
+ && let BackendRepr :: Memory { sized : true } = field. backend_repr
364
+ && count. is_power_of_two ( )
365
+ {
366
+ assert_eq ! ( field. size, self . layout. size) ;
367
+ // This is being deprecated, but for now stdarch still needs it for
369
368
// Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
370
369
let place = PlaceRef :: alloca ( bx, field) ;
371
370
self . val . store ( bx, place. val . with_type ( self . layout ) ) ;
372
- bx. load_operand ( place) . val
371
+ return bx. load_operand ( place) ;
372
+ } else {
373
+ // Part of https://github.com/rust-lang/compiler-team/issues/838
374
+ bug ! ( "Non-ref type {self:?} cannot project to ref field type {field:?}" ) ;
373
375
}
376
+ }
377
+
378
+ let val = if field. is_zst ( ) {
379
+ OperandValue :: ZeroSized
380
+ } else if field. size == self . layout . size {
381
+ assert_eq ! ( offset. bytes( ) , 0 ) ;
382
+ fx. codegen_transmute_operand ( bx, * self , field) . unwrap_or_else ( || {
383
+ bug ! (
384
+ "Expected `codegen_transmute_operand` to handle equal-size \
385
+ field {i:?} projection from {self:?} to {field:?}"
386
+ )
387
+ } )
374
388
} else {
375
389
let ( in_scalar, imm) = match ( self . val , self . layout . backend_repr ) {
376
390
// Extract a scalar component from a pair.
@@ -385,11 +399,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
385
399
}
386
400
}
387
401
388
- // `#[repr(simd)]` types are also immediate.
389
- ( OperandValue :: Immediate ( llval) , BackendRepr :: Vector { .. } ) => {
390
- ( None , bx. extract_element ( llval, bx. cx ( ) . const_usize ( i as u64 ) ) )
391
- }
392
-
393
402
_ => {
394
403
span_bug ! ( fx. mir. span, "OperandRef::extract_field({:?}): not applicable" , self )
395
404
}
@@ -415,14 +424,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
415
424
imm
416
425
}
417
426
}
418
- BackendRepr :: Memory { sized : true } => {
419
- span_bug ! (
420
- fx. mir. span,
421
- "Projecting into a simd type with padding doesn't work; \
422
- See <https://github.com/rust-lang/rust/issues/137108>",
423
- ) ;
424
- }
425
- BackendRepr :: ScalarPair ( _, _) | BackendRepr :: Memory { sized : false } => bug ! ( ) ,
427
+ BackendRepr :: ScalarPair ( _, _) | BackendRepr :: Memory { .. } => bug ! ( ) ,
426
428
} )
427
429
} ;
428
430
0 commit comments