about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2020-03-26 05:32:52 -0400
committerWesley Wiser <wwiser@gmail.com>2020-04-15 05:45:21 -0400
commit8da26e036630352a21a9ddc14bf53ad31e9b9ba0 (patch)
treec5f3621b6643930cb462094fa6b656a89d392f38 /src/test
parentba72b15666b2491415aec703a02c2364fe5e2790 (diff)
downloadrust-8da26e036630352a21a9ddc14bf53ad31e9b9ba0.tar.gz
rust-8da26e036630352a21a9ddc14bf53ad31e9b9ba0.zip
Use `call` instead of `invoke` for functions that cannot unwind
The `FnAbi` now knows if the function is allowed to unwind. If a
function isn't allowed to unwind, we can use a `call` instead of an
`invoke`.

This resolves an issue when calling LLVM intrinsics which cannot unwind
LLVM will generate an error if you attempt to invoke them so we need to
ignore cleanup blocks in codegen and generate a call instead.
Diffstat (limited to 'src/test')
-rw-r--r--src/test/codegen/c-variadic.rs16
-rw-r--r--src/test/codegen/call-llvm-intrinsics.rs27
2 files changed, 35 insertions, 8 deletions
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);
+    }
+}