@@ -18,6 +18,8 @@ use rustc_span::symbol::{sym, Symbol};
18
18
19
19
use crate :: * ;
20
20
21
+ pub use crate :: threads:: { ThreadId , ThreadSet , ThreadLocalStorage } ;
22
+
21
23
// Some global facts about the emulated machine.
22
24
pub const PAGE_SIZE : u64 = 4 * 1024 ; // FIXME: adjust to target architecture
23
25
pub const STACK_ADDR : u64 = 32 * PAGE_SIZE ; // not really about the "stack", but where we start assigning integer addresses to allocations
@@ -74,6 +76,7 @@ pub struct AllocExtra {
74
76
pub struct MemoryExtra {
75
77
pub stacked_borrows : Option < stacked_borrows:: MemoryExtra > ,
76
78
pub intptrcast : intptrcast:: MemoryExtra ,
79
+ pub tls : ThreadLocalStorage ,
77
80
78
81
/// Mapping extern static names to their canonical allocation.
79
82
extern_statics : FxHashMap < Symbol , AllocId > ,
@@ -100,6 +103,7 @@ impl MemoryExtra {
100
103
extern_statics : FxHashMap :: default ( ) ,
101
104
rng : RefCell :: new ( rng) ,
102
105
tracked_alloc_id,
106
+ tls : Default :: default ( ) ,
103
107
}
104
108
}
105
109
@@ -147,7 +151,7 @@ impl MemoryExtra {
147
151
}
148
152
149
153
/// The machine itself.
150
- pub struct Evaluator < ' tcx > {
154
+ pub struct Evaluator < ' mir , ' tcx > {
151
155
/// Environment variables set by `setenv`.
152
156
/// Miri does not expose env vars from the host to the emulated program.
153
157
pub ( crate ) env_vars : EnvVars < ' tcx > ,
@@ -182,9 +186,11 @@ pub struct Evaluator<'tcx> {
182
186
183
187
/// The "time anchor" for this machine's monotone clock (for `Instant` simulation).
184
188
pub ( crate ) time_anchor : Instant ,
189
+
190
+ pub ( crate ) threads : ThreadSet < ' mir , ' tcx > ,
185
191
}
186
192
187
- impl < ' tcx > Evaluator < ' tcx > {
193
+ impl < ' mir , ' tcx > Evaluator < ' mir , ' tcx > {
188
194
pub ( crate ) fn new ( communicate : bool , validate : bool ) -> Self {
189
195
Evaluator {
190
196
// `env_vars` could be initialized properly here if `Memory` were available before
@@ -201,12 +207,13 @@ impl<'tcx> Evaluator<'tcx> {
201
207
dir_handler : Default :: default ( ) ,
202
208
panic_payload : None ,
203
209
time_anchor : Instant :: now ( ) ,
210
+ threads : Default :: default ( ) ,
204
211
}
205
212
}
206
213
}
207
214
208
215
/// A rustc InterpCx for Miri.
209
- pub type MiriEvalContext < ' mir , ' tcx > = InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > ;
216
+ pub type MiriEvalContext < ' mir , ' tcx > = InterpCx < ' mir , ' tcx , Evaluator < ' mir , ' tcx > > ;
210
217
211
218
/// A little trait that's useful to be inherited by extension traits.
212
219
pub trait MiriEvalContextExt < ' mir , ' tcx > {
@@ -225,7 +232,7 @@ impl<'mir, 'tcx> MiriEvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx>
225
232
}
226
233
227
234
/// Machine hook implementations.
228
- impl < ' mir , ' tcx > Machine < ' mir , ' tcx > for Evaluator < ' tcx > {
235
+ impl < ' mir , ' tcx > Machine < ' mir , ' tcx > for Evaluator < ' mir , ' tcx > {
229
236
type MemoryKind = MiriMemoryKind ;
230
237
231
238
type FrameExtra = FrameData < ' tcx > ;
@@ -241,6 +248,19 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
241
248
242
249
const CHECK_ALIGN : bool = true ;
243
250
251
+ #[ inline( always) ]
252
+ fn stack < ' a > (
253
+ ecx : & ' a InterpCx < ' mir , ' tcx , Self >
254
+ ) -> & ' a [ Frame < ' mir , ' tcx , Self :: PointerTag , Self :: FrameExtra > ] {
255
+ ecx. active_thread_stack ( )
256
+ }
257
+
258
+ fn stack_mut < ' a > (
259
+ ecx : & ' a mut InterpCx < ' mir , ' tcx , Self >
260
+ ) -> & ' a mut Vec < Frame < ' mir , ' tcx , Self :: PointerTag , Self :: FrameExtra > > {
261
+ ecx. active_thread_stack_mut ( )
262
+ }
263
+
244
264
#[ inline( always) ]
245
265
fn enforce_validity ( ecx : & InterpCx < ' mir , ' tcx , Self > ) -> bool {
246
266
ecx. machine . validate
@@ -333,29 +353,39 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
333
353
334
354
fn canonical_alloc_id ( mem : & Memory < ' mir , ' tcx , Self > , id : AllocId ) -> AllocId {
335
355
let tcx = mem. tcx ;
336
- // Figure out if this is an extern static, and if yes, which one.
337
- let def_id = match tcx. alloc_map . lock ( ) . get ( id) {
338
- Some ( GlobalAlloc :: Static ( def_id) ) if tcx. is_foreign_item ( def_id) => def_id,
356
+ let alloc = tcx. alloc_map . lock ( ) . get ( id) ;
357
+ match alloc {
358
+ Some ( GlobalAlloc :: Static ( def_id) ) if tcx. is_foreign_item ( def_id) => {
359
+ // Figure out if this is an extern static, and if yes, which one.
360
+ let attrs = tcx. get_attrs ( def_id) ;
361
+ let link_name = match attr:: first_attr_value_str_by_name ( & attrs, sym:: link_name) {
362
+ Some ( name) => name,
363
+ None => tcx. item_name ( def_id) ,
364
+ } ;
365
+ // Check if we know this one.
366
+ if let Some ( canonical_id) = mem. extra . extern_statics . get ( & link_name) {
367
+ trace ! ( "canonical_alloc_id: {:?} ({}) -> {:?}" , id, link_name, canonical_id) ;
368
+ * canonical_id
369
+ } else {
370
+ // Return original id; `Memory::get_static_alloc` will throw an error.
371
+ id
372
+ }
373
+ } ,
374
+ Some ( GlobalAlloc :: Static ( def_id) ) if tcx. has_attr ( def_id, sym:: thread_local) => {
375
+ // We have a thread local, so we need to get a unique allocation id for it.
376
+ mem. extra . tls . get_or_register_allocation ( * tcx, id)
377
+ } ,
339
378
_ => {
340
379
// No need to canonicalize anything.
341
- return id ;
380
+ id
342
381
}
343
- } ;
344
- let attrs = tcx. get_attrs ( def_id) ;
345
- let link_name = match attr:: first_attr_value_str_by_name ( & attrs, sym:: link_name) {
346
- Some ( name) => name,
347
- None => tcx. item_name ( def_id) ,
348
- } ;
349
- // Check if we know this one.
350
- if let Some ( canonical_id) = mem. extra . extern_statics . get ( & link_name) {
351
- trace ! ( "canonical_alloc_id: {:?} ({}) -> {:?}" , id, link_name, canonical_id) ;
352
- * canonical_id
353
- } else {
354
- // Return original id; `Memory::get_static_alloc` will throw an error.
355
- id
356
382
}
357
383
}
358
384
385
+ fn resolve_thread_local_allocation_id ( extra : & Self :: MemoryExtra , id : AllocId ) -> AllocId {
386
+ extra. tls . resolve_allocation ( id)
387
+ }
388
+
359
389
fn init_allocation_extra < ' b > (
360
390
memory_extra : & MemoryExtra ,
361
391
id : AllocId ,
0 commit comments