@@ -25,6 +25,8 @@ use rustc_target::abi::{LayoutOf, Size};
2525
2626use crate :: * ;
2727
28+ pub use crate :: threads:: { ThreadId , ThreadSet , ThreadLocalStorage } ;
29+
2830// Some global facts about the emulated machine.
2931pub const PAGE_SIZE : u64 = 4 * 1024 ; // FIXME: adjust to target architecture
3032pub const STACK_ADDR : u64 = 32 * PAGE_SIZE ; // not really about the "stack", but where we start assigning integer addresses to allocations
@@ -81,6 +83,7 @@ pub struct AllocExtra {
8183pub struct MemoryExtra {
8284 pub stacked_borrows : Option < stacked_borrows:: MemoryExtra > ,
8385 pub intptrcast : intptrcast:: MemoryExtra ,
86+ pub tls : ThreadLocalStorage ,
8487
8588 /// Mapping extern static names to their canonical allocation.
8689 extern_statics : FxHashMap < Symbol , AllocId > ,
@@ -107,6 +110,7 @@ impl MemoryExtra {
107110 extern_statics : FxHashMap :: default ( ) ,
108111 rng : RefCell :: new ( rng) ,
109112 tracked_alloc_id,
113+ tls : Default :: default ( ) ,
110114 }
111115 }
112116
@@ -169,7 +173,7 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
169173}
170174
171175/// The machine itself.
172- pub struct Evaluator < ' tcx > {
176+ pub struct Evaluator < ' mir , ' tcx > {
173177 /// Environment variables set by `setenv`.
174178 /// Miri does not expose env vars from the host to the emulated program.
175179 pub ( crate ) env_vars : EnvVars < ' tcx > ,
@@ -205,6 +209,9 @@ pub struct Evaluator<'tcx> {
205209 /// The "time anchor" for this machine's monotone clock (for `Instant` simulation).
206210 pub ( crate ) time_anchor : Instant ,
207211
212+ /// The set of threads.
213+ pub ( crate ) threads : ThreadSet < ' mir , ' tcx > ,
214+
208215 /// Precomputed `TyLayout`s for primitive data types that are commonly used inside Miri.
209216 /// FIXME: Search through the rest of the codebase for more layout_of() calls that
210217 /// could be stored here.
@@ -235,12 +242,13 @@ impl<'tcx> Evaluator<'tcx> {
235242 panic_payload : None ,
236243 time_anchor : Instant :: now ( ) ,
237244 layouts,
245+ threads : Default :: default ( ) ,
238246 }
239247 }
240248}
241249
242250/// A rustc InterpCx for Miri.
243- pub type MiriEvalContext < ' mir , ' tcx > = InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ;
251+ pub type MiriEvalContext < ' mir , ' tcx > = InterpCx < ' mir , ' tcx , Evaluator < ' mir , ' tcx > > ;
244252
245253/// A little trait that's useful to be inherited by extension traits.
246254pub trait MiriEvalContextExt < ' mir , ' tcx > {
@@ -259,7 +267,7 @@ impl<'mir, 'tcx> MiriEvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx>
259267}
260268
261269/// Machine hook implementations.
262- impl < ' mir , ' tcx > Machine < ' mir , ' tcx > for Evaluator < ' tcx > {
270+ impl < ' mir , ' tcx > Machine < ' mir , ' tcx > for Evaluator < ' mir , ' tcx > {
263271 type MemoryKind = MiriMemoryKind ;
264272
265273 type FrameExtra = FrameData < ' tcx > ;
@@ -275,6 +283,19 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
275283
276284 const CHECK_ALIGN : bool = true ;
277285
286+ #[ inline( always) ]
287+ fn stack < ' a > (
288+ ecx : & ' a InterpCx < ' mir , ' tcx , Self >
289+ ) -> & ' a [ Frame < ' mir , ' tcx , Self :: PointerTag , Self :: FrameExtra > ] {
290+ ecx. active_thread_stack ( )
291+ }
292+
293+ fn stack_mut < ' a > (
294+ ecx : & ' a mut InterpCx < ' mir , ' tcx , Self >
295+ ) -> & ' a mut Vec < Frame < ' mir , ' tcx , Self :: PointerTag , Self :: FrameExtra > > {
296+ ecx. active_thread_stack_mut ( )
297+ }
298+
278299 #[ inline( always) ]
279300 fn enforce_validity ( ecx : & InterpCx < ' mir , ' tcx , Self > ) -> bool {
280301 ecx. machine . validate
@@ -367,29 +388,39 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
367388
368389 fn canonical_alloc_id ( mem : & Memory < ' mir , ' tcx , Self > , id : AllocId ) -> AllocId {
369390 let tcx = mem. tcx ;
370- // Figure out if this is an extern static, and if yes, which one.
371- let def_id = match tcx. alloc_map . lock ( ) . get ( id) {
372- Some ( GlobalAlloc :: Static ( def_id) ) if tcx. is_foreign_item ( def_id) => def_id,
391+ let alloc = tcx. alloc_map . lock ( ) . get ( id) ;
392+ match alloc {
393+ Some ( GlobalAlloc :: Static ( def_id) ) if tcx. is_foreign_item ( def_id) => {
394+ // Figure out if this is an extern static, and if yes, which one.
395+ let attrs = tcx. get_attrs ( def_id) ;
396+ let link_name = match attr:: first_attr_value_str_by_name ( & attrs, sym:: link_name) {
397+ Some ( name) => name,
398+ None => tcx. item_name ( def_id) ,
399+ } ;
400+ // Check if we know this one.
401+ if let Some ( canonical_id) = mem. extra . extern_statics . get ( & link_name) {
402+ trace ! ( "canonical_alloc_id: {:?} ({}) -> {:?}" , id, link_name, canonical_id) ;
403+ * canonical_id
404+ } else {
405+ // Return original id; `Memory::get_static_alloc` will throw an error.
406+ id
407+ }
408+ } ,
409+ Some ( GlobalAlloc :: Static ( def_id) ) if tcx. has_attr ( def_id, sym:: thread_local) => {
410+ // We have a thread local, so we need to get a unique allocation id for it.
411+ mem. extra . tls . get_or_register_allocation ( * tcx, id)
412+ } ,
373413 _ => {
374414 // No need to canonicalize anything.
375- return id ;
415+ id
376416 }
377- } ;
378- let attrs = tcx. get_attrs ( def_id) ;
379- let link_name = match attr:: first_attr_value_str_by_name ( & attrs, sym:: link_name) {
380- Some ( name) => name,
381- None => tcx. item_name ( def_id) ,
382- } ;
383- // Check if we know this one.
384- if let Some ( canonical_id) = mem. extra . extern_statics . get ( & link_name) {
385- trace ! ( "canonical_alloc_id: {:?} ({}) -> {:?}" , id, link_name, canonical_id) ;
386- * canonical_id
387- } else {
388- // Return original id; `Memory::get_static_alloc` will throw an error.
389- id
390417 }
391418 }
392419
420+ fn resolve_thread_local_allocation_id ( extra : & Self :: MemoryExtra , id : AllocId ) -> AllocId {
421+ extra. tls . resolve_allocation ( id)
422+ }
423+
393424 fn init_allocation_extra < ' b > (
394425 memory_extra : & MemoryExtra ,
395426 id : AllocId ,
0 commit comments