Move the global_item function to the EvalContext

This commit is contained in:
Oliver Schneider 2017-07-27 12:02:16 +02:00
parent 960dca172d
commit 728bb878ac
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
2 changed files with 62 additions and 54 deletions

View file

@ -5,6 +5,7 @@ license = "MIT/Apache-2.0"
name = "rustc_miri"
repository = "https://github.com/solson/miri"
version = "0.1.0"
workspace = "../.."
[lib]
test = false

View file

@ -155,6 +155,49 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
}
Ok(())
}
/// returns `true` if a stackframe was pushed
fn global_item(
&mut self,
def_id: DefId,
substs: &'tcx Substs<'tcx>,
span: Span,
mutability: Mutability,
) -> EvalResult<'tcx, bool> {
let instance = self.resolve_associated_const(def_id, substs);
let cid = GlobalId { instance, promoted: None };
if self.globals.contains_key(&cid) {
return Ok(false);
}
if self.tcx.has_attr(def_id, "linkage") {
// FIXME: check that it's `#[linkage = "extern_weak"]`
trace!("Initializing an extern global with NULL");
self.globals.insert(cid, Global::initialized(self.tcx.type_of(def_id), Value::ByVal(PrimVal::Bytes(0)), mutability));
return Ok(false);
}
let mir = self.load_mir(instance.def)?;
self.globals.insert(cid, Global::uninitialized(mir.return_ty));
let internally_mutable = !mir.return_ty.is_freeze(
self.tcx,
ty::ParamEnv::empty(Reveal::All),
span);
let mutability = if mutability == Mutability::Mutable || internally_mutable {
Mutability::Mutable
} else {
Mutability::Immutable
};
let cleanup = StackPopCleanup::MarkStatic(mutability);
let name = ty::tls::with(|tcx| tcx.item_path_str(def_id));
trace!("pushing stack frame for global: {}", name);
self.push_stack_frame(
instance,
span,
mir,
Lvalue::Global(cid),
cleanup,
)?;
Ok(true)
}
}
// WARNING: make sure that any methods implemented on this type don't ever access ecx.stack
@ -170,56 +213,19 @@ struct ConstantExtractor<'a, 'b: 'a, 'tcx: 'b, M: Machine<'tcx> + 'a> {
}
impl<'a, 'b, 'tcx, M: Machine<'tcx>> ConstantExtractor<'a, 'b, 'tcx, M> {
fn global_item(
&mut self,
def_id: DefId,
substs: &'tcx Substs<'tcx>,
span: Span,
mutability: Mutability,
) {
let instance = self.ecx.resolve_associated_const(def_id, substs);
let cid = GlobalId { instance, promoted: None };
if self.ecx.globals.contains_key(&cid) {
return;
}
if self.ecx.tcx.has_attr(def_id, "linkage") {
trace!("Initializing an extern global with NULL");
self.ecx.globals.insert(cid, Global::initialized(self.ecx.tcx.type_of(def_id), Value::ByVal(PrimVal::Bytes(0)), mutability));
return;
}
self.try(|this| {
let mir = this.ecx.load_mir(instance.def)?;
this.ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
let internally_mutable = !mir.return_ty.is_freeze(
this.ecx.tcx,
ty::ParamEnv::empty(Reveal::All),
span);
let mutability = if mutability == Mutability::Mutable || internally_mutable {
Mutability::Mutable
} else {
Mutability::Immutable
};
let cleanup = StackPopCleanup::MarkStatic(mutability);
let name = ty::tls::with(|tcx| tcx.item_path_str(def_id));
trace!("pushing stack frame for global: {}", name);
this.ecx.push_stack_frame(
instance,
span,
mir,
Lvalue::Global(cid),
cleanup,
)
});
}
fn try<F: FnOnce(&mut Self) -> EvalResult<'tcx>>(&mut self, f: F) {
if let Ok(ref mut n) = *self.new_constants {
*n += 1;
} else {
return;
}
if let Err(e) = f(self) {
*self.new_constants = Err(e);
fn try<F: FnOnce(&mut Self) -> EvalResult<'tcx, bool>>(&mut self, f: F) {
// previous constant errored
let n = match *self.new_constants {
Ok(n) => n,
Err(_) => return,
};
match f(self) {
// everything ok + a new stackframe
Ok(true) => *self.new_constants = Ok(n + 1),
// constant correctly evaluated, but no new stackframe
Ok(false) => {},
// constant eval errored
Err(err) => *self.new_constants = Err(err),
}
}
}
@ -231,7 +237,7 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
// already computed by rustc
mir::Literal::Value { .. } => {}
mir::Literal::Item { def_id, substs } => {
self.global_item(def_id, substs, constant.span, Mutability::Immutable);
self.try(|this| this.ecx.global_item(def_id, substs, constant.span, Mutability::Immutable));
},
mir::Literal::Promoted { index } => {
let cid = GlobalId {
@ -251,7 +257,8 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
mir,
Lvalue::Global(cid),
StackPopCleanup::MarkStatic(Mutability::Immutable),
)
)?;
Ok(true)
});
}
}
@ -271,7 +278,7 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
if let Some(node_item) = self.ecx.tcx.hir.get_if_local(def_id) {
if let hir::map::Node::NodeItem(&hir::Item { ref node, .. }) = node_item {
if let hir::ItemStatic(_, m, _) = *node {
self.global_item(def_id, substs, span, if m == hir::MutMutable { Mutability::Mutable } else { Mutability::Immutable });
self.try(|this| this.ecx.global_item(def_id, substs, span, if m == hir::MutMutable { Mutability::Mutable } else { Mutability::Immutable }));
return;
} else {
bug!("static def id doesn't point to static");
@ -282,7 +289,7 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
} else {
let def = self.ecx.tcx.describe_def(def_id).expect("static not found");
if let hir::def::Def::Static(_, mutable) = def {
self.global_item(def_id, substs, span, if mutable { Mutability::Mutable } else { Mutability::Immutable });
self.try(|this| this.ecx.global_item(def_id, substs, span, if mutable { Mutability::Mutable } else { Mutability::Immutable }));
} else {
bug!("static found but isn't a static: {:?}", def);
}