Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cg_llvm: Replace some DIBuilder wrappers with LLVM-C API bindings (part 1) #136375

Merged
merged 8 commits into from
Feb 5, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fn make_mir_scope<'ll, 'tcx>(
})
}
None => unsafe {
llvm::LLVMRustDIBuilderCreateLexicalBlock(
llvm::LLVMDIBuilderCreateLexicalBlock(
DIB(cx),
parent_scope.dbg_scope,
file_metadata,
Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(

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

let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
debug_context.builder,
debug_context.builder.as_ref(),
dwarf_const::DW_LANG_Rust,
compile_unit_file,
producer.as_c_char_ptr(),
Expand Down Expand Up @@ -1641,7 +1641,14 @@ pub(crate) fn extend_scope_to_file<'ll>(
file: &SourceFile,
) -> &'ll DILexicalBlock {
let file_metadata = file_metadata(cx, file);
unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
unsafe {
llvm::LLVMDIBuilderCreateLexicalBlockFile(
DIB(cx),
scope_metadata,
file_metadata,
/* Discriminator (default) */ 0u32,
)
}
}

fn tuple_field_name(field_index: usize) -> Cow<'static, str> {
Expand Down
18 changes: 5 additions & 13 deletions compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::builder::Builder;
use crate::common::{AsCCharPtr, CodegenCx};
use crate::llvm;
use crate::llvm::debuginfo::{
DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
DIArray, DIBuilderBox, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
DIVariable,
};
use crate::value::Value;
Expand All @@ -61,26 +61,18 @@ const DW_TAG_arg_variable: c_uint = 0x101;
/// A context object for maintaining all state needed by the debuginfo module.
pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
llmod: &'ll llvm::Module,
builder: &'ll mut DIBuilder<'ll>,
builder: DIBuilderBox<'ll>,
created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,

type_map: metadata::TypeMap<'ll, 'tcx>,
namespace_map: RefCell<DefIdMap<&'ll DIScope>>,
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> {
pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
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
CodegenUnitDebugContext {
llmod,
Expand All @@ -93,7 +85,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
}

pub(crate) fn finalize(&self, sess: &Session) {
unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder) };
unsafe { llvm::LLVMDIBuilderFinalize(self.builder.as_ref()) };

match sess.target.debuginfo_kind {
DebuginfoKind::Dwarf | DebuginfoKind::DwarfDsym => {
Expand Down Expand Up @@ -582,7 +574,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
(line, col)
};

unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) }
unsafe { llvm::LLVMDIBuilderCreateDebugLocation(self.llcx, line, col, scope, inlined_at) }
}

fn create_vtable_debuginfo(
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, Instance};

use super::utils::{DIB, debug_context};
use crate::common::{AsCCharPtr, CodegenCx};
use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::DIScope;

Expand Down Expand Up @@ -33,12 +33,12 @@ pub(crate) fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'l
};

let scope = unsafe {
llvm::LLVMRustDIBuilderCreateNameSpace(
llvm::LLVMDIBuilderCreateNameSpace(
DIB(cx),
parent_scope,
namespace_name_string.as_c_char_ptr(),
namespace_name_string.as_ptr(),
namespace_name_string.len(),
false, // ExportSymbols (only relevant for C++ anonymous namespaces)
llvm::False, // ExportSymbols (only relevant for C++ anonymous namespaces)
)
};

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub(crate) fn debug_context<'a, 'll, 'tcx>(
#[inline]
#[allow(non_snake_case)]
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 {
Expand Down
140 changes: 100 additions & 40 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
//! Bindings to the LLVM-C API (`LLVM*`), and to our own `extern "C"` wrapper
//! functions around the unstable LLVM C++ API (`LLVMRust*`).
//!
//! ## Passing pointer/length strings as `*const c_uchar`
//!
//! Normally it's a good idea for Rust-side bindings to match the corresponding
//! C-side function declarations as closely as possible. But when passing `&str`
//! or `&[u8]` data as a pointer/length pair, it's more convenient to declare
//! the Rust-side pointer as `*const c_uchar` instead of `*const c_char`.
//! Both pointer types have the same ABI, and using `*const c_uchar` avoids
//! the need for an extra cast from `*const u8` on the Rust side.

#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]

use std::fmt::Debug;
use std::marker::PhantomData;
use std::ptr;

use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
use bitflags::bitflags;
use libc::{c_char, c_int, c_uchar, c_uint, c_ulonglong, c_void, size_t};
use rustc_macros::TryFromU32;
use rustc_target::spec::SymbolVisibility;

use super::RustString;
use super::debuginfo::{
DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DILocation, DINameSpace,
DISPFlags, DIScope, DISubprogram, DISubrange, DITemplateTypeParameter, DIType, DIVariable,
DebugEmissionKind, DebugNameTableKind,
DIFile, DIFlags, DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram,
DISubrange, DITemplateTypeParameter, DIType, DIVariable, DebugEmissionKind, DebugNameTableKind,
};
use crate::llvm;

/// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`,
/// which has a different ABI from Rust or C++ `bool`.
Expand Down Expand Up @@ -789,12 +802,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 mod debuginfo {
use std::ptr;

use bitflags::bitflags;

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)]
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 DILocation = Metadata;
Expand Down Expand Up @@ -914,7 +965,6 @@ pub mod debuginfo {
}
}

use bitflags::bitflags;
// These values **must** match with LLVMRustAllocKindFlags
bitflags! {
#[repr(transparent)]
Expand Down Expand Up @@ -1672,6 +1722,50 @@ unsafe extern "C" {
) -> &'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`.
//
// FIXME(#134001): Audit all `Option` parameters, especially in lists, to check
// that they really are nullable on the C/C++ side. LLVM doesn't appear to
// actually document which ones are nullable.
unsafe extern "C" {
pub(crate) fn LLVMCreateDIBuilder<'ll>(M: &'ll Module) -> *mut DIBuilder<'ll>;
pub(crate) fn LLVMDisposeDIBuilder<'ll>(Builder: ptr::NonNull<DIBuilder<'ll>>);

pub(crate) fn LLVMDIBuilderFinalize<'ll>(Builder: &DIBuilder<'ll>);

pub(crate) fn LLVMDIBuilderCreateNameSpace<'ll>(
Builder: &DIBuilder<'ll>,
ParentScope: Option<&'ll Metadata>,
Name: *const c_uchar,
NameLen: size_t,
ExportSymbols: llvm::Bool,
) -> &'ll Metadata;

pub(crate) fn LLVMDIBuilderCreateLexicalBlock<'ll>(
Builder: &DIBuilder<'ll>,
Scope: &'ll Metadata,
File: &'ll Metadata,
Line: c_uint,
Column: c_uint,
) -> &'ll Metadata;

pub(crate) fn LLVMDIBuilderCreateLexicalBlockFile<'ll>(
Builder: &DIBuilder<'ll>,
Scope: &'ll Metadata,
File: &'ll Metadata,
Discriminator: c_uint, // (optional "DWARF path discriminator"; default is 0)
) -> &'ll Metadata;

pub(crate) fn LLVMDIBuilderCreateDebugLocation<'ll>(
Ctx: &'ll Context,
Line: c_uint,
Column: c_uint,
Scope: &'ll Metadata,
InlinedAt: Option<&'ll Metadata>,
) -> &'ll Metadata;
}

#[link(name = "llvm-wrapper", kind = "static")]
unsafe extern "C" {
pub fn LLVMRustInstallErrorHandlers();
Expand Down Expand Up @@ -1939,12 +2033,6 @@ unsafe extern "C" {
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 LLVMRustDIBuilderCreateCompileUnit<'a>(
Builder: &DIBuilder<'a>,
Lang: c_uint,
Expand Down Expand Up @@ -2107,20 +2195,6 @@ unsafe extern "C" {
Type: &'a DIType,
) -> &'a DIDerivedType;

pub fn LLVMRustDIBuilderCreateLexicalBlock<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIScope,
File: &'a DIFile,
Line: c_uint,
Col: c_uint,
) -> &'a DILexicalBlock;

pub fn LLVMRustDIBuilderCreateLexicalBlockFile<'a>(
Builder: &DIBuilder<'a>,
Scope: &'a DIScope,
File: &'a DIFile,
) -> &'a DILexicalBlock;

pub fn LLVMRustDIBuilderCreateStaticVariable<'a>(
Builder: &DIBuilder<'a>,
Context: Option<&'a DIScope>,
Expand Down Expand Up @@ -2245,27 +2319,13 @@ unsafe extern "C" {
Ty: &'a DIType,
) -> &'a DITemplateTypeParameter;

pub fn LLVMRustDIBuilderCreateNameSpace<'a>(
Builder: &DIBuilder<'a>,
Scope: Option<&'a DIScope>,
Name: *const c_char,
NameLen: size_t,
ExportSymbols: bool,
) -> &'a DINameSpace;

pub fn LLVMRustDICompositeTypeReplaceArrays<'a>(
Builder: &DIBuilder<'a>,
CompositeType: &'a DIType,
Elements: Option<&'a DIArray>,
Params: Option<&'a DIArray>,
);

pub fn LLVMRustDIBuilderCreateDebugLocation<'a>(
Line: c_uint,
Column: c_uint,
Scope: &'a DIScope,
InlinedAt: Option<&'a DILocation>,
) -> &'a DILocation;
pub fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
Location: &'a DILocation,
BD: c_uint,
Expand Down
Loading
Loading