Skip to content
/ rust Public
forked from rust-lang/rust

Commit 89e6d46

Browse files
authored
Rollup merge of rust-lang#150074 - more-va-arg, r=Mark-Simulacrum
Update provider API docs tracking issue: rust-lang#44930 Provide our own implementations in order to guarantee the behavior of `va_arg`. We will only be able to stabilize `c_variadic` on targets where we know and guarantee the properties of `va_arg`. r? workingjubilee
2 parents 0bb6670 + f89cce3 commit 89e6d46

File tree

1 file changed

+83
-23
lines changed

1 file changed

+83
-23
lines changed

compiler/rustc_codegen_llvm/src/va_arg.rs

Lines changed: 83 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
use rustc_abi::{Align, BackendRepr, Endian, HasDataLayout, Primitive, Size, TyAndLayout};
1+
use rustc_abi::{Align, BackendRepr, Endian, HasDataLayout, Primitive, Size};
22
use rustc_codegen_ssa::MemFlags;
33
use rustc_codegen_ssa::common::IntPredicate;
44
use rustc_codegen_ssa::mir::operand::OperandRef;
55
use rustc_codegen_ssa::traits::{
66
BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, LayoutTypeCodegenMethods,
77
};
8+
use rustc_middle::bug;
89
use rustc_middle::ty::Ty;
9-
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
10+
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
1011
use rustc_target::spec::{Abi, Arch, Env};
1112

1213
use crate::builder::Builder;
@@ -82,6 +83,7 @@ enum PassMode {
8283
enum SlotSize {
8384
Bytes8 = 8,
8485
Bytes4 = 4,
86+
Bytes1 = 1,
8587
}
8688

8789
enum AllowHigherAlign {
@@ -728,7 +730,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
728730
fn 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>(
751753
fn 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.
10061010
pub(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

Comments
 (0)