Rollup merge of #136375 - Zalathar:llvm-di-builder, r=workingjubilee
cg_llvm: Replace some DIBuilder wrappers with LLVM-C API bindings (part 1) Part of #134001, follow-up to #136326, extracted from #134009. This PR performs an arbitrary subset of the LLVM-C binding migrations from #134009, which should make it less tedious to review. The remaining migrations can occur in one or more subsequent PRs.
This commit is contained in:
commit
75989e98d8
7 changed files with 121 additions and 98 deletions
|
@ -127,7 +127,7 @@ fn make_mir_scope<'ll, 'tcx>(
|
|||
})
|
||||
}
|
||||
None => unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateLexicalBlock(
|
||||
llvm::LLVMDIBuilderCreateLexicalBlock(
|
||||
DIB(cx),
|
||||
parent_scope.dbg_scope,
|
||||
file_metadata,
|
||||
|
|
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
|
@ -61,7 +61,7 @@ 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>,
|
||||
|
@ -69,18 +69,10 @@ pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
|
|||
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,
|
||||
|
@ -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 => {
|
||||
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
)
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
//! 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)]
|
||||
|
||||
|
@ -5,17 +17,18 @@ 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`.
|
||||
|
@ -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;
|
||||
|
@ -914,7 +965,6 @@ pub mod debuginfo {
|
|||
}
|
||||
}
|
||||
|
||||
use bitflags::bitflags;
|
||||
// These values **must** match with LLVMRustAllocKindFlags
|
||||
bitflags! {
|
||||
#[repr(transparent)]
|
||||
|
@ -1675,6 +1725,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();
|
||||
|
@ -1942,12 +2036,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,
|
||||
|
@ -2110,20 +2198,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>,
|
||||
|
@ -2248,14 +2322,6 @@ 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,
|
||||
|
@ -2263,12 +2329,6 @@ unsafe extern "C" {
|
|||
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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue