about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-06-18 21:50:46 +0000
committerbors <bors@rust-lang.org>2019-06-18 21:50:46 +0000
commit605ea9d05c48957a291eec11eb7339788c3140ed (patch)
tree57b5bcd13ed3c9a67b234200959ca8a454edbebe /src/librustc_codegen_llvm
parent04a3dd8a872633ca1e4c217d11f741cc35cb19a5 (diff)
parentb9ea653aee231114acbe6d4b3c7b1d692772d060 (diff)
downloadrust-605ea9d05c48957a291eec11eb7339788c3140ed.tar.gz
rust-605ea9d05c48957a291eec11eb7339788c3140ed.zip
Auto merge of #59625 - immunant:copy_variadics_typealias, r=eddyb
Refactor C FFI variadics to more closely match their C counterparts, and add Clone implementation

We had to make some changes to expose `va_copy` and `va_end` directly to users (mainly for C2Rust, but not exclusively):
- redefine the Rust variadic structures to more closely correspond to C: `VaList` now matches `va_list`, and `VaListImpl` matches `__va_list_tag`
- add `Clone` for `VaListImpl`
- add explicit `as_va_list()` conversion function from `VaListImpl` to `VaList`
- add deref coercion from `VaList` to `VaListImpl`
- add support for the `asmjs` target

All these changes were needed for use cases like:
```Rust
let mut ap2 = va_copy(ap);
vprintf(fmt, ap2);
va_end(&mut ap2);
```
Diffstat (limited to 'src/librustc_codegen_llvm')
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs38
-rw-r--r--src/librustc_codegen_llvm/va_arg.rs12
2 files changed, 4 insertions, 46 deletions
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index dc3631e2ee1..7831c200114 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -146,15 +146,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                 self.va_end(args[0].immediate())
             }
             "va_copy" => {
-                let va_list = match (tcx.lang_items().va_list(), &result.layout.ty.sty) {
-                    (Some(did), ty::Adt(def, _)) if def.did == did => args[0].immediate(),
-                    (Some(_), _)  => self.load(args[0].immediate(),
-                                               tcx.data_layout.pointer_align.abi),
-                    (None, _) => bug!("`va_list` language item must be defined")
-                };
                 let intrinsic = self.cx().get_intrinsic(&("llvm.va_copy"));
-                self.call(intrinsic, &[llresult, va_list], None);
-                return;
+                self.call(intrinsic, &[args[0].immediate(), args[1].immediate()], None)
             }
             "va_arg" => {
                 match fn_ty.ret.layout.abi {
@@ -743,37 +736,12 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         self.call(expect, &[cond, self.const_bool(expected)], None)
     }
 
-    fn va_start(&mut self, list: &'ll Value) -> &'ll Value {
-        let target = &self.cx.tcx.sess.target.target;
-        let arch = &target.arch;
-        // A pointer to the architecture specific structure is passed to this
-        // function. For pointer variants (i686, RISC-V, Windows, etc), we
-        // should do do nothing, as the address to the pointer is needed. For
-        // architectures with a architecture specific structure (`Aarch64`,
-        // `X86_64`, etc), this function should load the structure from the
-        // address provided.
-        let va_list = match &**arch {
-            _ if target.options.is_like_windows => list,
-            "aarch64" if target.target_os == "ios" => list,
-            "aarch64" | "x86_64" | "powerpc" =>
-                self.load(list, self.tcx().data_layout.pointer_align.abi),
-            _ => list,
-        };
+    fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value {
         let intrinsic = self.cx().get_intrinsic("llvm.va_start");
         self.call(intrinsic, &[va_list], None)
     }
 
-    fn va_end(&mut self, list: &'ll Value) -> &'ll Value {
-        let target = &self.cx.tcx.sess.target.target;
-        let arch = &target.arch;
-        // See the comment in `va_start` for the purpose of the following.
-        let va_list = match &**arch {
-            _ if target.options.is_like_windows => list,
-            "aarch64" if target.target_os == "ios" => list,
-            "aarch64" | "x86_64" | "powerpc" =>
-                self.load(list, self.tcx().data_layout.pointer_align.abi),
-            _ => list,
-        };
+    fn va_end(&mut self, va_list: &'ll Value) -> &'ll Value {
         let intrinsic = self.cx().get_intrinsic("llvm.va_end");
         self.call(intrinsic, &[va_list], None)
     }
diff --git a/src/librustc_codegen_llvm/va_arg.rs b/src/librustc_codegen_llvm/va_arg.rs
index 410e00fe0b8..86b0ad761af 100644
--- a/src/librustc_codegen_llvm/va_arg.rs
+++ b/src/librustc_codegen_llvm/va_arg.rs
@@ -132,16 +132,6 @@ pub(super) fn emit_va_arg(
         // 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 (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()
-            };
-            bx.va_arg(va_list, bx.cx.layout_of(target_ty).llvm_type(bx.cx))
-        }
+        _ => bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx))
     }
 }