mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-31 21:47:15 +03:00
99 lines
3.0 KiB
Rust
99 lines
3.0 KiB
Rust
use std::ptr;
|
|
|
|
use libc::c_uint;
|
|
use rustc_abi::Align;
|
|
|
|
use crate::llvm::debuginfo::DIBuilder;
|
|
use crate::llvm::{self, Module, ToLlvmBool};
|
|
|
|
/// 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) };
|
|
}
|
|
}
|
|
|
|
/// Extension trait for defining safe wrappers and helper methods on
|
|
/// `&DIBuilder<'ll>`, without requiring it to be defined in the same crate.
|
|
pub(crate) trait DIBuilderExt<'ll> {
|
|
fn as_di_builder(&self) -> &DIBuilder<'ll>;
|
|
|
|
fn create_expression(&self, addr_ops: &[u64]) -> &'ll llvm::Metadata {
|
|
let this = self.as_di_builder();
|
|
unsafe { llvm::LLVMDIBuilderCreateExpression(this, addr_ops.as_ptr(), addr_ops.len()) }
|
|
}
|
|
|
|
fn create_static_variable(
|
|
&self,
|
|
scope: Option<&'ll llvm::Metadata>,
|
|
name: &str,
|
|
linkage_name: &str,
|
|
file: &'ll llvm::Metadata,
|
|
line_number: c_uint,
|
|
ty: &'ll llvm::Metadata,
|
|
is_local_to_unit: bool,
|
|
val: &'ll llvm::Value,
|
|
decl: Option<&'ll llvm::Metadata>,
|
|
align: Option<Align>,
|
|
) -> &'ll llvm::Metadata {
|
|
let this = self.as_di_builder();
|
|
let align_in_bits = align.map_or(0, |align| align.bits() as u32);
|
|
|
|
// `LLVMDIBuilderCreateGlobalVariableExpression` would assert if we
|
|
// gave it a null `Expr` pointer, so give it an empty expression
|
|
// instead, which is what the C++ `createGlobalVariableExpression`
|
|
// method would do if given a null `DIExpression` pointer.
|
|
let expr = self.create_expression(&[]);
|
|
|
|
let global_var_expr = unsafe {
|
|
llvm::LLVMDIBuilderCreateGlobalVariableExpression(
|
|
this,
|
|
scope,
|
|
name.as_ptr(),
|
|
name.len(),
|
|
linkage_name.as_ptr(),
|
|
linkage_name.len(),
|
|
file,
|
|
line_number,
|
|
ty,
|
|
is_local_to_unit.to_llvm_bool(),
|
|
expr,
|
|
decl,
|
|
align_in_bits,
|
|
)
|
|
};
|
|
|
|
unsafe { llvm::LLVMGlobalSetMetadata(val, llvm::MD_dbg, global_var_expr) };
|
|
|
|
global_var_expr
|
|
}
|
|
}
|
|
|
|
impl<'ll> DIBuilderExt<'ll> for &DIBuilder<'ll> {
|
|
fn as_di_builder(&self) -> &DIBuilder<'ll> {
|
|
self
|
|
}
|
|
|
|
// All other methods have default bodies that rely on `as_di_builder`.
|
|
}
|