diff options
| author | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2017-07-31 13:30:44 +0200 |
|---|---|---|
| committer | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2017-08-01 09:56:21 +0200 |
| commit | 23d351d6d496d61f859da9676a4c72c0be9643ea (patch) | |
| tree | e1165c6b908d48e02b545b38effb59f1d3cbe385 | |
| parent | adfea61665385428b9c9aced9442dba65464c3c8 (diff) | |
| download | rust-23d351d6d496d61f859da9676a4c72c0be9643ea.tar.gz rust-23d351d6d496d61f859da9676a4c72c0be9643ea.zip | |
Move tls code to its own file
| -rw-r--r-- | miri/fn_call.rs | 3 | ||||
| -rw-r--r-- | miri/lib.rs | 91 | ||||
| -rw-r--r-- | miri/tls.rs | 94 |
3 files changed, 101 insertions, 87 deletions
diff --git a/miri/fn_call.rs b/miri/fn_call.rs index cf3464ce3af..bef37c57981 100644 --- a/miri/fn_call.rs +++ b/miri/fn_call.rs @@ -12,9 +12,10 @@ use rustc_miri::interpret::*; use super::{ TlsKey, EvalContext, - MemoryExt, }; +use tls::MemoryExt; + use super::memory::Kind; pub trait EvalContextExt<'tcx> { diff --git a/miri/lib.rs b/miri/lib.rs index 89985593bc7..ab63ff7f29e 100644 --- a/miri/lib.rs +++ b/miri/lib.rs @@ -33,10 +33,12 @@ mod operator; mod intrinsic; mod helpers; mod memory; +mod tls; use fn_call::EvalContextExt as MissingFnsEvalContextExt; use operator::EvalContextExt as OperatorEvalContextExt; use intrinsic::EvalContextExt as IntrinsicEvalContextExt; +use tls::MemoryExt as TlsMemoryExt; pub fn eval_main<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -165,7 +167,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, Evaluator> { // FIXME: replace loop by some structure that works with stepping while let Some((instance, ptr, key)) = dtor { trace!("Running TLS dtor {:?} on {:?}", instance, ptr); - // TODO: Potentially, this has to support all the other possible instances? See eval_fn_call in terminator/mod.rs + // TODO: Potentially, this has to support all the other possible instances? + // See eval_fn_call in interpret/terminator/mod.rs let mir = self.load_mir(instance.def)?; self.push_stack_frame( instance, @@ -191,91 +194,6 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, Evaluator> { } } -trait MemoryExt<'tcx> { - fn create_tls_key(&mut self, dtor: Option<ty::Instance<'tcx>>) -> TlsKey; - fn delete_tls_key(&mut self, key: TlsKey) -> EvalResult<'tcx>; - fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Pointer>; - fn store_tls(&mut self, key: TlsKey, new_data: Pointer) -> EvalResult<'tcx>; - fn fetch_tls_dtor(&mut self, key: Option<TlsKey>) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Pointer, TlsKey)>>; -} - -impl<'a, 'tcx: 'a> MemoryExt<'tcx> for Memory<'a, 'tcx, Evaluator> { - fn create_tls_key(&mut self, dtor: Option<ty::Instance<'tcx>>) -> TlsKey { - let new_key = self.data.next_thread_local; - self.data.next_thread_local += 1; - self.data.thread_local.insert(new_key, TlsEntry { data: Pointer::null(), dtor }); - trace!("New TLS key allocated: {} with dtor {:?}", new_key, dtor); - return new_key; - } - - fn delete_tls_key(&mut self, key: TlsKey) -> EvalResult<'tcx> { - return match self.data.thread_local.remove(&key) { - Some(_) => { - trace!("TLS key {} removed", key); - Ok(()) - }, - None => Err(EvalError::TlsOutOfBounds) - } - } - - fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Pointer> { - return match self.data.thread_local.get(&key) { - Some(&TlsEntry { data, .. }) => { - trace!("TLS key {} loaded: {:?}", key, data); - Ok(data) - }, - None => Err(EvalError::TlsOutOfBounds) - } - } - - fn store_tls(&mut self, key: TlsKey, new_data: Pointer) -> EvalResult<'tcx> { - return match self.data.thread_local.get_mut(&key) { - Some(&mut TlsEntry { ref mut data, .. }) => { - trace!("TLS key {} stored: {:?}", key, new_data); - *data = new_data; - Ok(()) - }, - None => Err(EvalError::TlsOutOfBounds) - } - } - - /// Returns a dtor, its argument and its index, if one is supposed to run - /// - /// An optional destructor function may be associated with each key value. - /// At thread exit, if a key value has a non-NULL destructor pointer, - /// and the thread has a non-NULL value associated with that key, - /// the value of the key is set to NULL, and then the function pointed - /// to is called with the previously associated value as its sole argument. - /// The order of destructor calls is unspecified if more than one destructor - /// exists for a thread when it exits. - /// - /// If, after all the destructors have been called for all non-NULL values - /// with associated destructors, there are still some non-NULL values with - /// associated destructors, then the process is repeated. - /// If, after at least {PTHREAD_DESTRUCTOR_ITERATIONS} iterations of destructor - /// calls for outstanding non-NULL values, there are still some non-NULL values - /// with associated destructors, implementations may stop calling destructors, - /// or they may continue calling destructors until no non-NULL values with - /// associated destructors exist, even though this might result in an infinite loop. - fn fetch_tls_dtor(&mut self, key: Option<TlsKey>) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Pointer, TlsKey)>> { - use std::collections::Bound::*; - let start = match key { - Some(key) => Excluded(key), - None => Unbounded, - }; - for (&key, &mut TlsEntry { ref mut data, dtor }) in self.data.thread_local.range_mut((start, Unbounded)) { - if !data.is_null()? { - if let Some(dtor) = dtor { - let ret = Some((dtor, *data, key)); - *data = Pointer::null(); - return Ok(ret); - } - } - } - return Ok(None); - } -} - impl<'tcx> Machine<'tcx> for Evaluator { type Data = EvaluatorData; type MemoryData = MemoryData<'tcx>; @@ -329,6 +247,7 @@ impl<'tcx> Machine<'tcx> for Evaluator { ecx: &mut EvalContext<'a, 'tcx, Self>, ty: ty::Ty<'tcx>, ) -> EvalResult<'tcx, PrimVal> { + // FIXME: call the `exchange_malloc` lang item if available let size = ecx.type_size(ty)?.expect("box only works with sized types"); let align = ecx.type_align(ty)?; if size == 0 { diff --git a/miri/tls.rs b/miri/tls.rs new file mode 100644 index 00000000000..035cd7f0aaf --- /dev/null +++ b/miri/tls.rs @@ -0,0 +1,94 @@ +use rustc::ty; + +use super::{ + TlsKey, TlsEntry, + EvalResult, EvalError, + Pointer, + Memory, + Evaluator, +}; + +pub trait MemoryExt<'tcx> { + fn create_tls_key(&mut self, dtor: Option<ty::Instance<'tcx>>) -> TlsKey; + fn delete_tls_key(&mut self, key: TlsKey) -> EvalResult<'tcx>; + fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Pointer>; + fn store_tls(&mut self, key: TlsKey, new_data: Pointer) -> EvalResult<'tcx>; + fn fetch_tls_dtor(&mut self, key: Option<TlsKey>) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Pointer, TlsKey)>>; +} + +impl<'a, 'tcx: 'a> MemoryExt<'tcx> for Memory<'a, 'tcx, Evaluator> { + fn create_tls_key(&mut self, dtor: Option<ty::Instance<'tcx>>) -> TlsKey { + let new_key = self.data.next_thread_local; + self.data.next_thread_local += 1; + self.data.thread_local.insert(new_key, TlsEntry { data: Pointer::null(), dtor }); + trace!("New TLS key allocated: {} with dtor {:?}", new_key, dtor); + return new_key; + } + + fn delete_tls_key(&mut self, key: TlsKey) -> EvalResult<'tcx> { + return match self.data.thread_local.remove(&key) { + Some(_) => { + trace!("TLS key {} removed", key); + Ok(()) + }, + None => Err(EvalError::TlsOutOfBounds) + } + } + + fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Pointer> { + return match self.data.thread_local.get(&key) { + Some(&TlsEntry { data, .. }) => { + trace!("TLS key {} loaded: {:?}", key, data); + Ok(data) + }, + None => Err(EvalError::TlsOutOfBounds) + } + } + + fn store_tls(&mut self, key: TlsKey, new_data: Pointer) -> EvalResult<'tcx> { + return match self.data.thread_local.get_mut(&key) { + Some(&mut TlsEntry { ref mut data, .. }) => { + trace!("TLS key {} stored: {:?}", key, new_data); + *data = new_data; + Ok(()) + }, + None => Err(EvalError::TlsOutOfBounds) + } + } + + /// Returns a dtor, its argument and its index, if one is supposed to run + /// + /// An optional destructor function may be associated with each key value. + /// At thread exit, if a key value has a non-NULL destructor pointer, + /// and the thread has a non-NULL value associated with that key, + /// the value of the key is set to NULL, and then the function pointed + /// to is called with the previously associated value as its sole argument. + /// The order of destructor calls is unspecified if more than one destructor + /// exists for a thread when it exits. + /// + /// If, after all the destructors have been called for all non-NULL values + /// with associated destructors, there are still some non-NULL values with + /// associated destructors, then the process is repeated. + /// If, after at least {PTHREAD_DESTRUCTOR_ITERATIONS} iterations of destructor + /// calls for outstanding non-NULL values, there are still some non-NULL values + /// with associated destructors, implementations may stop calling destructors, + /// or they may continue calling destructors until no non-NULL values with + /// associated destructors exist, even though this might result in an infinite loop. + fn fetch_tls_dtor(&mut self, key: Option<TlsKey>) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Pointer, TlsKey)>> { + use std::collections::Bound::*; + let start = match key { + Some(key) => Excluded(key), + None => Unbounded, + }; + for (&key, &mut TlsEntry { ref mut data, dtor }) in self.data.thread_local.range_mut((start, Unbounded)) { + if !data.is_null()? { + if let Some(dtor) = dtor { + let ret = Some((dtor, *data, key)); + *data = Pointer::null(); + return Ok(ret); + } + } + } + return Ok(None); + } +} |
