blob: 5d874631ca1acf75314af0cc691559cbffc218c9 [file] [log] [blame] [edit]
use libc::c_uint;
use rustc_abi::Align;
use crate::llvm::debuginfo::DIBuilder;
use crate::llvm::{self, ToLlvmBool};
/// 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`.
}