about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-09-05 16:28:34 +0200
committerGitHub <noreply@github.com>2020-09-05 16:28:34 +0200
commitb4d387302416c90a3f70211770292d8d8ab5e07d (patch)
tree073b67192201ec0ec35e18a560a405e77847cbf1
parent45bdee8fde3a47dd0316e1b2bc30641102ea7912 (diff)
parentc23151bdb1b242d96d545cfe4c5f3314b6ef448c (diff)
Rollup merge of #76263 - tmiasko:inline-codegen-fn-attrs, r=ecstatic-morse
inliner: Check for codegen fn attributes compatibility

* Check for target features compatibility
* Check for no_sanitize attribute compatibility

Fixes #76259.
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs22
-rw-r--r--src/test/mir-opt/inline/inline-compatibility.rs39
-rw-r--r--src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff25
-rw-r--r--src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff25
-rw-r--r--src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff22
-rw-r--r--src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff22
6 files changed, 150 insertions, 5 deletions
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 0a3424bb944..d6e6371e886 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -4,7 +4,7 @@ use rustc_attr as attr;
 use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::{Subst, SubstsRef};
@@ -45,7 +45,8 @@ impl<'tcx> MirPass<'tcx> for Inline {
                 // based function.
                 debug!("function inlining is disabled when compiling with `instrument_coverage`");
             } else {
-                Inliner { tcx, source }.run_pass(body);
+                Inliner { tcx, source, codegen_fn_attrs: tcx.codegen_fn_attrs(source.def_id()) }
+                    .run_pass(body);
             }
         }
     }
@@ -54,6 +55,7 @@ impl<'tcx> MirPass<'tcx> for Inline {
 struct Inliner<'tcx> {
     tcx: TyCtxt<'tcx>,
     source: MirSource<'tcx>,
+    codegen_fn_attrs: &'tcx CodegenFnAttrs,
 }
 
 impl Inliner<'tcx> {
@@ -242,9 +244,19 @@ impl Inliner<'tcx> {
             return false;
         }
 
-        // Avoid inlining functions marked as no_sanitize if sanitizer is enabled,
-        // since instrumentation might be enabled and performed on the caller.
-        if self.tcx.sess.opts.debugging_opts.sanitizer.intersects(codegen_fn_attrs.no_sanitize) {
+        let self_features = &self.codegen_fn_attrs.target_features;
+        let callee_features = &codegen_fn_attrs.target_features;
+        if callee_features.iter().any(|feature| !self_features.contains(feature)) {
+            debug!("`callee has extra target features - not inlining");
+            return false;
+        }
+
+        let self_no_sanitize =
+            self.codegen_fn_attrs.no_sanitize & self.tcx.sess.opts.debugging_opts.sanitizer;
+        let callee_no_sanitize =
+            codegen_fn_attrs.no_sanitize & self.tcx.sess.opts.debugging_opts.sanitizer;
+        if self_no_sanitize != callee_no_sanitize {
+            debug!("`callee has incompatible no_sanitize attribute - not inlining");
             return false;
         }
 
diff --git a/src/test/mir-opt/inline/inline-compatibility.rs b/src/test/mir-opt/inline/inline-compatibility.rs
new file mode 100644
index 00000000000..ff9049edb4f
--- /dev/null
+++ b/src/test/mir-opt/inline/inline-compatibility.rs
@@ -0,0 +1,39 @@
+// Checks that only functions with compatible attributes are inlined.
+//
+// only-x86_64
+// needs-sanitizer-address
+// compile-flags: -Zsanitizer=address
+
+#![crate_type = "lib"]
+#![feature(no_sanitize)]
+#![feature(target_feature_11)]
+
+// EMIT_MIR inline_compatibility.inlined_target_feature.Inline.diff
+#[target_feature(enable = "sse2")]
+pub unsafe fn inlined_target_feature() {
+    target_feature();
+}
+
+// EMIT_MIR inline_compatibility.not_inlined_target_feature.Inline.diff
+pub unsafe fn not_inlined_target_feature() {
+    target_feature();
+}
+
+// EMIT_MIR inline_compatibility.inlined_no_sanitize.Inline.diff
+#[no_sanitize(address)]
+pub unsafe fn inlined_no_sanitize() {
+    no_sanitize();
+}
+
+// EMIT_MIR inline_compatibility.not_inlined_no_sanitize.Inline.diff
+pub unsafe fn not_inlined_no_sanitize() {
+    no_sanitize();
+}
+
+#[inline]
+#[target_feature(enable = "sse2")]
+pub unsafe fn target_feature() {}
+
+#[inline]
+#[no_sanitize(address, memory)]
+pub unsafe fn no_sanitize() {}
diff --git a/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff
new file mode 100644
index 00000000000..7b0ecaffdd7
--- /dev/null
+++ b/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff
@@ -0,0 +1,25 @@
+- // MIR for `inlined_no_sanitize` before Inline
++ // MIR for `inlined_no_sanitize` after Inline
+  
+  fn inlined_no_sanitize() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:24:37: 24:37
+      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:25:5: 25:18
++     scope 1 {
++     }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:25:5: 25:18
+-         _1 = no_sanitize() -> bb1;       // scope 0 at $DIR/inline-compatibility.rs:25:5: 25:18
+-                                          // mir::Constant
+-                                          // + span: $DIR/inline-compatibility.rs:25:5: 25:16
+-                                          // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(Scalar(<ZST>)) }
+-     }
+- 
+-     bb1: {
++         _1 = const ();                   // scope 1 at $DIR/inline-compatibility.rs:39:29: 39:31
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:25:18: 25:19
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:24:37: 26:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:26:2: 26:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff
new file mode 100644
index 00000000000..f55eae6c50a
--- /dev/null
+++ b/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff
@@ -0,0 +1,25 @@
+- // MIR for `inlined_target_feature` before Inline
++ // MIR for `inlined_target_feature` after Inline
+  
+  fn inlined_target_feature() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:13:40: 13:40
+      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:14:5: 14:21
++     scope 1 {
++     }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:14:5: 14:21
+-         _1 = target_feature() -> bb1;    // scope 0 at $DIR/inline-compatibility.rs:14:5: 14:21
+-                                          // mir::Constant
+-                                          // + span: $DIR/inline-compatibility.rs:14:5: 14:19
+-                                          // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(Scalar(<ZST>)) }
+-     }
+- 
+-     bb1: {
++         _1 = const ();                   // scope 1 at $DIR/inline-compatibility.rs:35:32: 35:34
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:14:21: 14:22
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:13:40: 15:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:15:2: 15:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff
new file mode 100644
index 00000000000..651eadc1e84
--- /dev/null
+++ b/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff
@@ -0,0 +1,22 @@
+- // MIR for `not_inlined_no_sanitize` before Inline
++ // MIR for `not_inlined_no_sanitize` after Inline
+  
+  fn not_inlined_no_sanitize() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:29:41: 29:41
+      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:30:5: 30:18
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:30:5: 30:18
+          _1 = no_sanitize() -> bb1;       // scope 0 at $DIR/inline-compatibility.rs:30:5: 30:18
+                                           // mir::Constant
+                                           // + span: $DIR/inline-compatibility.rs:30:5: 30:16
+                                           // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:30:18: 30:19
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:29:41: 31:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:31:2: 31:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff
new file mode 100644
index 00000000000..55b9edf3adc
--- /dev/null
+++ b/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff
@@ -0,0 +1,22 @@
+- // MIR for `not_inlined_target_feature` before Inline
++ // MIR for `not_inlined_target_feature` after Inline
+  
+  fn not_inlined_target_feature() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:18:44: 18:44
+      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:19:5: 19:21
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:19:5: 19:21
+          _1 = target_feature() -> bb1;    // scope 0 at $DIR/inline-compatibility.rs:19:5: 19:21
+                                           // mir::Constant
+                                           // + span: $DIR/inline-compatibility.rs:19:5: 19:19
+                                           // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:19:21: 19:22
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:18:44: 20:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:20:2: 20:2
+      }
+  }
+