@@ -40,6 +40,7 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
4040 align : Align ,
4141 slot_size : Align ,
4242 allow_higher_align : bool ,
43+ force_right_adjust : bool ,
4344) -> ( & ' ll Value , Align ) {
4445 let va_list_ty = bx. type_ptr ( ) ;
4546 let va_list_addr = list. immediate ( ) ;
@@ -57,7 +58,10 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
5758 let next = bx. inbounds_ptradd ( addr, full_direct_size) ;
5859 bx. store ( next, va_list_addr, bx. tcx ( ) . data_layout . pointer_align . abi ) ;
5960
60- if size. bytes ( ) < slot_size. bytes ( ) && bx. tcx ( ) . sess . target . endian == Endian :: Big {
61+ if size. bytes ( ) < slot_size. bytes ( )
62+ && bx. tcx ( ) . sess . target . endian == Endian :: Big
63+ && force_right_adjust
64+ {
6165 let adjusted_size = bx. cx ( ) . const_i32 ( ( slot_size. bytes ( ) - size. bytes ( ) ) as i32 ) ;
6266 let adjusted = bx. inbounds_ptradd ( addr, adjusted_size) ;
6367 ( adjusted, addr_align)
@@ -81,16 +85,23 @@ enum AllowHigherAlign {
8185 Yes ,
8286}
8387
88+ enum ForceRightAdjust {
89+ No ,
90+ Yes ,
91+ }
92+
8493fn emit_ptr_va_arg < ' ll , ' tcx > (
8594 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
8695 list : OperandRef < ' tcx , & ' ll Value > ,
8796 target_ty : Ty < ' tcx > ,
8897 pass_mode : PassMode ,
8998 slot_size : SlotSize ,
9099 allow_higher_align : AllowHigherAlign ,
100+ force_right_adjust : ForceRightAdjust ,
91101) -> & ' ll Value {
92102 let indirect = matches ! ( pass_mode, PassMode :: Indirect ) ;
93103 let allow_higher_align = matches ! ( allow_higher_align, AllowHigherAlign :: Yes ) ;
104+ let force_right_adjust = matches ! ( force_right_adjust, ForceRightAdjust :: Yes ) ;
94105 let slot_size = Align :: from_bytes ( slot_size as u64 ) . unwrap ( ) ;
95106
96107 let layout = bx. cx . layout_of ( target_ty) ;
@@ -103,8 +114,15 @@ fn emit_ptr_va_arg<'ll, 'tcx>(
103114 } else {
104115 ( layout. llvm_type ( bx. cx ) , layout. size , layout. align )
105116 } ;
106- let ( addr, addr_align) =
107- emit_direct_ptr_va_arg ( bx, list, size, align. abi , slot_size, allow_higher_align) ;
117+ let ( addr, addr_align) = emit_direct_ptr_va_arg (
118+ bx,
119+ list,
120+ size,
121+ align. abi ,
122+ slot_size,
123+ allow_higher_align,
124+ force_right_adjust,
125+ ) ;
108126 if indirect {
109127 let tmp_ret = bx. load ( llty, addr, addr_align) ;
110128 bx. load ( bx. cx . layout_of ( target_ty) . llvm_type ( bx. cx ) , tmp_ret, align. abi )
@@ -208,6 +226,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
208226 PassMode :: Direct ,
209227 SlotSize :: Bytes8 ,
210228 AllowHigherAlign :: Yes ,
229+ ForceRightAdjust :: No ,
211230 ) ;
212231 bx. br ( end) ;
213232
@@ -721,13 +740,25 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
721740 let target = & bx. cx . tcx . sess . target ;
722741
723742 match & * target. arch {
743+ // Windows x86
744+ "x86" if target. is_like_windows => emit_ptr_va_arg (
745+ bx,
746+ addr,
747+ target_ty,
748+ PassMode :: Direct ,
749+ SlotSize :: Bytes4 ,
750+ AllowHigherAlign :: No ,
751+ ForceRightAdjust :: No ,
752+ ) ,
753+ // Generic x86
724754 "x86" => emit_ptr_va_arg (
725755 bx,
726756 addr,
727757 target_ty,
728758 PassMode :: Direct ,
729759 SlotSize :: Bytes4 ,
730760 if target. is_like_windows { AllowHigherAlign :: No } else { AllowHigherAlign :: Yes } ,
761+ ForceRightAdjust :: No ,
731762 ) ,
732763 "aarch64" | "arm64ec" if target. is_like_windows || target. is_like_darwin => {
733764 emit_ptr_va_arg (
@@ -737,10 +768,23 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
737768 PassMode :: Direct ,
738769 SlotSize :: Bytes8 ,
739770 if target. is_like_windows { AllowHigherAlign :: No } else { AllowHigherAlign :: Yes } ,
771+ ForceRightAdjust :: No ,
740772 )
741773 }
742774 "aarch64" => emit_aapcs_va_arg ( bx, addr, target_ty) ,
743775 "s390x" => emit_s390x_va_arg ( bx, addr, target_ty) ,
776+ "powerpc64" | "powerpc64le" => emit_ptr_va_arg (
777+ bx,
778+ addr,
779+ target_ty,
780+ PassMode :: Direct ,
781+ SlotSize :: Bytes8 ,
782+ AllowHigherAlign :: Yes ,
783+ match & * target. arch {
784+ "powerpc64" => ForceRightAdjust :: Yes ,
785+ _ => ForceRightAdjust :: No ,
786+ } ,
787+ ) ,
744788 // Windows x86_64
745789 "x86_64" if target. is_like_windows => {
746790 let target_ty_size = bx. cx . size_of ( target_ty) . bytes ( ) ;
@@ -755,6 +799,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
755799 } ,
756800 SlotSize :: Bytes8 ,
757801 AllowHigherAlign :: No ,
802+ ForceRightAdjust :: No ,
758803 )
759804 }
760805 // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64.
0 commit comments