1
Fork 0

Introduce DIBuilderBox, an owning pointer to DIBuilder

This commit is contained in:
Zalathar 2025-01-31 16:29:09 +11:00
parent 854f22563c
commit 832fcfb64f
4 changed files with 53 additions and 20 deletions

View file

@ -931,7 +931,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
unsafe { unsafe {
let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile( let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile(
debug_context.builder, debug_context.builder.as_ref(),
name_in_debuginfo.as_c_char_ptr(), name_in_debuginfo.as_c_char_ptr(),
name_in_debuginfo.len(), name_in_debuginfo.len(),
work_dir.as_c_char_ptr(), work_dir.as_c_char_ptr(),
@ -944,7 +944,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
); );
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
debug_context.builder, debug_context.builder.as_ref(),
dwarf_const::DW_LANG_Rust, dwarf_const::DW_LANG_Rust,
compile_unit_file, compile_unit_file,
producer.as_c_char_ptr(), producer.as_c_char_ptr(),

View file

@ -34,7 +34,7 @@ use crate::builder::Builder;
use crate::common::{AsCCharPtr, CodegenCx}; use crate::common::{AsCCharPtr, CodegenCx};
use crate::llvm; use crate::llvm;
use crate::llvm::debuginfo::{ use crate::llvm::debuginfo::{
DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType, DIArray, DIBuilderBox, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
DIVariable, DIVariable,
}; };
use crate::value::Value; use crate::value::Value;
@ -61,7 +61,7 @@ const DW_TAG_arg_variable: c_uint = 0x101;
/// A context object for maintaining all state needed by the debuginfo module. /// A context object for maintaining all state needed by the debuginfo module.
pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> { pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
llmod: &'ll llvm::Module, llmod: &'ll llvm::Module,
builder: &'ll mut DIBuilder<'ll>, builder: DIBuilderBox<'ll>,
created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>, created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
type_map: metadata::TypeMap<'ll, 'tcx>, type_map: metadata::TypeMap<'ll, 'tcx>,
@ -69,18 +69,10 @@ pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
recursion_marker_type: OnceCell<&'ll DIType>, recursion_marker_type: OnceCell<&'ll DIType>,
} }
impl Drop for CodegenUnitDebugContext<'_, '_> {
fn drop(&mut self) {
unsafe {
llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
}
}
}
impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
pub(crate) fn new(llmod: &'ll llvm::Module) -> Self { pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
debug!("CodegenUnitDebugContext::new"); debug!("CodegenUnitDebugContext::new");
let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; let builder = DIBuilderBox::new(llmod);
// DIBuilder inherits context from the module, so we'd better use the same one // DIBuilder inherits context from the module, so we'd better use the same one
CodegenUnitDebugContext { CodegenUnitDebugContext {
llmod, llmod,
@ -93,7 +85,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
} }
pub(crate) fn finalize(&self, sess: &Session) { pub(crate) fn finalize(&self, sess: &Session) {
unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder) }; unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder.as_ref()) };
match sess.target.debuginfo_kind { match sess.target.debuginfo_kind {
DebuginfoKind::Dwarf | DebuginfoKind::DwarfDsym => { DebuginfoKind::Dwarf | DebuginfoKind::DwarfDsym => {

View file

@ -41,7 +41,7 @@ pub(crate) fn debug_context<'a, 'll, 'tcx>(
#[inline] #[inline]
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub(crate) fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { pub(crate) fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> {
cx.dbg_cx.as_ref().unwrap().builder cx.dbg_cx.as_ref().unwrap().builder.as_ref()
} }
pub(crate) fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { pub(crate) fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {

View file

@ -789,12 +789,50 @@ pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void
pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
pub mod debuginfo { pub mod debuginfo {
use std::ptr;
use bitflags::bitflags; use bitflags::bitflags;
use super::{InvariantOpaque, Metadata}; use super::{InvariantOpaque, Metadata};
use crate::llvm::{self, Module};
/// Opaque target type for references to an LLVM debuginfo builder.
///
/// `&'_ DIBuilder<'ll>` corresponds to `LLVMDIBuilderRef`, which is the
/// LLVM-C wrapper for `DIBuilder *`.
///
/// Debuginfo builders are created and destroyed during codegen, so the
/// builder reference typically has a shorter lifetime than the LLVM
/// session (`'ll`) that it participates in.
#[repr(C)] #[repr(C)]
pub struct DIBuilder<'a>(InvariantOpaque<'a>); pub struct DIBuilder<'ll>(InvariantOpaque<'ll>);
/// Owning pointer to a `DIBuilder<'ll>` that will dispose of the builder
/// when dropped. Use `.as_ref()` to get the underlying `&DIBuilder`
/// needed for debuginfo FFI calls.
pub(crate) struct DIBuilderBox<'ll> {
raw: ptr::NonNull<DIBuilder<'ll>>,
}
impl<'ll> DIBuilderBox<'ll> {
pub(crate) fn new(llmod: &'ll Module) -> Self {
let raw = unsafe { llvm::LLVMCreateDIBuilder(llmod) };
let raw = ptr::NonNull::new(raw).unwrap();
Self { raw }
}
pub(crate) fn as_ref(&self) -> &DIBuilder<'ll> {
// SAFETY: This is an owning pointer, so `&DIBuilder` is valid
// for as long as `&self` is.
unsafe { self.raw.as_ref() }
}
}
impl<'ll> Drop for DIBuilderBox<'ll> {
fn drop(&mut self) {
unsafe { llvm::LLVMDisposeDIBuilder(self.raw) };
}
}
pub type DIDescriptor = Metadata; pub type DIDescriptor = Metadata;
pub type DILocation = Metadata; pub type DILocation = Metadata;
@ -1672,6 +1710,13 @@ unsafe extern "C" {
) -> &'a Value; ) -> &'a Value;
} }
// FFI bindings for `DIBuilder` functions in the LLVM-C API.
// Try to keep these in the same order as in `llvm/include/llvm-c/DebugInfo.h`.
unsafe extern "C" {
pub(crate) fn LLVMCreateDIBuilder<'ll>(M: &'ll Module) -> *mut DIBuilder<'ll>;
pub(crate) fn LLVMDisposeDIBuilder<'ll>(Builder: ptr::NonNull<DIBuilder<'ll>>);
}
#[link(name = "llvm-wrapper", kind = "static")] #[link(name = "llvm-wrapper", kind = "static")]
unsafe extern "C" { unsafe extern "C" {
pub fn LLVMRustInstallErrorHandlers(); pub fn LLVMRustInstallErrorHandlers();
@ -1939,10 +1984,6 @@ unsafe extern "C" {
ValueLen: size_t, ValueLen: size_t,
); );
pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
pub fn LLVMRustDIBuilderDispose<'a>(Builder: &'a mut DIBuilder<'a>);
pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder<'_>); pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder<'_>);
pub fn LLVMRustDIBuilderCreateCompileUnit<'a>( pub fn LLVMRustDIBuilderCreateCompileUnit<'a>(