Use weak_odr linkage when reusing definitions across codegen units

When reuing a definition across codegen units, we obviously cannot use
internal linkage, but using external linkage means that we can end up
with multiple conflicting definitions of a single symbol across
multiple crates. Since the definitions should all be equal
semantically, we can use weak_odr linkage to resolve the situation.

Fixes #32518
This commit is contained in:
Björn Steinbrink
2016-03-28 17:57:31 +02:00
parent abb3a107e4
commit 22f4587586
8 changed files with 152 additions and 17 deletions

View File

@@ -2125,6 +2125,9 @@ extern {
pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef);
pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
pub fn LLVMRustUnsetComdat(V: ValueRef);
}
// LLVM requires symbols from this library, but apparently they're not printed
@@ -2149,6 +2152,24 @@ pub fn SetLinkage(global: ValueRef, link: Linkage) {
}
}
// Externally visible symbols that might appear in multiple translation units need to appear in
// their own comdat section so that the duplicates can be discarded at link time. This can for
// example happen for generics when using multiple codegen units. This function simply uses the
// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
// function.
// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
unsafe {
LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
}
}
pub fn UnsetComdat(val: ValueRef) {
unsafe {
LLVMRustUnsetComdat(val);
}
}
pub fn SetDLLStorageClass(global: ValueRef, class: DLLStorageClassTypes) {
unsafe {
LLVMRustSetDLLStorageClass(global, class);