@@ -354,25 +354,39 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
354354 }
355355
356356 sym:: volatile_load | sym:: unaligned_volatile_load => {
357- let result = PlaceRef {
358- val : result_place. unwrap ( ) ,
359- layout : result_layout,
360- } ;
361-
357+ // Note that we cannot just load the `llvm_type` because we should never load non-scalars.
358+ // Trying to do so blows up horribly in some cases -- for example loading a
359+ // `MaybeUninint<&dyn Trait>` would load as `{ [i64x2] }` which gives assertions later
360+ // (if we're lucky) from things not being pointers that ought to be.
362361 let ptr = args[ 0 ] . immediate ( ) ;
363- let load = self . volatile_load ( result_layout. llvm_type ( self ) , ptr) ;
364- let align = if name == sym:: unaligned_volatile_load {
365- 1
362+ let abi_align = result_layout. align . abi ;
363+ let ptr_align = if name == sym:: volatile_load { abi_align } else { Align :: ONE } ;
364+ if result_layout. is_zst ( ) {
365+ return IntrinsicResult :: Operand ( OperandValue :: ZeroSized ) ;
366+ } else if let BackendRepr :: Scalar ( scalar) = result_layout. backend_repr {
367+ let load = self . volatile_load ( self . type_from_scalar ( scalar) , ptr, ptr_align) ;
368+ self . to_immediate_scalar ( load, scalar)
366369 } else {
367- result_layout. align . bytes ( ) as u32
368- } ;
369- unsafe {
370- llvm:: LLVMSetAlignment ( load, align) ;
371- }
372- if !result_layout. is_zst ( ) {
373- self . store_to_place ( load, result. val ) ;
370+ // One day Rust will probably want to define how we split up a volatile load
371+ // of something that's *not* just an ordinary scalar, but for now we can just
372+ // use an LLVM integer type of the correct width and let it split it however.
373+ let llty = self . type_ix ( result_layout. size . bits ( ) ) ;
374+ let temp = if let Some ( result_place) = result_place {
375+ PlaceRef {
376+ val : result_place,
377+ layout : result_layout,
378+ }
379+ } else {
380+ PlaceRef :: alloca ( self , result_layout)
381+ } ;
382+ let llval = self . volatile_load ( llty, ptr, ptr_align) ;
383+ self . store ( llval, temp. val . llval , abi_align) ;
384+ return if result_place. is_none ( ) {
385+ IntrinsicResult :: Operand ( self . load_operand ( temp) . val )
386+ } else {
387+ IntrinsicResult :: WroteIntoPlace
388+ } ;
374389 }
375- return IntrinsicResult :: WroteIntoPlace ;
376390 }
377391 sym:: volatile_store => {
378392 let dst = args[ 0 ] . deref ( self . cx ( ) ) ;
0 commit comments