about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2018-11-02 13:22:48 +0100
committerNikita Popov <nikita.ppv@gmail.com>2018-11-06 19:24:28 +0100
commit66702fcd0ae34100aaf74a9bdf8da77b6e273616 (patch)
treea0f4b9a4286c59b051f68cdeec972d84b5da7b01
parent6cfc6033955dd2685dfa7baeec6f6bc3bfdfe2f1 (diff)
downloadrust-66702fcd0ae34100aaf74a9bdf8da77b6e273616.tar.gz
rust-66702fcd0ae34100aaf74a9bdf8da77b6e273616.zip
Run name-anon-globals after LTO passes as well
If we're going to emit bitcode (through ThinLTOBuffer), then we
need to ensure that anon globals are named. This was already done
after optimization passes, but also has to happen after LTO passes,
as we always emit the final result in a ThinLTO-compatible manner.

Fixes #51947.
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs7
-rw-r--r--src/librustc_codegen_llvm/back/write.rs8
-rw-r--r--src/test/ui/issue-51947.rs17
3 files changed, 30 insertions, 2 deletions
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 8f940e0d22a..3d96fef7c0d 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -605,6 +605,13 @@ fn run_pass_manager(cgcx: &CodegenContext,
             }
         });
 
+        // We always generate bitcode through ThinLTOBuffers,
+        // which do not support anonymous globals
+        if config.bitcode_needed() {
+            let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr() as *const _);
+            llvm::LLVMRustAddPass(pm, pass.unwrap());
+        }
+
         if config.verify_llvm_ir {
             let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
             llvm::LLVMRustAddPass(pm, pass.unwrap());
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index d04e80195f0..184be4b9eab 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -337,6 +337,11 @@ impl ModuleConfig {
         self.merge_functions = sess.opts.optimize == config::OptLevel::Default ||
                                sess.opts.optimize == config::OptLevel::Aggressive;
     }
+
+    pub fn bitcode_needed(&self) -> bool {
+        self.emit_bc || self.obj_is_bitcode
+            || self.emit_bc_compressed || self.embed_bitcode
+    }
 }
 
 /// Assembler name and command used by codegen when no_integrated_as is enabled
@@ -564,8 +569,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
             // Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need
             // to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise
             // we'll get errors in LLVM.
-            let using_thin_buffers = config.emit_bc || config.obj_is_bitcode
-                || config.emit_bc_compressed || config.embed_bitcode;
+            let using_thin_buffers = config.bitcode_needed();
             let mut have_name_anon_globals_pass = false;
             if !config.no_prepopulate_passes {
                 llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
diff --git a/src/test/ui/issue-51947.rs b/src/test/ui/issue-51947.rs
new file mode 100644
index 00000000000..7b79807e4d7
--- /dev/null
+++ b/src/test/ui/issue-51947.rs
@@ -0,0 +1,17 @@
+// compile-pass
+
+#![crate_type = "lib"]
+#![feature(linkage)]
+
+// MergeFunctions will merge these via an anonymous internal
+// backing function, which must be named if ThinLTO buffers are used
+
+#[linkage = "weak"]
+pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
+    a + b + c
+}
+
+#[linkage = "weak"]
+pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
+    a + b + c
+}