@@ -22,6 +22,8 @@ use rustc_span::{source_map::Span, symbol::{sym, Symbol}};
2222
2323use crate :: * ;
2424
25+ pub use crate :: threads:: { ThreadId , ThreadSet , ThreadLocalStorage } ;
26+
2527// Some global facts about the emulated machine.
2628pub const PAGE_SIZE : u64 = 4 * 1024 ; // FIXME: adjust to target architecture
2729pub const STACK_ADDR : u64 = 32 * PAGE_SIZE ; // not really about the "stack", but where we start assigning integer addresses to allocations
@@ -78,6 +80,7 @@ pub struct AllocExtra {
7880pub struct MemoryExtra {
7981 pub stacked_borrows : Option < stacked_borrows:: MemoryExtra > ,
8082 pub intptrcast : intptrcast:: MemoryExtra ,
83+ pub tls : ThreadLocalStorage ,
8184
8285 /// Mapping extern static names to their canonical allocation.
8386 extern_statics : FxHashMap < Symbol , AllocId > ,
@@ -104,6 +107,7 @@ impl MemoryExtra {
104107 extern_statics : FxHashMap :: default ( ) ,
105108 rng : RefCell :: new ( rng) ,
106109 tracked_alloc_id,
110+ tls : Default :: default ( ) ,
107111 }
108112 }
109113
@@ -151,7 +155,7 @@ impl MemoryExtra {
151155}
152156
153157/// The machine itself.
154- pub struct Evaluator < ' tcx > {
158+ pub struct Evaluator < ' mir , ' tcx > {
155159 /// Environment variables set by `setenv`.
156160 /// Miri does not expose env vars from the host to the emulated program.
157161 pub ( crate ) env_vars : EnvVars < ' tcx > ,
@@ -186,9 +190,11 @@ pub struct Evaluator<'tcx> {
186190
187191 /// The "time anchor" for this machine's monotone clock (for `Instant` simulation).
188192 pub ( crate ) time_anchor : Instant ,
193+
194+ pub ( crate ) threads : ThreadSet < ' mir , ' tcx > ,
189195}
190196
191- impl < ' tcx > Evaluator < ' tcx > {
197+ impl < ' mir , ' tcx > Evaluator < ' mir , ' tcx > {
192198 pub ( crate ) fn new ( communicate : bool , validate : bool ) -> Self {
193199 Evaluator {
194200 // `env_vars` could be initialized properly here if `Memory` were available before
@@ -205,12 +211,13 @@ impl<'tcx> Evaluator<'tcx> {
205211 dir_handler : Default :: default ( ) ,
206212 panic_payload : None ,
207213 time_anchor : Instant :: now ( ) ,
214+ threads : Default :: default ( ) ,
208215 }
209216 }
210217}
211218
212219/// A rustc InterpCx for Miri.
213- pub type MiriEvalContext < ' mir , ' tcx > = InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ;
220+ pub type MiriEvalContext < ' mir , ' tcx > = InterpCx < ' mir , ' tcx , Evaluator < ' mir , ' tcx > > ;
214221
215222/// A little trait that's useful to be inherited by extension traits.
216223pub trait MiriEvalContextExt < ' mir , ' tcx > {
@@ -229,7 +236,7 @@ impl<'mir, 'tcx> MiriEvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx>
229236}
230237
231238/// Machine hook implementations.
232- impl < ' mir , ' tcx > Machine < ' mir , ' tcx > for Evaluator < ' tcx > {
239+ impl < ' mir , ' tcx > Machine < ' mir , ' tcx > for Evaluator < ' mir , ' tcx > {
233240 type MemoryKind = MiriMemoryKind ;
234241
235242 type FrameExtra = FrameData < ' tcx > ;
@@ -245,6 +252,19 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
245252
246253 const CHECK_ALIGN : bool = true ;
247254
255+ #[ inline( always) ]
256+ fn stack < ' a > (
257+ ecx : & ' a InterpCx < ' mir , ' tcx , Self >
258+ ) -> & ' a [ Frame < ' mir , ' tcx , Self :: PointerTag , Self :: FrameExtra > ] {
259+ ecx. active_thread_stack ( )
260+ }
261+
262+ fn stack_mut < ' a > (
263+ ecx : & ' a mut InterpCx < ' mir , ' tcx , Self >
264+ ) -> & ' a mut Vec < Frame < ' mir , ' tcx , Self :: PointerTag , Self :: FrameExtra > > {
265+ ecx. active_thread_stack_mut ( )
266+ }
267+
248268 #[ inline( always) ]
249269 fn enforce_validity ( ecx : & InterpCx < ' mir , ' tcx , Self > ) -> bool {
250270 ecx. machine . validate
@@ -339,29 +359,39 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
339359
340360 fn canonical_alloc_id ( mem : & Memory < ' mir , ' tcx , Self > , id : AllocId ) -> AllocId {
341361 let tcx = mem. tcx ;
342- // Figure out if this is an extern static, and if yes, which one.
343- let def_id = match tcx. alloc_map . lock ( ) . get ( id) {
344- Some ( GlobalAlloc :: Static ( def_id) ) if tcx. is_foreign_item ( def_id) => def_id,
362+ let alloc = tcx. alloc_map . lock ( ) . get ( id) ;
363+ match alloc {
364+ Some ( GlobalAlloc :: Static ( def_id) ) if tcx. is_foreign_item ( def_id) => {
365+ // Figure out if this is an extern static, and if yes, which one.
366+ let attrs = tcx. get_attrs ( def_id) ;
367+ let link_name = match attr:: first_attr_value_str_by_name ( & attrs, sym:: link_name) {
368+ Some ( name) => name,
369+ None => tcx. item_name ( def_id) ,
370+ } ;
371+ // Check if we know this one.
372+ if let Some ( canonical_id) = mem. extra . extern_statics . get ( & link_name) {
373+ trace ! ( "canonical_alloc_id: {:?} ({}) -> {:?}" , id, link_name, canonical_id) ;
374+ * canonical_id
375+ } else {
376+ // Return original id; `Memory::get_static_alloc` will throw an error.
377+ id
378+ }
379+ } ,
380+ Some ( GlobalAlloc :: Static ( def_id) ) if tcx. has_attr ( def_id, sym:: thread_local) => {
381+ // We have a thread local, so we need to get a unique allocation id for it.
382+ mem. extra . tls . get_or_register_allocation ( * tcx, id)
383+ } ,
345384 _ => {
346385 // No need to canonicalize anything.
347- return id ;
386+ id
348387 }
349- } ;
350- let attrs = tcx. get_attrs ( def_id) ;
351- let link_name = match attr:: first_attr_value_str_by_name ( & attrs, sym:: link_name) {
352- Some ( name) => name,
353- None => tcx. item_name ( def_id) ,
354- } ;
355- // Check if we know this one.
356- if let Some ( canonical_id) = mem. extra . extern_statics . get ( & link_name) {
357- trace ! ( "canonical_alloc_id: {:?} ({}) -> {:?}" , id, link_name, canonical_id) ;
358- * canonical_id
359- } else {
360- // Return original id; `Memory::get_static_alloc` will throw an error.
361- id
362388 }
363389 }
364390
391+ fn resolve_thread_local_allocation_id ( extra : & Self :: MemoryExtra , id : AllocId ) -> AllocId {
392+ extra. tls . resolve_allocation ( id)
393+ }
394+
365395 fn init_allocation_extra < ' b > (
366396 memory_extra : & MemoryExtra ,
367397 id : AllocId ,
0 commit comments