about summary refs log tree commit diff
path: root/src/test/codegen
diff options
context:
space:
mode:
authorAndrei Homescu <ah@immunant.com>2019-03-25 14:28:03 -0700
committerAndrei Homescu <ah@immunant.com>2019-06-17 16:04:49 -0700
commitb9ea653aee231114acbe6d4b3c7b1d692772d060 (patch)
treeeceeeff8ba9582d6fb956358c1dc06eceadb2a29 /src/test/codegen
parent70456a6cbd67c0547d22997007afaaed0819767e (diff)
downloadrust-b9ea653aee231114acbe6d4b3c7b1d692772d060.tar.gz
rust-b9ea653aee231114acbe6d4b3c7b1d692772d060.zip
Expose `VaListImpl` as the Rust equivalent of `__va_list_tag` and implement Clone for it.
Diffstat (limited to 'src/test/codegen')
-rw-r--r--src/test/codegen/c-variadic-copy.rs16
-rw-r--r--src/test/codegen/c-variadic-opt.rs15
-rw-r--r--src/test/codegen/c-variadic.rs2
3 files changed, 30 insertions, 3 deletions
diff --git a/src/test/codegen/c-variadic-copy.rs b/src/test/codegen/c-variadic-copy.rs
new file mode 100644
index 00000000000..4c61c4fcf68
--- /dev/null
+++ b/src/test/codegen/c-variadic-copy.rs
@@ -0,0 +1,16 @@
+// Tests that `VaListImpl::clone` gets inlined into a call to `llvm.va_copy`
+
+#![crate_type = "lib"]
+#![feature(c_variadic)]
+#![no_std]
+use core::ffi::VaList;
+
+extern "C" {
+    fn foreign_c_variadic_1(_: VaList, ...);
+}
+
+pub unsafe extern "C" fn clone_variadic(ap: VaList) {
+    let mut ap2 = ap.clone();
+    // CHECK: call void @llvm.va_copy
+    foreign_c_variadic_1(ap2.as_va_list(), 42i32);
+}
diff --git a/src/test/codegen/c-variadic-opt.rs b/src/test/codegen/c-variadic-opt.rs
index 8594d309b0a..969dce80f58 100644
--- a/src/test/codegen/c-variadic-opt.rs
+++ b/src/test/codegen/c-variadic-opt.rs
@@ -10,10 +10,21 @@ extern "C" {
 }
 
 // Ensure that `va_start` and `va_end` are properly injected even
-// when the "spoofed" `VaList` is not used.
+// when the "spoofed" `VaListImpl` is not used.
 #[no_mangle]
 pub unsafe extern "C" fn c_variadic_no_use(fmt: *const i8, mut ap: ...) -> i32 {
     // CHECK: call void @llvm.va_start
-    vprintf(fmt, ap)
+    vprintf(fmt, ap.as_va_list())
+    // CHECK: call void @llvm.va_end
+}
+
+// Check that `VaListImpl::clone` gets inlined into a direct call to `llvm.va_copy`
+#[no_mangle]
+pub unsafe extern "C" fn c_variadic_clone(fmt: *const i8, mut ap: ...) -> i32 {
+    // CHECK: call void @llvm.va_start
+    let mut ap2 = ap.clone();
+    // CHECK: call void @llvm.va_copy
+    let res = vprintf(fmt, ap2.as_va_list());
+    res
     // CHECK: call void @llvm.va_end
 }
diff --git a/src/test/codegen/c-variadic.rs b/src/test/codegen/c-variadic.rs
index 09c18ed90b2..13be5ced27f 100644
--- a/src/test/codegen/c-variadic.rs
+++ b/src/test/codegen/c-variadic.rs
@@ -23,7 +23,7 @@ pub unsafe extern "C" fn use_foreign_c_variadic_0() {
 }
 
 // Ensure that we do not remove the `va_list` passed to the foreign function when
-// removing the "spoofed" `VaList` that is used by Rust defined C-variadics.
+// removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics.
 pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) {
     // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap)
     foreign_c_variadic_1(ap);