summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorWesley Wiser <wesleywiser@microsoft.com>2022-12-07 13:48:34 -0500
committerWesley Wiser <wesleywiser@microsoft.com>2022-12-08 20:38:23 -0500
commit7253057887b6de77e6847844311da517d2ada1eb (patch)
treef0fa2e56c5451afb1edcf4488162aefa1d5e7aa1 /compiler/rustc_codegen_ssa/src
parentb33d1e26b220062e23bb202c6765663c157d971b (diff)
downloadrust-7253057887b6de77e6847844311da517d2ada1eb.tar.gz
rust-7253057887b6de77e6847844311da517d2ada1eb.zip
Don't generate pointer loads to spills unless necessary
In order for LLVM to correctly generate debuginfo for msvc, we sometimes
need to spill arguments to the stack and perform some direct & indirect
offsets into the value. Previously, this code always performed those
actions, even when not required as LLVM would clean it up during
optimization.

However, when MIR inlining is enabled, this can cause problems as the
operations occur prior to the spilled value being initialized. To solve
this, we first calculate the necessary offsets using just the type which
is side-effect free and does not alter the LLVM IR. Then, if we are in a
situation which requires us to generate the LLVM IR (and this situation
only occurs for arguments, not local variables) then we perform the same
calculation again, this time generating the appropriate LLVM IR as we
go.
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs29
1 files changed, 27 insertions, 2 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 8935d42548f..b7982b633f5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -103,6 +103,28 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
     }
 }
 
+impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
+    for TyAndLayout<'tcx>
+{
+    fn deref(&self, bx: &mut Bx) -> Self {
+        bx.cx().layout_of(
+            self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)).ty,
+        )
+    }
+
+    fn layout(&self) -> TyAndLayout<'tcx> {
+        *self
+    }
+
+    fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
+        self.field(bx.cx(), field.index())
+    }
+
+    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
+        self.for_variant(bx.cx(), variant)
+    }
+}
+
 struct DebugInfoOffset<T> {
     /// Offset from the `base` used to calculate the debuginfo offset.
     direct_offset: Size,
@@ -340,8 +362,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let Some(dbg_var) = var.dbg_var else { continue };
             let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
 
-            let DebugInfoOffset { direct_offset, indirect_offsets, result: place } =
-                calculate_debuginfo_offset(bx, local, &var, base);
+            let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
+                calculate_debuginfo_offset(bx, local, &var, base.layout);
 
             // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
             // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -359,6 +381,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
 
             if should_create_individual_allocas {
+                let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
+                    calculate_debuginfo_offset(bx, local, &var, base);
+
                 // Create a variable which will be a pointer to the actual value
                 let ptr_ty = bx.tcx().mk_ty(ty::RawPtr(ty::TypeAndMut {
                     mutbl: mir::Mutability::Mut,