]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/mod.rs
054fb5f458117b485b43ed5719b9830961ef1338
[rust.git] / src / librustc_mir / build / mod.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 use build;
13 use build::scope::{CachedBlock, DropKind};
14 use hair::cx::Cx;
15 use hair::{LintLevel, BindingMode, PatternKind};
16 use rustc::hir;
17 use rustc::hir::Node;
18 use rustc::hir::def_id::{DefId, LocalDefId};
19 use rustc::middle::region;
20 use rustc::mir::*;
21 use rustc::mir::visit::{MutVisitor, TyContext};
22 use rustc::ty::{self, Ty, TyCtxt};
23 use rustc::ty::subst::Substs;
24 use rustc::util::nodemap::NodeMap;
25 use rustc_target::spec::PanicStrategy;
26 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
27 use shim;
28 use std::mem;
29 use std::u32;
30 use rustc_target::spec::abi::Abi;
31 use syntax::ast;
32 use syntax::attr::{self, UnwindAttr};
33 use syntax::symbol::keywords;
34 use syntax_pos::Span;
35 use transform::MirSource;
36 use util as mir_util;
37
38 use super::lints;
39
40 /// Construct the MIR for a given def-id.
41 pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
42     let id = tcx.hir.as_local_node_id(def_id).unwrap();
43
44     // Figure out what primary body this item has.
45     let (body_id, return_ty_span) = match tcx.hir.get(id) {
46         Node::Variant(variant) =>
47             return create_constructor_shim(tcx, id, &variant.node.data),
48         Node::StructCtor(ctor) =>
49             return create_constructor_shim(tcx, id, ctor),
50
51         Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, decl, body_id, _, _), .. })
52         | Node::Item(hir::Item { node: hir::ItemKind::Fn(decl, _, _, body_id), .. })
53         | Node::ImplItem(
54             hir::ImplItem {
55                 node: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, body_id),
56                 ..
57             }
58         )
59         | Node::TraitItem(
60             hir::TraitItem {
61                 node: hir::TraitItemKind::Method(
62                     hir::MethodSig { decl, .. },
63                     hir::TraitMethod::Provided(body_id),
64                 ),
65                 ..
66             }
67         ) => {
68             (*body_id, decl.output.span())
69         }
70         Node::Item(hir::Item { node: hir::ItemKind::Static(ty, _, body_id), .. })
71         | Node::Item(hir::Item { node: hir::ItemKind::Const(ty, body_id), .. })
72         | Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Const(ty, body_id), .. })
73         | Node::TraitItem(
74             hir::TraitItem { node: hir::TraitItemKind::Const(ty, Some(body_id)), .. }
75         ) => {
76             (*body_id, ty.span)
77         }
78         Node::AnonConst(hir::AnonConst { body, id, .. }) => {
79             (*body, tcx.hir.span(*id))
80         }
81
82         _ => span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id),
83     };
84
85     tcx.infer_ctxt().enter(|infcx| {
86         let cx = Cx::new(&infcx, id);
87         let mut mir = if cx.tables().tainted_by_errors {
88             build::construct_error(cx, body_id)
89         } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind {
90             // fetch the fully liberated fn signature (that is, all bound
91             // types/lifetimes replaced)
92             let fn_hir_id = tcx.hir.node_to_hir_id(id);
93             let fn_sig = cx.tables().liberated_fn_sigs()[fn_hir_id].clone();
94             let fn_def_id = tcx.hir.local_def_id(id);
95
96             let ty = tcx.type_of(fn_def_id);
97             let mut abi = fn_sig.abi;
98             let implicit_argument = match ty.sty {
99                 ty::Closure(..) => {
100                     // HACK(eddyb) Avoid having RustCall on closures,
101                     // as it adds unnecessary (and wrong) auto-tupling.
102                     abi = Abi::Rust;
103                     Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
104                 }
105                 ty::Generator(..) => {
106                     let gen_ty = tcx.body_tables(body_id).node_id_to_type(fn_hir_id);
107                     Some(ArgInfo(gen_ty, None, None, None))
108                 }
109                 _ => None,
110             };
111
112             // FIXME: safety in closures
113             let safety = match fn_sig.unsafety {
114                 hir::Unsafety::Normal => Safety::Safe,
115                 hir::Unsafety::Unsafe => Safety::FnUnsafe,
116             };
117
118             let safety = match fn_sig.unsafety {
119                 hir::Unsafety::Normal => Safety::Safe,
120                 hir::Unsafety::Unsafe => {
121                     if tcx.is_min_const_fn(fn_def_id) => {
122                         // As specified in #55607, a `const unsafe fn` differs
123                         // from an `unsafe fn` in that its body is still considered
124                         // safe code by default.
125                         assert!(!implicit_argument.is_none());
126                         Safety::Safe
127                     } else {
128                         Safety::Unsafe
129                     }
130                 }
131             };
132
133             let body = tcx.hir.body(body_id);
134             let explicit_arguments =
135                 body.arguments
136                     .iter()
137                     .enumerate()
138                     .map(|(index, arg)| {
139                         let owner_id = tcx.hir.body_owner(body_id);
140                         let opt_ty_info;
141                         let self_arg;
142                         if let Some(ref fn_decl) = tcx.hir.fn_decl(owner_id) {
143                             let ty_hir_id = fn_decl.inputs[index].hir_id;
144                             let ty_span = tcx.hir.span(tcx.hir.hir_to_node_id(ty_hir_id));
145                             opt_ty_info = Some(ty_span);
146                             self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
147                                 match fn_decl.implicit_self {
148                                     hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm),
149                                     hir::ImplicitSelfKind::Mut => Some(ImplicitSelfKind::Mut),
150                                     hir::ImplicitSelfKind::ImmRef => Some(ImplicitSelfKind::ImmRef),
151                                     hir::ImplicitSelfKind::MutRef => Some(ImplicitSelfKind::MutRef),
152                                     _ => None,
153                                 }
154                             } else {
155                                 None
156                             };
157                         } else {
158                             opt_ty_info = None;
159                             self_arg = None;
160                         }
161                         ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
162                     });
163
164             let arguments = implicit_argument.into_iter().chain(explicit_arguments);
165
166             let (yield_ty, return_ty) = if body.is_generator {
167                 let gen_sig = match ty.sty {
168                     ty::Generator(gen_def_id, gen_substs, ..) =>
169                         gen_substs.sig(gen_def_id, tcx),
170                     _ =>
171                         span_bug!(tcx.hir.span(id), "generator w/o generator type: {:?}", ty),
172                 };
173                 (Some(gen_sig.yield_ty), gen_sig.return_ty)
174             } else {
175                 (None, fn_sig.output())
176             };
177
178             build::construct_fn(cx, id, arguments, safety, abi,
179                                 return_ty, yield_ty, return_ty_span, body)
180         } else {
181             build::construct_const(cx, body_id, return_ty_span)
182         };
183
184         // Convert the Mir to global types.
185         let mut globalizer = GlobalizeMir {
186             tcx,
187             span: mir.span
188         };
189         globalizer.visit_mir(&mut mir);
190         let mir = unsafe {
191             mem::transmute::<Mir, Mir<'tcx>>(mir)
192         };
193
194         mir_util::dump_mir(tcx, None, "mir_map", &0,
195                            MirSource::item(def_id), &mir, |_, _| Ok(()) );
196
197         lints::check(tcx, &mir, def_id);
198
199         mir
200     })
201 }
202
203 /// A pass to lift all the types and substitutions in a Mir
204 /// to the global tcx. Sadly, we don't have a "folder" that
205 /// can change 'tcx so we have to transmute afterwards.
206 struct GlobalizeMir<'a, 'gcx: 'a> {
207     tcx: TyCtxt<'a, 'gcx, 'gcx>,
208     span: Span
209 }
210
211 impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
212     fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
213         if let Some(lifted) = self.tcx.lift(ty) {
214             *ty = lifted;
215         } else {
216             span_bug!(self.span,
217                       "found type `{:?}` with inference types/regions in MIR",
218                       ty);
219         }
220     }
221
222     fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
223         if let Some(lifted) = self.tcx.lift(region) {
224             *region = lifted;
225         } else {
226             span_bug!(self.span,
227                       "found region `{:?}` with inference types/regions in MIR",
228                       region);
229         }
230     }
231
232     fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
233         if let Some(lifted) = self.tcx.lift(constant) {
234             *constant = lifted;
235         } else {
236             span_bug!(self.span,
237                       "found constant `{:?}` with inference types/regions in MIR",
238                       constant);
239         }
240     }
241
242     fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, _: Location) {
243         if let Some(lifted) = self.tcx.lift(substs) {
244             *substs = lifted;
245         } else {
246             span_bug!(self.span,
247                       "found substs `{:?}` with inference types/regions in MIR",
248                       substs);
249         }
250     }
251 }
252
253 fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
254                                      ctor_id: ast::NodeId,
255                                      v: &'tcx hir::VariantData)
256                                      -> Mir<'tcx>
257 {
258     let span = tcx.hir.span(ctor_id);
259     if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
260         tcx.infer_ctxt().enter(|infcx| {
261             let mut mir = shim::build_adt_ctor(&infcx, ctor_id, fields, span);
262
263             // Convert the Mir to global types.
264             let tcx = infcx.tcx.global_tcx();
265             let mut globalizer = GlobalizeMir {
266                 tcx,
267                 span: mir.span
268             };
269             globalizer.visit_mir(&mut mir);
270             let mir = unsafe {
271                 mem::transmute::<Mir, Mir<'tcx>>(mir)
272             };
273
274             mir_util::dump_mir(tcx, None, "mir_map", &0,
275                                MirSource::item(tcx.hir.local_def_id(ctor_id)),
276                                &mir, |_, _| Ok(()) );
277
278             mir
279         })
280     } else {
281         span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
282     }
283 }
284
285 ///////////////////////////////////////////////////////////////////////////
286 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
287
288 fn liberated_closure_env_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
289                                             closure_expr_id: ast::NodeId,
290                                             body_id: hir::BodyId)
291                                             -> Ty<'tcx> {
292     let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id);
293     let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
294
295     let (closure_def_id, closure_substs) = match closure_ty.sty {
296         ty::Closure(closure_def_id, closure_substs) => (closure_def_id, closure_substs),
297         _ => bug!("closure expr does not have closure type: {:?}", closure_ty)
298     };
299
300     let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap();
301     tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty)
302 }
303
304 #[derive(Debug, PartialEq, Eq)]
305 pub enum BlockFrame {
306     /// Evaluation is currently within a statement.
307     ///
308     /// Examples include:
309     ///  1. `EXPR;`
310     ///  2. `let _ = EXPR;`
311     ///  3. `let x = EXPR;`
312     Statement {
313         /// If true, then statement discards result from evaluating
314         /// the expression (such as examples 1 and 2 above).
315         ignores_expr_result: bool
316     },
317
318     /// Evaluation is currently within the tail expression of a block.
319     ///
320     /// Example: `{ STMT_1; STMT_2; EXPR }`
321     TailExpr {
322         /// If true, then the surrounding context of the block ignores
323         /// the result of evaluating the block's tail expression.
324         ///
325         /// Example: `let _ = { STMT_1; EXPR };`
326         tail_result_is_ignored: bool
327     },
328
329     /// Generic mark meaning that the block occurred as a subexpression
330     /// where the result might be used.
331     ///
332     /// Examples: `foo(EXPR)`, `match EXPR { ... }`
333     SubExpr,
334 }
335
336 impl BlockFrame {
337     fn is_tail_expr(&self) -> bool {
338         match *self {
339             BlockFrame::TailExpr { .. } => true,
340
341             BlockFrame::Statement { .. } |
342             BlockFrame::SubExpr => false,
343         }
344     }
345     fn is_statement(&self) -> bool {
346         match *self {
347             BlockFrame::Statement { .. } => true,
348
349             BlockFrame::TailExpr { .. } |
350             BlockFrame::SubExpr => false,
351         }
352     }
353  }
354
355 #[derive(Debug)]
356 struct BlockContext(Vec<BlockFrame>);
357
358 struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
359     hir: Cx<'a, 'gcx, 'tcx>,
360     cfg: CFG<'tcx>,
361
362     fn_span: Span,
363     arg_count: usize,
364
365     /// the current set of scopes, updated as we traverse;
366     /// see the `scope` module for more details
367     scopes: Vec<scope::Scope<'tcx>>,
368
369     /// the block-context: each time we build the code within an hair::Block,
370     /// we push a frame here tracking whether we are building a statement or
371     /// if we are pushing the tail expression of the block. This is used to
372     /// embed information in generated temps about whether they were created
373     /// for a block tail expression or not.
374     ///
375     /// It would be great if we could fold this into `self.scopes`
376     /// somehow; but right now I think that is very tightly tied to
377     /// the code generation in ways that we cannot (or should not)
378     /// start just throwing new entries onto that vector in order to
379     /// distinguish the context of EXPR1 from the context of EXPR2 in
380     /// `{ STMTS; EXPR1 } + EXPR2`
381     block_context: BlockContext,
382
383     /// The current unsafe block in scope, even if it is hidden by
384     /// a PushUnsafeBlock
385     unpushed_unsafe: Safety,
386
387     /// The number of `push_unsafe_block` levels in scope
388     push_unsafe_count: usize,
389
390     /// the current set of breakables; see the `scope` module for more
391     /// details
392     breakable_scopes: Vec<scope::BreakableScope<'tcx>>,
393
394     /// the vector of all scopes that we have created thus far;
395     /// we track this for debuginfo later
396     source_scopes: IndexVec<SourceScope, SourceScopeData>,
397     source_scope_local_data: IndexVec<SourceScope, SourceScopeLocalData>,
398     source_scope: SourceScope,
399
400     /// the guard-context: each time we build the guard expression for
401     /// a match arm, we push onto this stack, and then pop when we
402     /// finish building it.
403     guard_context: Vec<GuardFrame>,
404
405     /// Maps node ids of variable bindings to the `Local`s created for them.
406     /// (A match binding can have two locals; the 2nd is for the arm's guard.)
407     var_indices: NodeMap<LocalsForNode>,
408     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
409     upvar_decls: Vec<UpvarDecl>,
410     unit_temp: Option<Place<'tcx>>,
411
412     /// cached block with the RESUME terminator; this is created
413     /// when first set of cleanups are built.
414     cached_resume_block: Option<BasicBlock>,
415     /// cached block with the RETURN terminator
416     cached_return_block: Option<BasicBlock>,
417     /// cached block with the UNREACHABLE terminator
418     cached_unreachable_block: Option<BasicBlock>,
419 }
420
421 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
422     fn is_bound_var_in_guard(&self, id: ast::NodeId) -> bool {
423         self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
424     }
425
426     fn var_local_id(&self, id: ast::NodeId, for_guard: ForGuard) -> Local {
427         self.var_indices[&id].local_id(for_guard)
428     }
429 }
430
431 impl BlockContext {
432     fn new() -> Self { BlockContext(vec![]) }
433     fn push(&mut self, bf: BlockFrame) { self.0.push(bf); }
434     fn pop(&mut self) -> Option<BlockFrame> { self.0.pop() }
435
436     /// Traverses the frames on the BlockContext, searching for either
437     /// the first block-tail expression frame with no intervening
438     /// statement frame.
439     ///
440     /// Notably, this skips over `SubExpr` frames; this method is
441     /// meant to be used in the context of understanding the
442     /// relationship of a temp (created within some complicated
443     /// expression) with its containing expression, and whether the
444     /// value of that *containing expression* (not the temp!) is
445     /// ignored.
446     fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
447         for bf in self.0.iter().rev() {
448             match bf {
449                 BlockFrame::SubExpr => continue,
450                 BlockFrame::Statement { .. } => break,
451                 &BlockFrame::TailExpr { tail_result_is_ignored } =>
452                     return Some(BlockTailInfo { tail_result_is_ignored })
453             }
454         }
455
456         return None;
457     }
458
459     /// Looks at the topmost frame on the BlockContext and reports
460     /// whether its one that would discard a block tail result.
461     ///
462     /// Unlike `currently_within_ignored_tail_expression`, this does
463     /// *not* skip over `SubExpr` frames: here, we want to know
464     /// whether the block result itself is discarded.
465     fn currently_ignores_tail_results(&self) -> bool {
466         match self.0.last() {
467             // no context: conservatively assume result is read
468             None => false,
469
470             // sub-expression: block result feeds into some computation
471             Some(BlockFrame::SubExpr) => false,
472
473             // otherwise: use accumulated is_ignored state.
474             Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) |
475             Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
476         }
477     }
478 }
479
480 #[derive(Debug)]
481 enum LocalsForNode {
482     /// In the usual case, a node-id for an identifier maps to at most
483     /// one Local declaration.
484     One(Local),
485
486     /// The exceptional case is identifiers in a match arm's pattern
487     /// that are referenced in a guard of that match arm. For these,
488     /// we can have `2+k` Locals, where `k` is the number of candidate
489     /// patterns (separated by `|`) in the arm.
490     ///
491     /// * `for_arm_body` is the Local used in the arm body (which is
492     ///   just like the `One` case above),
493     ///
494     /// * `ref_for_guard` is the Local used in the arm's guard (which
495     ///   is a reference to a temp that is an alias of
496     ///   `for_arm_body`).
497     ///
498     /// * `vals_for_guard` is the `k` Locals; at most one of them will
499     ///   get initialized by the arm's execution, and after it is
500     ///   initialized, `ref_for_guard` will be assigned a reference to
501     ///   it.
502     ///
503     /// There reason we have `k` Locals rather than just 1 is to
504     /// accommodate some restrictions imposed by two-phase borrows,
505     /// which apply when we have a `ref mut` pattern.
506     ForGuard { vals_for_guard: Vec<Local>, ref_for_guard: Local, for_arm_body: Local },
507 }
508
509 #[derive(Debug)]
510 struct GuardFrameLocal {
511     id: ast::NodeId,
512 }
513
514 impl GuardFrameLocal {
515     fn new(id: ast::NodeId, _binding_mode: BindingMode) -> Self {
516         GuardFrameLocal {
517             id: id,
518         }
519     }
520 }
521
522 #[derive(Debug)]
523 struct GuardFrame {
524     /// These are the id's of names that are bound by patterns of the
525     /// arm of *this* guard.
526     ///
527     /// (Frames higher up the stack will have the id's bound in arms
528     /// further out, such as in a case like:
529     ///
530     /// match E1 {
531     ///      P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1,
532     /// }
533     ///
534     /// here, when building for FIXME
535     locals: Vec<GuardFrameLocal>,
536 }
537
538 /// ForGuard indicates whether we are talking about:
539 ///   1. the temp for a local binding used solely within guard expressions,
540 ///   2. the temp that holds reference to (1.), which is actually what the
541 ///      guard expressions see, or
542 ///   3. the temp for use outside of guard expressions.
543 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
544 enum ForGuard {
545     /// The `usize` identifies for which candidate pattern we want the
546     /// local binding. We keep a temp per-candidate to accommodate
547     /// two-phase borrows (see `LocalsForNode` documentation).
548     ValWithinGuard(usize),
549     RefWithinGuard,
550     OutsideGuard,
551 }
552
553 impl LocalsForNode {
554     fn local_id(&self, for_guard: ForGuard) -> Local {
555         match (self, for_guard) {
556             (&LocalsForNode::One(local_id), ForGuard::OutsideGuard) |
557             (&LocalsForNode::ForGuard { ref_for_guard: local_id, .. }, ForGuard::RefWithinGuard) |
558             (&LocalsForNode::ForGuard { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) =>
559                 local_id,
560
561             (&LocalsForNode::ForGuard { ref vals_for_guard, .. },
562              ForGuard::ValWithinGuard(pat_idx)) =>
563                 vals_for_guard[pat_idx],
564
565             (&LocalsForNode::One(_), ForGuard::ValWithinGuard(_)) |
566             (&LocalsForNode::One(_), ForGuard::RefWithinGuard) =>
567                 bug!("anything with one local should never be within a guard."),
568         }
569     }
570 }
571
572 struct CFG<'tcx> {
573     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
574 }
575
576 newtype_index! {
577     pub struct ScopeId { .. }
578 }
579
580 ///////////////////////////////////////////////////////////////////////////
581 /// The `BlockAnd` "monad" packages up the new basic block along with a
582 /// produced value (sometimes just unit, of course). The `unpack!`
583 /// macro (and methods below) makes working with `BlockAnd` much more
584 /// convenient.
585
586 #[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
587 struct BlockAnd<T>(BasicBlock, T);
588
589 trait BlockAndExtension {
590     fn and<T>(self, v: T) -> BlockAnd<T>;
591     fn unit(self) -> BlockAnd<()>;
592 }
593
594 impl BlockAndExtension for BasicBlock {
595     fn and<T>(self, v: T) -> BlockAnd<T> {
596         BlockAnd(self, v)
597     }
598
599     fn unit(self) -> BlockAnd<()> {
600         BlockAnd(self, ())
601     }
602 }
603
604 /// Update a block pointer and return the value.
605 /// Use it like `let x = unpack!(block = self.foo(block, foo))`.
606 macro_rules! unpack {
607     ($x:ident = $c:expr) => {
608         {
609             let BlockAnd(b, v) = $c;
610             $x = b;
611             v
612         }
613     };
614
615     ($c:expr) => {
616         {
617             let BlockAnd(b, ()) = $c;
618             b
619         }
620     };
621 }
622
623 fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
624                                          fn_def_id: DefId,
625                                          abi: Abi)
626                                          -> bool {
627     // Not callable from C, so we can safely unwind through these
628     if abi == Abi::Rust || abi == Abi::RustCall { return false; }
629
630     // We never unwind, so it's not relevant to stop an unwind
631     if tcx.sess.panic_strategy() != PanicStrategy::Unwind { return false; }
632
633     // We cannot add landing pads, so don't add one
634     if tcx.sess.no_landing_pads() { return false; }
635
636     // This is a special case: some functions have a C abi but are meant to
637     // unwind anyway. Don't stop them.
638     let attrs = &tcx.get_attrs(fn_def_id);
639     match attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs) {
640         None => {
641             // FIXME(rust-lang/rust#48251) -- Had to disable
642             // abort-on-panic for backwards compatibility reasons.
643             false
644         }
645
646         Some(UnwindAttr::Allowed) => false,
647         Some(UnwindAttr::Aborts) => true,
648     }
649 }
650
651 ///////////////////////////////////////////////////////////////////////////
652 /// the main entry point for building MIR for a function
653
654 struct ArgInfo<'gcx>(Ty<'gcx>,
655                      Option<Span>,
656                      Option<&'gcx hir::Pat>,
657                      Option<ImplicitSelfKind>);
658
659 fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
660                                    fn_id: ast::NodeId,
661                                    arguments: A,
662                                    safety: Safety,
663                                    abi: Abi,
664                                    return_ty: Ty<'gcx>,
665                                    yield_ty: Option<Ty<'gcx>>,
666                                    return_ty_span: Span,
667                                    body: &'gcx hir::Body)
668                                    -> Mir<'tcx>
669     where A: Iterator<Item=ArgInfo<'gcx>>
670 {
671     let arguments: Vec<_> = arguments.collect();
672
673     let tcx = hir.tcx();
674     let span = tcx.hir.span(fn_id);
675
676     // Gather the upvars of a closure, if any.
677     let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
678         freevars.iter().map(|fv| {
679             let var_id = fv.var_id();
680             let var_hir_id = tcx.hir.node_to_hir_id(var_id);
681             let closure_expr_id = tcx.hir.local_def_id(fn_id);
682             let capture = hir.tables().upvar_capture(ty::UpvarId {
683                 var_path: ty::UpvarPath {hir_id: var_hir_id},
684                 closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
685             });
686             let by_ref = match capture {
687                 ty::UpvarCapture::ByValue => false,
688                 ty::UpvarCapture::ByRef(..) => true
689             };
690             let mut decl = UpvarDecl {
691                 debug_name: keywords::Invalid.name(),
692                 var_hir_id: ClearCrossCrate::Set(var_hir_id),
693                 by_ref,
694                 mutability: Mutability::Not,
695             };
696             if let Some(Node::Binding(pat)) = tcx.hir.find(var_id) {
697                 if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
698                     decl.debug_name = ident.name;
699
700                     if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
701                         if bm == ty::BindByValue(hir::MutMutable) {
702                             decl.mutability = Mutability::Mut;
703                         } else {
704                             decl.mutability = Mutability::Not;
705                         }
706                     } else {
707                         tcx.sess.delay_span_bug(pat.span, "missing binding mode");
708                     }
709                 }
710             }
711             decl
712         }).collect()
713     });
714
715     let mut builder = Builder::new(hir,
716         span,
717         arguments.len(),
718         safety,
719         return_ty,
720         return_ty_span,
721         upvar_decls);
722
723     let fn_def_id = tcx.hir.local_def_id(fn_id);
724     let call_site_scope = region::Scope {
725         id: body.value.hir_id.local_id,
726         data: region::ScopeData::CallSite
727     };
728     let arg_scope = region::Scope {
729         id: body.value.hir_id.local_id,
730         data: region::ScopeData::Arguments
731     };
732     let mut block = START_BLOCK;
733     let source_info = builder.source_info(span);
734     let call_site_s = (call_site_scope, source_info);
735     unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| {
736         if should_abort_on_panic(tcx, fn_def_id, abi) {
737             builder.schedule_abort();
738         }
739
740         let arg_scope_s = (arg_scope, source_info);
741         unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, block, |builder| {
742             builder.args_and_body(block, &arguments, arg_scope, &body.value)
743         }));
744         // Attribute epilogue to function's closing brace
745         let fn_end = span.shrink_to_hi();
746         let source_info = builder.source_info(fn_end);
747         let return_block = builder.return_block();
748         builder.cfg.terminate(block, source_info,
749                               TerminatorKind::Goto { target: return_block });
750         builder.cfg.terminate(return_block, source_info,
751                               TerminatorKind::Return);
752         // Attribute any unreachable codepaths to the function's closing brace
753         if let Some(unreachable_block) = builder.cached_unreachable_block {
754             builder.cfg.terminate(unreachable_block, source_info,
755                                   TerminatorKind::Unreachable);
756         }
757         return_block.unit()
758     }));
759     assert_eq!(block, builder.return_block());
760
761     let mut spread_arg = None;
762     if abi == Abi::RustCall {
763         // RustCall pseudo-ABI untuples the last argument.
764         spread_arg = Some(Local::new(arguments.len()));
765     }
766     let closure_expr_id = tcx.hir.local_def_id(fn_id);
767     info!("fn_id {:?} has attrs {:?}", closure_expr_id,
768           tcx.get_attrs(closure_expr_id));
769
770     let mut mir = builder.finish(yield_ty);
771     mir.spread_arg = spread_arg;
772     mir
773 }
774
775 fn construct_const<'a, 'gcx, 'tcx>(
776     hir: Cx<'a, 'gcx, 'tcx>,
777     body_id: hir::BodyId,
778     ty_span: Span,
779 ) -> Mir<'tcx> {
780     let tcx = hir.tcx();
781     let ast_expr = &tcx.hir.body(body_id).value;
782     let ty = hir.tables().expr_ty_adjusted(ast_expr);
783     let owner_id = tcx.hir.body_owner(body_id);
784     let span = tcx.hir.span(owner_id);
785     let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, ty_span,vec![]);
786
787     let mut block = START_BLOCK;
788     let expr = builder.hir.mirror(ast_expr);
789     unpack!(block = builder.into_expr(&Place::Local(RETURN_PLACE), block, expr));
790
791     let source_info = builder.source_info(span);
792     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
793
794     // Constants can't `return` so a return block should not be created.
795     assert_eq!(builder.cached_return_block, None);
796
797     // Constants may be match expressions in which case an unreachable block may
798     // be created, so terminate it properly.
799     if let Some(unreachable_block) = builder.cached_unreachable_block {
800         builder.cfg.terminate(unreachable_block, source_info,
801                               TerminatorKind::Unreachable);
802     }
803
804     builder.finish(None)
805 }
806
807 fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
808                                    body_id: hir::BodyId)
809                                    -> Mir<'tcx> {
810     let owner_id = hir.tcx().hir.body_owner(body_id);
811     let span = hir.tcx().hir.span(owner_id);
812     let ty = hir.tcx().types.err;
813     let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![]);
814     let source_info = builder.source_info(span);
815     builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
816     builder.finish(None)
817 }
818
819 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
820     fn new(hir: Cx<'a, 'gcx, 'tcx>,
821            span: Span,
822            arg_count: usize,
823            safety: Safety,
824            return_ty: Ty<'tcx>,
825            return_span: Span,
826            upvar_decls: Vec<UpvarDecl>)
827            -> Builder<'a, 'gcx, 'tcx> {
828         let lint_level = LintLevel::Explicit(hir.root_lint_level);
829         let mut builder = Builder {
830             hir,
831             cfg: CFG { basic_blocks: IndexVec::new() },
832             fn_span: span,
833             arg_count,
834             scopes: vec![],
835             block_context: BlockContext::new(),
836             source_scopes: IndexVec::new(),
837             source_scope: OUTERMOST_SOURCE_SCOPE,
838             source_scope_local_data: IndexVec::new(),
839             guard_context: vec![],
840             push_unsafe_count: 0,
841             unpushed_unsafe: safety,
842             breakable_scopes: vec![],
843             local_decls: IndexVec::from_elem_n(
844                 LocalDecl::new_return_place(return_ty, return_span),
845                 1,
846             ),
847             upvar_decls,
848             var_indices: Default::default(),
849             unit_temp: None,
850             cached_resume_block: None,
851             cached_return_block: None,
852             cached_unreachable_block: None,
853         };
854
855         assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
856         assert_eq!(
857             builder.new_source_scope(span, lint_level, Some(safety)),
858             OUTERMOST_SOURCE_SCOPE);
859         builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None;
860
861         builder
862     }
863
864     fn finish(self,
865               yield_ty: Option<Ty<'tcx>>)
866               -> Mir<'tcx> {
867         for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
868             if block.terminator.is_none() {
869                 span_bug!(self.fn_span, "no terminator on block {:?}", index);
870             }
871         }
872
873         Mir::new(self.cfg.basic_blocks,
874                  self.source_scopes,
875                  ClearCrossCrate::Set(self.source_scope_local_data),
876                  IndexVec::new(),
877                  yield_ty,
878                  self.local_decls,
879                  self.arg_count,
880                  self.upvar_decls,
881                  self.fn_span
882         )
883     }
884
885     fn args_and_body(&mut self,
886                      mut block: BasicBlock,
887                      arguments: &[ArgInfo<'gcx>],
888                      argument_scope: region::Scope,
889                      ast_body: &'gcx hir::Expr)
890                      -> BlockAnd<()>
891     {
892         // Allocate locals for the function arguments
893         for &ArgInfo(ty, _, pattern, _) in arguments.iter() {
894             // If this is a simple binding pattern, give the local a name for
895             // debuginfo and so that error reporting knows that this is a user
896             // variable. For any other pattern the pattern introduces new
897             // variables which will be named instead.
898             let mut name = None;
899             if let Some(pat) = pattern {
900                 match pat.node {
901                     hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _)
902                     | hir::PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, _) => {
903                         name = Some(ident.name);
904                     }
905                     _ => (),
906                 }
907             }
908
909             let source_info = SourceInfo {
910                 scope: OUTERMOST_SOURCE_SCOPE,
911                 span: pattern.map_or(self.fn_span, |pat| pat.span)
912             };
913             self.local_decls.push(LocalDecl {
914                 mutability: Mutability::Mut,
915                 ty,
916                 user_ty: UserTypeProjections::none(),
917                 source_info,
918                 visibility_scope: source_info.scope,
919                 name,
920                 internal: false,
921                 is_user_variable: None,
922                 is_block_tail: None,
923             });
924         }
925
926         let mut scope = None;
927         // Bind the argument patterns
928         for (index, arg_info) in arguments.iter().enumerate() {
929             // Function arguments always get the first Local indices after the return place
930             let local = Local::new(index + 1);
931             let place = Place::Local(local);
932             let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
933
934             if let Some(pattern) = pattern {
935                 let pattern = self.hir.pattern_from_hir(pattern);
936                 let span = pattern.span;
937
938                 match *pattern.kind {
939                     // Don't introduce extra copies for simple bindings
940                     PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => {
941                         self.local_decls[local].mutability = mutability;
942                         self.local_decls[local].is_user_variable =
943                             if let Some(kind) = self_binding {
944                                 Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))
945                             } else {
946                                 let binding_mode = ty::BindingMode::BindByValue(mutability.into());
947                                 Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
948                                     binding_mode,
949                                     opt_ty_info,
950                                     opt_match_place: Some((Some(place.clone()), span)),
951                                     pat_span: span,
952                                 })))
953                             };
954                         self.var_indices.insert(var, LocalsForNode::One(local));
955                     }
956                     _ => {
957                         scope = self.declare_bindings(scope, ast_body.span,
958                                                       LintLevel::Inherited, &[pattern.clone()],
959                                                       matches::ArmHasGuard(false),
960                                                       Some((Some(&place), span)));
961                         unpack!(block = self.place_into_pattern(block, pattern, &place, false));
962                     }
963                 }
964             }
965
966             // Make sure we drop (parts of) the argument even when not matched on.
967             self.schedule_drop(
968                 pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
969                 argument_scope, &place, ty,
970                 DropKind::Value { cached_block: CachedBlock::default() },
971             );
972         }
973
974         // Enter the argument pattern bindings source scope, if it exists.
975         if let Some(source_scope) = scope {
976             self.source_scope = source_scope;
977         }
978
979         let body = self.hir.mirror(ast_body);
980         self.into(&Place::Local(RETURN_PLACE), block, body)
981     }
982
983     fn get_unit_temp(&mut self) -> Place<'tcx> {
984         match self.unit_temp {
985             Some(ref tmp) => tmp.clone(),
986             None => {
987                 let ty = self.hir.unit_ty();
988                 let fn_span = self.fn_span;
989                 let tmp = self.temp(ty, fn_span);
990                 self.unit_temp = Some(tmp.clone());
991                 tmp
992             }
993         }
994     }
995
996     fn return_block(&mut self) -> BasicBlock {
997         match self.cached_return_block {
998             Some(rb) => rb,
999             None => {
1000                 let rb = self.cfg.start_new_block();
1001                 self.cached_return_block = Some(rb);
1002                 rb
1003             }
1004         }
1005     }
1006
1007     fn unreachable_block(&mut self) -> BasicBlock {
1008         match self.cached_unreachable_block {
1009             Some(ub) => ub,
1010             None => {
1011                 let ub = self.cfg.start_new_block();
1012                 self.cached_unreachable_block = Some(ub);
1013                 ub
1014             }
1015         }
1016     }
1017 }
1018
1019 ///////////////////////////////////////////////////////////////////////////
1020 // Builder methods are broken up into modules, depending on what kind
1021 // of thing is being lowered. Note that they use the `unpack` macro
1022 // above extensively.
1023
1024 mod block;
1025 mod cfg;
1026 mod expr;
1027 mod into;
1028 mod matches;
1029 mod misc;
1030 mod scope;