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
|
@ -43,6 +43,7 @@ pub enum ExportedSymbol<'tcx> {
|
|||
NonGeneric(DefId),
|
||||
Generic(DefId, SubstsRef<'tcx>),
|
||||
DropGlue(Ty<'tcx>),
|
||||
ThreadLocalShim(DefId),
|
||||
NoDefId(ty::SymbolName<'tcx>),
|
||||
}
|
||||
|
||||
|
@ -58,6 +59,10 @@ impl<'tcx> ExportedSymbol<'tcx> {
|
|||
ExportedSymbol::DropGlue(ty) => {
|
||||
tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty))
|
||||
}
|
||||
ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance {
|
||||
def: ty::InstanceDef::ThreadLocalShim(def_id),
|
||||
substs: ty::InternalSubsts::empty(),
|
||||
}),
|
||||
ExportedSymbol::NoDefId(symbol_name) => symbol_name,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -382,6 +382,7 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||
| InstanceDef::ClosureOnceShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::CloneShim(..)
|
||||
| InstanceDef::ThreadLocalShim(..)
|
||||
| InstanceDef::FnPtrAddrShim(..) => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,17 +164,7 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
Rvalue::Repeat(ref operand, count) => {
|
||||
tcx.mk_array_with_const_len(operand.ty(local_decls, tcx), count)
|
||||
}
|
||||
Rvalue::ThreadLocalRef(did) => {
|
||||
let static_ty = tcx.type_of(did).subst_identity();
|
||||
if tcx.is_mutable_static(did) {
|
||||
tcx.mk_mut_ptr(static_ty)
|
||||
} else if tcx.is_foreign_item(did) {
|
||||
tcx.mk_imm_ptr(static_ty)
|
||||
} else {
|
||||
// FIXME: These things don't *really* have 'static lifetime.
|
||||
tcx.mk_imm_ref(tcx.lifetimes.re_static, static_ty)
|
||||
}
|
||||
}
|
||||
Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did),
|
||||
Rvalue::Ref(reg, bk, ref place) => {
|
||||
let place_ty = place.ty(local_decls, tcx).ty;
|
||||
tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() })
|
||||
|
|
|
@ -335,6 +335,7 @@ macro_rules! make_mir_visitor {
|
|||
ty::InstanceDef::VTableShim(_def_id) |
|
||||
ty::InstanceDef::ReifyShim(_def_id) |
|
||||
ty::InstanceDef::Virtual(_def_id, _) |
|
||||
ty::InstanceDef::ThreadLocalShim(_def_id) |
|
||||
ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
|
||||
ty::InstanceDef::DropGlue(_def_id, None) => {}
|
||||
|
||||
|
|
|
@ -82,6 +82,11 @@ pub enum InstanceDef<'tcx> {
|
|||
/// The `DefId` is the ID of the `call_once` method in `FnOnce`.
|
||||
ClosureOnceShim { call_once: DefId, track_caller: bool },
|
||||
|
||||
/// Compiler-generated accessor for thread locals which returns a reference to the thread local
|
||||
/// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking
|
||||
/// native support.
|
||||
ThreadLocalShim(DefId),
|
||||
|
||||
/// `core::ptr::drop_in_place::<T>`.
|
||||
///
|
||||
/// The `DefId` is for `core::ptr::drop_in_place`.
|
||||
|
@ -156,6 +161,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
| InstanceDef::FnPtrShim(def_id, _)
|
||||
| InstanceDef::Virtual(def_id, _)
|
||||
| InstanceDef::Intrinsic(def_id)
|
||||
| InstanceDef::ThreadLocalShim(def_id)
|
||||
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
|
||||
| InstanceDef::DropGlue(def_id, _)
|
||||
| InstanceDef::CloneShim(def_id, _)
|
||||
|
@ -167,7 +173,9 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
|
||||
match self {
|
||||
ty::InstanceDef::Item(def) => Some(def.did),
|
||||
ty::InstanceDef::DropGlue(def_id, Some(_)) => Some(def_id),
|
||||
ty::InstanceDef::DropGlue(def_id, Some(_)) | InstanceDef::ThreadLocalShim(def_id) => {
|
||||
Some(def_id)
|
||||
}
|
||||
InstanceDef::VTableShim(..)
|
||||
| InstanceDef::ReifyShim(..)
|
||||
| InstanceDef::FnPtrShim(..)
|
||||
|
@ -192,6 +200,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
|
||||
| InstanceDef::DropGlue(def_id, _)
|
||||
| InstanceDef::CloneShim(def_id, _)
|
||||
| InstanceDef::ThreadLocalShim(def_id)
|
||||
| InstanceDef::FnPtrAddrShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
|
||||
}
|
||||
}
|
||||
|
@ -215,6 +224,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
let def_id = match *self {
|
||||
ty::InstanceDef::Item(def) => def.did,
|
||||
ty::InstanceDef::DropGlue(_, Some(_)) => return false,
|
||||
ty::InstanceDef::ThreadLocalShim(_) => return false,
|
||||
_ => return true,
|
||||
};
|
||||
matches!(
|
||||
|
@ -255,6 +265,9 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
)
|
||||
});
|
||||
}
|
||||
if let ty::InstanceDef::ThreadLocalShim(..) = *self {
|
||||
return false;
|
||||
}
|
||||
tcx.codegen_fn_attrs(self.def_id()).requests_inline()
|
||||
}
|
||||
|
||||
|
@ -278,6 +291,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
pub fn has_polymorphic_mir_body(&self) -> bool {
|
||||
match *self {
|
||||
InstanceDef::CloneShim(..)
|
||||
| InstanceDef::ThreadLocalShim(..)
|
||||
| InstanceDef::FnPtrAddrShim(..)
|
||||
| InstanceDef::FnPtrShim(..)
|
||||
| InstanceDef::DropGlue(_, Some(_)) => false,
|
||||
|
@ -310,6 +324,7 @@ fn fmt_instance(
|
|||
InstanceDef::Item(_) => Ok(()),
|
||||
InstanceDef::VTableShim(_) => write!(f, " - shim(vtable)"),
|
||||
InstanceDef::ReifyShim(_) => write!(f, " - shim(reify)"),
|
||||
InstanceDef::ThreadLocalShim(_) => write!(f, " - shim(tls)"),
|
||||
InstanceDef::Intrinsic(_) => write!(f, " - intrinsic"),
|
||||
InstanceDef::Virtual(_, num) => write!(f, " - virtual#{}", num),
|
||||
InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({})", ty),
|
||||
|
|
|
@ -2386,6 +2386,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..) => self.mir_shims(instance),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -597,6 +597,28 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.static_mutability(def_id) == Some(hir::Mutability::Mut)
|
||||
}
|
||||
|
||||
/// Returns `true` if the item pointed to by `def_id` is a thread local which needs a
|
||||
/// thread local shim generated.
|
||||
#[inline]
|
||||
pub fn needs_thread_local_shim(self, def_id: DefId) -> bool {
|
||||
!self.sess.target.dll_tls_export
|
||||
&& self.is_thread_local_static(def_id)
|
||||
&& !self.is_foreign_item(def_id)
|
||||
}
|
||||
|
||||
/// Returns the type a reference to the thread local takes in MIR.
|
||||
pub fn thread_local_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
|
||||
let static_ty = self.type_of(def_id).subst_identity();
|
||||
if self.is_mutable_static(def_id) {
|
||||
self.mk_mut_ptr(static_ty)
|
||||
} else if self.is_foreign_item(def_id) {
|
||||
self.mk_imm_ptr(static_ty)
|
||||
} else {
|
||||
// FIXME: These things don't *really* have 'static lifetime.
|
||||
self.mk_imm_ref(self.lifetimes.re_static, static_ty)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the type of the pointer to the static that we use in MIR.
|
||||
pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
|
||||
// Make sure that any constants in the static's type are evaluated.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue