Skip to content

Commit

Permalink
TLS on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Jul 16, 2018
1 parent 216b8f7 commit e1a3b96
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
30 changes: 29 additions & 1 deletion src/fn_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
}

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

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

// Windows TLS
"TlsAlloc" => {
// This just creates a key; Windows does not natively support TLS dtors.

// Figure out how large a TLS key actually is. This is c::DWORD.
let key_size = self.layout_of(dest_ty)?.size;

// Create key and return it
let key = self.memory.create_tls_key(None) as u128;
if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) {
return err!(OutOfTls);
}
self.write_scalar(dest, Scalar::from_u128(key), dest_ty)?;
}
"TlsGetValue" => {
let key = self.value_to_scalar(args[0])?.to_bytes()?;
let ptr = self.memory.load_tls(key)?;
self.write_ptr(dest, ptr, dest_ty)?;
}
"TlsSetValue" => {
let key = self.value_to_scalar(args[0])?.to_bytes()?;
let new_ptr = self.into_ptr(args[1].value)?;
self.memory.store_tls(key, new_ptr)?;

// Return success (1)
self.write_scalar(dest, Scalar::from_u128(1), dest_ty)?;
}

// We can't execute anything else
_ => {
return err!(Unimplemented(
Expand Down
20 changes: 18 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,12 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
main_id: DefId,
start_wrapper: Option<DefId>,
) -> EvalResult<'tcx, (EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>, Option<Pointer>)> {
let mut ecx = EvalContext::new(tcx.at(syntax::codemap::DUMMY_SP), ty::ParamEnv::reveal_all(), Default::default(), Default::default());
let mut ecx = EvalContext::new(
tcx.at(syntax::codemap::DUMMY_SP),
ty::ParamEnv::reveal_all(),
Default::default(),
MemoryData::new()
);

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

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

impl<'tcx> MemoryData<'tcx> {
fn new() -> Self {
MemoryData {
next_thread_local: 1, // start with 1 as we must not use 0 on Windows
thread_local: BTreeMap::new(),
locks: HashMap::new(),
statics: HashMap::new(),
}
}
}

impl<'tcx> Hash for MemoryData<'tcx> {
fn hash<H: Hasher>(&self, state: &mut H) {
let MemoryData {
Expand Down
1 change: 1 addition & 0 deletions src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
None => self.memory.fetch_tls_dtor(None)?,
};
}
// FIXME: On a windows target, call `unsafe extern "system" fn on_tls_callback`.
Ok(())
}
}

0 comments on commit e1a3b96

Please sign in to comment.