about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-03-03 21:26:16 +0100
committerGitHub <noreply@github.com>2020-03-03 21:26:16 +0100
commit587ca17cdb2b6dc202389a59e2b236dd63c711a3 (patch)
tree5c22fea42afdf5b355a065f336d2df20be80ad73
parent099cd7f402dd2ccec7f35c13c585c650243d018c (diff)
parentb0e288d9f1d8b0f4038bb955a68308b892d54ea3 (diff)
downloadrust-587ca17cdb2b6dc202389a59e2b236dd63c711a3.tar.gz
rust-587ca17cdb2b6dc202389a59e2b236dd63c711a3.zip
Rollup merge of #69665 - tmiasko:new-pass-manager-thin-lto-opt, r=nikic
Invoke OptimizerLastEPCallbacks in PreLinkThinLTO

The default ThinLTO pre-link pipeline does not include optimizer last
extension points. Thus, when using the new LLVM pass manager & ThinLTO
& sanitizers on any opt-level different from zero, the sanitizer
function passes would be omitted from the pipeline.

Add optimizer last extensions points manually to the pipeline, but guard
registration with stage check in the case this behaviour changes in the
future.
-rw-r--r--src/rustllvm/PassWrapper.cpp12
-rw-r--r--src/test/codegen/sanitizer-recover.rs4
-rw-r--r--src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs27
-rw-r--r--src/tools/compiletest/src/header/tests.rs18
4 files changed, 57 insertions, 4 deletions
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 65071c3ed86..90d24d20737 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -868,8 +868,10 @@ LLVMRustOptimizeWithNewPassManager(
     } else {
       for (const auto &C : PipelineStartEPCallbacks)
         PB.registerPipelineStartEPCallback(C);
-      for (const auto &C : OptimizerLastEPCallbacks)
-        PB.registerOptimizerLastEPCallback(C);
+      if (OptStage != LLVMRustOptStage::PreLinkThinLTO) {
+        for (const auto &C : OptimizerLastEPCallbacks)
+          PB.registerOptimizerLastEPCallback(C);
+      }
 
       switch (OptStage) {
       case LLVMRustOptStage::PreLinkNoLTO:
@@ -877,6 +879,12 @@ LLVMRustOptimizeWithNewPassManager(
         break;
       case LLVMRustOptStage::PreLinkThinLTO:
         MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
+        if (!OptimizerLastEPCallbacks.empty()) {
+          FunctionPassManager FPM(DebugPassManager);
+          for (const auto &C : OptimizerLastEPCallbacks)
+            C(FPM, OptLevel);
+          MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+        }
         break;
       case LLVMRustOptStage::PreLinkFatLTO:
         MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
diff --git a/src/test/codegen/sanitizer-recover.rs b/src/test/codegen/sanitizer-recover.rs
index 9a583725b0b..05b4ab5653c 100644
--- a/src/test/codegen/sanitizer-recover.rs
+++ b/src/test/codegen/sanitizer-recover.rs
@@ -14,8 +14,8 @@
 //[MSAN-RECOVER-LTO] compile-flags: -Zsanitizer=memory  -Zsanitizer-recover=memory -C lto=fat
 //
 // MSAN-NOT:         @__msan_keep_going
-// MSAN-RECOVER:     @__msan_keep_going = weak_odr {{.*}} constant i32 1
-// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}} constant i32 1
+// MSAN-RECOVER:     @__msan_keep_going = weak_odr {{.*}}constant i32 1
+// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}}constant i32 1
 
 // ASAN-LABEL: define i32 @penguin(
 // ASAN:         call void @__asan_report_load4(i64 %0)
diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
new file mode 100644
index 00000000000..61d5d51cfd2
--- /dev/null
+++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
@@ -0,0 +1,27 @@
+// Regression test for sanitizer function instrumentation passes not
+// being run when compiling with new LLVM pass manager and ThinLTO.
+// Note: The issue occured only on non-zero opt-level.
+//
+// min-llvm-version 9.0
+// needs-sanitizer-support
+// only-x86_64
+//
+// no-prefer-dynamic
+// revisions: opt0 opt1
+// compile-flags: -Znew-llvm-pass-manager=yes -Zsanitizer=address -Clto=thin
+//[opt0]compile-flags: -Copt-level=0
+//[opt1]compile-flags: -Copt-level=1
+// run-fail
+// error-pattern: ERROR: AddressSanitizer: stack-use-after-scope
+
+static mut P: *mut usize = std::ptr::null_mut();
+
+fn main() {
+    unsafe {
+        {
+            let mut x = 0;
+            P = &mut x;
+        }
+        std::ptr::write_volatile(P, 123);
+    }
+}
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 38fa778219d..6c478f7e29d 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -110,6 +110,24 @@ fn no_system_llvm() {
 }
 
 #[test]
+fn llvm_version() {
+    let mut config = config();
+
+    config.llvm_version = Some("8.1.2-rust".to_owned());
+    assert!(parse_rs(&config, "// min-llvm-version 9.0").ignore);
+
+    config.llvm_version = Some("9.0.1-rust-1.43.0-dev".to_owned());
+    assert!(parse_rs(&config, "// min-llvm-version 9.2").ignore);
+
+    config.llvm_version = Some("9.3.1-rust-1.43.0-dev".to_owned());
+    assert!(!parse_rs(&config, "// min-llvm-version 9.2").ignore);
+
+    // FIXME.
+    // config.llvm_version = Some("10.0.0-rust".to_owned());
+    // assert!(!parse_rs(&config, "// min-llvm-version 9.0").ignore);
+}
+
+#[test]
 fn ignore_target() {
     let mut config = config();
     config.target = "x86_64-unknown-linux-gnu".to_owned();