From a9d62be557a648f254c6850e2a08917686a26976 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Wed, 27 Mar 2019 13:00:37 +0000 Subject: [PATCH] Fix LLVM IR generated for C-variadic arguments It is possible to create malformed LLVM IR given variadic arguments that are aggregate types. This occurs due to improper tracking of the current argument in the functions list of arguments. --- src/librustc_codegen_ssa/mir/block.rs | 15 ++------------- src/test/codegen/issue-58881.rs | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 src/test/codegen/issue-58881.rs diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 98da07a905e..26442faa321 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -20,7 +20,7 @@ use super::{FunctionCx, LocalRef}; use super::place::PlaceRef; -use super::operand::{OperandValue, OperandRef}; +use super::operand::OperandRef; use super::operand::OperandValue::{Pair, Ref, Immediate}; /// Used by `FunctionCx::codegen_terminator` for emitting common patterns @@ -695,18 +695,7 @@ fn codegen_call_terminator<'b>( // an "spoofed" `VaList`. This argument is ignored, but we need to // populate it with a dummy operand so that the users real arguments // are not overwritten. - let i = if sig.c_variadic && last_arg_idx.map(|x| x == i).unwrap_or(false) { - let layout = match self.cx.tcx().lang_items().va_list() { - Some(did) => bx.cx().layout_of(bx.tcx().type_of(did)), - None => bug!("`va_list` language item required for C-variadics"), - }; - let op = OperandRef { - val: OperandValue::Immediate( - bx.cx().const_undef(bx.cx().immediate_backend_type(layout) - )), - layout: layout, - }; - self.codegen_argument(&mut bx, op, &mut llargs, &fn_ty.args[i]); + let i = if sig.c_variadic && last_arg_idx.map(|x| i >= x).unwrap_or(false) { if i + 1 < fn_ty.args.len() { i + 1 } else { diff --git a/src/test/codegen/issue-58881.rs b/src/test/codegen/issue-58881.rs new file mode 100644 index 00000000000..de451324f03 --- /dev/null +++ b/src/test/codegen/issue-58881.rs @@ -0,0 +1,21 @@ +// compile-flags: -C no-prepopulate-passes +// +// only-x86_64 +// ignore-windows + +#![crate_type = "lib"] + +extern "C" { + fn variadic_fn(_: i32, ...); +} + +#[repr(C)] +struct Foo(u8); +#[repr(C)] +struct Bar(u64, u64, u64); + +// Ensure that emit arguments of the correct type. +pub unsafe fn test_call_variadic() { + // CHECK: call void (i32, ...) @variadic_fn(i32 0, i8 {{.*}}, %Bar* {{.*}}) + variadic_fn(0, Foo(0), Bar(0, 0, 0)) +}