1- use rustc_abi:: { Align , BackendRepr , Endian , HasDataLayout , Primitive , Size , TyAndLayout } ;
1+ use rustc_abi:: { Align , BackendRepr , Endian , HasDataLayout , Primitive , Size } ;
22use rustc_codegen_ssa:: MemFlags ;
33use rustc_codegen_ssa:: common:: IntPredicate ;
44use rustc_codegen_ssa:: mir:: operand:: OperandRef ;
55use rustc_codegen_ssa:: traits:: {
66 BaseTypeCodegenMethods , BuilderMethods , ConstCodegenMethods , LayoutTypeCodegenMethods ,
77} ;
88use rustc_middle:: ty:: Ty ;
9- use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
9+ use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
1010use rustc_target:: spec:: { Abi , Arch , Env } ;
1111
1212use crate :: builder:: Builder ;
@@ -82,6 +82,7 @@ enum PassMode {
8282enum SlotSize {
8383 Bytes8 = 8 ,
8484 Bytes4 = 4 ,
85+ Bytes1 = 1 ,
8586}
8687
8788enum AllowHigherAlign {
@@ -728,7 +729,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
728729fn copy_to_temporary_if_more_aligned < ' ll , ' tcx > (
729730 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
730731 reg_addr : & ' ll Value ,
731- layout : TyAndLayout < ' tcx , Ty < ' tcx > > ,
732+ layout : TyAndLayout < ' tcx > ,
732733 src_align : Align ,
733734) -> & ' ll Value {
734735 if layout. layout . align . abi > src_align {
@@ -751,7 +752,7 @@ fn copy_to_temporary_if_more_aligned<'ll, 'tcx>(
751752fn x86_64_sysv64_va_arg_from_memory < ' ll , ' tcx > (
752753 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
753754 va_list_addr : & ' ll Value ,
754- layout : TyAndLayout < ' tcx , Ty < ' tcx > > ,
755+ layout : TyAndLayout < ' tcx > ,
755756) -> & ' ll Value {
756757 let dl = bx. cx . data_layout ( ) ;
757758 let ptr_align_abi = dl. data_layout ( ) . pointer_align ( ) . abi ;
@@ -1003,15 +1004,17 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
10031004 return bx. load ( layout. llvm_type ( bx) , value_ptr, layout. align . abi ) ;
10041005}
10051006
1007+ /// Determine the va_arg implementation to use. The LLVM va_arg instruction
1008+ /// is lacking in some instances, so we should only use it as a fallback.
10061009pub ( super ) fn emit_va_arg < ' ll , ' tcx > (
10071010 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
10081011 addr : OperandRef < ' tcx , & ' ll Value > ,
10091012 target_ty : Ty < ' tcx > ,
10101013) -> & ' ll Value {
1011- // Determine the va_arg implementation to use. The LLVM va_arg instruction
1012- // is lacking in some instances, so we should only use it as a fallback.
1013- let target = & bx. cx . tcx . sess . target ;
1014+ let layout = bx. cx . layout_of ( target_ty) ;
1015+ let target_ty_size = layout. layout . size ( ) . bytes ( ) ;
10141016
1017+ let target = & bx. cx . tcx . sess . target ;
10151018 match target. arch {
10161019 Arch :: X86 => emit_ptr_va_arg (
10171020 bx,
@@ -1069,23 +1072,78 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
10691072 AllowHigherAlign :: Yes ,
10701073 ForceRightAdjust :: No ,
10711074 ) ,
1075+ Arch :: LoongArch32 => emit_ptr_va_arg (
1076+ bx,
1077+ addr,
1078+ target_ty,
1079+ if target_ty_size > 2 * 4 { PassMode :: Indirect } else { PassMode :: Direct } ,
1080+ SlotSize :: Bytes4 ,
1081+ AllowHigherAlign :: Yes ,
1082+ ForceRightAdjust :: No ,
1083+ ) ,
1084+ Arch :: LoongArch64 => emit_ptr_va_arg (
1085+ bx,
1086+ addr,
1087+ target_ty,
1088+ if target_ty_size > 2 * 8 { PassMode :: Indirect } else { PassMode :: Direct } ,
1089+ SlotSize :: Bytes8 ,
1090+ AllowHigherAlign :: Yes ,
1091+ ForceRightAdjust :: No ,
1092+ ) ,
1093+ Arch :: AmdGpu => emit_ptr_va_arg (
1094+ bx,
1095+ addr,
1096+ target_ty,
1097+ PassMode :: Direct ,
1098+ SlotSize :: Bytes4 ,
1099+ AllowHigherAlign :: No ,
1100+ ForceRightAdjust :: No ,
1101+ ) ,
1102+ Arch :: Nvptx64 => emit_ptr_va_arg (
1103+ bx,
1104+ addr,
1105+ target_ty,
1106+ PassMode :: Direct ,
1107+ SlotSize :: Bytes1 ,
1108+ AllowHigherAlign :: Yes ,
1109+ ForceRightAdjust :: No ,
1110+ ) ,
1111+ Arch :: Wasm32 | Arch :: Wasm64 => emit_ptr_va_arg (
1112+ bx,
1113+ addr,
1114+ target_ty,
1115+ if layout. is_aggregate ( ) || layout. is_zst ( ) || layout. is_1zst ( ) {
1116+ PassMode :: Indirect
1117+ } else {
1118+ PassMode :: Direct
1119+ } ,
1120+ SlotSize :: Bytes4 ,
1121+ AllowHigherAlign :: Yes ,
1122+ ForceRightAdjust :: No ,
1123+ ) ,
1124+ Arch :: CSky => emit_ptr_va_arg (
1125+ bx,
1126+ addr,
1127+ target_ty,
1128+ PassMode :: Direct ,
1129+ SlotSize :: Bytes4 ,
1130+ AllowHigherAlign :: Yes ,
1131+ ForceRightAdjust :: No ,
1132+ ) ,
10721133 // Windows x86_64
1073- Arch :: X86_64 if target. is_like_windows => {
1074- let target_ty_size = bx. cx . size_of ( target_ty) . bytes ( ) ;
1075- emit_ptr_va_arg (
1076- bx,
1077- addr,
1078- target_ty,
1079- if target_ty_size > 8 || !target_ty_size. is_power_of_two ( ) {
1080- PassMode :: Indirect
1081- } else {
1082- PassMode :: Direct
1083- } ,
1084- SlotSize :: Bytes8 ,
1085- AllowHigherAlign :: No ,
1086- ForceRightAdjust :: No ,
1087- )
1088- }
1134+ Arch :: X86_64 if target. is_like_windows => emit_ptr_va_arg (
1135+ bx,
1136+ addr,
1137+ target_ty,
1138+ if target_ty_size > 8 || !target_ty_size. is_power_of_two ( ) {
1139+ PassMode :: Indirect
1140+ } else {
1141+ PassMode :: Direct
1142+ } ,
1143+ SlotSize :: Bytes8 ,
1144+ AllowHigherAlign :: No ,
1145+ ForceRightAdjust :: No ,
1146+ ) ,
10891147 // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64.
10901148 Arch :: X86_64 => emit_x86_64_sysv64_va_arg ( bx, addr, target_ty) ,
10911149 Arch :: Xtensa => emit_xtensa_va_arg ( bx, addr, target_ty) ,
0 commit comments