Skip to content

Commit a9d62be

Browse files
committed
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.
1 parent b0fcfa7 commit a9d62be

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

src/librustc_codegen_ssa/mir/block.rs

+2-13
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use syntax_pos::Pos;
2020

2121
use super::{FunctionCx, LocalRef};
2222
use super::place::PlaceRef;
23-
use super::operand::{OperandValue, OperandRef};
23+
use super::operand::OperandRef;
2424
use super::operand::OperandValue::{Pair, Ref, Immediate};
2525

2626
/// Used by `FunctionCx::codegen_terminator` for emitting common patterns
@@ -695,18 +695,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
695695
// an "spoofed" `VaList`. This argument is ignored, but we need to
696696
// populate it with a dummy operand so that the users real arguments
697697
// are not overwritten.
698-
let i = if sig.c_variadic && last_arg_idx.map(|x| x == i).unwrap_or(false) {
699-
let layout = match self.cx.tcx().lang_items().va_list() {
700-
Some(did) => bx.cx().layout_of(bx.tcx().type_of(did)),
701-
None => bug!("`va_list` language item required for C-variadics"),
702-
};
703-
let op = OperandRef {
704-
val: OperandValue::Immediate(
705-
bx.cx().const_undef(bx.cx().immediate_backend_type(layout)
706-
)),
707-
layout: layout,
708-
};
709-
self.codegen_argument(&mut bx, op, &mut llargs, &fn_ty.args[i]);
698+
let i = if sig.c_variadic && last_arg_idx.map(|x| i >= x).unwrap_or(false) {
710699
if i + 1 < fn_ty.args.len() {
711700
i + 1
712701
} else {

src/test/codegen/issue-58881.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// compile-flags: -C no-prepopulate-passes
2+
//
3+
// only-x86_64
4+
// ignore-windows
5+
6+
#![crate_type = "lib"]
7+
8+
extern "C" {
9+
fn variadic_fn(_: i32, ...);
10+
}
11+
12+
#[repr(C)]
13+
struct Foo(u8);
14+
#[repr(C)]
15+
struct Bar(u64, u64, u64);
16+
17+
// Ensure that emit arguments of the correct type.
18+
pub unsafe fn test_call_variadic() {
19+
// CHECK: call void (i32, ...) @variadic_fn(i32 0, i8 {{.*}}, %Bar* {{.*}})
20+
variadic_fn(0, Foo(0), Bar(0, 0, 0))
21+
}

0 commit comments

Comments
 (0)