about summary refs log tree commit diff
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-29 16:20:37 +0000
committerbors <bors@rust-lang.org>2023-03-29 16:20:37 +0000
commitf98598c6cd34947efa9e3977338e9bce62d1997c (patch)
treedbcaccc8c251182adeb2beccb32b687f598e0623 /compiler/rustc_middle
parent86792086646b61342c9417b78b8a535392f1045f (diff)
parentd499bbb99d72c991f1d1691f83ffe96bcfafc80a (diff)
downloadrust-f98598c6cd34947efa9e3977338e9bce62d1997c.tar.gz
rust-f98598c6cd34947efa9e3977338e9bce62d1997c.zip
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.
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs5
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs1
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs12
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs1
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs17
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/util.rs22
7 files changed, 47 insertions, 12 deletions
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index 631fd09ec4c..c0c0fd07b6e 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -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,
         }
     }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 90397f01bc8..f592f1515c1 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -382,6 +382,7 @@ impl<'tcx> CodegenUnit<'tcx> {
                             | InstanceDef::ClosureOnceShim { .. }
                             | InstanceDef::DropGlue(..)
                             | InstanceDef::CloneShim(..)
+                            | InstanceDef::ThreadLocalShim(..)
                             | InstanceDef::FnPtrAddrShim(..) => None,
                         }
                     }
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 0aa2c500f51..ee439df8b6b 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -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() })
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 9b31ad783fc..b39fc3aaaff 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -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) => {}
 
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 036b4477679..e73225f70cc 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -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),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c9dd3e499a8..7df90fab56f 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -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),
         }
     }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index dcd9743196e..e9c0552812b 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -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.