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.
This commit is contained in:
commit
7ff376b3b2
@ -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_")
|
||||
}
|
||||
}
|
||||
|
11
src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile
Normal file
11
src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
ifeq ($(PROFILER_SUPPORT),1)
|
||||
$(RUSTC) -O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)/test.profraw" --emit=llvm-ir test.rs
|
||||
# We expect symbols starting with "__llvm_profile_".
|
||||
$(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll
|
||||
# We do NOT expect the "__imp_" version of these symbols.
|
||||
$(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit
|
||||
$(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit
|
||||
endif
|
@ -0,0 +1 @@
|
||||
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user