codegen: Generate dbg_value for the ref statement

This commit is contained in:
dianqk
2025-06-18 22:04:48 +08:00
parent 85b2f70693
commit 1bd89bd42e
12 changed files with 431 additions and 14 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,