/*!
Managing the scope stack. The scopes are tied to lexical scopes, so as
we descend the HAIR, we push a scope on the stack, build its
contents, and then pop it off. Every scope is named by a
`region::Scope`.

### SEME Regions

When pushing a new scope, we record the current point in the graph (a
basic block); this marks the entry to the scope. We then generate more
stuff in the control-flow graph. Whenever the scope is exited, either
via a `break` or `return` or just by fallthrough, that marks an exit
from the scope. Each lexical scope thus corresponds to a single-entry,
multiple-exit (SEME) region in the control-flow graph.

For now, we keep a mapping from each `region::Scope` to its
corresponding SEME region for later reference (see caveat in next
paragraph). This is because region scopes are tied to
them. Eventually, when we shift to non-lexical lifetimes, there should
be no need to remember this mapping.

### Not so SEME Regions

In the course of building matches, it sometimes happens that certain code
(namely guards) gets executed multiple times. This means that the scope lexical
scope may in fact correspond to multiple, disjoint SEME regions. So in fact our
mapping is from one scope to a vector of SEME regions.

Also in matches, the scopes assigned to arms are not even SEME regions! Each
arm has a single region with one entry for each pattern. We manually
manipulate the scheduled drops in this scope to avoid dropping things multiple
times, although drop elaboration would clean this up for value drops.

### Drops

The primary purpose for scopes is to insert drops: while building
the contents, we also accumulate places that need to be dropped upon
exit from each scope. This is done by calling `schedule_drop`. Once a
drop is scheduled, whenever we branch out we will insert drops of all
those places onto the outgoing edge. Note that we don't know the full
set of scheduled drops up front, and so whenever we exit from the
scope we only drop the values scheduled thus far. For example, consider
the scope S corresponding to this loop:

```
# let cond = true;
loop {
    let x = ..;
    if cond { break; }
    let y = ..;
}
```

When processing the `let x`, we will add one drop to the scope for
`x`.  The break will then insert a drop for `x`. When we process `let
y`, we will add another drop (in fact, to a subscope, but let's ignore
that for now); any later drops would also drop `y`.

### Early exit

There are numerous "normal" ways to early exit a scope: `break`,
`continue`, `return` (panics are handled separately). Whenever an
early exit occurs, the method `exit_scope` is called. It is given the
current point in execution where the early exit occurs, as well as the
scope you want to branch to (note that all early exits from to some
other enclosing scope). `exit_scope` will record this exit point and
also add all drops.

Panics are handled in a similar fashion, except that a panic always
returns out to the `DIVERGE_BLOCK`. To trigger a panic, simply call
`panic(p)` with the current point `p`. Or else you can call
`diverge_cleanup`, which will produce a block that you can branch to
which does the appropriate cleanup and then diverges. `panic(p)`
simply calls `diverge_cleanup()` and adds an edge from `p` to the
result.

### Loop scopes

In addition to the normal scope stack, we track a loop scope stack
that contains only loops. It tracks where a `break` and `continue`
should go to.

*/

use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
use crate::hair::{Expr, ExprRef, LintLevel};
use rustc::middle::region;
use rustc::ty::Ty;
use rustc::hir;
use rustc::mir::*;
use syntax_pos::{DUMMY_SP, Span};
use rustc_data_structures::fx::FxHashMap;
use std::collections::hash_map::Entry;
use std::mem;

#[derive(Debug)]
struct Scope {
    /// The source scope this scope was created in.
    source_scope: SourceScope,

    /// the region span of this scope within source code.
    region_scope: region::Scope,

    /// the span of that region_scope
    region_scope_span: Span,

    /// Whether there's anything to do for the cleanup path, that is,
    /// when unwinding through this scope. This includes destructors,
    /// but not StorageDead statements, which don't get emitted at all
    /// for unwinding, for several reasons:
    ///  * clang doesn't emit llvm.lifetime.end for C++ unwinding
    ///  * LLVM's memory dependency analysis can't handle it atm
    ///  * polluting the cleanup MIR with StorageDead creates
    ///    landing pads even though there's no actual destructors
    ///  * freeing up stack space has no effect during unwinding
    /// Note that for generators we do emit StorageDeads, for the
    /// use of optimizations in the MIR generator transform.
    needs_cleanup: bool,

    /// set of places to drop when exiting this scope. This starts
    /// out empty but grows as variables are declared during the
    /// building process. This is a stack, so we always drop from the
    /// end of the vector (top of the stack) first.
    drops: Vec<DropData>,

    /// The cache for drop chain on “normal” exit into a particular BasicBlock.
    cached_exits: FxHashMap<(BasicBlock, region::Scope), BasicBlock>,

    /// The cache for drop chain on "generator drop" exit.
    cached_generator_drop: Option<BasicBlock>,

    /// The cache for drop chain on "unwind" exit.
    cached_unwind: CachedBlock,
}

#[derive(Debug, Default)]
pub struct Scopes<'tcx> {
    scopes: Vec<Scope>,
    /// The current set of breakable scopes. See module comment for more details.
    breakable_scopes: Vec<BreakableScope<'tcx>>,
}

#[derive(Debug)]
struct DropData {
    /// span where drop obligation was incurred (typically where place was declared)
    span: Span,

    /// local to drop
    local: Local,

    /// Whether this is a value Drop or a StorageDead.
    kind: DropKind,

    /// The cached blocks for unwinds.
    cached_block: CachedBlock,
}

#[derive(Debug, Default, Clone, Copy)]
struct CachedBlock {
    /// The cached block for the cleanups-on-diverge path. This block
    /// contains code to run the current drop and all the preceding
    /// drops (i.e., those having lower index in Drop’s Scope drop
    /// array)
    unwind: Option<BasicBlock>,

    /// The cached block for unwinds during cleanups-on-generator-drop path
    ///
    /// This is split from the standard unwind path here to prevent drop
    /// elaboration from creating drop flags that would have to be captured
    /// by the generator. I'm not sure how important this optimization is,
    /// but it is here.
    generator_drop: Option<BasicBlock>,
}

#[derive(Debug)]
pub(crate) enum DropKind {
    Value,
    Storage,
}

#[derive(Clone, Debug)]
struct BreakableScope<'tcx> {
    /// Region scope of the loop
    region_scope: region::Scope,
    /// Where the body of the loop begins. `None` if block
    continue_block: Option<BasicBlock>,
    /// Block to branch into when the loop or block terminates (either by being `break`-en out
    /// from, or by having its condition to become false)
    break_block: BasicBlock,
    /// The destination of the loop/block expression itself (i.e., where to put the result of a
    /// `break` expression)
    break_destination: Place<'tcx>,
}

/// The target of an expression that breaks out of a scope
#[derive(Clone, Copy, Debug)]
pub enum BreakableTarget {
    Continue(region::Scope),
    Break(region::Scope),
    Return,
}

impl CachedBlock {
    fn invalidate(&mut self) {
        self.generator_drop = None;
        self.unwind = None;
    }

    fn get(&self, generator_drop: bool) -> Option<BasicBlock> {
        if generator_drop {
            self.generator_drop
        } else {
            self.unwind
        }
    }

    fn ref_mut(&mut self, generator_drop: bool) -> &mut Option<BasicBlock> {
        if generator_drop {
            &mut self.generator_drop
        } else {
            &mut self.unwind
        }
    }
}

impl Scope {
    /// Invalidates all the cached blocks in the scope.
    ///
    /// Should always be run for all inner scopes when a drop is pushed into some scope enclosing a
    /// larger extent of code.
    ///
    /// `storage_only` controls whether to invalidate only drop paths that run `StorageDead`.
    /// `this_scope_only` controls whether to invalidate only drop paths that refer to the current
    /// top-of-scope (as opposed to dependent scopes).
    fn invalidate_cache(&mut self, storage_only: bool, is_generator: bool, this_scope_only: bool) {
        // FIXME: maybe do shared caching of `cached_exits` etc. to handle functions
        // with lots of `try!`?

        // cached exits drop storage and refer to the top-of-scope
        self.cached_exits.clear();

        // the current generator drop and unwind refer to top-of-scope
        self.cached_generator_drop = None;

        let ignore_unwinds = storage_only && !is_generator;
        if !ignore_unwinds {
            self.cached_unwind.invalidate();
        }

        if !ignore_unwinds && !this_scope_only {
            for drop_data in &mut self.drops {
                drop_data.cached_block.invalidate();
            }
        }
    }

    /// Given a span and this scope's source scope, make a SourceInfo.
    fn source_info(&self, span: Span) -> SourceInfo {
        SourceInfo {
            span,
            scope: self.source_scope
        }
    }
}

impl<'tcx> Scopes<'tcx> {
    fn len(&self) -> usize {
        self.scopes.len()
    }

    fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo), vis_scope: SourceScope) {
        debug!("push_scope({:?})", region_scope);
        self.scopes.push(Scope {
            source_scope: vis_scope,
            region_scope: region_scope.0,
            region_scope_span: region_scope.1.span,
            needs_cleanup: false,
            drops: vec![],
            cached_generator_drop: None,
            cached_exits: Default::default(),
            cached_unwind: CachedBlock::default(),
        });
    }

    fn pop_scope(
        &mut self,
        region_scope: (region::Scope, SourceInfo),
    ) -> (Scope, Option<BasicBlock>) {
        let scope = self.scopes.pop().unwrap();
        assert_eq!(scope.region_scope, region_scope.0);
        let unwind_to = self.scopes.last()
            .and_then(|next_scope| next_scope.cached_unwind.get(false));
        (scope, unwind_to)
    }

    fn may_panic(&self, scope_count: usize) -> bool {
        let len = self.len();
        self.scopes[(len - scope_count)..].iter().any(|s| s.needs_cleanup)
    }

    /// Finds the breakable scope for a given label. This is used for
    /// resolving `return`, `break` and `continue`.
    fn find_breakable_scope(
        &self,
        span: Span,
        target: BreakableTarget,
    ) -> (BasicBlock, region::Scope, Option<Place<'tcx>>) {
        let get_scope = |scope: region::Scope| {
            // find the loop-scope by its `region::Scope`.
            self.breakable_scopes.iter()
                .rfind(|breakable_scope| breakable_scope.region_scope == scope)
                .unwrap_or_else(|| span_bug!(span, "no enclosing breakable scope found"))
        };
        match target {
            BreakableTarget::Return => {
                let scope = &self.breakable_scopes[0];
                if scope.break_destination != Place::return_place() {
                    span_bug!(span, "`return` in item with no return scope");
                }
                (scope.break_block, scope.region_scope, Some(scope.break_destination.clone()))
            }
            BreakableTarget::Break(scope) => {
                let scope = get_scope(scope);
                (scope.break_block, scope.region_scope, Some(scope.break_destination.clone()))
            }
            BreakableTarget::Continue(scope) => {
                let scope = get_scope(scope);
                let continue_block = scope.continue_block
                    .unwrap_or_else(|| span_bug!(span, "missing `continue` block"));
                (continue_block, scope.region_scope, None)
            }
        }
    }

    fn num_scopes_above(&self, region_scope: region::Scope, span: Span) -> usize {
        let scope_count = self.scopes.iter().rev()
            .position(|scope| scope.region_scope == region_scope)
            .unwrap_or_else(|| {
                span_bug!(span, "region_scope {:?} does not enclose", region_scope)
            });
        let len = self.len();
        assert!(scope_count < len, "should not use `exit_scope` to pop ALL scopes");
        scope_count
    }

    fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item=&mut Scope> + '_ {
        self.scopes.iter_mut().rev()
    }

    fn top_scopes(&mut self, count: usize) -> impl DoubleEndedIterator<Item=&mut Scope> + '_ {
        let len = self.len();
        self.scopes[len - count..].iter_mut()
    }

    /// Returns the topmost active scope, which is known to be alive until
    /// the next scope expression.
    pub(super) fn topmost(&self) -> region::Scope {
        self.scopes.last().expect("topmost_scope: no scopes present").region_scope
    }

    fn source_info(&self, index: usize, span: Span) -> SourceInfo {
        self.scopes[self.len() - index].source_info(span)
    }
}

impl<'a, 'tcx> Builder<'a, 'tcx> {
    // Adding and removing scopes
    // ==========================
    //  Start a breakable scope, which tracks where `continue`, `break` and
    //  `return` should branch to.
    pub fn in_breakable_scope<F, R>(&mut self,
                                    loop_block: Option<BasicBlock>,
                                    break_block: BasicBlock,
                                    break_destination: Place<'tcx>,
                                    f: F) -> R
        where F: FnOnce(&mut Builder<'a, 'tcx>) -> R
    {
        let region_scope = self.scopes.topmost();
        let scope = BreakableScope {
            region_scope,
            continue_block: loop_block,
            break_block,
            break_destination,
        };
        self.scopes.breakable_scopes.push(scope);
        let res = f(self);
        let breakable_scope = self.scopes.breakable_scopes.pop().unwrap();
        assert!(breakable_scope.region_scope == region_scope);
        res
    }

    pub fn in_opt_scope<F, R>(&mut self,
                              opt_scope: Option<(region::Scope, SourceInfo)>,
                              f: F)
                              -> BlockAnd<R>
        where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
    {
        debug!("in_opt_scope(opt_scope={:?})", opt_scope);
        if let Some(region_scope) = opt_scope { self.push_scope(region_scope); }
        let mut block;
        let rv = unpack!(block = f(self));
        if let Some(region_scope) = opt_scope {
            unpack!(block = self.pop_scope(region_scope, block));
        }
        debug!("in_scope: exiting opt_scope={:?} block={:?}", opt_scope, block);
        block.and(rv)
    }

    /// Convenience wrapper that pushes a scope and then executes `f`
    /// to build its contents, popping the scope afterwards.
    pub fn in_scope<F, R>(&mut self,
                          region_scope: (region::Scope, SourceInfo),
                          lint_level: LintLevel,
                          f: F)
                          -> BlockAnd<R>
        where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
    {
        debug!("in_scope(region_scope={:?})", region_scope);
        let source_scope = self.source_scope;
        let tcx = self.hir.tcx();
        if let LintLevel::Explicit(current_hir_id) = lint_level {
            // Use `maybe_lint_level_root_bounded` with `root_lint_level` as a bound
            // to avoid adding Hir dependences on our parents.
            // We estimate the true lint roots here to avoid creating a lot of source scopes.

            let parent_root = tcx.maybe_lint_level_root_bounded(
                self.source_scope_local_data[source_scope].lint_root,
                self.hir.root_lint_level,
            );
            let current_root = tcx.maybe_lint_level_root_bounded(
                current_hir_id,
                self.hir.root_lint_level
            );

            if parent_root != current_root {
                self.source_scope = self.new_source_scope(
                    region_scope.1.span,
                    LintLevel::Explicit(current_root),
                    None
                );
            }
        }
        self.push_scope(region_scope);
        let mut block;
        let rv = unpack!(block = f(self));
        unpack!(block = self.pop_scope(region_scope, block));
        self.source_scope = source_scope;
        debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
        block.and(rv)
    }

    /// Push a scope onto the stack. You can then build code in this
    /// scope and call `pop_scope` afterwards. Note that these two
    /// calls must be paired; using `in_scope` as a convenience
    /// wrapper maybe preferable.
    pub fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
        self.scopes.push_scope(region_scope, self.source_scope);
    }

    /// Pops a scope, which should have region scope `region_scope`,
    /// adding any drops onto the end of `block` that are needed.
    /// This must match 1-to-1 with `push_scope`.
    pub fn pop_scope(&mut self,
                     region_scope: (region::Scope, SourceInfo),
                     mut block: BasicBlock)
                     -> BlockAnd<()> {
        debug!("pop_scope({:?}, {:?})", region_scope, block);
        // If we are emitting a `drop` statement, we need to have the cached
        // diverge cleanup pads ready in case that drop panics.
        if self.scopes.may_panic(1) {
            self.diverge_cleanup();
        }
        let (scope, unwind_to) = self.scopes.pop_scope(region_scope);
        let unwind_to = unwind_to.unwrap_or_else(|| self.resume_block());

        unpack!(block = build_scope_drops(
            &mut self.cfg,
            self.is_generator,
            &scope,
            block,
            unwind_to,
            self.arg_count,
            false,
        ));

        block.unit()
    }

    pub fn break_scope(
        &mut self,
        mut block: BasicBlock,
        value: Option<ExprRef<'tcx>>,
        scope: BreakableTarget,
        source_info: SourceInfo,
    ) -> BlockAnd<()> {
        let (mut target_block, region_scope, destination)
            = self.scopes.find_breakable_scope(source_info.span, scope);
        if let BreakableTarget::Return = scope {
            // We call this now, rather than when we start lowering the
            // function so that the return block doesn't precede the entire
            // rest of the CFG. Some passes and LLVM prefer blocks to be in
            // approximately CFG order.
            target_block = self.return_block();
        }
        if let Some(destination) = destination {
            if let Some(value) = value {
                debug!("stmt_expr Break val block_context.push(SubExpr)");
                self.block_context.push(BlockFrame::SubExpr);
                unpack!(block = self.into(&destination, block, value));
                self.block_context.pop();
            } else {
                self.cfg.push_assign_unit(block, source_info, &destination)
            }
        } else {
            assert!(value.is_none(), "`return` and `break` should have a destination");
        }
        self.exit_scope(source_info.span, region_scope, block, target_block);
        self.cfg.start_new_block().unit()
    }

    /// Branch out of `block` to `target`, exiting all scopes up to
    /// and including `region_scope`. This will insert whatever drops are
    /// needed. See module comment for details.
    pub fn exit_scope(&mut self,
                      span: Span,
                      region_scope: region::Scope,
                      mut block: BasicBlock,
                      target: BasicBlock) {
        debug!("exit_scope(region_scope={:?}, block={:?}, target={:?})",
               region_scope, block, target);
        let scope_count = self.scopes.num_scopes_above(region_scope, span);

        // If we are emitting a `drop` statement, we need to have the cached
        // diverge cleanup pads ready in case that drop panics.
        let may_panic = self.scopes.may_panic(scope_count);
        if may_panic {
            self.diverge_cleanup();
        }

        let mut scopes = self.scopes.top_scopes(scope_count + 1).rev();
        let mut scope = scopes.next().unwrap();
        for next_scope in scopes {
            if scope.drops.is_empty() {
                scope = next_scope;
                continue;
            }
            let source_info = scope.source_info(span);
            block = match scope.cached_exits.entry((target, region_scope)) {
                Entry::Occupied(e) => {
                    self.cfg.terminate(block, source_info,
                                    TerminatorKind::Goto { target: *e.get() });
                    return;
                }
                Entry::Vacant(v) => {
                    let b = self.cfg.start_new_block();
                    self.cfg.terminate(block, source_info,
                                    TerminatorKind::Goto { target: b });
                    v.insert(b);
                    b
                }
            };

            let unwind_to = next_scope.cached_unwind.get(false).unwrap_or_else(|| {
                debug_assert!(!may_panic, "cached block not present?");
                START_BLOCK
            });

            unpack!(block = build_scope_drops(
                &mut self.cfg,
                self.is_generator,
                scope,
                block,
                unwind_to,
                self.arg_count,
                false,
            ));

            scope = next_scope;
        }

        let source_info = self.scopes.source_info(scope_count, span);
        self.cfg.terminate(block, source_info, TerminatorKind::Goto { target });
    }

    /// Creates a path that performs all required cleanup for dropping a generator.
    ///
    /// This path terminates in GeneratorDrop. Returns the start of the path.
    /// None indicates there’s no cleanup to do at this point.
    pub fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
        // Fill in the cache for unwinds
        self.diverge_cleanup_gen(true);

        let src_info = self.scopes.source_info(self.scopes.len(), self.fn_span);
        let resume_block = self.resume_block();
        let mut scopes = self.scopes.iter_mut().peekable();
        let mut block = self.cfg.start_new_block();
        let result = block;

        while let Some(scope) = scopes.next() {
            block = if let Some(b) = scope.cached_generator_drop {
                self.cfg.terminate(block, src_info,
                                   TerminatorKind::Goto { target: b });
                return Some(result);
            } else {
                let b = self.cfg.start_new_block();
                scope.cached_generator_drop = Some(b);
                self.cfg.terminate(block, src_info,
                                   TerminatorKind::Goto { target: b });
                b
            };

            let unwind_to = scopes.peek().as_ref().map(|scope| {
                scope.cached_unwind.get(true).unwrap_or_else(|| {
                    span_bug!(src_info.span, "cached block not present?")
                })
            }).unwrap_or(resume_block);

            unpack!(block = build_scope_drops(
                &mut self.cfg,
                self.is_generator,
                scope,
                block,
                unwind_to,
                self.arg_count,
                true,
            ));
        }

        self.cfg.terminate(block, src_info, TerminatorKind::GeneratorDrop);

        Some(result)
    }

    /// Creates a new source scope, nested in the current one.
    pub fn new_source_scope(&mut self,
                            span: Span,
                            lint_level: LintLevel,
                            safety: Option<Safety>) -> SourceScope {
        let parent = self.source_scope;
        debug!("new_source_scope({:?}, {:?}, {:?}) - parent({:?})={:?}",
               span, lint_level, safety,
               parent, self.source_scope_local_data.get(parent));
        let scope = self.source_scopes.push(SourceScopeData {
            span,
            parent_scope: Some(parent),
        });
        let scope_local_data = SourceScopeLocalData {
            lint_root: if let LintLevel::Explicit(lint_root) = lint_level {
                lint_root
            } else {
                self.source_scope_local_data[parent].lint_root
            },
            safety: safety.unwrap_or_else(|| {
                self.source_scope_local_data[parent].safety
            })
        };
        self.source_scope_local_data.push(scope_local_data);
        scope
    }

    /// Given a span and the current source scope, make a SourceInfo.
    pub fn source_info(&self, span: Span) -> SourceInfo {
        SourceInfo {
            span,
            scope: self.source_scope
        }
    }

    // Finding scopes
    // ==============
    /// Returns the scope that we should use as the lifetime of an
    /// operand. Basically, an operand must live until it is consumed.
    /// This is similar to, but not quite the same as, the temporary
    /// scope (which can be larger or smaller).
    ///
    /// Consider:
    ///
    ///     let x = foo(bar(X, Y));
    ///
    /// We wish to pop the storage for X and Y after `bar()` is
    /// called, not after the whole `let` is completed.
    ///
    /// As another example, if the second argument diverges:
    ///
    ///     foo(Box::new(2), panic!())
    ///
    /// We would allocate the box but then free it on the unwinding
    /// path; we would also emit a free on the 'success' path from
    /// panic, but that will turn out to be removed as dead-code.
    ///
    /// When building statics/constants, returns `None` since
    /// intermediate values do not have to be dropped in that case.
    pub fn local_scope(&self) -> Option<region::Scope> {
        match self.hir.body_owner_kind {
            hir::BodyOwnerKind::Const |
            hir::BodyOwnerKind::Static(_) =>
                // No need to free storage in this context.
                None,
            hir::BodyOwnerKind::Closure |
            hir::BodyOwnerKind::Fn =>
                Some(self.scopes.topmost()),
        }
    }

    // Schedule an abort block - this is used for some ABIs that cannot unwind
    pub fn schedule_abort(&mut self) -> BasicBlock {
        let source_info = self.scopes.source_info(self.scopes.len(), self.fn_span);
        let abortblk = self.cfg.start_new_cleanup_block();
        self.cfg.terminate(abortblk, source_info, TerminatorKind::Abort);
        self.cached_resume_block = Some(abortblk);
        abortblk
    }

    // Scheduling drops
    // ================
    pub fn schedule_drop_storage_and_value(
        &mut self,
        span: Span,
        region_scope: region::Scope,
        local: Local,
        place_ty: Ty<'tcx>,
    ) {
        self.schedule_drop(span, region_scope, local, place_ty, DropKind::Storage);
        self.schedule_drop(span, region_scope, local, place_ty, DropKind::Value);
    }

    /// Indicates that `place` should be dropped on exit from
    /// `region_scope`.
    ///
    /// When called with `DropKind::Storage`, `place` should be a local
    /// with an index higher than the current `self.arg_count`.
    pub fn schedule_drop(
        &mut self,
        span: Span,
        region_scope: region::Scope,
        local: Local,
        place_ty: Ty<'tcx>,
        drop_kind: DropKind,
    ) {
        let needs_drop = self.hir.needs_drop(place_ty);
        match drop_kind {
            DropKind::Value => if !needs_drop { return },
            DropKind::Storage => {
                if local.index() <= self.arg_count {
                    span_bug!(
                        span, "`schedule_drop` called with local {:?} and arg_count {}",
                        local,
                        self.arg_count,
                    )
                }
            }
        }

        for scope in self.scopes.iter_mut() {
            let this_scope = scope.region_scope == region_scope;
            // When building drops, we try to cache chains of drops in such a way so these drops
            // could be reused by the drops which would branch into the cached (already built)
            // blocks.  This, however, means that whenever we add a drop into a scope which already
            // had some blocks built (and thus, cached) for it, we must invalidate all caches which
            // might branch into the scope which had a drop just added to it. This is necessary,
            // because otherwise some other code might use the cache to branch into already built
            // chain of drops, essentially ignoring the newly added drop.
            //
            // For example consider there’s two scopes with a drop in each. These are built and
            // thus the caches are filled:
            //
            // +--------------------------------------------------------+
            // | +---------------------------------+                    |
            // | | +--------+     +-------------+  |  +---------------+ |
            // | | | return | <-+ | drop(outer) | <-+ |  drop(middle) | |
            // | | +--------+     +-------------+  |  +---------------+ |
            // | +------------|outer_scope cache|--+                    |
            // +------------------------------|middle_scope cache|------+
            //
            // Now, a new, inner-most scope is added along with a new drop into both inner-most and
            // outer-most scopes:
            //
            // +------------------------------------------------------------+
            // | +----------------------------------+                       |
            // | | +--------+      +-------------+  |   +---------------+   | +-------------+
            // | | | return | <+   | drop(new)   | <-+  |  drop(middle) | <--+| drop(inner) |
            // | | +--------+  |   | drop(outer) |  |   +---------------+   | +-------------+
            // | |             +-+ +-------------+  |                       |
            // | +---|invalid outer_scope cache|----+                       |
            // +----=----------------|invalid middle_scope cache|-----------+
            //
            // If, when adding `drop(new)` we do not invalidate the cached blocks for both
            // outer_scope and middle_scope, then, when building drops for the inner (right-most)
            // scope, the old, cached blocks, without `drop(new)` will get used, producing the
            // wrong results.
            //
            // The cache and its invalidation for unwind branch is somewhat special. The cache is
            // per-drop, rather than per scope, which has a several different implications. Adding
            // a new drop into a scope will not invalidate cached blocks of the prior drops in the
            // scope. That is true, because none of the already existing drops will have an edge
            // into a block with the newly added drop.
            //
            // Note that this code iterates scopes from the inner-most to the outer-most,
            // invalidating caches of each scope visited. This way bare minimum of the
            // caches gets invalidated. i.e., if a new drop is added into the middle scope, the
            // cache of outer scope stays intact.
            scope.invalidate_cache(!needs_drop, self.is_generator, this_scope);
            if this_scope {
                if let DropKind::Value = drop_kind {
                    scope.needs_cleanup = true;
                }

                let region_scope_span = region_scope.span(self.hir.tcx(),
                                                          &self.hir.region_scope_tree);
                // Attribute scope exit drops to scope's closing brace.
                let scope_end = self.hir.tcx().sess.source_map().end_point(region_scope_span);

                scope.drops.push(DropData {
                    span: scope_end,
                    local,
                    kind: drop_kind,
                    cached_block: CachedBlock::default(),
                });
                return;
            }
        }
        span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local);
    }

    // Other
    // =====
    /// Branch based on a boolean condition.
    ///
    /// This is a special case because the temporary for the condition needs to
    /// be dropped on both the true and the false arm.
    pub fn test_bool(
        &mut self,
        mut block: BasicBlock,
        condition: Expr<'tcx>,
        source_info: SourceInfo,
    ) -> (BasicBlock, BasicBlock) {
        let cond = unpack!(block = self.as_local_operand(block, condition));
        let true_block = self.cfg.start_new_block();
        let false_block = self.cfg.start_new_block();
        let term = TerminatorKind::if_(
            self.hir.tcx(),
            cond.clone(),
            true_block,
            false_block,
        );
        self.cfg.terminate(block, source_info, term);

        match cond {
            // Don't try to drop a constant
            Operand::Constant(_) => (),
            // If constants and statics, we don't generate StorageLive for this
            // temporary, so don't try to generate StorageDead for it either.
            _ if self.local_scope().is_none() => (),
            Operand::Copy(Place {
                base: PlaceBase::Local(cond_temp),
                projection: box [],
            })
            | Operand::Move(Place {
                base: PlaceBase::Local(cond_temp),
                projection: box [],
            }) => {
                // Manually drop the condition on both branches.
                let top_scope = self.scopes.scopes.last_mut().unwrap();
                let top_drop_data = top_scope.drops.pop().unwrap();

                match top_drop_data.kind {
                    DropKind::Value { .. } => {
                        bug!("Drop scheduled on top of condition variable")
                    }
                    DropKind::Storage => {
                        let source_info = top_scope.source_info(top_drop_data.span);
                        let local = top_drop_data.local;
                        assert_eq!(local, cond_temp, "Drop scheduled on top of condition");
                        self.cfg.push(
                            true_block,
                            Statement {
                                source_info,
                                kind: StatementKind::StorageDead(local)
                            },
                        );
                        self.cfg.push(
                            false_block,
                            Statement {
                                source_info,
                                kind: StatementKind::StorageDead(local)
                            },
                        );
                    }
                }

                top_scope.invalidate_cache(true, self.is_generator, true);
            }
            _ => bug!("Expected as_local_operand to produce a temporary"),
        }

        (true_block, false_block)
    }

    /// Creates a path that performs all required cleanup for unwinding.
    ///
    /// This path terminates in Resume. Returns the start of the path.
    /// See module comment for more details.
    pub fn diverge_cleanup(&mut self) -> BasicBlock {
        self.diverge_cleanup_gen(false)
    }

    fn resume_block(&mut self) -> BasicBlock {
        if let Some(target) = self.cached_resume_block {
            target
        } else {
            let resumeblk = self.cfg.start_new_cleanup_block();
            self.cfg.terminate(resumeblk,
                               SourceInfo {
                                   scope: OUTERMOST_SOURCE_SCOPE,
                                   span: self.fn_span
                               },
                               TerminatorKind::Resume);
            self.cached_resume_block = Some(resumeblk);
            resumeblk
        }
    }

    fn diverge_cleanup_gen(&mut self, generator_drop: bool) -> BasicBlock {
        // Build up the drops in **reverse** order. The end result will
        // look like:
        //
        //    scopes[n] -> scopes[n-1] -> ... -> scopes[0]
        //
        // However, we build this in **reverse order**. That is, we
        // process scopes[0], then scopes[1], etc, pointing each one at
        // the result generates from the one before. Along the way, we
        // store caches. If everything is cached, we'll just walk right
        // to left reading the cached results but never created anything.

        // Find the last cached block
        debug!("diverge_cleanup_gen(self.scopes = {:?})", self.scopes);
        let cached_cleanup = self.scopes.iter_mut().enumerate()
            .find_map(|(idx, ref scope)| {
                let cached_block = scope.cached_unwind.get(generator_drop)?;
                Some((cached_block, idx))
            });
        let (mut target, first_uncached) = cached_cleanup
            .unwrap_or_else(|| (self.resume_block(), self.scopes.len()));

        for scope in self.scopes.top_scopes(first_uncached) {
            target = build_diverge_scope(&mut self.cfg, scope.region_scope_span,
                                         scope, target, generator_drop, self.is_generator);
        }

        target
    }

    /// Utility function for *non*-scope code to build their own drops
    pub fn build_drop_and_replace(&mut self,
                                  block: BasicBlock,
                                  span: Span,
                                  location: Place<'tcx>,
                                  value: Operand<'tcx>) -> BlockAnd<()> {
        let source_info = self.source_info(span);
        let next_target = self.cfg.start_new_block();
        let diverge_target = self.diverge_cleanup();
        self.cfg.terminate(block, source_info,
                           TerminatorKind::DropAndReplace {
                               location,
                               value,
                               target: next_target,
                               unwind: Some(diverge_target),
                           });
        next_target.unit()
    }

    /// Creates an Assert terminator and return the success block.
    /// If the boolean condition operand is not the expected value,
    /// a runtime panic will be caused with the given message.
    pub fn assert(&mut self, block: BasicBlock,
                  cond: Operand<'tcx>,
                  expected: bool,
                  msg: AssertMessage<'tcx>,
                  span: Span)
                  -> BasicBlock {
        let source_info = self.source_info(span);

        let success_block = self.cfg.start_new_block();
        let cleanup = self.diverge_cleanup();

        self.cfg.terminate(block, source_info,
                           TerminatorKind::Assert {
                               cond,
                               expected,
                               msg,
                               target: success_block,
                               cleanup: Some(cleanup),
                           });

        success_block
    }

    // `match` arm scopes
    // ==================
    /// Unschedules any drops in the top scope.
    ///
    /// This is only needed for `match` arm scopes, because they have one
    /// entrance per pattern, but only one exit.
    pub(crate) fn clear_top_scope(&mut self, region_scope: region::Scope) {
        let top_scope = self.scopes.scopes.last_mut().unwrap();

        assert_eq!(top_scope.region_scope, region_scope);

        top_scope.drops.clear();
        top_scope.invalidate_cache(false, self.is_generator, true);
    }
}

/// Builds drops for pop_scope and exit_scope.
fn build_scope_drops<'tcx>(
    cfg: &mut CFG<'tcx>,
    is_generator: bool,
    scope: &Scope,
    mut block: BasicBlock,
    last_unwind_to: BasicBlock,
    arg_count: usize,
    generator_drop: bool,
) -> BlockAnd<()> {
    debug!("build_scope_drops({:?} -> {:?})", block, scope);

    // Build up the drops in evaluation order. The end result will
    // look like:
    //
    // [SDs, drops[n]] --..> [SDs, drop[1]] -> [SDs, drop[0]] -> [[SDs]]
    //               |                    |                 |
    //               :                    |                 |
    //                                    V                 V
    // [drop[n]] -...-> [drop[1]] ------> [drop[0]] ------> [last_unwind_to]
    //
    // The horizontal arrows represent the execution path when the drops return
    // successfully. The downwards arrows represent the execution path when the
    // drops panic (panicking while unwinding will abort, so there's no need for
    // another set of arrows).
    //
    // For generators, we unwind from a drop on a local to its StorageDead
    // statement. For other functions we don't worry about StorageDead. The
    // drops for the unwind path should have already been generated by
    // `diverge_cleanup_gen`.

    for drop_idx in (0..scope.drops.len()).rev() {
        let drop_data = &scope.drops[drop_idx];
        let source_info = scope.source_info(drop_data.span);
        let local = drop_data.local;
        match drop_data.kind {
            DropKind::Value => {
                let unwind_to = get_unwind_to(scope, is_generator, drop_idx, generator_drop)
                    .unwrap_or(last_unwind_to);

                let next = cfg.start_new_block();
                cfg.terminate(block, source_info, TerminatorKind::Drop {
                    location: local.into(),
                    target: next,
                    unwind: Some(unwind_to)
                });
                block = next;
            }
            DropKind::Storage => {
                // Only temps and vars need their storage dead.
                assert!(local.index() > arg_count);
                cfg.push(block, Statement {
                    source_info,
                    kind: StatementKind::StorageDead(local)
                });
            }
        }
    }
    block.unit()
}

fn get_unwind_to(
    scope: &Scope,
    is_generator: bool,
    unwind_from: usize,
    generator_drop: bool,
) -> Option<BasicBlock> {
    for drop_idx in (0..unwind_from).rev() {
        let drop_data = &scope.drops[drop_idx];
        match (is_generator, &drop_data.kind) {
            (true, DropKind::Storage) => {
                return Some(drop_data.cached_block.get(generator_drop).unwrap_or_else(|| {
                    span_bug!(drop_data.span, "cached block not present for {:?}", drop_data)
                }));
            }
            (false, DropKind::Value) => {
                return Some(drop_data.cached_block.get(generator_drop).unwrap_or_else(|| {
                    span_bug!(drop_data.span, "cached block not present for {:?}", drop_data)
                }));
            }
            _ => (),
        }
    }
    None
}

fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>,
                             span: Span,
                             scope: &mut Scope,
                             mut target: BasicBlock,
                             generator_drop: bool,
                             is_generator: bool)
                             -> BasicBlock
{
    // Build up the drops in **reverse** order. The end result will
    // look like:
    //
    //    [drops[n]] -...-> [drops[0]] -> [target]
    //
    // The code in this function reads from right to left. At each
    // point, we check for cached blocks representing the
    // remainder. If everything is cached, we'll just walk right to
    // left reading the cached results but never create anything.

    let source_scope = scope.source_scope;
    let source_info = |span| SourceInfo {
        span,
        scope: source_scope
    };

    // We keep track of StorageDead statements to prepend to our current block
    // and store them here, in reverse order.
    let mut storage_deads = vec![];

    let mut target_built_by_us = false;

    // Build up the drops. Here we iterate the vector in
    // *forward* order, so that we generate drops[0] first (right to
    // left in diagram above).
    debug!("build_diverge_scope({:?})", scope.drops);
    for (j, drop_data) in scope.drops.iter_mut().enumerate() {
        debug!("build_diverge_scope drop_data[{}]: {:?}", j, drop_data);
        // Only full value drops are emitted in the diverging path,
        // not StorageDead, except in the case of generators.
        //
        // Note: This may not actually be what we desire (are we
        // "freeing" stack storage as we unwind, or merely observing a
        // frozen stack)? In particular, the intent may have been to
        // match the behavior of clang, but on inspection eddyb says
        // this is not what clang does.
        match drop_data.kind {
            DropKind::Storage if is_generator => {
                storage_deads.push(Statement {
                    source_info: source_info(drop_data.span),
                    kind: StatementKind::StorageDead(drop_data.local)
                });
                if !target_built_by_us {
                    // We cannot add statements to an existing block, so we create a new
                    // block for our StorageDead statements.
                    let block = cfg.start_new_cleanup_block();
                    let source_info = SourceInfo { span: DUMMY_SP, scope: source_scope };
                    cfg.terminate(block, source_info,
                                    TerminatorKind::Goto { target: target });
                    target = block;
                    target_built_by_us = true;
                }
                *drop_data.cached_block.ref_mut(generator_drop) = Some(target);
            }
            DropKind::Storage => {}
            DropKind::Value => {
                let cached_block = drop_data.cached_block.ref_mut(generator_drop);
                target = if let Some(cached_block) = *cached_block {
                    storage_deads.clear();
                    target_built_by_us = false;
                    cached_block
                } else {
                    push_storage_deads(cfg, target, &mut storage_deads);
                    let block = cfg.start_new_cleanup_block();
                    cfg.terminate(
                        block,
                        source_info(drop_data.span),
                        TerminatorKind::Drop {
                            location: drop_data.local.into(),
                            target,
                            unwind: None
                        },
                    );
                    *cached_block = Some(block);
                    target_built_by_us = true;
                    block
                };
            }
        };
    }
    push_storage_deads(cfg, target, &mut storage_deads);
    *scope.cached_unwind.ref_mut(generator_drop) = Some(target);

    assert!(storage_deads.is_empty());
    debug!("build_diverge_scope({:?}, {:?}) = {:?}", scope, span, target);

    target
}

fn push_storage_deads(cfg: &mut CFG<'tcx>,
                      target: BasicBlock,
                      storage_deads: &mut Vec<Statement<'tcx>>) {
    if storage_deads.is_empty() { return; }
    let statements = &mut cfg.block_data_mut(target).statements;
    storage_deads.reverse();
    debug!("push_storage_deads({:?}), storage_deads={:?}, statements={:?}",
           target, storage_deads, statements);
    storage_deads.append(statements);
    mem::swap(statements, storage_deads);
    assert!(storage_deads.is_empty());
}
