about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm/back
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-04-14 00:39:44 +0200
committerGitHub <noreply@github.com>2019-04-14 00:39:44 +0200
commit7ff376b3b27d2e5c5c01b336924bcc3e507e5c4d (patch)
tree78ad46500c21bb3cad0f686c2ae348b115f39b93 /src/librustc_codegen_llvm/back
parentc4a3332d38c6c92394b5f7818f0a963fbcf86052 (diff)
parent724ca0584e2be0714edf2f30b86230666d7a9d19 (diff)
downloadrust-7ff376b3b27d2e5c5c01b336924bcc3e507e5c4d.tar.gz
rust-7ff376b3b27d2e5c5c01b336924bcc3e507e5c4d.zip
Rollup merge of #59812 - michaelwoerister:profile-gen-msvc-imp, r=alexcrichton
Exclude profiler-generated symbols from MSVC __imp_-symbol workaround.

LLVM's profiling instrumentation adds a few symbols that are used by the profiler runtime. Since these show up as globals in the LLVM IR, the compiler generates `dllimport`-related `__imp_` stubs for them. This can lead to linker errors because the instrumentation symbols have weak linkage or are in a comdat section, but the `__imp_` stubs aren't.

Instead of trying to replicate the linkage/comdat setup for the stubs, this PR just excludes the profiler-related symbols from stub-generation since they aren't supposed to be referenced via `__declspec(dllimport)` anywhere anyway.

r? @alexcrichton

EDIT: I considered making this more general, i.e. inferring from the symbol name if it is a Rust symbol or not. But then I figured out that that would yield false negatives for `#[no_mangle]` et al, so I went with a blacklist approach.
Diffstat (limited to 'src/librustc_codegen_llvm/back')
-rw-r--r--src/librustc_codegen_llvm/back/write.rs18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 4d52df91a8d..3ae169a597a 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -793,6 +793,7 @@ fn create_msvc_imps(
     } else {
         "\x01__imp_"
     };
+
     unsafe {
         let i8p_ty = Type::i8p_llcx(llcx);
         let globals = base::iter_globals(llmod)
@@ -800,14 +801,23 @@ fn create_msvc_imps(
                 llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage &&
                     llvm::LLVMIsDeclaration(val) == 0
             })
-            .map(move |val| {
+            .filter_map(|val| {
+                // Exclude some symbols that we know are not Rust symbols.
                 let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
+                if ignored(name.to_bytes()) {
+                    None
+                } else {
+                    Some((val, name))
+                }
+            })
+            .map(move |(val, name)| {
                 let mut imp_name = prefix.as_bytes().to_vec();
                 imp_name.extend(name.to_bytes());
                 let imp_name = CString::new(imp_name).unwrap();
                 (imp_name, val)
             })
             .collect::<Vec<_>>();
+
         for (imp_name, val) in globals {
             let imp = llvm::LLVMAddGlobal(llmod,
                                           i8p_ty,
@@ -816,4 +826,10 @@ fn create_msvc_imps(
             llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
         }
     }
+
+    // Use this function to exclude certain symbols from `__imp` generation.
+    fn ignored(symbol_name: &[u8]) -> bool {
+        // These are symbols generated by LLVM's profiling instrumentation
+        symbol_name.starts_with(b"__llvm_profile_")
+    }
 }