@@ -40,6 +40,7 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
40
40
align : Align ,
41
41
slot_size : Align ,
42
42
allow_higher_align : bool ,
43
+ force_right_adjust : bool ,
43
44
) -> ( & ' ll Value , Align ) {
44
45
let va_list_ty = bx. type_ptr ( ) ;
45
46
let va_list_addr = list. immediate ( ) ;
@@ -57,7 +58,10 @@ fn emit_direct_ptr_va_arg<'ll, 'tcx>(
57
58
let next = bx. inbounds_ptradd ( addr, full_direct_size) ;
58
59
bx. store ( next, va_list_addr, bx. tcx ( ) . data_layout . pointer_align . abi ) ;
59
60
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
+ {
61
65
let adjusted_size = bx. cx ( ) . const_i32 ( ( slot_size. bytes ( ) - size. bytes ( ) ) as i32 ) ;
62
66
let adjusted = bx. inbounds_ptradd ( addr, adjusted_size) ;
63
67
( adjusted, addr_align)
@@ -81,16 +85,23 @@ enum AllowHigherAlign {
81
85
Yes ,
82
86
}
83
87
88
+ enum ForceRightAdjust {
89
+ No ,
90
+ Yes ,
91
+ }
92
+
84
93
fn emit_ptr_va_arg < ' ll , ' tcx > (
85
94
bx : & mut Builder < ' _ , ' ll , ' tcx > ,
86
95
list : OperandRef < ' tcx , & ' ll Value > ,
87
96
target_ty : Ty < ' tcx > ,
88
97
pass_mode : PassMode ,
89
98
slot_size : SlotSize ,
90
99
allow_higher_align : AllowHigherAlign ,
100
+ force_right_adjust : ForceRightAdjust ,
91
101
) -> & ' ll Value {
92
102
let indirect = matches ! ( pass_mode, PassMode :: Indirect ) ;
93
103
let allow_higher_align = matches ! ( allow_higher_align, AllowHigherAlign :: Yes ) ;
104
+ let force_right_adjust = matches ! ( force_right_adjust, ForceRightAdjust :: Yes ) ;
94
105
let slot_size = Align :: from_bytes ( slot_size as u64 ) . unwrap ( ) ;
95
106
96
107
let layout = bx. cx . layout_of ( target_ty) ;
@@ -103,8 +114,15 @@ fn emit_ptr_va_arg<'ll, 'tcx>(
103
114
} else {
104
115
( layout. llvm_type ( bx. cx ) , layout. size , layout. align )
105
116
} ;
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
+ ) ;
108
126
if indirect {
109
127
let tmp_ret = bx. load ( llty, addr, addr_align) ;
110
128
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>(
208
226
PassMode :: Direct ,
209
227
SlotSize :: Bytes8 ,
210
228
AllowHigherAlign :: Yes ,
229
+ ForceRightAdjust :: No ,
211
230
) ;
212
231
bx. br ( end) ;
213
232
@@ -721,13 +740,25 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
721
740
let target = & bx. cx . tcx . sess . target ;
722
741
723
742
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
724
754
"x86" => emit_ptr_va_arg (
725
755
bx,
726
756
addr,
727
757
target_ty,
728
758
PassMode :: Direct ,
729
759
SlotSize :: Bytes4 ,
730
760
if target. is_like_windows { AllowHigherAlign :: No } else { AllowHigherAlign :: Yes } ,
761
+ ForceRightAdjust :: No ,
731
762
) ,
732
763
"aarch64" | "arm64ec" if target. is_like_windows || target. is_like_darwin => {
733
764
emit_ptr_va_arg (
@@ -737,10 +768,23 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
737
768
PassMode :: Direct ,
738
769
SlotSize :: Bytes8 ,
739
770
if target. is_like_windows { AllowHigherAlign :: No } else { AllowHigherAlign :: Yes } ,
771
+ ForceRightAdjust :: No ,
740
772
)
741
773
}
742
774
"aarch64" => emit_aapcs_va_arg ( bx, addr, target_ty) ,
743
775
"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
+ ) ,
744
788
// Windows x86_64
745
789
"x86_64" if target. is_like_windows => {
746
790
let target_ty_size = bx. cx . size_of ( target_ty) . bytes ( ) ;
@@ -755,6 +799,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
755
799
} ,
756
800
SlotSize :: Bytes8 ,
757
801
AllowHigherAlign :: No ,
802
+ ForceRightAdjust :: No ,
758
803
)
759
804
}
760
805
// This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64.
0 commit comments