rustc_codegen_llvm/debuginfo/
di_builder.rs

1use libc::c_uint;
2use rustc_abi::Align;
3
4use crate::llvm::debuginfo::DIBuilder;
5use crate::llvm::{self, ToLlvmBool};
6
7/// Extension trait for defining safe wrappers and helper methods on
8/// `&DIBuilder<'ll>`, without requiring it to be defined in the same crate.
9pub(crate) trait DIBuilderExt<'ll> {
10    fn as_di_builder(&self) -> &DIBuilder<'ll>;
11
12    fn create_expression(&self, addr_ops: &[u64]) -> &'ll llvm::Metadata {
13        let this = self.as_di_builder();
14        unsafe { llvm::LLVMDIBuilderCreateExpression(this, addr_ops.as_ptr(), addr_ops.len()) }
15    }
16
17    fn create_static_variable(
18        &self,
19        scope: Option<&'ll llvm::Metadata>,
20        name: &str,
21        linkage_name: &str,
22        file: &'ll llvm::Metadata,
23        line_number: c_uint,
24        ty: &'ll llvm::Metadata,
25        is_local_to_unit: bool,
26        val: &'ll llvm::Value,
27        decl: Option<&'ll llvm::Metadata>,
28        align: Option<Align>,
29    ) -> &'ll llvm::Metadata {
30        let this = self.as_di_builder();
31        let align_in_bits = align.map_or(0, |align| align.bits() as u32);
32
33        // `LLVMDIBuilderCreateGlobalVariableExpression` would assert if we
34        // gave it a null `Expr` pointer, so give it an empty expression
35        // instead, which is what the C++ `createGlobalVariableExpression`
36        // method would do if given a null `DIExpression` pointer.
37        let expr = self.create_expression(&[]);
38
39        let global_var_expr = unsafe {
40            llvm::LLVMDIBuilderCreateGlobalVariableExpression(
41                this,
42                scope,
43                name.as_ptr(),
44                name.len(),
45                linkage_name.as_ptr(),
46                linkage_name.len(),
47                file,
48                line_number,
49                ty,
50                is_local_to_unit.to_llvm_bool(),
51                expr,
52                decl,
53                align_in_bits,
54            )
55        };
56
57        unsafe { llvm::LLVMGlobalSetMetadata(val, llvm::MD_dbg, global_var_expr) };
58
59        global_var_expr
60    }
61}
62
63impl<'ll> DIBuilderExt<'ll> for &DIBuilder<'ll> {
64    fn as_di_builder(&self) -> &DIBuilder<'ll> {
65        self
66    }
67
68    // All other methods have default bodies that rely on `as_di_builder`.
69}