Skip to content

Commit

Permalink
Use constants for DWARF opcodes, instead of FFI calls
Browse files Browse the repository at this point in the history
  • Loading branch information
Zalathar committed Jan 5, 2025
1 parent 8daa6b6 commit dd63b74
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 24 deletions.
8 changes: 8 additions & 0 deletions compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,11 @@ pub(crate) const DW_ATE_float: c_uint = 0x04;
pub(crate) const DW_ATE_signed: c_uint = 0x05;
pub(crate) const DW_ATE_unsigned: c_uint = 0x07;
pub(crate) const DW_ATE_UTF: c_uint = 0x10;

// DWARF expression operators

pub(crate) const DW_OP_deref: u64 = 0x06;
pub(crate) const DW_OP_plus_uconst: u64 = 0x23;
/// Defined by LLVM in `llvm/include/llvm/BinaryFormat/Dwarf.h`.
/// Double-checked by a static assertion in `RustWrapper.cpp`.
pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000;
15 changes: 6 additions & 9 deletions compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,29 +153,26 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
indirect_offsets: &[Size],
fragment: Option<Range<Size>>,
) {
use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst};

// Convert the direct and indirect offsets and fragment byte range to address ops.
// FIXME(eddyb) use `const`s instead of getting the values via FFI,
// the values should match the ones in the DWARF standard anyway.
let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
let op_llvm_fragment = || unsafe { llvm::LLVMRustDIBuilderCreateOpLLVMFragment() };
let mut addr_ops = SmallVec::<[u64; 8]>::new();

if direct_offset.bytes() > 0 {
addr_ops.push(op_plus_uconst());
addr_ops.push(DW_OP_plus_uconst);
addr_ops.push(direct_offset.bytes() as u64);
}
for &offset in indirect_offsets {
addr_ops.push(op_deref());
addr_ops.push(DW_OP_deref);
if offset.bytes() > 0 {
addr_ops.push(op_plus_uconst());
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(op_llvm_fragment());
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);
}
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2177,9 +2177,6 @@ unsafe extern "C" {
Location: &'a DILocation,
BD: c_uint,
) -> Option<&'a DILocation>;
pub fn LLVMRustDIBuilderCreateOpDeref() -> u64;
pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> u64;
pub fn LLVMRustDIBuilderCreateOpLLVMFragment() -> u64;

pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
Expand Down
18 changes: 6 additions & 12 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ using namespace llvm;
using namespace llvm::sys;
using namespace llvm::object;

// This opcode is an LLVM detail that could hypothetically change, so verify
// that the hard-coded value in `dwarf_const.rs` still agrees with LLVM.
static_assert(
dwarf::DW_OP_LLVM_fragment == 0x1000,
"DW_OP_LLVM_fragment has changed from the value used by Rust-side code");

// LLVMAtomicOrdering is already an enum - don't create another
// one.
static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
Expand Down Expand Up @@ -1397,18 +1403,6 @@ LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location,
return wrap(NewLoc.has_value() ? NewLoc.value() : nullptr);
}

extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
return dwarf::DW_OP_deref;
}

extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
return dwarf::DW_OP_plus_uconst;
}

extern "C" uint64_t LLVMRustDIBuilderCreateOpLLVMFragment() {
return dwarf::DW_OP_LLVM_fragment;
}

extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
auto OS = RawRustStringOstream(Str);
unwrap<llvm::Type>(Ty)->print(OS);
Expand Down

0 comments on commit dd63b74

Please sign in to comment.