Skip to content

Commit 981d272

Browse files
committed
update for ptr provenance
1 parent 317f905 commit 981d272

File tree

3 files changed

+113
-9
lines changed

3 files changed

+113
-9
lines changed

src/intrinsic.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
252252
_ => {
253253
// Do it in memory
254254
let mplace = self.force_allocation(dest)?;
255-
assert!(mplace.extra.is_none());
255+
assert!(mplace.meta.is_none());
256256
self.memory.write_repeat(mplace.ptr, 0, dest.layout.size)?;
257257
}
258258
}
@@ -410,7 +410,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
410410
_ => {
411411
// Do it in memory
412412
let mplace = self.force_allocation(dest)?;
413-
assert!(mplace.extra.is_none());
413+
assert!(mplace.meta.is_none());
414414
self.memory.mark_definedness(mplace.ptr.to_ptr()?, dest.layout.size, false)?;
415415
}
416416
}

src/lib.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ extern crate rustc_mir;
1313
extern crate rustc_target;
1414
extern crate syntax;
1515

16+
use std::collections::HashMap;
17+
use std::borrow::Cow;
18+
1619
use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
1720
use rustc::ty::layout::{TyLayout, LayoutOf, Size};
1821
use rustc::hir::def_id::DefId;
@@ -21,11 +24,10 @@ use rustc::mir;
2124
use syntax::ast::Mutability;
2225
use syntax::attr;
2326

24-
use std::collections::HashMap;
2527

2628
pub use rustc::mir::interpret::*;
2729
pub use rustc_mir::interpret::*;
28-
pub use rustc_mir::interpret;
30+
pub use rustc_mir::interpret::{self, AllocMap}; // resolve ambiguity
2931

3032
mod fn_call;
3133
mod operator;
@@ -34,13 +36,15 @@ mod helpers;
3436
mod tls;
3537
mod locks;
3638
mod range_map;
39+
mod mono_hash_map;
3740

3841
use fn_call::EvalContextExt as MissingFnsEvalContextExt;
3942
use operator::EvalContextExt as OperatorEvalContextExt;
4043
use intrinsic::EvalContextExt as IntrinsicEvalContextExt;
4144
use tls::{EvalContextExt as TlsEvalContextExt, TlsData};
4245
use range_map::RangeMap;
4346
use helpers::FalibleScalarExt;
47+
use mono_hash_map::MonoHashMap;
4448

4549
pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
4650
tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -231,8 +235,11 @@ pub struct Evaluator<'tcx> {
231235
impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
232236
type MemoryData = ();
233237
type MemoryKinds = MiriMemoryKind;
238+
type PointerTag = (); // still WIP
234239

235-
const MUT_STATIC_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::MutStatic);
240+
type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<()>)>;
241+
242+
const STATIC_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::MutStatic);
236243

237244
/// Returns Ok() when the function was handled, fail otherwise
238245
fn find_fn(
@@ -307,7 +314,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
307314
fn find_foreign_static(
308315
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
309316
def_id: DefId,
310-
) -> EvalResult<'tcx, &'tcx Allocation> {
317+
) -> EvalResult<'tcx, Cow<'tcx, Allocation>> {
311318
let attrs = tcx.get_attrs(def_id);
312319
let link_name = match attr::first_attr_value_str_by_name(&attrs, "link_name") {
313320
Some(name) => name.as_str(),
@@ -318,14 +325,13 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
318325
"__cxa_thread_atexit_impl" => {
319326
// This should be all-zero, pointer-sized
320327
let data = vec![0; tcx.data_layout.pointer_size.bytes() as usize];
321-
let alloc = Allocation::from_bytes(&data[..], tcx.data_layout.pointer_align);
322-
tcx.intern_const_alloc(alloc)
328+
Allocation::from_bytes(&data[..], tcx.data_layout.pointer_align)
323329
}
324330
_ => return err!(Unimplemented(
325331
format!("can't access foreign static: {}", link_name),
326332
)),
327333
};
328-
Ok(alloc)
334+
Ok(Cow::Owned(alloc))
329335
}
330336

331337
fn validation_op(
@@ -343,4 +349,11 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
343349
// We are not interested in detecting loops
344350
Ok(())
345351
}
352+
353+
fn static_with_default_tag(
354+
alloc: &'_ Allocation
355+
) -> Cow<'_, Allocation<Self::PointerTag>> {
356+
let alloc = alloc.clone();
357+
Cow::Owned(alloc)
358+
}
346359
}

src/mono_hash_map.rs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//! This is a "monotonic HashMap": A HashMap that, when shared, can be pushed to but not
2+
//! otherwise mutated. We also Box items in the map. This means we can safely provide
3+
//! shared references into existing items in the HashMap, because they will not be dropped
4+
//! (from being removed) or moved (because they are boxed).
5+
//! The API is is completely tailored to what `memory.rs` needs. It is still in
6+
//! a separate file to minimize the amount of code that has to care about the unsafety.
7+
8+
use std::collections::hash_map::Entry;
9+
use std::cell::RefCell;
10+
use std::hash::Hash;
11+
use std::borrow::Borrow;
12+
13+
use rustc_data_structures::fx::FxHashMap;
14+
15+
use super::AllocMap;
16+
17+
#[derive(Debug, Clone)]
18+
pub struct MonoHashMap<K: Hash + Eq, V>(RefCell<FxHashMap<K, Box<V>>>);
19+
20+
impl<K: Hash + Eq, V> Default for MonoHashMap<K, V> {
21+
fn default() -> Self {
22+
MonoHashMap(RefCell::new(Default::default()))
23+
}
24+
}
25+
26+
impl<K: Hash + Eq, V> AllocMap<K, V> for MonoHashMap<K, V> {
27+
#[inline(always)]
28+
fn contains_key<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> bool
29+
where K: Borrow<Q>
30+
{
31+
self.0.get_mut().contains_key(k)
32+
}
33+
34+
#[inline(always)]
35+
fn insert(&mut self, k: K, v: V) -> Option<V>
36+
{
37+
self.0.get_mut().insert(k, Box::new(v)).map(|x| *x)
38+
}
39+
40+
#[inline(always)]
41+
fn remove<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> Option<V>
42+
where K: Borrow<Q>
43+
{
44+
self.0.get_mut().remove(k).map(|x| *x)
45+
}
46+
47+
#[inline(always)]
48+
fn filter_map_collect<T>(&self, mut f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T> {
49+
self.0.borrow()
50+
.iter()
51+
.filter_map(move |(k, v)| f(k, &*v))
52+
.collect()
53+
}
54+
55+
/// The most interesting method: Providing a shared ref without
56+
/// holding the `RefCell` open, and inserting new data if the key
57+
/// is not used yet.
58+
/// `vacant` is called if the key is not found in the map;
59+
/// if it returns a reference, that is used directly, if it
60+
/// returns owned data, that is put into the map and returned.
61+
#[inline(always)]
62+
fn get_or<E>(
63+
&self,
64+
k: K,
65+
vacant: impl FnOnce() -> Result<V, E>
66+
) -> Result<&V, E> {
67+
let val: *const V = match self.0.borrow_mut().entry(k) {
68+
Entry::Occupied(entry) => &**entry.get(),
69+
Entry::Vacant(entry) => &**entry.insert(Box::new(vacant()?)),
70+
};
71+
// This is safe because `val` points into a `Box`, that we know will not move and
72+
// will also not be dropped as long as the shared reference `self` is live.
73+
unsafe { Ok(&*val) }
74+
}
75+
76+
#[inline(always)]
77+
fn get_mut_or<E>(
78+
&mut self,
79+
k: K,
80+
vacant: impl FnOnce() -> Result<V, E>
81+
) -> Result<&mut V, E>
82+
{
83+
match self.0.get_mut().entry(k) {
84+
Entry::Occupied(e) => Ok(e.into_mut()),
85+
Entry::Vacant(e) => {
86+
let v = vacant()?;
87+
Ok(e.insert(Box::new(v)))
88+
}
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)