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} ;
8+ use rustc_middle:: bug;
89use rustc_middle:: ty:: Ty ;
9- use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
10+ use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
1011use rustc_target:: spec:: { Abi , Arch , Env } ;
1112
1213use crate :: builder:: Builder ;
@@ -82,6 +83,7 @@ enum PassMode {
8283enum SlotSize {
8384 Bytes8 = 8 ,
8485 Bytes4 = 4 ,
86+ Bytes1 = 1 ,
8587}
8688
8789enum AllowHigherAlign {
@@ -728,7 +730,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
728730fn copy_to_temporary_if_more_aligned < ' ll , ' tcx > (
729731 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
730732 reg_addr : & ' ll Value ,
731- layout : TyAndLayout < ' tcx , Ty < ' tcx > > ,
733+ layout : TyAndLayout < ' tcx > ,
732734 src_align : Align ,
733735) -> & ' ll Value {
734736 if layout. layout . align . abi > src_align {
@@ -751,7 +753,7 @@ fn copy_to_temporary_if_more_aligned<'ll, 'tcx>(
751753fn x86_64_sysv64_va_arg_from_memory < ' ll , ' tcx > (
752754 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
753755 va_list_addr : & ' ll Value ,
754- layout : TyAndLayout < ' tcx , Ty < ' tcx > > ,
756+ layout : TyAndLayout < ' tcx > ,
755757) -> & ' ll Value {
756758 let dl = bx. cx . data_layout ( ) ;
757759 let ptr_align_abi = dl. data_layout ( ) . pointer_align ( ) . abi ;
@@ -1003,15 +1005,17 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
10031005 return bx. load ( layout. llvm_type ( bx) , value_ptr, layout. align . abi ) ;
10041006}
10051007
1008+ /// Determine the va_arg implementation to use. The LLVM va_arg instruction
1009+ /// is lacking in some instances, so we should only use it as a fallback.
10061010pub ( super ) fn emit_va_arg < ' ll , ' tcx > (
10071011 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
10081012 addr : OperandRef < ' tcx , & ' ll Value > ,
10091013 target_ty : Ty < ' tcx > ,
10101014) -> & ' 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 ;
1015+ let layout = bx. cx . layout_of ( target_ty) ;
1016+ let target_ty_size = layout. layout . size ( ) . bytes ( ) ;
10141017
1018+ let target = & bx. cx . tcx . sess . target ;
10151019 match target. arch {
10161020 Arch :: X86 => emit_ptr_va_arg (
10171021 bx,
@@ -1069,23 +1073,79 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
10691073 AllowHigherAlign :: Yes ,
10701074 ForceRightAdjust :: No ,
10711075 ) ,
1076+ Arch :: LoongArch32 => emit_ptr_va_arg (
1077+ bx,
1078+ addr,
1079+ target_ty,
1080+ if target_ty_size > 2 * 4 { PassMode :: Indirect } else { PassMode :: Direct } ,
1081+ SlotSize :: Bytes4 ,
1082+ AllowHigherAlign :: Yes ,
1083+ ForceRightAdjust :: No ,
1084+ ) ,
1085+ Arch :: LoongArch64 => emit_ptr_va_arg (
1086+ bx,
1087+ addr,
1088+ target_ty,
1089+ if target_ty_size > 2 * 8 { PassMode :: Indirect } else { PassMode :: Direct } ,
1090+ SlotSize :: Bytes8 ,
1091+ AllowHigherAlign :: Yes ,
1092+ ForceRightAdjust :: No ,
1093+ ) ,
1094+ Arch :: AmdGpu => emit_ptr_va_arg (
1095+ bx,
1096+ addr,
1097+ target_ty,
1098+ PassMode :: Direct ,
1099+ SlotSize :: Bytes4 ,
1100+ AllowHigherAlign :: No ,
1101+ ForceRightAdjust :: No ,
1102+ ) ,
1103+ Arch :: Nvptx64 => emit_ptr_va_arg (
1104+ bx,
1105+ addr,
1106+ target_ty,
1107+ PassMode :: Direct ,
1108+ SlotSize :: Bytes1 ,
1109+ AllowHigherAlign :: Yes ,
1110+ ForceRightAdjust :: No ,
1111+ ) ,
1112+ Arch :: Wasm32 => emit_ptr_va_arg (
1113+ bx,
1114+ addr,
1115+ target_ty,
1116+ if layout. is_aggregate ( ) || layout. is_zst ( ) || layout. is_1zst ( ) {
1117+ PassMode :: Indirect
1118+ } else {
1119+ PassMode :: Direct
1120+ } ,
1121+ SlotSize :: Bytes4 ,
1122+ AllowHigherAlign :: Yes ,
1123+ ForceRightAdjust :: No ,
1124+ ) ,
1125+ Arch :: Wasm64 => bug ! ( "c-variadic functions are not fully implemented for wasm64" ) ,
1126+ Arch :: CSky => emit_ptr_va_arg (
1127+ bx,
1128+ addr,
1129+ target_ty,
1130+ PassMode :: Direct ,
1131+ SlotSize :: Bytes4 ,
1132+ AllowHigherAlign :: Yes ,
1133+ ForceRightAdjust :: No ,
1134+ ) ,
10721135 // 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- }
1136+ Arch :: X86_64 if target. is_like_windows => emit_ptr_va_arg (
1137+ bx,
1138+ addr,
1139+ target_ty,
1140+ if target_ty_size > 8 || !target_ty_size. is_power_of_two ( ) {
1141+ PassMode :: Indirect
1142+ } else {
1143+ PassMode :: Direct
1144+ } ,
1145+ SlotSize :: Bytes8 ,
1146+ AllowHigherAlign :: No ,
1147+ ForceRightAdjust :: No ,
1148+ ) ,
10891149 // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64.
10901150 Arch :: X86_64 => emit_x86_64_sysv64_va_arg ( bx, addr, target_ty) ,
10911151 Arch :: Xtensa => emit_xtensa_va_arg ( bx, addr, target_ty) ,
0 commit comments