Skip to content

Commit 89696a4

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents 4d76dd1 + 16d791b commit 89696a4

File tree

5 files changed

+57
-37
lines changed

5 files changed

+57
-37
lines changed

src/helpers.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4343
})
4444
}
4545

46+
/// Write a 0 of the appropriate size to `dest`.
47+
fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
48+
self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
49+
}
50+
51+
/// Test if this immediate equals 0.
52+
fn is_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, bool> {
53+
let this = self.eval_context_ref();
54+
let null = Scalar::from_int(0, this.memory().pointer_size());
55+
this.ptr_eq(val, null)
56+
}
57+
58+
/// Turn a Scalar into an Option<NonNullScalar>
59+
fn test_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, Option<Scalar<Tag>>> {
60+
let this = self.eval_context_ref();
61+
Ok(if this.is_null(val)? {
62+
None
63+
} else {
64+
Some(val)
65+
})
66+
}
67+
4668
/// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
4769
/// will be true if this is frozen, false if this is in an `UnsafeCell`.
4870
fn visit_freeze_sensitive(

src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ extern crate rustc_target;
1515
mod shims;
1616
mod operator;
1717
mod helpers;
18-
mod tls;
1918
mod range_map;
2019
mod mono_hash_map;
2120
mod stacked_borrows;
@@ -31,8 +30,8 @@ pub use rustc_mir::interpret::{self, AllocMap, PlaceTy};
3130
pub use crate::shims::{EvalContextExt as ShimsEvalContextExt};
3231
pub use crate::shims::foreign_items::EvalContextExt as ForeignItemsEvalContextExt;
3332
pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
33+
pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
3434
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
35-
pub use crate::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
3635
pub use crate::range_map::RangeMap;
3736
pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};
3837
pub use crate::mono_hash_map::MonoHashMap;

src/shims/foreign_items.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4949
ptr: Scalar<Tag>,
5050
) -> InterpResult<'tcx> {
5151
let this = self.eval_context_mut();
52-
if !ptr.is_null_ptr(this) {
52+
if !this.is_null(ptr)? {
5353
let ptr = this.force_ptr(ptr)?;
5454
this.memory_mut().deallocate(
5555
ptr,
@@ -67,7 +67,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6767
) -> InterpResult<'tcx, Scalar<Tag>> {
6868
let this = self.eval_context_mut();
6969
let align = this.min_align();
70-
if old_ptr.is_null_ptr(this) {
70+
if this.is_null(old_ptr)? {
7171
if new_size == 0 {
7272
Ok(Scalar::from_int(0, this.pointer_size()))
7373
} else {
@@ -429,7 +429,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
429429
let mut success = None;
430430
{
431431
let name_ptr = this.read_scalar(args[0])?.not_undef()?;
432-
if !name_ptr.is_null_ptr(this) {
432+
if !this.is_null(name_ptr)? {
433433
let name_ptr = name_ptr.to_ptr()?;
434434
let name = this
435435
.memory()
@@ -457,7 +457,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
457457
let name_ptr = this.read_scalar(args[0])?.not_undef()?;
458458
let value_ptr = this.read_scalar(args[1])?.to_ptr()?;
459459
let value = this.memory().get(value_ptr.alloc_id)?.read_c_str(tcx, value_ptr)?;
460-
if !name_ptr.is_null_ptr(this) {
460+
if !this.is_null(name_ptr)? {
461461
let name_ptr = name_ptr.to_ptr()?;
462462
let name = this.memory().get(name_ptr.alloc_id)?.read_c_str(tcx, name_ptr)?;
463463
if !name.is_empty() && !name.contains(&b'=') {
@@ -640,14 +640,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
640640
let key_ptr = this.read_scalar(args[0])?.not_undef()?;
641641

642642
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
643-
let dtor = match this.read_scalar(args[1])?.not_undef()? {
644-
Scalar::Ptr(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr)?),
645-
Scalar::Raw { data: 0, size } => {
646-
// NULL pointer
647-
assert_eq!(size as u64, this.memory().pointer_size().bytes());
648-
None
649-
},
650-
Scalar::Raw { .. } => return err!(ReadBytesAsPointer),
643+
let dtor = match this.test_null(this.read_scalar(args[1])?.not_undef()?)? {
644+
Some(dtor_ptr) => Some(this.memory().get_fn(dtor_ptr.to_ptr()?)?),
645+
None => None,
651646
};
652647

653648
// Figure out how large a pthread TLS key actually is.
@@ -659,7 +654,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
659654
let key_layout = this.layout_of(key_type)?;
660655

661656
// Create key and write it into the memory where `key_ptr` wants it.
662-
let key = this.machine.tls.create_tls_key(dtor, tcx) as u128;
657+
let key = this.machine.tls.create_tls_key(dtor) as u128;
663658
if key_layout.size.bits() < 128 && key >= (1u128 << key_layout.size.bits() as u128) {
664659
return err!(OutOfTls);
665660
}
@@ -684,13 +679,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
684679
}
685680
"pthread_getspecific" => {
686681
let key = this.read_scalar(args[0])?.to_bits(args[0].layout.size)?;
687-
let ptr = this.machine.tls.load_tls(key)?;
682+
let ptr = this.machine.tls.load_tls(key, tcx)?;
688683
this.write_scalar(ptr, dest)?;
689684
}
690685
"pthread_setspecific" => {
691686
let key = this.read_scalar(args[0])?.to_bits(args[0].layout.size)?;
692687
let new_ptr = this.read_scalar(args[1])?.not_undef()?;
693-
this.machine.tls.store_tls(key, new_ptr)?;
688+
this.machine.tls.store_tls(key, this.test_null(new_ptr)?)?;
694689

695690
// Return success (`0`).
696691
this.write_null(dest)?;
@@ -844,7 +839,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
844839
// This just creates a key; Windows does not natively support TLS destructors.
845840

846841
// Create key and return it.
847-
let key = this.machine.tls.create_tls_key(None, tcx) as u128;
842+
let key = this.machine.tls.create_tls_key(None) as u128;
848843

849844
// Figure out how large a TLS key actually is. This is `c::DWORD`.
850845
if dest.layout.size.bits() < 128
@@ -855,13 +850,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
855850
}
856851
"TlsGetValue" => {
857852
let key = this.read_scalar(args[0])?.to_u32()? as u128;
858-
let ptr = this.machine.tls.load_tls(key)?;
853+
let ptr = this.machine.tls.load_tls(key, tcx)?;
859854
this.write_scalar(ptr, dest)?;
860855
}
861856
"TlsSetValue" => {
862857
let key = this.read_scalar(args[0])?.to_u32()? as u128;
863858
let new_ptr = this.read_scalar(args[1])?.not_undef()?;
864-
this.machine.tls.store_tls(key, new_ptr)?;
859+
this.machine.tls.store_tls(key, this.test_null(new_ptr)?)?;
865860

866861
// Return success (`1`).
867862
this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
@@ -938,10 +933,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
938933
Ok(())
939934
}
940935

941-
fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
942-
self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
943-
}
944-
945936
/// Evaluates the scalar at the specified path. Returns Some(val)
946937
/// if the path could be resolved, and None otherwise
947938
fn eval_path_scalar(&mut self, path: &[&str]) -> InterpResult<'tcx, Option<ScalarMaybeUndef<Tag>>> {

src/shims/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod foreign_items;
22
pub mod intrinsics;
3+
pub mod tls;
34

45
use rustc::{ty, mir};
56

src/tls.rs renamed to src/shims/tls.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@ use rustc::{ty, ty::layout::HasDataLayout, mir};
66
use crate::{
77
InterpResult, InterpError, StackPopCleanup,
88
MPlaceTy, Scalar, Tag,
9+
HelpersEvalContextExt,
910
};
1011

1112
pub type TlsKey = u128;
1213

1314
#[derive(Copy, Clone, Debug)]
1415
pub struct TlsEntry<'tcx> {
15-
pub(crate) data: Scalar<Tag>, // Will eventually become a map from thread IDs to `Scalar`s, if we ever support more than one thread.
16+
/// The data for this key. None is used to represent NULL.
17+
/// (We normalize this early to avoid having to do a NULL-ptr-test each time we access the data.)
18+
/// Will eventually become a map from thread IDs to `Scalar`s, if we ever support more than one thread.
19+
pub(crate) data: Option<Scalar<Tag>>,
1620
pub(crate) dtor: Option<ty::Instance<'tcx>>,
1721
}
1822

@@ -38,14 +42,13 @@ impl<'tcx> TlsData<'tcx> {
3842
pub fn create_tls_key(
3943
&mut self,
4044
dtor: Option<ty::Instance<'tcx>>,
41-
cx: &impl HasDataLayout,
4245
) -> TlsKey {
4346
let new_key = self.next_key;
4447
self.next_key += 1;
4548
self.keys.insert(
4649
new_key,
4750
TlsEntry {
48-
data: Scalar::ptr_null(cx).into(),
51+
data: None,
4952
dtor,
5053
},
5154
);
@@ -63,17 +66,21 @@ impl<'tcx> TlsData<'tcx> {
6366
}
6467
}
6568

66-
pub fn load_tls(&mut self, key: TlsKey) -> InterpResult<'tcx, Scalar<Tag>> {
69+
pub fn load_tls(
70+
&mut self,
71+
key: TlsKey,
72+
cx: &impl HasDataLayout,
73+
) -> InterpResult<'tcx, Scalar<Tag>> {
6774
match self.keys.get(&key) {
6875
Some(&TlsEntry { data, .. }) => {
6976
trace!("TLS key {} loaded: {:?}", key, data);
70-
Ok(data)
77+
Ok(data.unwrap_or_else(|| Scalar::ptr_null(cx).into()))
7178
}
7279
None => err!(TlsOutOfBounds),
7380
}
7481
}
7582

76-
pub fn store_tls(&mut self, key: TlsKey, new_data: Scalar<Tag>) -> InterpResult<'tcx> {
83+
pub fn store_tls(&mut self, key: TlsKey, new_data: Option<Scalar<Tag>>) -> InterpResult<'tcx> {
7784
match self.keys.get_mut(&key) {
7885
Some(&mut TlsEntry { ref mut data, .. }) => {
7986
trace!("TLS key {} stored: {:?}", key, new_data);
@@ -105,7 +112,6 @@ impl<'tcx> TlsData<'tcx> {
105112
fn fetch_tls_dtor(
106113
&mut self,
107114
key: Option<TlsKey>,
108-
cx: &impl HasDataLayout,
109115
) -> Option<(ty::Instance<'tcx>, Scalar<Tag>, TlsKey)> {
110116
use std::collections::Bound::*;
111117

@@ -117,10 +123,10 @@ impl<'tcx> TlsData<'tcx> {
117123
for (&key, &mut TlsEntry { ref mut data, dtor }) in
118124
thread_local.range_mut((start, Unbounded))
119125
{
120-
if !data.is_null_ptr(cx) {
126+
if let Some(data_scalar) = *data {
121127
if let Some(dtor) = dtor {
122-
let ret = Some((dtor, *data, key));
123-
*data = Scalar::ptr_null(cx);
128+
let ret = Some((dtor, data_scalar, key));
129+
*data = None;
124130
return ret;
125131
}
126132
}
@@ -133,10 +139,11 @@ impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tc
133139
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
134140
fn run_tls_dtors(&mut self) -> InterpResult<'tcx> {
135141
let this = self.eval_context_mut();
136-
let mut dtor = this.machine.tls.fetch_tls_dtor(None, &*this.tcx);
142+
let mut dtor = this.machine.tls.fetch_tls_dtor(None);
137143
// FIXME: replace loop by some structure that works with stepping
138144
while let Some((instance, ptr, key)) = dtor {
139145
trace!("Running TLS dtor {:?} on {:?}", instance, ptr);
146+
assert!(!this.is_null(ptr).unwrap(), "Data can't be NULL when dtor is called!");
140147
// TODO: Potentially, this has to support all the other possible instances?
141148
// See eval_fn_call in interpret/terminator/mod.rs
142149
let mir = this.load_mir(instance.def)?;
@@ -157,9 +164,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
157164
// step until out of stackframes
158165
this.run()?;
159166

160-
dtor = match this.machine.tls.fetch_tls_dtor(Some(key), &*this.tcx) {
167+
dtor = match this.machine.tls.fetch_tls_dtor(Some(key)) {
161168
dtor @ Some(_) => dtor,
162-
None => this.machine.tls.fetch_tls_dtor(None, &*this.tcx),
169+
None => this.machine.tls.fetch_tls_dtor(None),
163170
};
164171
}
165172
// FIXME: On a windows target, call `unsafe extern "system" fn on_tls_callback`.

0 commit comments

Comments
 (0)