Skip to content

Commit

Permalink
codegen: Fix va_list - aaarch64 iOS/Windows
Browse files Browse the repository at this point in the history
According to the Apple developer docs:

> The type va_list is an alias for char * rather than for the struct
> type specified in the generic PCS.

The current implementation uses the generic Aarch64 structure for VaList
for Aarch64 iOS.

Windows always uses the char * variant of the va_list.
  • Loading branch information
dlrobertson committed Dec 7, 2018
1 parent fc84f5f commit 3dfd8f7
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 10 deletions.
2 changes: 2 additions & 0 deletions src/libcore/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ impl fmt::Debug for c_void {
/// Basic implementation of a `va_list`.
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
not(target_arch = "x86_64")),
all(target_arch = "aarch4", target_os = "ios"),
windows))]
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
Expand Down Expand Up @@ -192,6 +193,7 @@ impl<'a> VaList<'a> {
where F: for<'copy> FnOnce(VaList<'copy>) -> R {
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
not(target_arch = "x86_64")),
all(target_arch = "aarch4", target_os = "ios"),
windows))]
let mut ap = va_copy(self);
#[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
Expand Down
36 changes: 26 additions & 10 deletions src/librustc_codegen_llvm/va_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,30 @@ pub(super) fn emit_va_arg(
) -> &'ll Value {
// Determine the va_arg implementation to use. The LLVM va_arg instruction
// is lacking in some instances, so we should only use it as a fallback.
let target = &bx.cx.tcx.sess.target.target;
let arch = &bx.cx.tcx.sess.target.target.arch;
match (&**arch,
bx.cx.tcx.sess.target.target.options.is_like_windows) {
match (&**arch, target.options.is_like_windows) {
// Windows x86
("x86", true) => {
emit_ptr_va_arg(bx, addr, target_ty, false,
Align::from_bytes(4).unwrap(), false)
}
// Generic x86
("x86", _) => {
emit_ptr_va_arg(bx, addr, target_ty, false,
Align::from_bytes(4).unwrap(), true)
}
// Windows Aarch64
("aarch4", true) => {
emit_ptr_va_arg(bx, addr, target_ty, false,
Align::from_bytes(8).unwrap(), false)
}
// iOS Aarch64
("aarch4", _) if target.target_os == "ios" => {
emit_ptr_va_arg(bx, addr, target_ty, false,
Align::from_bytes(8).unwrap(), true)
}
// Windows x86_64
("x86_64", true) => {
let target_ty_size = bx.cx.size_of(target_ty).bytes();
let indirect = if target_ty_size > 8 || !target_ty_size.is_power_of_two() {
Expand All @@ -122,15 +139,14 @@ pub(super) fn emit_va_arg(
emit_ptr_va_arg(bx, addr, target_ty, indirect,
Align::from_bytes(8).unwrap(), false)
}
("x86", false) => {
emit_ptr_va_arg(bx, addr, target_ty, false,
Align::from_bytes(4).unwrap(), true)
}
// For all other architecture/OS combinations fall back to using
// the LLVM va_arg instruction.
// https://llvm.org/docs/LangRef.html#va-arg-instruction
_ => {
let va_list = if (bx.tcx().sess.target.target.arch == "aarch64" ||
bx.tcx().sess.target.target.arch == "x86_64" ||
bx.tcx().sess.target.target.arch == "powerpc") &&
!bx.tcx().sess.target.target.options.is_like_windows {
let va_list = if (target.arch == "aarch64" ||
target.arch == "x86_64" ||
target.arch == "powerpc") &&
!target.options.is_like_windows {
bx.load(addr.immediate(), bx.tcx().data_layout.pointer_align.abi)
} else {
addr.immediate()
Expand Down

0 comments on commit 3dfd8f7

Please sign in to comment.