about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm
diff options
context:
space:
mode:
authordianqk <dianqk@dianqk.net>2025-06-18 22:04:48 +0800
committerdianqk <dianqk@dianqk.net>2025-10-02 14:55:51 +0800
commit1bd89bd42e0bb6f29b8af5d6bdf3f756196bb8ee (patch)
tree8d7ac71c287300c9ce4f2b3a1cfbe05b998bf9ae /compiler/rustc_codegen_llvm
parent85b2f706939528b5796d98e82c183637f8338cd1 (diff)
downloadrust-1bd89bd42e0bb6f29b8af5d6bdf3f756196bb8ee.tar.gz
rust-1bd89bd42e0bb6f29b8af5d6bdf3f756196bb8ee.zip
codegen: Generate `dbg_value` for the ref statement
Diffstat (limited to 'compiler/rustc_codegen_llvm')
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs53
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs9
3 files changed, 63 insertions, 2 deletions
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs b/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
index 40842915222..52d04625749 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
@@ -35,3 +35,6 @@ declare_constant!(DW_OP_plus_uconst: u64);
 /// Double-checked by a static assertion in `RustWrapper.cpp`.
 #[allow(non_upper_case_globals)]
 pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000;
+// It describes the actual value of a source variable which might not exist in registers or in memory.
+#[allow(non_upper_case_globals)]
+pub(crate) const DW_OP_stack_value: u64 = 0x9f;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index af64e4ebed0..c6ad1c2e18e 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -156,7 +156,7 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
         variable_alloca: Self::Value,
         direct_offset: Size,
         indirect_offsets: &[Size],
-        fragment: Option<Range<Size>>,
+        fragment: &Option<Range<Size>>,
     ) {
         use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst};
 
@@ -187,7 +187,6 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
             llvm::LLVMDIBuilderCreateExpression(di_builder, addr_ops.as_ptr(), addr_ops.len())
         };
         unsafe {
-            // FIXME(eddyb) replace `llvm.dbg.declare` with `llvm.dbg.addr`.
             llvm::LLVMDIBuilderInsertDeclareRecordAtEnd(
                 di_builder,
                 variable_alloca,
@@ -199,6 +198,56 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
         };
     }
 
+    fn dbg_var_value(
+        &mut self,
+        dbg_var: &'ll DIVariable,
+        dbg_loc: &'ll DILocation,
+        value: Self::Value,
+        direct_offset: Size,
+        indirect_offsets: &[Size],
+        fragment: &Option<Range<Size>>,
+    ) {
+        use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst, DW_OP_stack_value};
+
+        // Convert the direct and indirect offsets and fragment byte range to address ops.
+        let mut addr_ops = SmallVec::<[u64; 8]>::new();
+
+        if direct_offset.bytes() > 0 {
+            addr_ops.push(DW_OP_plus_uconst);
+            addr_ops.push(direct_offset.bytes() as u64);
+            addr_ops.push(DW_OP_stack_value);
+        }
+        for &offset in indirect_offsets {
+            addr_ops.push(DW_OP_deref);
+            if offset.bytes() > 0 {
+                addr_ops.push(DW_OP_plus_uconst);
+                addr_ops.push(offset.bytes() as u64);
+            }
+        }
+        if let Some(fragment) = fragment {
+            // `DW_OP_LLVM_fragment` takes as arguments the fragment's
+            // offset and size, both of them in bits.
+            addr_ops.push(DW_OP_LLVM_fragment);
+            addr_ops.push(fragment.start.bits() as u64);
+            addr_ops.push((fragment.end - fragment.start).bits() as u64);
+        }
+
+        let di_builder = DIB(self.cx());
+        let addr_expr = unsafe {
+            llvm::LLVMDIBuilderCreateExpression(di_builder, addr_ops.as_ptr(), addr_ops.len())
+        };
+        unsafe {
+            llvm::LLVMDIBuilderInsertDbgValueRecordAtEnd(
+                di_builder,
+                value,
+                dbg_var,
+                addr_expr,
+                dbg_loc,
+                self.llbb(),
+            );
+        }
+    }
+
     fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) {
         unsafe {
             llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index e9f92267a7d..7fbba029407 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1991,6 +1991,15 @@ unsafe extern "C" {
         Block: &'ll BasicBlock,
     ) -> &'ll DbgRecord;
 
+    pub(crate) fn LLVMDIBuilderInsertDbgValueRecordAtEnd<'ll>(
+        Builder: &DIBuilder<'ll>,
+        Val: &'ll Value,
+        VarInfo: &'ll Metadata,
+        Expr: &'ll Metadata,
+        DebugLoc: &'ll Metadata,
+        Block: &'ll BasicBlock,
+    ) -> &'ll DbgRecord;
+
     pub(crate) fn LLVMDIBuilderCreateAutoVariable<'ll>(
         Builder: &DIBuilder<'ll>,
         Scope: &'ll Metadata,