about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src/mir
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2020-05-30 15:02:32 -0400
committerWesley Wiser <wwiser@gmail.com>2020-12-06 20:48:25 -0500
commit01aec8d18556be5e8d498c2f331b9015b7befde2 (patch)
tree319bf10bc8a93fda56f200deedadf76c7a534b8e /compiler/rustc_codegen_ssa/src/mir
parentb776d1c3e3db8befabb123ebb1e46c3531eaed46 (diff)
downloadrust-01aec8d18556be5e8d498c2f331b9015b7befde2.tar.gz
rust-01aec8d18556be5e8d498c2f331b9015b7befde2.zip
[mir-opt] Allow debuginfo to be generated for a constant or a Place
Prior to this commit, debuginfo was always generated by mapping a name
to a Place. This has the side-effect that `SimplifyLocals` cannot remove
locals that are only used for debuginfo because their other uses have
been const-propagated.

To allow these locals to be removed, we now allow debuginfo to point to
a constant value. The `ConstProp` pass detects when debuginfo points to
a local with a known constant value and replaces it with the value. This
allows the later `SimplifyLocals` pass to remove the local.
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/mir')
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs105
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs2
3 files changed, 76 insertions, 35 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index c8001b8daf0..3a85c268e0e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -11,7 +11,7 @@ use super::FunctionCx;
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn eval_mir_constant_to_operand(
-        &mut self,
+        &self,
         bx: &mut Bx,
         constant: &mir::Constant<'tcx>,
     ) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
@@ -21,7 +21,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     }
 
     pub fn eval_mir_constant(
-        &mut self,
+        &self,
         constant: &mir::Constant<'tcx>,
     ) -> Result<ConstValue<'tcx>, ErrorHandled> {
         match self.monomorphize(constant.literal).val {
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index c4191a4e23d..d5b2cbaa558 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
 use rustc_target::abi::{LayoutOf, Size};
 
-use super::operand::OperandValue;
+use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
 use super::{FunctionCx, LocalRef};
 
@@ -116,6 +116,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         span
     }
 
+    fn spill_operand_to_stack(
+        operand: &OperandRef<'tcx, Bx::Value>,
+        name: Option<String>,
+        bx: &mut Bx,
+    ) -> PlaceRef<'tcx, Bx::Value> {
+        // "Spill" the value onto the stack, for debuginfo,
+        // without forcing non-debuginfo uses of the local
+        // to also load from the stack every single time.
+        // FIXME(#68817) use `llvm.dbg.value` instead,
+        // at least for the cases which LLVM handles correctly.
+        let spill_slot = PlaceRef::alloca(bx, operand.layout);
+        if let Some(name) = name {
+            bx.set_var_name(spill_slot.llval, &(name + ".dbg.spill"));
+        }
+        operand.val.store(bx, spill_slot);
+        spill_slot
+    }
+
     /// Apply debuginfo and/or name, after creating the `alloca` for a local,
     /// or initializing the local with an operand (whichever applies).
     pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
@@ -226,17 +244,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     return;
                 }
 
-                // "Spill" the value onto the stack, for debuginfo,
-                // without forcing non-debuginfo uses of the local
-                // to also load from the stack every single time.
-                // FIXME(#68817) use `llvm.dbg.value` instead,
-                // at least for the cases which LLVM handles correctly.
-                let spill_slot = PlaceRef::alloca(bx, operand.layout);
-                if let Some(name) = name {
-                    bx.set_var_name(spill_slot.llval, &(name + ".dbg.spill"));
-                }
-                operand.val.store(bx, spill_slot);
-                spill_slot
+                Self::spill_operand_to_stack(operand, name, bx)
             }
 
             LocalRef::Place(place) => *place,
@@ -308,6 +316,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     /// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`.
     pub fn compute_per_local_var_debug_info(
         &self,
+        bx: &mut Bx,
     ) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
         let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
 
@@ -322,31 +331,63 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             } else {
                 None
             };
+
             let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
-                let place = var.place;
-                let var_ty = self.monomorphized_place_ty(place.as_ref());
-                let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
-                    && place.projection.is_empty()
-                    && var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE
-                {
-                    let arg_index = place.local.index() - 1;
-
-                    // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
-                    // offset in closures to account for the hidden environment?
-                    // Also, is this `+ 1` needed at all?
-                    VariableKind::ArgumentVariable(arg_index + 1)
-                } else {
-                    VariableKind::LocalVariable
+                let (var_ty, var_kind) = match var.value {
+                    mir::VarDebugInfoContents::Place(place) => {
+                        let var_ty = self.monomorphized_place_ty(place.as_ref());
+                        let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
+                            && place.projection.is_empty()
+                            && var.source_info.scope == mir::OUTERMOST_SOURCE_SCOPE
+                        {
+                            let arg_index = place.local.index() - 1;
+
+                            // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
+                            // offset in closures to account for the hidden environment?
+                            // Also, is this `+ 1` needed at all?
+                            VariableKind::ArgumentVariable(arg_index + 1)
+                        } else {
+                            VariableKind::LocalVariable
+                        };
+                        (var_ty, var_kind)
+                    }
+                    mir::VarDebugInfoContents::Const(c) => {
+                        let ty = self.monomorphize(c.literal.ty);
+                        (ty, VariableKind::LocalVariable)
+                    }
                 };
+
                 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
             });
 
-            per_local[var.place.local].push(PerLocalVarDebugInfo {
-                name: var.name,
-                source_info: var.source_info,
-                dbg_var,
-                projection: var.place.projection,
-            });
+            match var.value {
+                mir::VarDebugInfoContents::Place(place) => {
+                    per_local[place.local].push(PerLocalVarDebugInfo {
+                        name: var.name,
+                        source_info: var.source_info,
+                        dbg_var,
+                        projection: place.projection,
+                    });
+                }
+                mir::VarDebugInfoContents::Const(c) => {
+                    if let Some(dbg_var) = dbg_var {
+                        let dbg_loc = match self.dbg_loc(var.source_info) {
+                            Some(dbg_loc) => dbg_loc,
+                            None => continue,
+                        };
+
+                        if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) {
+                            let base = Self::spill_operand_to_stack(
+                                &operand,
+                                Some(var.name.to_string()),
+                                bx,
+                            );
+
+                            bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[]);
+                        }
+                    }
+                }
+            }
         }
         Some(per_local)
     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 640f805d5e8..285140060be 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -186,7 +186,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         caller_location: None,
     };
 
-    fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info();
+    fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx);
 
     for const_ in &mir.required_consts {
         if let Err(err) = fx.eval_mir_constant(const_) {