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
3 changed files with 29 additions and 1 deletions
|
@ -793,6 +793,7 @@ fn create_msvc_imps(
|
||||||
} else {
|
} else {
|
||||||
"\x01__imp_"
|
"\x01__imp_"
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let i8p_ty = Type::i8p_llcx(llcx);
|
let i8p_ty = Type::i8p_llcx(llcx);
|
||||||
let globals = base::iter_globals(llmod)
|
let globals = base::iter_globals(llmod)
|
||||||
|
@ -800,14 +801,23 @@ fn create_msvc_imps(
|
||||||
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage &&
|
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage &&
|
||||||
llvm::LLVMIsDeclaration(val) == 0
|
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));
|
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();
|
let mut imp_name = prefix.as_bytes().to_vec();
|
||||||
imp_name.extend(name.to_bytes());
|
imp_name.extend(name.to_bytes());
|
||||||
let imp_name = CString::new(imp_name).unwrap();
|
let imp_name = CString::new(imp_name).unwrap();
|
||||||
(imp_name, val)
|
(imp_name, val)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for (imp_name, val) in globals {
|
for (imp_name, val) in globals {
|
||||||
let imp = llvm::LLVMAddGlobal(llmod,
|
let imp = llvm::LLVMAddGlobal(llmod,
|
||||||
i8p_ty,
|
i8p_ty,
|
||||||
|
@ -816,4 +826,10 @@ fn create_msvc_imps(
|
||||||
llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
|
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…
Add table
Add a link
Reference in a new issue