@@ -402,8 +402,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
402402 indirect_dest : PlaceRef < ' tcx , V > ,
403403 ) {
404404 debug ! ( "OperandRef::store_unsized: operand={:?}, indirect_dest={:?}" , self , indirect_dest) ;
405- let flags = MemFlags :: empty ( ) ;
406-
407405 // `indirect_dest` must have `*mut T` type. We extract `T` out of it.
408406 let unsized_ty = indirect_dest
409407 . layout
@@ -416,17 +414,23 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
416414 bug ! ( "store_unsized called with a sized value" )
417415 } ;
418416
419- // FIXME: choose an appropriate alignment, or use dynamic align somehow
420- let max_align = Align :: from_bits ( 128 ) . unwrap ( ) ;
421- let min_align = Align :: from_bits ( 8 ) . unwrap ( ) ;
422-
423- // Allocate an appropriate region on the stack, and copy the value into it
424- let ( llsize, _) = glue:: size_and_align_of_dst ( bx, unsized_ty, Some ( llextra) ) ;
425- let lldst = bx. byte_array_alloca ( llsize, max_align) ;
426- bx. memcpy ( lldst, max_align, llptr, min_align, llsize, flags) ;
417+ // Allocate an appropriate region on the stack, and copy the value into it. Since alloca
418+ // doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the
419+ // pointer manually.
420+ let ( size, align) = glue:: size_and_align_of_dst ( bx, unsized_ty, Some ( llextra) ) ;
421+ let one = bx. const_usize ( 1 ) ;
422+ let align_minus_1 = bx. sub ( align, one) ;
423+ let size_extra = bx. add ( size, align_minus_1) ;
424+ let min_align = Align :: ONE ;
425+ let alloca = bx. byte_array_alloca ( size_extra, min_align) ;
426+ let address = bx. ptrtoint ( alloca, bx. type_isize ( ) ) ;
427+ let neg_address = bx. neg ( address) ;
428+ let offset = bx. and ( neg_address, align_minus_1) ;
429+ let dst = bx. inbounds_gep ( bx. type_i8 ( ) , alloca, & [ offset] ) ;
430+ bx. memcpy ( dst, min_align, llptr, min_align, size, MemFlags :: empty ( ) ) ;
427431
428432 // Store the allocated region and the extra to the indirect place.
429- let indirect_operand = OperandValue :: Pair ( lldst , llextra) ;
433+ let indirect_operand = OperandValue :: Pair ( dst , llextra) ;
430434 indirect_operand. store ( bx, indirect_dest) ;
431435 }
432436}
0 commit comments