Skip to content

Commit e1a3b96

Browse files
committed
TLS on Windows
1 parent 216b8f7 commit e1a3b96

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

src/fn_call.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
607607
}
608608

609609
"_tlv_atexit" => {
610-
return err!(Unimplemented("can't interpret with full mir for osx target".to_owned()));
610+
return err!(Unimplemented("Thread-local store is not fully supported on macOS".to_owned()));
611611
},
612612

613613
// Stub out all the other pthread calls to just return 0
@@ -643,6 +643,34 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
643643
self.write_scalar(dest, Scalar::from_u128(120), dest_ty)?;
644644
},
645645

646+
// Windows TLS
647+
"TlsAlloc" => {
648+
// This just creates a key; Windows does not natively support TLS dtors.
649+
650+
// Figure out how large a TLS key actually is. This is c::DWORD.
651+
let key_size = self.layout_of(dest_ty)?.size;
652+
653+
// Create key and return it
654+
let key = self.memory.create_tls_key(None) as u128;
655+
if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) {
656+
return err!(OutOfTls);
657+
}
658+
self.write_scalar(dest, Scalar::from_u128(key), dest_ty)?;
659+
}
660+
"TlsGetValue" => {
661+
let key = self.value_to_scalar(args[0])?.to_bytes()?;
662+
let ptr = self.memory.load_tls(key)?;
663+
self.write_ptr(dest, ptr, dest_ty)?;
664+
}
665+
"TlsSetValue" => {
666+
let key = self.value_to_scalar(args[0])?.to_bytes()?;
667+
let new_ptr = self.into_ptr(args[1].value)?;
668+
self.memory.store_tls(key, new_ptr)?;
669+
670+
// Return success (1)
671+
self.write_scalar(dest, Scalar::from_u128(1), dest_ty)?;
672+
}
673+
646674
// We can't execute anything else
647675
_ => {
648676
return err!(Unimplemented(

src/lib.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,12 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
141141
main_id: DefId,
142142
start_wrapper: Option<DefId>,
143143
) -> EvalResult<'tcx, (EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>, Option<Pointer>)> {
144-
let mut ecx = EvalContext::new(tcx.at(syntax::codemap::DUMMY_SP), ty::ParamEnv::reveal_all(), Default::default(), Default::default());
144+
let mut ecx = EvalContext::new(
145+
tcx.at(syntax::codemap::DUMMY_SP),
146+
ty::ParamEnv::reveal_all(),
147+
Default::default(),
148+
MemoryData::new()
149+
);
145150

146151
let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
147152
let main_mir = ecx.load_mir(main_instance.def)?;
@@ -338,7 +343,7 @@ pub struct TlsEntry<'tcx> {
338343
dtor: Option<ty::Instance<'tcx>>,
339344
}
340345

341-
#[derive(Clone, Default, PartialEq, Eq)]
346+
#[derive(Clone, PartialEq, Eq)]
342347
pub struct MemoryData<'tcx> {
343348
/// The Key to use for the next thread-local allocation.
344349
next_thread_local: TlsKey,
@@ -355,6 +360,17 @@ pub struct MemoryData<'tcx> {
355360
statics: HashMap<GlobalId<'tcx>, AllocId>,
356361
}
357362

363+
impl<'tcx> MemoryData<'tcx> {
364+
fn new() -> Self {
365+
MemoryData {
366+
next_thread_local: 1, // start with 1 as we must not use 0 on Windows
367+
thread_local: BTreeMap::new(),
368+
locks: HashMap::new(),
369+
statics: HashMap::new(),
370+
}
371+
}
372+
}
373+
358374
impl<'tcx> Hash for MemoryData<'tcx> {
359375
fn hash<H: Hasher>(&self, state: &mut H) {
360376
let MemoryData {

src/tls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
139139
None => self.memory.fetch_tls_dtor(None)?,
140140
};
141141
}
142+
// FIXME: On a windows target, call `unsafe extern "system" fn on_tls_callback`.
142143
Ok(())
143144
}
144145
}

0 commit comments

Comments
 (0)