Move the global_item function to the EvalContext
This commit is contained in:
parent
960dca172d
commit
728bb878ac
2 changed files with 62 additions and 54 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue