summaryrefslogtreecommitdiffstats
path: root/src/librustc_mir/interpret/step.rs
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-01-16 09:31:48 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:34:05 +0100
commitb33e4e784e9906c732dcb3e0b6872f65dc8f5597 (patch)
tree13e1196b1fb3c26f969d5f6e7e28003bf76e058e /src/librustc_mir/interpret/step.rs
parentPrepare for using miri in trans (diff)
downloadgrust-b33e4e784e9906c732dcb3e0b6872f65dc8f5597.tar.gz
grust-b33e4e784e9906c732dcb3e0b6872f65dc8f5597.tar.bz2
grust-b33e4e784e9906c732dcb3e0b6872f65dc8f5597.tar.xz
Fully use miri in trans
Diffstat (limited to 'src/librustc_mir/interpret/step.rs')
-rw-r--r--src/librustc_mir/interpret/step.rs241
1 files changed, 7 insertions, 234 deletions
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 2b0f9041d5..21e81ff668 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -2,21 +2,12 @@
2//! 2//!
3//! The main entry point is the `step` method. 3//! The main entry point is the `step` method.
4 4
5use rustc::hir;
6use rustc::mir::visit::{Visitor, PlaceContext};
7use rustc::mir; 5use rustc::mir;
8use rustc::ty::{self, Instance};
9use rustc::ty::layout::LayoutOf;
10use rustc::middle::const_val::ConstVal;
11use rustc::mir::interpret::GlobalId;
12 6
13use rustc::mir::interpret::{EvalResult, EvalErrorKind}; 7use rustc::mir::interpret::EvalResult;
14use super::{EvalContext, StackPopCleanup, Place, Machine}; 8use super::{EvalContext, Machine};
15 9
16use syntax::codemap::Span; 10impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
17use syntax::ast::Mutability;
18
19impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
20 pub fn inc_step_counter_and_check_limit(&mut self, n: u64) -> EvalResult<'tcx> { 11 pub fn inc_step_counter_and_check_limit(&mut self, n: u64) -> EvalResult<'tcx> {
21 self.steps_remaining = self.steps_remaining.saturating_sub(n); 12 self.steps_remaining = self.steps_remaining.saturating_sub(n);
22 if self.steps_remaining > 0 { 13 if self.steps_remaining > 0 {
@@ -41,52 +32,14 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
41 let old_frames = self.cur_frame(); 32 let old_frames = self.cur_frame();
42 33
43 if let Some(stmt) = basic_block.statements.get(stmt_id) { 34 if let Some(stmt) = basic_block.statements.get(stmt_id) {
44 let mut new = Ok(false); 35 assert_eq!(old_frames, self.cur_frame());
45 ConstantExtractor { 36 self.statement(stmt)?;
46 span: stmt.source_info.span,
47 instance: self.frame().instance,
48 ecx: self,
49 mir,
50 new_constant: &mut new,
51 }.visit_statement(
52 block,
53 stmt,
54 mir::Location {
55 block,
56 statement_index: stmt_id,
57 },
58 );
59 // if ConstantExtractor added a new frame, we don't execute anything here
60 // but await the next call to step
61 if !new? {
62 assert_eq!(old_frames, self.cur_frame());
63 self.statement(stmt)?;
64 }
65 return Ok(true); 37 return Ok(true);
66 } 38 }
67 39
68 let terminator = basic_block.terminator(); 40 let terminator = basic_block.terminator();
69 let mut new = Ok(false); 41 assert_eq!(old_frames, self.cur_frame());
70 ConstantExtractor { 42 self.terminator(terminator)?;
71 span: terminator.source_info.span,
72 instance: self.frame().instance,
73 ecx: self,
74 mir,
75 new_constant: &mut new,
76 }.visit_terminator(
77 block,
78 terminator,
79 mir::Location {
80 block,
81 statement_index: stmt_id,
82 },
83 );
84 // if ConstantExtractor added a new frame, we don't execute anything here
85 // but await the next call to step
86 if !new? {
87 assert_eq!(old_frames, self.cur_frame());
88 self.terminator(terminator)?;
89 }
90 Ok(true) 43 Ok(true)
91 } 44 }
92 45
@@ -152,184 +105,4 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
152 } 105 }
153 Ok(()) 106 Ok(())
154 } 107 }
155
156 /// returns `true` if a stackframe was pushed
157 fn global_item(
158 &mut self,
159 instance: Instance<'tcx>,
160 span: Span,
161 mutability: Mutability,
162 ) -> EvalResult<'tcx, bool> {
163 debug!("global_item: {:?}", instance);
164 let cid = GlobalId {
165 instance,
166 promoted: None,
167 };
168 if self.tcx.interpret_interner.borrow().get_cached(cid).is_some() {
169 return Ok(false);
170 }
171 if self.tcx.has_attr(instance.def_id(), "linkage") {
172 M::global_item_with_linkage(self, cid.instance, mutability)?;
173 return Ok(false);
174 }
175 let instance_ty = instance.ty(self.tcx);
176 let layout = self.layout_of(instance_ty)?;
177 assert!(!layout.is_unsized());
178 let ptr = self.memory.allocate(
179 layout.size.bytes(),
180 layout.align,
181 None,
182 )?;
183 self.tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
184 let internally_mutable = !layout.ty.is_freeze(self.tcx, self.param_env, span);
185 let mutability = if mutability == Mutability::Mutable || internally_mutable {
186 Mutability::Mutable
187 } else {
188 Mutability::Immutable
189 };
190 let cleanup = StackPopCleanup::MarkStatic(mutability);
191 let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
192 trace!("pushing stack frame for global: {}", name);
193 let mir = self.load_mir(instance.def)?;
194 self.push_stack_frame(
195 instance,
196 span,
197 mir,
198 Place::from_ptr(ptr, layout.align),
199 cleanup,
200 )?;
201 Ok(true)
202 }
203}
204
205struct ConstantExtractor<'a, 'b: 'a, 'tcx: 'b, M: Machine<'tcx> + 'a> {
206 span: Span,
207 ecx: &'a mut EvalContext<'b, 'tcx, M>,
208 mir: &'tcx mir::Mir<'tcx>,
209 instance: ty::Instance<'tcx>,
210 // Whether a stackframe for a new constant has been pushed
211 new_constant: &'a mut EvalResult<'tcx, bool>,
212}
213
214impl<'a, 'b, 'tcx, M: Machine<'tcx>> ConstantExtractor<'a, 'b, 'tcx, M> {
215 fn try<F: FnOnce(&mut Self) -> EvalResult<'tcx, bool>>(&mut self, f: F) {
216 match *self.new_constant {
217 // already computed a constant, don't do more than one per iteration
218 Ok(true) => {},
219 // no constants computed yet
220 Ok(false) => *self.new_constant = f(self),
221 // error happened, abort the visitor traversing
222 Err(_) => {},
223 }
224 }
225}
226
227impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx, M> {
228 fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: mir::Location) {
229 self.super_constant(constant, location);
230 self.try(|this| {
231 match constant.literal {
232 // already computed by rustc
233 mir::Literal::Value { value: &ty::Const { val: ConstVal::Unevaluated(def_id, substs), .. } } => {
234 debug!("global_item: {:?}, {:#?}", def_id, substs);
235 let substs = this.ecx.tcx.trans_apply_param_substs(this.instance.substs, &substs);
236 debug!("global_item_new_substs: {:#?}", substs);
237 debug!("global_item_param_env: {:#?}", this.ecx.param_env);
238 let instance = Instance::resolve(
239 this.ecx.tcx,
240 this.ecx.param_env,
241 def_id,
242 substs,
243 ).ok_or(EvalErrorKind::TypeckError)?; // turn error prop into a panic to expose associated type in const issue
244 this.ecx.global_item(
245 instance,
246 constant.span,
247 Mutability::Immutable,
248 )
249 }
250 mir::Literal::Value { .. } => Ok(false),
251 mir::Literal::Promoted { index } => {
252 let cid = GlobalId {
253 instance: this.instance,
254 promoted: Some(index),
255 };
256 if this.ecx.tcx.interpret_interner.borrow().get_cached(cid).is_some() {
257 return Ok(false);
258 }
259 let mir = &this.mir.promoted[index];
260 let ty = this.ecx.monomorphize(mir.return_ty(), this.instance.substs);
261 let layout = this.ecx.layout_of(ty)?;
262 assert!(!layout.is_unsized());
263 let ptr = this.ecx.memory.allocate(
264 layout.size.bytes(),
265 layout.align,
266 None,
267 )?;
268 this.ecx.tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
269 trace!("pushing stack frame for {:?}", index);
270 this.ecx.push_stack_frame(
271 this.instance,
272 constant.span,
273 mir,
274 Place::from_ptr(ptr, layout.align),
275 StackPopCleanup::MarkStatic(Mutability::Immutable),
276 )?;
277 Ok(true)
278 }
279 }
280 });
281 }
282
283 fn visit_place(
284 &mut self,
285 place: &mir::Place<'tcx>,
286 context: PlaceContext<'tcx>,
287 location: mir::Location,
288 ) {
289 self.super_place(place, context, location);
290 self.try(|this| {
291 if let mir::Place::Static(ref static_) = *place {
292 let def_id = static_.def_id;
293 let span = this.span;
294 if let Some(node_item) = this.ecx.tcx.hir.get_if_local(def_id) {
295 if let hir::map::Node::NodeItem(&hir::Item { ref node, .. }) = node_item {
296 if let hir::ItemStatic(_, m, _) = *node {
297 let instance = Instance::mono(this.ecx.tcx, def_id);
298 this.ecx.global_item(
299 instance,
300 span,
301 if m == hir::MutMutable {
302 Mutability::Mutable
303 } else {
304 Mutability::Immutable
305 },
306 )
307 } else {
308 bug!("static def id doesn't point to static");
309 }
310 } else {
311 bug!("static def id doesn't point to item");
312 }
313 } else {
314 let def = this.ecx.tcx.describe_def(def_id).expect("static not found");
315 if let hir::def::Def::Static(_, mutable) = def {
316 let instance = Instance::mono(this.ecx.tcx, def_id);
317 this.ecx.global_item(
318 instance,
319 span,
320 if mutable {
321 Mutability::Mutable
322 } else {
323 Mutability::Immutable
324 },
325 )
326 } else {
327 bug!("static found but isn't a static: {:?}", def);
328 }
329 }
330 } else {
331 Ok(false)
332 }
333 });
334 }
335} 108}