about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs4
-rw-r--r--src/test/codegen/c-variadic.rs16
-rw-r--r--src/test/codegen/call-llvm-intrinsics.rs27
3 files changed, 38 insertions, 9 deletions
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 219d5aa77ea..49131386508 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -111,7 +111,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
         cleanup: Option<mir::BasicBlock>,
     ) {
-        if let Some(cleanup) = cleanup {
+        // If there is a cleanup block and the function we're calling can unwind, then
+        // do an invoke, otherwise do a call.
+        if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
             let ret_bx = if let Some((_, target)) = destination {
                 fx.blocks[target]
             } else {
diff --git a/src/test/codegen/c-variadic.rs b/src/test/codegen/c-variadic.rs
index 971f4e3e12e..29c82686731 100644
--- a/src/test/codegen/c-variadic.rs
+++ b/src/test/codegen/c-variadic.rs
@@ -16,13 +16,13 @@ extern "C" {
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_0() {
     // Ensure that we correctly call foreign C-variadic functions.
-    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0)
+    // CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM:i32( signext)?]] 0)
     foreign_c_variadic_0(0);
-    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42)
+    // CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42)
     foreign_c_variadic_0(0, 42i32);
-    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
+    // CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024)
     foreign_c_variadic_0(0, 42i32, 1024i32);
-    // CHECK: invoke void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
+    // CHECK: call void (i32, ...) @foreign_c_variadic_0([[PARAM]] 0, [[PARAM]] 42, [[PARAM]] 1024, [[PARAM]] 0)
     foreign_c_variadic_0(0, 42i32, 1024i32, 0i32);
 }
 
@@ -30,24 +30,24 @@ pub unsafe extern "C" fn use_foreign_c_variadic_0() {
 // removing the "spoofed" `VaListImpl` that is used by Rust defined C-variadics.
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_1_0(ap: VaList) {
-    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap)
+    // CHECK: call void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap)
     foreign_c_variadic_1(ap);
 }
 
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_1_1(ap: VaList) {
-    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 42)
+    // CHECK: call void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 42)
     foreign_c_variadic_1(ap, 42i32);
 }
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_1_2(ap: VaList) {
-    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42)
+    // CHECK: call void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42)
     foreign_c_variadic_1(ap, 2i32, 42i32);
 }
 
 #[unwind(aborts)] // FIXME(#58794)
 pub unsafe extern "C" fn use_foreign_c_variadic_1_3(ap: VaList) {
-    // CHECK: invoke void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42, [[PARAM]] 0)
+    // CHECK: call void ({{.*}}*, ...) @foreign_c_variadic_1({{.*}} %ap, [[PARAM]] 2, [[PARAM]] 42, [[PARAM]] 0)
     foreign_c_variadic_1(ap, 2i32, 42i32, 0i32);
 }
 
diff --git a/src/test/codegen/call-llvm-intrinsics.rs b/src/test/codegen/call-llvm-intrinsics.rs
new file mode 100644
index 00000000000..c7a464a9b0e
--- /dev/null
+++ b/src/test/codegen/call-llvm-intrinsics.rs
@@ -0,0 +1,27 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(link_llvm_intrinsics)]
+#![crate_type = "lib"]
+
+struct A;
+
+impl Drop for A {
+    fn drop(&mut self) {
+        println!("A");
+    }
+}
+
+extern {
+    #[link_name = "llvm.sqrt.f32"]
+    fn sqrt(x: f32) -> f32;
+}
+
+pub fn do_call() {
+    let _a = A;
+
+    unsafe {
+        // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them
+        // CHECK: call float @llvm.sqrt.f32(float 4.000000e+00
+        sqrt(4.0);
+    }
+}