Auto merge of #108089 - Zoxc:windows-tls, r=bjorn3
Support TLS access into dylibs on Windows This allows access to `#[thread_local]` in upstream dylibs on Windows by introducing a MIR shim to return the address of the thread local. Accesses that go into an upstream dylib will call the MIR shim to get the address of it. `convert_tls_rvalues` is introduced in `rustc_codegen_ssa` which rewrites MIR TLS accesses to dummy calls which are replaced with calls to the MIR shims when the dummy calls are lowered to backend calls. A new `dll_tls_export` target option enables this behavior with a `false` value which is set for Windows platforms. This fixes https://github.com/rust-lang/rust/issues/84933.
This commit is contained in:
commit
f98598c6cd
28 changed files with 262 additions and 95 deletions
|
@ -177,14 +177,29 @@ fn exported_symbols_provider_local(
|
|||
|
||||
// FIXME: Sorting this is unnecessary since we are sorting later anyway.
|
||||
// Can we skip the later sorting?
|
||||
let mut symbols: Vec<_> = tcx.with_stable_hashing_context(|hcx| {
|
||||
tcx.reachable_non_generics(LOCAL_CRATE)
|
||||
.to_sorted(&hcx, true)
|
||||
.into_iter()
|
||||
.map(|(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info))
|
||||
.collect()
|
||||
let sorted = tcx.with_stable_hashing_context(|hcx| {
|
||||
tcx.reachable_non_generics(LOCAL_CRATE).to_sorted(&hcx, true)
|
||||
});
|
||||
|
||||
let mut symbols: Vec<_> =
|
||||
sorted.iter().map(|(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info)).collect();
|
||||
|
||||
// Export TLS shims
|
||||
if !tcx.sess.target.dll_tls_export {
|
||||
symbols.extend(sorted.iter().filter_map(|(&def_id, &info)| {
|
||||
tcx.needs_thread_local_shim(def_id).then(|| {
|
||||
(
|
||||
ExportedSymbol::ThreadLocalShim(def_id),
|
||||
SymbolExportInfo {
|
||||
level: info.level,
|
||||
kind: SymbolExportKind::Text,
|
||||
used: info.used,
|
||||
},
|
||||
)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
if tcx.entry_fn(()).is_some() {
|
||||
let exported_symbol =
|
||||
ExportedSymbol::NoDefId(SymbolName::new(tcx, tcx.sess.target.entry_name.as_ref()));
|
||||
|
@ -380,7 +395,9 @@ fn upstream_monomorphizations_provider(
|
|||
continue;
|
||||
}
|
||||
}
|
||||
ExportedSymbol::NonGeneric(..) | ExportedSymbol::NoDefId(..) => {
|
||||
ExportedSymbol::NonGeneric(..)
|
||||
| ExportedSymbol::ThreadLocalShim(..)
|
||||
| ExportedSymbol::NoDefId(..) => {
|
||||
// These are no monomorphizations
|
||||
continue;
|
||||
}
|
||||
|
@ -500,6 +517,16 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
|
|||
instantiating_crate,
|
||||
)
|
||||
}
|
||||
ExportedSymbol::ThreadLocalShim(def_id) => {
|
||||
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
|
||||
tcx,
|
||||
ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
substs: ty::InternalSubsts::empty(),
|
||||
},
|
||||
instantiating_crate,
|
||||
)
|
||||
}
|
||||
ExportedSymbol::DropGlue(ty) => rustc_symbol_mangling::symbol_name_for_instance_in_crate(
|
||||
tcx,
|
||||
Instance::resolve_drop_in_place(tcx, ty),
|
||||
|
@ -548,6 +575,8 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
|
|||
ExportedSymbol::DropGlue(..) => None,
|
||||
// NoDefId always follow the target's default symbol decoration scheme.
|
||||
ExportedSymbol::NoDefId(..) => None,
|
||||
// ThreadLocalShim always follow the target's default symbol decoration scheme.
|
||||
ExportedSymbol::ThreadLocalShim(..) => None,
|
||||
};
|
||||
|
||||
let (conv, args) = instance
|
||||
|
|
|
@ -516,8 +516,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
mir::Rvalue::ThreadLocalRef(def_id) => {
|
||||
assert!(bx.cx().tcx().is_static(def_id));
|
||||
let static_ = bx.get_static(def_id);
|
||||
let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
|
||||
let static_ = if !def_id.is_local() && bx.cx().tcx().needs_thread_local_shim(def_id)
|
||||
{
|
||||
let instance = ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
substs: ty::InternalSubsts::empty(),
|
||||
};
|
||||
let fn_ptr = bx.get_fn_addr(instance);
|
||||
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
|
||||
bx.call(fn_ty, Some(fn_abi), fn_ptr, &[], None)
|
||||
} else {
|
||||
bx.get_static(def_id)
|
||||
};
|
||||
OperandRef { val: OperandValue::Immediate(static_), layout }
|
||||
}
|
||||
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue