Skip to content

Commit 7ff376b

Browse files
authored
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.
2 parents c4a3332 + 724ca05 commit 7ff376b

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

src/librustc_codegen_llvm/back/write.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -793,21 +793,31 @@ fn create_msvc_imps(
793793
} else {
794794
"\x01__imp_"
795795
};
796+
796797
unsafe {
797798
let i8p_ty = Type::i8p_llcx(llcx);
798799
let globals = base::iter_globals(llmod)
799800
.filter(|&val| {
800801
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage &&
801802
llvm::LLVMIsDeclaration(val) == 0
802803
})
803-
.map(move |val| {
804+
.filter_map(|val| {
805+
// Exclude some symbols that we know are not Rust symbols.
804806
let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
807+
if ignored(name.to_bytes()) {
808+
None
809+
} else {
810+
Some((val, name))
811+
}
812+
})
813+
.map(move |(val, name)| {
805814
let mut imp_name = prefix.as_bytes().to_vec();
806815
imp_name.extend(name.to_bytes());
807816
let imp_name = CString::new(imp_name).unwrap();
808817
(imp_name, val)
809818
})
810819
.collect::<Vec<_>>();
820+
811821
for (imp_name, val) in globals {
812822
let imp = llvm::LLVMAddGlobal(llmod,
813823
i8p_ty,
@@ -816,4 +826,10 @@ fn create_msvc_imps(
816826
llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
817827
}
818828
}
829+
830+
// Use this function to exclude certain symbols from `__imp` generation.
831+
fn ignored(symbol_name: &[u8]) -> bool {
832+
// These are symbols generated by LLVM's profiling instrumentation
833+
symbol_name.starts_with(b"__llvm_profile_")
834+
}
819835
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-include ../tools.mk
2+
3+
all:
4+
ifeq ($(PROFILER_SUPPORT),1)
5+
$(RUSTC) -O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)/test.profraw" --emit=llvm-ir test.rs
6+
# We expect symbols starting with "__llvm_profile_".
7+
$(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll
8+
# We do NOT expect the "__imp_" version of these symbols.
9+
$(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit
10+
$(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit
11+
endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}

0 commit comments

Comments
 (0)