about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2019-09-13 10:28:14 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2019-10-31 20:00:16 +0200
commitc58e6b5752058760263fa85cd4057d8784f3b852 (patch)
treea4683091ac6bd55c6137d5fe2ce7c4ff5f594b83 /src
parent5059a3c7d4afd00458d5bd2f033a0b9c91bd8bf8 (diff)
downloadrust-c58e6b5752058760263fa85cd4057d8784f3b852.tar.gz
rust-c58e6b5752058760263fa85cd4057d8784f3b852.zip
rustc_codegen_ssa: move local variable debuginfo to mir::debuginfo.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs22
-rw-r--r--src/librustc_codegen_ssa/mir/debuginfo.rs179
-rw-r--r--src/librustc_codegen_ssa/mir/mod.rs263
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs4
4 files changed, 227 insertions, 241 deletions
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 604deffcf94..2e5dc3db31a 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -7,6 +7,7 @@ use rustc_index::vec::{Idx, IndexVec};
 use rustc::mir::{self, Location, TerminatorKind};
 use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::traversal;
+use rustc::session::config::DebugInfo;
 use rustc::ty;
 use rustc::ty::layout::{LayoutOf, HasTyCtxt};
 use syntax_pos::DUMMY_SP;
@@ -21,13 +22,20 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     analyzer.visit_body(mir);
 
-    for (index, (ty, span)) in mir.local_decls.iter()
-        .map(|l| (l.ty, l.source_info.span))
-        .enumerate()
+    for (local, decl) in mir.local_decls.iter_enumerated()
     {
-        let ty = fx.monomorphize(&ty);
-        debug!("local {} has type {:?}", index, ty);
-        let layout = fx.cx.spanned_layout_of(ty, span);
+        // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
+        // of putting everything in allocas just so we can use llvm.dbg.declare.
+        if fx.cx.sess().opts.debuginfo == DebugInfo::Full {
+            if mir.local_kind(local) == mir::LocalKind::Arg || decl.name.is_some() {
+                analyzer.not_ssa(local);
+                continue;
+            }
+        }
+
+        let ty = fx.monomorphize(&decl.ty);
+        debug!("local {:?} has type `{}`", local, ty);
+        let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
         if fx.cx.is_backend_immediate(layout) {
             // These sorts of types are immediates that we can store
             // in an Value without an alloca.
@@ -40,7 +48,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             // (e.g., structs) into an alloca unconditionally, just so
             // that we don't have to deal with having two pathways
             // (gep vs extractvalue etc).
-            analyzer.not_ssa(mir::Local::new(index));
+            analyzer.not_ssa(local);
         }
     }
 
diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs
index a253523f181..d6b91c1f6bb 100644
--- a/src/librustc_codegen_ssa/mir/debuginfo.rs
+++ b/src/librustc_codegen_ssa/mir/debuginfo.rs
@@ -1,10 +1,16 @@
+use rustc_index::vec::Idx;
 use rustc::hir::def_id::CrateNum;
 use rustc::mir;
+use rustc::session::config::DebugInfo;
+use rustc::ty::{self, UpvarSubsts};
+use rustc::ty::layout::HasTyCtxt;
+use rustc_target::abi::{Variants, VariantIdx};
 use crate::traits::*;
 
 use syntax_pos::{DUMMY_SP, BytePos, Span};
+use syntax::symbol::kw;
 
-use super::FunctionCx;
+use super::{FunctionCx, LocalRef};
 
 pub enum FunctionDebugContext<D> {
     RegularContext(FunctionDebugContextData<D>),
@@ -142,4 +148,175 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             scope_metadata
         }
     }
+
+    pub fn debug_declare_locals(&self, bx: &mut Bx) {
+        let tcx = self.cx.tcx();
+        let upvar_debuginfo = &self.mir.__upvar_debuginfo_codegen_only_do_not_use;
+
+        if bx.sess().opts.debuginfo != DebugInfo::Full {
+            return;
+        }
+
+        for (local, local_ref) in self.locals.iter_enumerated() {
+            if local == mir::RETURN_PLACE {
+                continue;
+            }
+
+            // FIXME(eddyb) add debuginfo for unsized places too.
+            let place = match local_ref {
+                LocalRef::Place(place) => place,
+                _ => continue,
+            };
+
+            let decl = &self.mir.local_decls[local];
+            let (name, kind) = if self.mir.local_kind(local) == mir::LocalKind::Arg {
+                let arg_index = local.index() - 1;
+
+                // Add debuginfo even to unnamed arguments.
+                // FIXME(eddyb) is this really needed?
+                let name = if arg_index == 0 && !upvar_debuginfo.is_empty() {
+                    // Hide closure environments from debuginfo.
+                    // FIXME(eddyb) shouldn't `ArgumentVariable` indices
+                    // be offset to account for the hidden environment?
+                    None
+                } else {
+                    Some(decl.name.unwrap_or(kw::Invalid))
+                };
+                (name, VariableKind::ArgumentVariable(arg_index + 1))
+            } else {
+                (decl.name, VariableKind::LocalVariable)
+            };
+            if let Some(name) = name {
+                let (scope, span) = self.debug_loc(mir::SourceInfo {
+                    span: decl.source_info.span,
+                    scope: decl.visibility_scope,
+                });
+                if let Some(scope) = scope {
+                    bx.declare_local(&self.debug_context, name, place.layout.ty, scope,
+                        VariableAccess::DirectVariable { alloca: place.llval },
+                        kind, span);
+                }
+            }
+        }
+
+        // Declare closure captures as if they were local variables.
+        // FIXME(eddyb) generalize this to `name => place` mappings.
+        let upvar_scope = if !upvar_debuginfo.is_empty() {
+            self.scopes[mir::OUTERMOST_SOURCE_SCOPE].scope_metadata
+        } else {
+            None
+        };
+        if let Some(scope) = upvar_scope {
+            let place = match self.locals[mir::Local::new(1)] {
+                LocalRef::Place(place) => place,
+                _ => bug!(),
+            };
+
+            let pin_did = tcx.lang_items().pin_type();
+            let (closure_layout, env_ref) = match place.layout.ty.kind {
+                ty::RawPtr(ty::TypeAndMut { ty, .. }) |
+                ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
+                ty::Adt(def, substs) if Some(def.did) == pin_did => {
+                    match substs.type_at(0).kind {
+                        ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
+                        _ => (place.layout, false),
+                    }
+                }
+                _ => (place.layout, false)
+            };
+
+            let (def_id, upvar_substs) = match closure_layout.ty.kind {
+                ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
+                ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
+                _ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty)
+            };
+            let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
+
+            let extra_locals = {
+                let upvars = upvar_debuginfo
+                    .iter()
+                    .zip(upvar_tys)
+                    .enumerate()
+                    .map(|(i, (upvar, ty))| {
+                        (None, i, upvar.debug_name, upvar.by_ref, ty, scope, DUMMY_SP)
+                    });
+
+                let generator_fields = self.mir.generator_layout.as_ref().map(|generator_layout| {
+                    let (def_id, gen_substs) = match closure_layout.ty.kind {
+                        ty::Generator(def_id, substs, _) => (def_id, substs),
+                        _ => bug!("generator layout without generator substs"),
+                    };
+                    let state_tys = gen_substs.as_generator().state_tys(def_id, tcx);
+
+                    generator_layout.variant_fields.iter()
+                        .zip(state_tys)
+                        .enumerate()
+                        .flat_map(move |(variant_idx, (fields, tys))| {
+                            let variant_idx = Some(VariantIdx::from(variant_idx));
+                            fields.iter()
+                                .zip(tys)
+                                .enumerate()
+                                .filter_map(move |(i, (field, ty))| {
+                                    let decl = &generator_layout.
+                                        __local_debuginfo_codegen_only_do_not_use[*field];
+                                    if let Some(name) = decl.name {
+                                        let ty = self.monomorphize(&ty);
+                                        let (var_scope, var_span) = self.debug_loc(mir::SourceInfo {
+                                            span: decl.source_info.span,
+                                            scope: decl.visibility_scope,
+                                        });
+                                        let var_scope = var_scope.unwrap_or(scope);
+                                        Some((variant_idx, i, name, false, ty, var_scope, var_span))
+                                    } else {
+                                        None
+                                    }
+                            })
+                        })
+                }).into_iter().flatten();
+
+                upvars.chain(generator_fields)
+            };
+
+            for (variant_idx, field, name, by_ref, ty, var_scope, var_span) in extra_locals {
+                let fields = match variant_idx {
+                    Some(variant_idx) => {
+                        match &closure_layout.variants {
+                            Variants::Multiple { variants, .. } => {
+                                &variants[variant_idx].fields
+                            },
+                            _ => bug!("variant index on univariant layout"),
+                        }
+                    }
+                    None => &closure_layout.fields,
+                };
+                let byte_offset_of_var_in_env = fields.offset(field).bytes();
+
+                let ops = bx.debuginfo_upvar_ops_sequence(byte_offset_of_var_in_env);
+
+                // The environment and the capture can each be indirect.
+                let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
+
+                let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.kind) {
+                    ty
+                } else {
+                    ops = &ops[..ops.len() - 1];
+                    ty
+                };
+
+                let variable_access = VariableAccess::IndirectVariable {
+                    alloca: place.llval,
+                    address_operations: &ops
+                };
+                bx.declare_local(
+                    &self.debug_context,
+                    name,
+                    ty,
+                    var_scope,
+                    variable_access,
+                    VariableKind::LocalVariable,
+                    var_span
+                );
+            }
+        }
+    }
 }
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 650584fbdf7..8e9e2139373 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -1,22 +1,17 @@
-use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts, Instance};
+use rustc::ty::{self, Ty, TypeFoldable, Instance};
 use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Body};
-use rustc::session::config::DebugInfo;
 use rustc_target::abi::call::{FnType, PassMode};
-use rustc_target::abi::{Variants, VariantIdx};
 use crate::base;
 use crate::traits::*;
 
-use syntax_pos::DUMMY_SP;
-use syntax::symbol::kw;
-
 use std::iter;
 
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 
 use self::analyze::CleanupKind;
-use self::debuginfo::{VariableAccess, VariableKind, FunctionDebugContext};
+use self::debuginfo::FunctionDebugContext;
 use self::place::PlaceRef;
 use rustc::mir::traversal;
 
@@ -189,62 +184,38 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             let layout = bx.layout_of(fx.monomorphize(&decl.ty));
             assert!(!layout.ty.has_erasable_regions());
 
-            if let Some(name) = decl.name {
-                // User variable
-                let debug_scope = fx.scopes[decl.visibility_scope];
-                let dbg = debug_scope.is_valid() &&
-                    bx.sess().opts.debuginfo == DebugInfo::Full;
+            if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
+                debug!("alloc: {:?} (return place) -> place", local);
+                let llretptr = bx.get_param(0);
+                return LocalRef::Place(PlaceRef::new_sized(llretptr, layout));
+            }
 
-                if !memory_locals.contains(local) && !dbg {
-                    debug!("alloc: {:?} ({}) -> operand", local, name);
-                    return LocalRef::new_operand(&mut bx, layout);
-                }
+            let decl_name = decl.name.map(|name| name.as_str());
+            let decl_name = decl_name.as_ref().map(|name| &name[..]);
+            let name;
+            let name = if let Some(name) = decl_name {
+                name
+            } else {
+                // FIXME(eddyb) compute something else for the name so no work is done
+                // unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
+                name = format!("{:?}", local);
+                &name
+            };
 
+            if memory_locals.contains(local) {
                 debug!("alloc: {:?} ({}) -> place", local, name);
                 if layout.is_unsized() {
-                    let indirect_place =
-                        PlaceRef::alloca_unsized_indirect(&mut bx, layout);
+                    let indirect_place = PlaceRef::alloca_unsized_indirect(&mut bx, layout);
                     bx.set_var_name(indirect_place.llval, name);
-                    // FIXME: add an appropriate debuginfo
                     LocalRef::UnsizedPlace(indirect_place)
                 } else {
                     let place = PlaceRef::alloca(&mut bx, layout);
                     bx.set_var_name(place.llval, name);
-                    if dbg {
-                        let (scope, span) = fx.debug_loc(mir::SourceInfo {
-                            span: decl.source_info.span,
-                            scope: decl.visibility_scope,
-                        });
-                        bx.declare_local(&fx.debug_context, name, layout.ty, scope.unwrap(),
-                            VariableAccess::DirectVariable { alloca: place.llval },
-                            VariableKind::LocalVariable, span);
-                    }
                     LocalRef::Place(place)
                 }
             } else {
-                // Temporary or return place
-                if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
-                    debug!("alloc: {:?} (return place) -> place", local);
-                    let llretptr = bx.get_param(0);
-                    LocalRef::Place(PlaceRef::new_sized(llretptr, layout))
-                } else if memory_locals.contains(local) {
-                    debug!("alloc: {:?} -> place", local);
-                    if layout.is_unsized() {
-                        let indirect_place = PlaceRef::alloca_unsized_indirect(&mut bx, layout);
-                        bx.set_var_name(indirect_place.llval, format_args!("{:?}", local));
-                        LocalRef::UnsizedPlace(indirect_place)
-                    } else {
-                        let place = PlaceRef::alloca(&mut bx, layout);
-                        bx.set_var_name(place.llval, format_args!("{:?}", local));
-                        LocalRef::Place(place)
-                    }
-                } else {
-                    // If this is an immediate local, we do not create an
-                    // alloca in advance. Instead we wait until we see the
-                    // definition and update the operand there.
-                    debug!("alloc: {:?} -> operand", local);
-                    LocalRef::new_operand(&mut bx, layout)
-                }
+                debug!("alloc: {:?} ({}) -> operand", local, name);
+                LocalRef::new_operand(&mut bx, layout)
             }
         };
 
@@ -255,6 +226,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             .collect()
     };
 
+    // Apply debuginfo to the newly allocated locals.
+    fx.debug_declare_locals(&mut bx);
+
     // Branch to the START block, if it's not the entry block.
     if reentrant_start_block {
         bx.br(fx.blocks[mir::START_BLOCK]);
@@ -363,18 +337,9 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     memory_locals: &BitSet<mir::Local>,
 ) -> Vec<LocalRef<'tcx, Bx::Value>> {
     let mir = fx.mir;
-    let tcx = fx.cx.tcx();
     let mut idx = 0;
     let mut llarg_idx = fx.fn_ty.ret.is_indirect() as usize;
 
-    // Get the argument scope, if it exists and if we need it.
-    let arg_scope = fx.scopes[mir::OUTERMOST_SOURCE_SCOPE];
-    let arg_scope = if bx.sess().opts.debuginfo == DebugInfo::Full {
-        arg_scope.scope_metadata
-    } else {
-        None
-    };
-
     mir.args_iter().enumerate().map(|(arg_index, local)| {
         let arg_decl = &mir.local_decls[local];
 
@@ -409,22 +374,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 bx.store_fn_arg(arg, &mut llarg_idx, pr_field);
             }
 
-            // Now that we have one alloca that contains the aggregate value,
-            // we can create one debuginfo entry for the argument.
-            arg_scope.map(|scope| {
-                let variable_access = VariableAccess::DirectVariable {
-                    alloca: place.llval
-                };
-                bx.declare_local(
-                    &fx.debug_context,
-                    arg_decl.name.unwrap_or(kw::Invalid),
-                    arg_ty, scope,
-                    variable_access,
-                    VariableKind::ArgumentVariable(arg_index + 1),
-                    DUMMY_SP
-                );
-            });
-
             return LocalRef::Place(place);
         }
 
@@ -435,21 +384,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             bx.set_var_name(va_list.llval, name);
             bx.va_start(va_list.llval);
 
-            arg_scope.map(|scope| {
-                let variable_access = VariableAccess::DirectVariable {
-                    alloca: va_list.llval
-                };
-                bx.declare_local(
-                    &fx.debug_context,
-                    arg_decl.name.unwrap_or(kw::Invalid),
-                    va_list.layout.ty,
-                    scope,
-                    variable_access,
-                    VariableKind::ArgumentVariable(arg_index + 1),
-                    DUMMY_SP
-                );
-            });
-
             return LocalRef::Place(va_list);
         }
 
@@ -459,7 +393,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             llarg_idx += 1;
         }
 
-        if arg_scope.is_none() && !memory_locals.contains(local) {
+        if !memory_locals.contains(local) {
             // We don't have to cast or keep the argument in the alloca.
             // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
             // of putting everything in allocas just so we can use llvm.dbg.declare.
@@ -493,14 +427,14 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             }
         }
 
-        let place = if arg.is_sized_indirect() {
+        if arg.is_sized_indirect() {
             // Don't copy an indirect argument to an alloca, the caller
             // already put it in a temporary alloca and gave it up.
             // FIXME: lifetimes
             let llarg = bx.get_param(llarg_idx);
             bx.set_var_name(llarg, &name);
             llarg_idx += 1;
-            PlaceRef::new_sized(llarg, arg.layout)
+            LocalRef::Place(PlaceRef::new_sized(llarg, arg.layout))
         } else if arg.is_unsized_indirect() {
             // As the storage for the indirect argument lives during
             // the whole function call, we just copy the fat pointer.
@@ -513,149 +447,12 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout);
             bx.set_var_name(tmp.llval, name);
             indirect_operand.store(bx, tmp);
-            tmp
+            LocalRef::UnsizedPlace(tmp)
         } else {
             let tmp = PlaceRef::alloca(bx, arg.layout);
             bx.set_var_name(tmp.llval, name);
             bx.store_fn_arg(arg, &mut llarg_idx, tmp);
-            tmp
-        };
-        let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use;
-        arg_scope.map(|scope| {
-            // Is this a regular argument?
-            if arg_index > 0 || upvar_debuginfo.is_empty() {
-                // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
-                // need to insert a deref here, but the C ABI uses a pointer and a copy using the
-                // byval attribute, for which LLVM always does the deref itself,
-                // so we must not add it.
-                let variable_access = VariableAccess::DirectVariable {
-                    alloca: place.llval
-                };
-
-                bx.declare_local(
-                    &fx.debug_context,
-                    arg_decl.name.unwrap_or(kw::Invalid),
-                    arg.layout.ty,
-                    scope,
-                    variable_access,
-                    VariableKind::ArgumentVariable(arg_index + 1),
-                    DUMMY_SP
-                );
-                return;
-            }
-
-            let pin_did = tcx.lang_items().pin_type();
-            // Or is it the closure environment?
-            let (closure_layout, env_ref) = match arg.layout.ty.kind {
-                ty::RawPtr(ty::TypeAndMut { ty, .. }) |
-                ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
-                ty::Adt(def, substs) if Some(def.did) == pin_did => {
-                    match substs.type_at(0).kind {
-                        ty::Ref(_, ty, _)  => (bx.layout_of(ty), true),
-                        _ => (arg.layout, false),
-                    }
-                }
-                _ => (arg.layout, false)
-            };
-
-            let (def_id, upvar_substs) = match closure_layout.ty.kind {
-                ty::Closure(def_id, substs) => (def_id,
-                    UpvarSubsts::Closure(substs)),
-                ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
-                _ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty)
-            };
-            let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
-
-            let extra_locals = {
-                let upvars = upvar_debuginfo
-                    .iter()
-                    .zip(upvar_tys)
-                    .enumerate()
-                    .map(|(i, (upvar, ty))| {
-                        (None, i, upvar.debug_name, upvar.by_ref, ty, scope, DUMMY_SP)
-                    });
-
-                let generator_fields = mir.generator_layout.as_ref().map(|generator_layout| {
-                    let (def_id, gen_substs) = match closure_layout.ty.kind {
-                        ty::Generator(def_id, substs, _) => (def_id, substs),
-                        _ => bug!("generator layout without generator substs"),
-                    };
-                    let state_tys = gen_substs.as_generator().state_tys(def_id, tcx);
-
-                    generator_layout.variant_fields.iter()
-                        .zip(state_tys)
-                        .enumerate()
-                        .flat_map(move |(variant_idx, (fields, tys))| {
-                            let variant_idx = Some(VariantIdx::from(variant_idx));
-                            fields.iter()
-                                .zip(tys)
-                                .enumerate()
-                                .filter_map(move |(i, (field, ty))| {
-                                    let decl = &generator_layout.
-                                        __local_debuginfo_codegen_only_do_not_use[*field];
-                                    if let Some(name) = decl.name {
-                                        let ty = fx.monomorphize(&ty);
-                                        let (var_scope, var_span) = fx.debug_loc(mir::SourceInfo {
-                                            span: decl.source_info.span,
-                                            scope: decl.visibility_scope,
-                                        });
-                                        let var_scope = var_scope.unwrap_or(scope);
-                                        Some((variant_idx, i, name, false, ty, var_scope, var_span))
-                                    } else {
-                                        None
-                                    }
-                            })
-                        })
-                }).into_iter().flatten();
-
-                upvars.chain(generator_fields)
-            };
-
-            for (variant_idx, field, name, by_ref, ty, var_scope, var_span) in extra_locals {
-                let fields = match variant_idx {
-                    Some(variant_idx) => {
-                        match &closure_layout.variants {
-                            Variants::Multiple { variants, .. } => {
-                                &variants[variant_idx].fields
-                            },
-                            _ => bug!("variant index on univariant layout"),
-                        }
-                    }
-                    None => &closure_layout.fields,
-                };
-                let byte_offset_of_var_in_env = fields.offset(field).bytes();
-
-                let ops = bx.debuginfo_upvar_ops_sequence(byte_offset_of_var_in_env);
-
-                // The environment and the capture can each be indirect.
-                let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
-
-                let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.kind) {
-                    ty
-                } else {
-                    ops = &ops[..ops.len() - 1];
-                    ty
-                };
-
-                let variable_access = VariableAccess::IndirectVariable {
-                    alloca: place.llval,
-                    address_operations: &ops
-                };
-                bx.declare_local(
-                    &fx.debug_context,
-                    name,
-                    ty,
-                    var_scope,
-                    variable_access,
-                    VariableKind::LocalVariable,
-                    var_span
-                );
-            }
-        });
-        if arg.is_unsized_indirect() {
-            LocalRef::UnsizedPlace(place)
-        } else {
-            LocalRef::Place(place)
+            LocalRef::Place(tmp)
         }
     }).collect()
 }
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 1d1bc2a81a2..3e7c4ef49fb 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -68,6 +68,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         }
     }
 
+    // FIXME(eddyb) pass something else for the name so no work is done
+    // unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
     pub fn alloca<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
         layout: TyLayout<'tcx>,
@@ -78,6 +80,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
     }
 
     /// Returns a place for an indirect reference to an unsized place.
+    // FIXME(eddyb) pass something else for the name so no work is done
+    // unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
     pub fn alloca_unsized_indirect<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
         layout: TyLayout<'tcx>,