Skip to main content

inkwell/
debug_info.rs

1//! Debug symbols - `DebugInfoBuilder` interface
2//!
3//! # Example usage
4//!
5//! ## Setting up the module for holding debug info:
6//! ```ignore
7//! let context = Context::create();
8//! let module = context.create_module("bin");
9//!
10//! let debug_metadata_version = context.i32_type().const_int(3, false);
11//! module.add_basic_value_flag(
12//!     "Debug Info Version",
13//!     inkwell::module::FlagBehavior::Warning,
14//!     debug_metadata_version,
15//! );
16//! let builder = context.create_builder();
17//! let (dibuilder, compile_unit) = module.create_debug_info_builder(
18//!     true,
19//!     /* language */ inkwell::debug_info::DWARFSourceLanguage::C,
20//!     /* filename */ "source_file",
21//!     /* directory */ ".",
22//!     /* producer */ "my llvm compiler frontend",
23//!     /* is_optimized */ false,
24//!     /* compiler command line flags */ "",
25//!     /* runtime_ver */ 0,
26//!     /* split_name */ "",
27//!     /* kind */ inkwell::debug_info::DWARFEmissionKind::Full,
28//!     /* dwo_id */ 0,
29//!     /* split_debug_inling */ false,
30//!     /* debug_info_for_profiling */ false,
31//! );
32//! ```
33//! ## Creating function debug info
34//! ```ignore
35//!  let ditype = dibuilder.create_basic_type(
36//!      "type_name",
37//!      0_u64,
38//!      0x00,
39//!      inkwell::debug_info::DIFlags::Public,
40//!  ).unwrap();
41//!  let subroutine_type = dibuilder.create_subroutine_type(
42//!      compile_unit.get_file(),
43//!      /* return type */ Some(ditype.as_type()),
44//!      /* parameter types */ &[],
45//!      inkwell::debug_info::DIFlags::Public,
46//!  );
47//!  let func_scope: DISubprogram<'_> = dibuilder.create_function(
48//!      /* scope */ compile_unit.as_debug_info_scope(),
49//!      /* func name */ "main",
50//!      /* linkage_name */ None,
51//!      /* file */ compile_unit.get_file(),
52//!      /* line_no */ 0,
53//!      /* DIType */ subroutine_type,
54//!      /* is_local_to_unit */ true,
55//!      /* is_definition */ true,
56//!      /* scope_line */ 0,
57//!      /* flags */ inkwell::debug_info::DIFlags::Public,
58//!      /* is_optimized */ false,
59//!  );
60//! ```
61//! The `DISubprogram` value must be attached to the generated `FunctionValue`:
62//! ```ignore
63//! /* after creating function: */
64//!     let fn_val = module.add_function(fn_name_str, fn_type, None);
65//!     fn_val.set_subprogram(func_scope);
66//! ```
67//!
68//! ## Setting debug locations
69//! ```ignore
70//! let lexical_block = dibuilder.create_lexical_block(
71//!         /* scope */ func_scope.as_debug_info_scope(),
72//!         /* file */ compile_unit.get_file(),
73//!         /* line_no */ 0,
74//!         /* column_no */ 0);
75//!
76//! let loc = dibuilder
77//!     .create_debug_location(&context, /* line */ 0, /* column */ 0,
78//!     /* current_scope */ lexical_block.as_debug_info_scope(),
79//!     /* inlined_at */ None);
80//! builder.set_current_debug_location(&context, loc);
81//!
82//! // Create global variable
83//! let gv = module.add_global(context.i64_type(), Some(inkwell::AddressSpace::Global), "gv");
84//!
85//!
86//! let const_v = di.create_constant_expression(10);
87//!
88//! let gv_debug = di.create_global_variable_expression(cu.get_file().as_debug_info_scope(), "gv", "", cu.get_file(), 1, ditype.as_type(), true, Some(const_v), None, 8);
89//!
90//! let meta_value: inkwell::values::BasicMetadataValueEnum = gv_debug.as_metadata_value(&context).into();
91//! let metadata = context.metadata_node(&[meta_value]);
92//! gv.set_metadata(metadata, 0);//dbg
93//!
94//! ```
95//!
96//! ## Finalize debug info
97//! Before any kind of code generation (including verification passes; they generate code and
98//! validate debug info), do:
99//! ```ignore
100//! dibuilder.finalize();
101//! ```
102
103use crate::basic_block::BasicBlock;
104use crate::context::{AsContextRef, Context};
105pub use crate::debug_info::flags::{DIFlags, DIFlagsConstants};
106use crate::module::Module;
107use crate::values::{AsValueRef, BasicValueEnum, InstructionValue, MetadataValue, PointerValue};
108use crate::AddressSpace;
109
110use llvm_sys::core::LLVMMetadataAsValue;
111
112use llvm_sys::debuginfo::LLVMDIBuilderCreateTypedef;
113pub use llvm_sys::debuginfo::LLVMDWARFTypeEncoding;
114use llvm_sys::debuginfo::LLVMDebugMetadataVersion;
115use llvm_sys::debuginfo::LLVMDisposeDIBuilder;
116use llvm_sys::debuginfo::LLVMMetadataReplaceAllUsesWith;
117use llvm_sys::debuginfo::LLVMTemporaryMDNode;
118use llvm_sys::debuginfo::{LLVMCreateDIBuilder, LLVMCreateDIBuilderDisallowUnresolved};
119use llvm_sys::debuginfo::{
120    LLVMDIBuilderCreateArrayType, LLVMDIBuilderCreateAutoVariable, LLVMDIBuilderCreateBasicType,
121    LLVMDIBuilderCreateCompileUnit, LLVMDIBuilderCreateDebugLocation, LLVMDIBuilderCreateExpression,
122    LLVMDIBuilderCreateFile, LLVMDIBuilderCreateFunction, LLVMDIBuilderCreateLexicalBlock,
123    LLVMDIBuilderCreateMemberType, LLVMDIBuilderCreateNameSpace, LLVMDIBuilderCreateParameterVariable,
124    LLVMDIBuilderCreatePointerType, LLVMDIBuilderCreateReferenceType, LLVMDIBuilderCreateStructType,
125    LLVMDIBuilderCreateSubroutineType, LLVMDIBuilderCreateUnionType, LLVMDIBuilderFinalize,
126    LLVMDIBuilderGetOrCreateSubrange, LLVMDILocationGetColumn, LLVMDILocationGetLine, LLVMDILocationGetScope,
127    LLVMDITypeGetAlignInBits, LLVMDITypeGetOffsetInBits, LLVMDITypeGetSizeInBits,
128};
129
130use llvm_sys::debuginfo::{LLVMDIBuilderCreateEnumerationType, LLVMDIBuilderCreateEnumerator};
131
132#[llvm_versions(..19.1)]
133use llvm_sys::debuginfo::{
134    LLVMDIBuilderInsertDbgValueBefore, LLVMDIBuilderInsertDeclareAtEnd, LLVMDIBuilderInsertDeclareBefore,
135};
136
137#[llvm_versions(19.1..)]
138use llvm_sys::debuginfo::{
139    LLVMDIBuilderInsertDbgValueRecordBefore as LLVMDIBuilderInsertDbgValueBefore,
140    LLVMDIBuilderInsertDeclareRecordAtEnd as LLVMDIBuilderInsertDeclareAtEnd,
141    LLVMDIBuilderInsertDeclareRecordBefore as LLVMDIBuilderInsertDeclareBefore,
142};
143
144#[llvm_versions(19.1..)]
145use llvm_sys::prelude::LLVMValueRef;
146
147use llvm_sys::debuginfo::{LLVMDIBuilderCreateConstantValueExpression, LLVMDIBuilderCreateGlobalVariableExpression};
148use llvm_sys::prelude::{LLVMDIBuilderRef, LLVMMetadataRef};
149use std::convert::TryInto;
150use std::marker::PhantomData;
151use std::ops::Range;
152
153/// Gets the version of debug metadata produced by the current LLVM version.
154pub fn debug_metadata_version() -> libc::c_uint {
155    unsafe { LLVMDebugMetadataVersion() }
156}
157
158/// A builder object to create debug info metadata. Used along with `Builder` while producing
159/// IR. Created by `Module::create_debug_info_builder`. See `debug_info` module level
160/// documentation for more.
161#[derive(Debug, PartialEq, Eq)]
162pub struct DebugInfoBuilder<'ctx> {
163    pub(crate) builder: LLVMDIBuilderRef,
164    _marker: PhantomData<&'ctx Context>,
165}
166
167/// Any kind of debug information scope (i.e. visibility of a source code symbol). Scopes are
168/// created by special `DebugInfoBuilder` methods (eg `create_lexical_block`) and can be turned
169/// into a `DIScope` with the `AsDIScope::as_debug_info_scope` trait method.
170#[derive(Clone, Copy, Debug, PartialEq, Eq)]
171pub struct DIScope<'ctx> {
172    metadata_ref: LLVMMetadataRef,
173    _marker: PhantomData<&'ctx Context>,
174}
175
176impl DIScope<'_> {
177    /// Acquires the underlying raw pointer belonging to this `DIScope` type.
178    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
179        self.metadata_ref
180    }
181}
182
183/// Specific scopes (i.e. `DILexicalBlock`) can be turned into a `DIScope` with the
184/// `AsDIScope::as_debug_info_scope` trait method.
185pub trait AsDIScope<'ctx> {
186    #[allow(clippy::wrong_self_convention)]
187    fn as_debug_info_scope(self) -> DIScope<'ctx>;
188}
189
190impl<'ctx> DebugInfoBuilder<'ctx> {
191    pub(crate) fn new(
192        module: &Module,
193        allow_unresolved: bool,
194        language: DWARFSourceLanguage,
195        filename: &str,
196        directory: &str,
197        producer: &str,
198        is_optimized: bool,
199        flags: &str,
200        runtime_ver: libc::c_uint,
201        split_name: &str,
202        kind: DWARFEmissionKind,
203        dwo_id: libc::c_uint,
204        split_debug_inlining: bool,
205        debug_info_for_profiling: bool,
206        #[cfg(any(
207            feature = "llvm11-0",
208            feature = "llvm12-0",
209            feature = "llvm13-0",
210            feature = "llvm14-0",
211            feature = "llvm15-0",
212            feature = "llvm16-0",
213            feature = "llvm17-0",
214            feature = "llvm18-1",
215            feature = "llvm19-1",
216            feature = "llvm20-1",
217            feature = "llvm21-1"
218        ))]
219        sysroot: &str,
220        #[cfg(any(
221            feature = "llvm11-0",
222            feature = "llvm12-0",
223            feature = "llvm13-0",
224            feature = "llvm14-0",
225            feature = "llvm15-0",
226            feature = "llvm16-0",
227            feature = "llvm17-0",
228            feature = "llvm18-1",
229            feature = "llvm19-1",
230            feature = "llvm20-1",
231            feature = "llvm21-1"
232        ))]
233        sdk: &str,
234    ) -> (Self, DICompileUnit<'ctx>) {
235        let builder = unsafe {
236            if allow_unresolved {
237                LLVMCreateDIBuilder(module.module.get())
238            } else {
239                LLVMCreateDIBuilderDisallowUnresolved(module.module.get())
240            }
241        };
242
243        let builder = DebugInfoBuilder {
244            builder,
245            _marker: PhantomData,
246        };
247
248        let file = builder.create_file(filename, directory);
249
250        let cu = builder.create_compile_unit(
251            language,
252            file,
253            producer,
254            is_optimized,
255            flags,
256            runtime_ver,
257            split_name,
258            kind,
259            dwo_id,
260            split_debug_inlining,
261            debug_info_for_profiling,
262            #[cfg(any(
263                feature = "llvm11-0",
264                feature = "llvm12-0",
265                feature = "llvm13-0",
266                feature = "llvm14-0",
267                feature = "llvm15-0",
268                feature = "llvm16-0",
269                feature = "llvm17-0",
270                feature = "llvm18-1",
271                feature = "llvm19-1",
272                feature = "llvm20-1",
273                feature = "llvm21-1",
274            ))]
275            sysroot,
276            #[cfg(any(
277                feature = "llvm11-0",
278                feature = "llvm12-0",
279                feature = "llvm13-0",
280                feature = "llvm14-0",
281                feature = "llvm15-0",
282                feature = "llvm16-0",
283                feature = "llvm17-0",
284                feature = "llvm18-1",
285                feature = "llvm19-1",
286                feature = "llvm20-1",
287                feature = "llvm21-1",
288            ))]
289            sdk,
290        );
291
292        (builder, cu)
293    }
294
295    /// Acquires the underlying raw pointer belonging to this `DebugInfoBuilder` type.
296    pub fn as_mut_ptr(&self) -> LLVMDIBuilderRef {
297        self.builder
298    }
299
300    /// A DICompileUnit provides an anchor for all debugging information generated during this instance of compilation.
301    ///
302    /// * `language` - Source programming language
303    /// * `file` - File info
304    /// * `producer` - Identify the producer of debugging information and code. Usually this is a compiler version string.
305    /// * `is_optimized` - A boolean flag which indicates whether optimization is enabled or not.
306    /// * `flags` - This string lists command line options. This string is directly embedded in debug info output which may be used by a tool analyzing generated debugging information.
307    /// * `runtime_ver` - This indicates runtime version for languages like Objective-C.
308    /// * `split_name` - The name of the file that we'll split debug info out into.
309    /// * `kind` - The kind of debug information to generate.
310    /// * `dwo_id` - The DWOId if this is a split skeleton compile unit.
311    /// * `split_debug_inlining` - Whether to emit inline debug info.
312    /// * `debug_info_for_profiling` - Whether to emit extra debug info for profile collection.
313    fn create_compile_unit(
314        &self,
315        language: DWARFSourceLanguage,
316        file: DIFile<'ctx>,
317        producer: &str,
318        is_optimized: bool,
319        flags: &str,
320        runtime_ver: libc::c_uint,
321        split_name: &str,
322        kind: DWARFEmissionKind,
323        dwo_id: libc::c_uint,
324        split_debug_inlining: bool,
325        debug_info_for_profiling: bool,
326        #[cfg(any(
327            feature = "llvm11-0",
328            feature = "llvm12-0",
329            feature = "llvm13-0",
330            feature = "llvm14-0",
331            feature = "llvm15-0",
332            feature = "llvm16-0",
333            feature = "llvm17-0",
334            feature = "llvm18-1",
335            feature = "llvm19-1",
336            feature = "llvm20-1",
337            feature = "llvm21-1",
338        ))]
339        sysroot: &str,
340        #[cfg(any(
341            feature = "llvm11-0",
342            feature = "llvm12-0",
343            feature = "llvm13-0",
344            feature = "llvm14-0",
345            feature = "llvm15-0",
346            feature = "llvm16-0",
347            feature = "llvm17-0",
348            feature = "llvm18-1",
349            feature = "llvm19-1",
350            feature = "llvm20-1",
351            feature = "llvm21-1",
352        ))]
353        sdk: &str,
354    ) -> DICompileUnit<'ctx> {
355        let metadata_ref = unsafe {
356            LLVMDIBuilderCreateCompileUnit(
357                self.builder,
358                language.into(),
359                file.metadata_ref,
360                producer.as_ptr() as _,
361                producer.len(),
362                is_optimized as _,
363                flags.as_ptr() as _,
364                flags.len(),
365                runtime_ver,
366                split_name.as_ptr() as _,
367                split_name.len(),
368                kind.into(),
369                dwo_id,
370                split_debug_inlining as _,
371                debug_info_for_profiling as _,
372                sysroot.as_ptr() as _,
373                sysroot.len(),
374                sdk.as_ptr() as _,
375                sdk.len(),
376            )
377        };
378
379        DICompileUnit {
380            file,
381            metadata_ref,
382            _marker: PhantomData,
383        }
384    }
385
386    /// A DIFunction provides an anchor for all debugging information generated for the specified subprogram.
387    ///
388    /// * `scope` - Function scope.
389    /// * `name` - Function name.
390    /// * `linkage_name` - Mangled function name, if any.
391    /// * `file` - File where this variable is defined.
392    /// * `line_no` - Line number.
393    /// * `ty` - Function type.
394    /// * `is_local_to_unit` - True if this function is not externally visible.
395    /// * `is_definition` - True if this is a function definition ("When isDefinition: false,
396    ///   subprograms describe a declaration in the type tree as opposed to a definition of a
397    ///   function").
398    /// * `scope_line` - Set to the beginning of the scope this starts
399    /// * `flags` - E.g.: LLVMDIFlagLValueReference. These flags are used to emit dwarf attributes.
400    /// * `is_optimized` - True if optimization is ON.
401    pub fn create_function(
402        &self,
403        scope: DIScope<'ctx>,
404        name: &str,
405        linkage_name: Option<&str>,
406        file: DIFile<'ctx>,
407        line_no: u32,
408        ditype: DISubroutineType<'ctx>,
409        is_local_to_unit: bool,
410        is_definition: bool,
411        scope_line: u32,
412        flags: DIFlags,
413        is_optimized: bool,
414    ) -> DISubprogram<'ctx> {
415        let linkage_name = linkage_name.unwrap_or(name);
416
417        let metadata_ref = unsafe {
418            LLVMDIBuilderCreateFunction(
419                self.builder,
420                scope.metadata_ref,
421                name.as_ptr() as _,
422                name.len(),
423                linkage_name.as_ptr() as _,
424                linkage_name.len(),
425                file.metadata_ref,
426                line_no,
427                ditype.metadata_ref,
428                is_local_to_unit as _,
429                is_definition as _,
430                scope_line as libc::c_uint,
431                flags,
432                is_optimized as _,
433            )
434        };
435        DISubprogram {
436            metadata_ref,
437            _marker: PhantomData,
438        }
439    }
440
441    /// Create a lexical block scope.
442    pub fn create_lexical_block(
443        &self,
444        parent_scope: DIScope<'ctx>,
445        file: DIFile<'ctx>,
446        line: u32,
447        column: u32,
448    ) -> DILexicalBlock<'ctx> {
449        let metadata_ref = unsafe {
450            LLVMDIBuilderCreateLexicalBlock(
451                self.builder,
452                parent_scope.metadata_ref,
453                file.metadata_ref,
454                line as libc::c_uint,
455                column as libc::c_uint,
456            )
457        };
458        DILexicalBlock {
459            metadata_ref,
460            _marker: PhantomData,
461        }
462    }
463
464    /// Create a file scope.
465    pub fn create_file(&self, filename: &str, directory: &str) -> DIFile<'ctx> {
466        let metadata_ref = unsafe {
467            LLVMDIBuilderCreateFile(
468                self.builder,
469                filename.as_ptr() as _,
470                filename.len(),
471                directory.as_ptr() as _,
472                directory.len(),
473            )
474        };
475        DIFile {
476            metadata_ref,
477            _marker: PhantomData,
478        }
479    }
480
481    /// Create a debug location.
482    pub fn create_debug_location(
483        &self,
484        context: impl AsContextRef<'ctx>,
485        line: u32,
486        column: u32,
487        scope: DIScope<'ctx>,
488        inlined_at: Option<DILocation<'ctx>>,
489    ) -> DILocation<'ctx> {
490        let metadata_ref = unsafe {
491            LLVMDIBuilderCreateDebugLocation(
492                context.as_ctx_ref(),
493                line,
494                column,
495                scope.metadata_ref,
496                inlined_at.map(|l| l.metadata_ref).unwrap_or(std::ptr::null_mut()),
497            )
498        };
499        DILocation {
500            metadata_ref,
501            _marker: PhantomData,
502        }
503    }
504
505    /// Create a primitive basic type. `encoding` is an unsigned int flag (`DW_ATE_*`
506    /// enum) defined by the chosen DWARF standard.
507    pub fn create_basic_type(
508        &self,
509        name: &str,
510        size_in_bits: u64,
511        encoding: LLVMDWARFTypeEncoding,
512        flags: DIFlags,
513    ) -> Result<DIBasicType<'ctx>, crate::error::Error> {
514        if name.is_empty() {
515            // Also, LLVM returns the same type if you ask for the same
516            // (name, size_in_bits, encoding).
517            return Err(crate::error::Error::EmptyNameError);
518        }
519        let metadata_ref = unsafe {
520            LLVMDIBuilderCreateBasicType(
521                self.builder,
522                name.as_ptr() as _,
523                name.len(),
524                size_in_bits,
525                encoding,
526                flags,
527            )
528        };
529        Ok(DIBasicType {
530            metadata_ref,
531            _marker: PhantomData,
532        })
533    }
534
535    /// Create a typedef (alias) of `ditype`
536    pub fn create_typedef(
537        &self,
538        ditype: DIType<'ctx>,
539        name: &str,
540        file: DIFile<'ctx>,
541        line_no: u32,
542        scope: DIScope<'ctx>,
543        align_in_bits: u32,
544    ) -> DIDerivedType<'ctx> {
545        let metadata_ref = unsafe {
546            LLVMDIBuilderCreateTypedef(
547                self.builder,
548                ditype.metadata_ref,
549                name.as_ptr() as _,
550                name.len(),
551                file.metadata_ref,
552                line_no,
553                scope.metadata_ref,
554                align_in_bits,
555            )
556        };
557        DIDerivedType {
558            metadata_ref,
559            _marker: PhantomData,
560        }
561    }
562
563    /// Create union type of multiple types.
564    pub fn create_union_type(
565        &self,
566        scope: DIScope<'ctx>,
567        name: &str,
568        file: DIFile<'ctx>,
569        line_no: u32,
570        size_in_bits: u64,
571        align_in_bits: u32,
572        flags: DIFlags,
573        elements: &[DIType<'ctx>],
574        runtime_language: u32,
575        unique_id: &str,
576    ) -> DICompositeType<'ctx> {
577        let mut elements: Vec<LLVMMetadataRef> = elements.iter().map(|dt| dt.metadata_ref).collect();
578        let metadata_ref = unsafe {
579            LLVMDIBuilderCreateUnionType(
580                self.builder,
581                scope.metadata_ref,
582                name.as_ptr() as _,
583                name.len(),
584                file.metadata_ref,
585                line_no,
586                size_in_bits,
587                align_in_bits,
588                flags,
589                elements.as_mut_ptr(),
590                elements.len().try_into().unwrap(),
591                runtime_language,
592                unique_id.as_ptr() as _,
593                unique_id.len(),
594            )
595        };
596        DICompositeType {
597            metadata_ref,
598            _marker: PhantomData,
599        }
600    }
601
602    /// Create a type for a non-static member.
603    pub fn create_member_type(
604        &self,
605        scope: DIScope<'ctx>,
606        name: &str,
607        file: DIFile<'ctx>,
608        line_no: libc::c_uint,
609        size_in_bits: u64,
610        align_in_bits: u32,
611        offset_in_bits: u64,
612        flags: DIFlags,
613        ty: DIType<'ctx>,
614    ) -> DIDerivedType<'ctx> {
615        let metadata_ref = unsafe {
616            LLVMDIBuilderCreateMemberType(
617                self.builder,
618                scope.metadata_ref,
619                name.as_ptr() as _,
620                name.len(),
621                file.metadata_ref,
622                line_no,
623                size_in_bits,
624                align_in_bits,
625                offset_in_bits,
626                flags,
627                ty.metadata_ref,
628            )
629        };
630        DIDerivedType {
631            metadata_ref,
632            _marker: PhantomData,
633        }
634    }
635
636    /// Create a struct type.
637    pub fn create_struct_type(
638        &self,
639        scope: DIScope<'ctx>,
640        name: &str,
641        file: DIFile<'ctx>,
642        line_no: libc::c_uint,
643        size_in_bits: u64,
644        align_in_bits: u32,
645        flags: DIFlags,
646        derived_from: Option<DIType<'ctx>>,
647        elements: &[DIType<'ctx>],
648        runtime_language: libc::c_uint,
649        vtable_holder: Option<DIType<'ctx>>,
650        unique_id: &str,
651    ) -> DICompositeType<'ctx> {
652        let mut elements: Vec<LLVMMetadataRef> = elements.iter().map(|dt| dt.metadata_ref).collect();
653        let derived_from = derived_from.map_or(std::ptr::null_mut(), |dt| dt.metadata_ref);
654        let vtable_holder = vtable_holder.map_or(std::ptr::null_mut(), |dt| dt.metadata_ref);
655        let metadata_ref = unsafe {
656            LLVMDIBuilderCreateStructType(
657                self.builder,
658                scope.metadata_ref,
659                name.as_ptr() as _,
660                name.len(),
661                file.metadata_ref,
662                line_no,
663                size_in_bits,
664                align_in_bits,
665                flags,
666                derived_from,
667                elements.as_mut_ptr(),
668                elements.len().try_into().unwrap(),
669                runtime_language,
670                vtable_holder,
671                unique_id.as_ptr() as _,
672                unique_id.len(),
673            )
674        };
675        DICompositeType {
676            metadata_ref,
677            _marker: PhantomData,
678        }
679    }
680
681    /// Create a function type
682    pub fn create_subroutine_type(
683        &self,
684        file: DIFile<'ctx>,
685        return_type: Option<DIType<'ctx>>,
686        parameter_types: &[DIType<'ctx>],
687        flags: DIFlags,
688    ) -> DISubroutineType<'ctx> {
689        let mut p = vec![return_type.map_or(std::ptr::null_mut(), |t| t.metadata_ref)];
690        p.append(
691            &mut parameter_types
692                .iter()
693                .map(|t| t.metadata_ref)
694                .collect::<Vec<LLVMMetadataRef>>(),
695        );
696        let metadata_ref = unsafe {
697            LLVMDIBuilderCreateSubroutineType(
698                self.builder,
699                file.metadata_ref,
700                p.as_mut_ptr(),
701                p.len().try_into().unwrap(),
702                flags,
703            )
704        };
705        DISubroutineType {
706            metadata_ref,
707            _marker: PhantomData,
708        }
709    }
710
711    /// Creates a pointer type
712    pub fn create_pointer_type(
713        &self,
714        name: &str,
715        pointee: DIType<'ctx>,
716        size_in_bits: u64,
717        align_in_bits: u32,
718        address_space: AddressSpace,
719    ) -> DIDerivedType<'ctx> {
720        let metadata_ref = unsafe {
721            LLVMDIBuilderCreatePointerType(
722                self.builder,
723                pointee.metadata_ref,
724                size_in_bits,
725                align_in_bits,
726                address_space.0,
727                name.as_ptr() as _,
728                name.len(),
729            )
730        };
731
732        DIDerivedType {
733            metadata_ref,
734            _marker: PhantomData,
735        }
736    }
737
738    /// Creates a pointer type
739    pub fn create_reference_type(&self, pointee: DIType<'ctx>, tag: u32) -> DIDerivedType<'ctx> {
740        let metadata_ref = unsafe { LLVMDIBuilderCreateReferenceType(self.builder, tag, pointee.metadata_ref) };
741
742        DIDerivedType {
743            metadata_ref,
744            _marker: PhantomData,
745        }
746    }
747
748    /// Creates an array type
749    pub fn create_array_type(
750        &self,
751        inner_type: DIType<'ctx>,
752        size_in_bits: u64,
753        align_in_bits: u32,
754        subscripts: &[Range<i64>],
755    ) -> DICompositeType<'ctx> {
756        //Create subranges
757        let mut subscripts = subscripts
758            .iter()
759            .map(|range| {
760                let lower = range.start;
761                let upper = range.end;
762                let subscript_size = upper - lower;
763                unsafe { LLVMDIBuilderGetOrCreateSubrange(self.builder, lower, subscript_size) }
764            })
765            .collect::<Vec<_>>();
766        let metadata_ref = unsafe {
767            LLVMDIBuilderCreateArrayType(
768                self.builder,
769                size_in_bits,
770                align_in_bits,
771                inner_type.metadata_ref,
772                subscripts.as_mut_ptr(),
773                subscripts.len().try_into().unwrap(),
774            )
775        };
776
777        DICompositeType {
778            metadata_ref,
779            _marker: PhantomData,
780        }
781    }
782
783    /// Create an enumeration type
784    pub fn create_enumeration_type(
785        &self,
786        scope: DIScope<'ctx>,
787        name: &str,
788        file: DIFile<'ctx>,
789        line_no: u32,
790        size_in_bits: u64,
791        align_in_bits: u32,
792        elements: &[DIEnumerator<'ctx>],
793        inner_type: DIType<'ctx>,
794    ) -> DICompositeType<'ctx> {
795        let mut elements: Vec<LLVMMetadataRef> = elements.iter().map(|dt| dt.metadata_ref).collect();
796        let metadata_ref = unsafe {
797            LLVMDIBuilderCreateEnumerationType(
798                self.builder,
799                scope.metadata_ref,
800                name.as_ptr() as _,
801                name.len(),
802                file.metadata_ref,
803                line_no,
804                size_in_bits,
805                align_in_bits,
806                elements.as_mut_ptr(),
807                elements.len().try_into().unwrap(),
808                inner_type.metadata_ref,
809            )
810        };
811
812        DICompositeType {
813            metadata_ref,
814            _marker: PhantomData,
815        }
816    }
817
818    /// Create an enumerator
819    pub fn create_enumerator(&self, name: &str, value: i64, is_unsigned: bool) -> DIEnumerator<'ctx> {
820        let metadata_ref = unsafe {
821            LLVMDIBuilderCreateEnumerator(self.builder, name.as_ptr() as _, name.len(), value, is_unsigned as i32)
822        };
823
824        DIEnumerator {
825            metadata_ref,
826            _marker: PhantomData,
827        }
828    }
829
830    pub fn create_global_variable_expression(
831        &self,
832        scope: DIScope<'ctx>,
833        name: &str,
834        linkage: &str,
835        file: DIFile<'ctx>,
836        line_no: u32,
837        ty: DIType<'ctx>,
838        local_to_unit: bool,
839        expression: Option<DIExpression>,
840        declaration: Option<DIScope>,
841        align_in_bits: u32,
842    ) -> DIGlobalVariableExpression<'ctx> {
843        let expression_ptr = expression.map_or(std::ptr::null_mut(), |dt| dt.metadata_ref);
844        let decl_ptr = declaration.map_or(std::ptr::null_mut(), |dt| dt.metadata_ref);
845        let metadata_ref = unsafe {
846            LLVMDIBuilderCreateGlobalVariableExpression(
847                self.builder,
848                scope.metadata_ref,
849                name.as_ptr() as _,
850                name.len(),
851                linkage.as_ptr() as _,
852                linkage.len(),
853                file.metadata_ref,
854                line_no,
855                ty.metadata_ref,
856                local_to_unit as _,
857                expression_ptr,
858                decl_ptr,
859                align_in_bits,
860            )
861        };
862        DIGlobalVariableExpression {
863            metadata_ref,
864            _marker: PhantomData,
865        }
866    }
867
868    pub fn create_constant_expression(&self, value: i64) -> DIExpression<'ctx> {
869        let metadata_ref = unsafe { LLVMDIBuilderCreateConstantValueExpression(self.builder, value as _) };
870
871        DIExpression {
872            metadata_ref,
873            _marker: PhantomData,
874        }
875    }
876
877    /// Create function parameter variable.
878    pub fn create_parameter_variable(
879        &self,
880        scope: DIScope<'ctx>,
881        name: &str,
882        arg_no: u32,
883        file: DIFile<'ctx>,
884        line_no: u32,
885        ty: DIType<'ctx>,
886        always_preserve: bool,
887        flags: DIFlags,
888    ) -> DILocalVariable<'ctx> {
889        let metadata_ref = unsafe {
890            LLVMDIBuilderCreateParameterVariable(
891                self.builder,
892                scope.metadata_ref,
893                name.as_ptr() as _,
894                name.len(),
895                arg_no,
896                file.metadata_ref,
897                line_no,
898                ty.metadata_ref,
899                always_preserve as _,
900                flags,
901            )
902        };
903        DILocalVariable {
904            metadata_ref,
905            _marker: PhantomData,
906        }
907    }
908
909    /// Create local automatic storage variable.
910    pub fn create_auto_variable(
911        &self,
912        scope: DIScope<'ctx>,
913        name: &str,
914        file: DIFile<'ctx>,
915        line_no: u32,
916        ty: DIType<'ctx>,
917        always_preserve: bool,
918        flags: DIFlags,
919        align_in_bits: u32,
920    ) -> DILocalVariable<'ctx> {
921        let metadata_ref = unsafe {
922            LLVMDIBuilderCreateAutoVariable(
923                self.builder,
924                scope.metadata_ref,
925                name.as_ptr() as _,
926                name.len(),
927                file.metadata_ref,
928                line_no,
929                ty.metadata_ref,
930                always_preserve as _,
931                flags,
932                align_in_bits,
933            )
934        };
935        DILocalVariable {
936            metadata_ref,
937            _marker: PhantomData,
938        }
939    }
940
941    pub fn create_namespace(&self, scope: DIScope<'ctx>, name: &str, export_symbols: bool) -> DINamespace<'ctx> {
942        let metadata_ref = unsafe {
943            LLVMDIBuilderCreateNameSpace(
944                self.builder,
945                scope.metadata_ref,
946                name.as_ptr() as _,
947                name.len(),
948                export_symbols as _,
949            )
950        };
951        DINamespace {
952            metadata_ref,
953            _marker: PhantomData,
954        }
955    }
956
957    /// Insert a variable declaration (`llvm.dbg.declare`) before a specified instruction.
958    pub fn insert_declare_before_instruction(
959        &self,
960        storage: PointerValue<'ctx>,
961        var_info: Option<DILocalVariable<'ctx>>,
962        expr: Option<DIExpression<'ctx>>,
963        debug_loc: DILocation<'ctx>,
964        instruction: InstructionValue<'ctx>,
965    ) -> InstructionValue<'ctx> {
966        let value_ref = unsafe {
967            LLVMDIBuilderInsertDeclareBefore(
968                self.builder,
969                storage.as_value_ref(),
970                var_info.map(|v| v.metadata_ref).unwrap_or(std::ptr::null_mut()),
971                expr.unwrap_or_else(|| self.create_expression(vec![])).metadata_ref,
972                debug_loc.metadata_ref,
973                instruction.as_value_ref(),
974            )
975        };
976
977        #[cfg(any(feature = "llvm19-1", feature = "llvm20-1", feature = "llvm21-1"))]
978        {
979            // In LLVM 19+, the insert... functions return a DbgRecord, not a Value.
980            // We need to cast it to a ValueRef to create an InstructionValue.
981            // This is unsafe, but it's the only way to do it.
982            unsafe { InstructionValue::new(value_ref as LLVMValueRef) }
983        }
984
985        #[cfg(not(any(feature = "llvm19-1", feature = "llvm20-1", feature = "llvm21-1")))]
986        {
987            unsafe { InstructionValue::new(value_ref) }
988        }
989    }
990
991    /// Insert a variable declaration (`llvm.dbg.declare` intrinsic) at the end of `block`
992    pub fn insert_declare_at_end(
993        &self,
994        storage: PointerValue<'ctx>,
995        var_info: Option<DILocalVariable<'ctx>>,
996        expr: Option<DIExpression<'ctx>>,
997        debug_loc: DILocation<'ctx>,
998        block: BasicBlock<'ctx>,
999    ) -> InstructionValue<'ctx> {
1000        let value_ref = unsafe {
1001            LLVMDIBuilderInsertDeclareAtEnd(
1002                self.builder,
1003                storage.as_value_ref(),
1004                var_info.map(|v| v.metadata_ref).unwrap_or(std::ptr::null_mut()),
1005                expr.unwrap_or_else(|| self.create_expression(vec![])).metadata_ref,
1006                debug_loc.metadata_ref,
1007                block.basic_block,
1008            )
1009        };
1010
1011        #[cfg(any(feature = "llvm19-1", feature = "llvm20-1", feature = "llvm21-1"))]
1012        {
1013            // In LLVM 19+, the insert... functions return a DbgRecord, not a Value.
1014            // We need to cast it to a ValueRef to create an InstructionValue.
1015            // This is unsafe, but it's the only way to do it.
1016            unsafe { InstructionValue::new(value_ref as LLVMValueRef) }
1017        }
1018
1019        #[cfg(not(any(feature = "llvm19-1", feature = "llvm20-1", feature = "llvm21-1")))]
1020        {
1021            unsafe { InstructionValue::new(value_ref) }
1022        }
1023    }
1024
1025    /// Create an expression
1026    pub fn create_expression(&self, mut address_operations: Vec<i64>) -> DIExpression<'ctx> {
1027        let metadata_ref = unsafe {
1028            LLVMDIBuilderCreateExpression(
1029                self.builder,
1030                address_operations.as_mut_ptr() as *mut _,
1031                address_operations.len(),
1032            )
1033        };
1034        DIExpression {
1035            metadata_ref,
1036            _marker: PhantomData,
1037        }
1038    }
1039
1040    /// Insert a new llvm.dbg.value intrinsic call before an instruction.
1041    pub fn insert_dbg_value_before(
1042        &self,
1043        value: BasicValueEnum<'ctx>,
1044        var_info: DILocalVariable<'ctx>,
1045        expr: Option<DIExpression<'ctx>>,
1046        debug_loc: DILocation<'ctx>,
1047        instruction: InstructionValue<'ctx>,
1048    ) -> InstructionValue<'ctx> {
1049        let value_ref = unsafe {
1050            LLVMDIBuilderInsertDbgValueBefore(
1051                self.builder,
1052                value.as_value_ref(),
1053                var_info.metadata_ref,
1054                expr.unwrap_or_else(|| self.create_expression(vec![])).metadata_ref,
1055                debug_loc.metadata_ref,
1056                instruction.as_value_ref(),
1057            )
1058        };
1059
1060        #[cfg(any(feature = "llvm19-1", feature = "llvm20-1", feature = "llvm21-1"))]
1061        {
1062            // In LLVM 19+, the insert... functions return a DbgRecord, not a Value.
1063            // We need to cast it to a ValueRef to create an InstructionValue.
1064            // This is unsafe, but it's the only way to do it.
1065            unsafe { InstructionValue::new(value_ref as LLVMValueRef) }
1066        }
1067
1068        #[cfg(not(any(feature = "llvm19-1", feature = "llvm20-1", feature = "llvm21-1")))]
1069        {
1070            unsafe { InstructionValue::new(value_ref) }
1071        }
1072    }
1073
1074    /// Construct a placeholders derived type to be used when building debug info with circular references.
1075    ///
1076    /// All placeholders must be replaced before calling finalize().
1077    pub unsafe fn create_placeholder_derived_type(&self, context: impl AsContextRef<'ctx>) -> DIDerivedType<'ctx> {
1078        let metadata_ref = LLVMTemporaryMDNode(context.as_ctx_ref(), std::ptr::null_mut(), 0);
1079        DIDerivedType {
1080            metadata_ref,
1081            _marker: PhantomData,
1082        }
1083    }
1084
1085    /// Deletes a placeholder, replacing all uses of it with another derived type.
1086    ///
1087    /// # Safety:
1088    /// This and any other copies of this placeholder made by Copy or Clone
1089    /// become dangling pointers after calling this method.
1090    pub unsafe fn replace_placeholder_derived_type(
1091        &self,
1092        placeholder: DIDerivedType<'ctx>,
1093        other: DIDerivedType<'ctx>,
1094    ) {
1095        LLVMMetadataReplaceAllUsesWith(placeholder.metadata_ref, other.metadata_ref);
1096    }
1097
1098    /// Construct any deferred debug info descriptors. May generate invalid metadata if debug info
1099    /// is incomplete. Module/function verification can then fail.
1100    ///
1101    /// Call before any kind of code generation (including verification). Can be called more than once.
1102    pub fn finalize(&self) {
1103        unsafe { LLVMDIBuilderFinalize(self.builder) };
1104    }
1105}
1106
1107impl Drop for DebugInfoBuilder<'_> {
1108    fn drop(&mut self) {
1109        self.finalize();
1110        unsafe { LLVMDisposeDIBuilder(self.builder) }
1111    }
1112}
1113
1114/// Source file scope for debug info
1115#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1116pub struct DIFile<'ctx> {
1117    pub(crate) metadata_ref: LLVMMetadataRef,
1118    _marker: PhantomData<&'ctx Context>,
1119}
1120
1121impl<'ctx> AsDIScope<'ctx> for DIFile<'ctx> {
1122    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1123        DIScope {
1124            metadata_ref: self.metadata_ref,
1125            _marker: PhantomData,
1126        }
1127    }
1128}
1129
1130impl DIFile<'_> {
1131    /// Acquires the underlying raw pointer belonging to this `DIFile` type.
1132    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1133        self.metadata_ref
1134    }
1135}
1136
1137/// Compilation unit scope for debug info
1138#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1139pub struct DICompileUnit<'ctx> {
1140    file: DIFile<'ctx>,
1141    pub(crate) metadata_ref: LLVMMetadataRef,
1142    _marker: PhantomData<&'ctx Context>,
1143}
1144
1145impl<'ctx> DICompileUnit<'ctx> {
1146    pub fn get_file(&self) -> DIFile<'ctx> {
1147        self.file
1148    }
1149
1150    /// Acquires the underlying raw pointer belonging to this `DICompileUnit` type.
1151    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1152        self.metadata_ref
1153    }
1154}
1155
1156impl<'ctx> AsDIScope<'ctx> for DICompileUnit<'ctx> {
1157    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1158        DIScope {
1159            metadata_ref: self.metadata_ref,
1160            _marker: PhantomData,
1161        }
1162    }
1163}
1164
1165/// Namespace scope for debug info
1166#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1167pub struct DINamespace<'ctx> {
1168    pub(crate) metadata_ref: LLVMMetadataRef,
1169    _marker: PhantomData<&'ctx Context>,
1170}
1171
1172impl DINamespace<'_> {
1173    /// Acquires the underlying raw pointer belonging to this `DINamespace` type.
1174    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1175        self.metadata_ref
1176    }
1177}
1178
1179impl<'ctx> AsDIScope<'ctx> for DINamespace<'ctx> {
1180    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1181        DIScope {
1182            metadata_ref: self.metadata_ref,
1183            _marker: PhantomData,
1184        }
1185    }
1186}
1187
1188/// Function body scope for debug info
1189#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1190pub struct DISubprogram<'ctx> {
1191    pub(crate) metadata_ref: LLVMMetadataRef,
1192    pub(crate) _marker: PhantomData<&'ctx Context>,
1193}
1194
1195impl<'ctx> AsDIScope<'ctx> for DISubprogram<'ctx> {
1196    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1197        DIScope {
1198            metadata_ref: self.metadata_ref,
1199            _marker: PhantomData,
1200        }
1201    }
1202}
1203
1204impl DISubprogram<'_> {
1205    /// Acquires the underlying raw pointer belonging to this `DISubprogram` type.
1206    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1207        self.metadata_ref
1208    }
1209}
1210
1211/// Any kind of debug info type
1212#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1213pub struct DIType<'ctx> {
1214    pub(crate) metadata_ref: LLVMMetadataRef,
1215    _marker: PhantomData<&'ctx Context>,
1216}
1217
1218impl DIType<'_> {
1219    pub fn get_size_in_bits(&self) -> u64 {
1220        unsafe { LLVMDITypeGetSizeInBits(self.metadata_ref) }
1221    }
1222
1223    pub fn get_align_in_bits(&self) -> u32 {
1224        unsafe { LLVMDITypeGetAlignInBits(self.metadata_ref) }
1225    }
1226
1227    pub fn get_offset_in_bits(&self) -> u64 {
1228        unsafe { LLVMDITypeGetOffsetInBits(self.metadata_ref) }
1229    }
1230
1231    /// Acquires the underlying raw pointer belonging to this `DIType` type.
1232    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1233        self.metadata_ref
1234    }
1235}
1236
1237impl<'ctx> AsDIScope<'ctx> for DIType<'ctx> {
1238    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1239        DIScope {
1240            metadata_ref: self.metadata_ref,
1241            _marker: PhantomData,
1242        }
1243    }
1244}
1245
1246/// A wrapper around a single type, such as a typedef or member type.
1247#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1248pub struct DIDerivedType<'ctx> {
1249    pub(crate) metadata_ref: LLVMMetadataRef,
1250    _marker: PhantomData<&'ctx Context>,
1251}
1252
1253impl<'ctx> DIDerivedType<'ctx> {
1254    pub fn as_type(&self) -> DIType<'ctx> {
1255        DIType {
1256            metadata_ref: self.metadata_ref,
1257            _marker: PhantomData,
1258        }
1259    }
1260}
1261
1262impl DIDerivedType<'_> {
1263    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1264        self.metadata_ref
1265    }
1266}
1267
1268impl<'ctx> AsDIScope<'ctx> for DIDerivedType<'ctx> {
1269    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1270        DIScope {
1271            metadata_ref: self.metadata_ref,
1272            _marker: PhantomData,
1273        }
1274    }
1275}
1276
1277/// A primitive debug info type created by `create_basic_type` method of `DebugInfoBuilder`
1278#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1279pub struct DIBasicType<'ctx> {
1280    pub(crate) metadata_ref: LLVMMetadataRef,
1281    _marker: PhantomData<&'ctx Context>,
1282}
1283
1284impl<'ctx> DIBasicType<'ctx> {
1285    pub fn as_type(&self) -> DIType<'ctx> {
1286        DIType {
1287            metadata_ref: self.metadata_ref,
1288            _marker: PhantomData,
1289        }
1290    }
1291
1292    /// Acquires the underlying raw pointer belonging to this `DIBasicType` type.
1293    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1294        self.metadata_ref
1295    }
1296}
1297
1298impl<'ctx> AsDIScope<'ctx> for DIBasicType<'ctx> {
1299    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1300        DIScope {
1301            metadata_ref: self.metadata_ref,
1302            _marker: PhantomData,
1303        }
1304    }
1305}
1306/// A wrapper around an array of types, such as a union or struct.
1307#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1308pub struct DICompositeType<'ctx> {
1309    pub(crate) metadata_ref: LLVMMetadataRef,
1310    _marker: PhantomData<&'ctx Context>,
1311}
1312
1313impl<'ctx> DICompositeType<'ctx> {
1314    pub fn as_type(&self) -> DIType<'ctx> {
1315        DIType {
1316            metadata_ref: self.metadata_ref,
1317            _marker: PhantomData,
1318        }
1319    }
1320
1321    /// Acquires the underlying raw pointer belonging to this `DICompositeType` type.
1322    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1323        self.metadata_ref
1324    }
1325}
1326
1327impl<'ctx> AsDIScope<'ctx> for DICompositeType<'ctx> {
1328    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1329        DIScope {
1330            metadata_ref: self.metadata_ref,
1331            _marker: PhantomData,
1332        }
1333    }
1334}
1335
1336/// Metadata representing the type of a function
1337#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1338pub struct DISubroutineType<'ctx> {
1339    pub(crate) metadata_ref: LLVMMetadataRef,
1340    _marker: PhantomData<&'ctx Context>,
1341}
1342
1343/// Lexical block scope for debug info
1344#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1345pub struct DILexicalBlock<'ctx> {
1346    pub(crate) metadata_ref: LLVMMetadataRef,
1347    _marker: PhantomData<&'ctx Context>,
1348}
1349
1350impl<'ctx> AsDIScope<'ctx> for DILexicalBlock<'ctx> {
1351    fn as_debug_info_scope(self) -> DIScope<'ctx> {
1352        DIScope {
1353            metadata_ref: self.metadata_ref,
1354            _marker: PhantomData,
1355        }
1356    }
1357}
1358
1359impl DILexicalBlock<'_> {
1360    /// Acquires the underlying raw pointer belonging to this `DILexicalBlock` type.
1361    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1362        self.metadata_ref
1363    }
1364}
1365
1366/// A debug location within the source code. Contains the following information:
1367///
1368/// - line, column
1369/// - scope
1370/// - inlined at
1371///
1372/// Created by `create_debug_location` of `DebugInfoBuilder` and consumed by
1373/// `set_current_debug_location` of `Builder`.
1374#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1375pub struct DILocation<'ctx> {
1376    pub(crate) metadata_ref: LLVMMetadataRef,
1377    pub(crate) _marker: PhantomData<&'ctx Context>,
1378}
1379
1380impl<'ctx> DILocation<'ctx> {
1381    pub fn get_line(&self) -> u32 {
1382        unsafe { LLVMDILocationGetLine(self.metadata_ref) }
1383    }
1384
1385    pub fn get_column(&self) -> u32 {
1386        unsafe { LLVMDILocationGetColumn(self.metadata_ref) }
1387    }
1388
1389    pub fn get_scope(&self) -> DIScope<'ctx> {
1390        DIScope {
1391            metadata_ref: unsafe { LLVMDILocationGetScope(self.metadata_ref) },
1392            _marker: PhantomData,
1393        }
1394    }
1395
1396    /// Acquires the underlying raw pointer belonging to this `DILocation` type.
1397    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1398        self.metadata_ref
1399    }
1400}
1401
1402/// Metadata representing a variable inside a scope
1403#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1404pub struct DILocalVariable<'ctx> {
1405    pub(crate) metadata_ref: LLVMMetadataRef,
1406    _marker: PhantomData<&'ctx Context>,
1407}
1408
1409impl DILocalVariable<'_> {
1410    /// Acquires the underlying raw pointer belonging to this `DILocalVariable` type.
1411    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1412        self.metadata_ref
1413    }
1414}
1415
1416#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1417pub struct DIGlobalVariableExpression<'ctx> {
1418    pub(crate) metadata_ref: LLVMMetadataRef,
1419    _marker: PhantomData<&'ctx Context>,
1420}
1421
1422impl<'ctx> DIGlobalVariableExpression<'ctx> {
1423    pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> {
1424        unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) }
1425    }
1426
1427    /// Acquires the underlying raw pointer belonging to this `DIGlobalVariableExpression` type.
1428    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1429        self.metadata_ref
1430    }
1431}
1432
1433/// Specialized metadata node that contains a DWARF-like expression.
1434///
1435/// # Remarks
1436///
1437/// See also the [LLVM language reference](https://llvm.org/docs/LangRef.html#diexpression).
1438#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1439pub struct DIExpression<'ctx> {
1440    pub(crate) metadata_ref: LLVMMetadataRef,
1441    _marker: PhantomData<&'ctx Context>,
1442}
1443
1444impl DIExpression<'_> {
1445    /// Acquires the underlying raw pointer belonging to this `DIExpression` type.
1446    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1447        self.metadata_ref
1448    }
1449}
1450
1451#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1452pub struct DIEnumerator<'ctx> {
1453    pub(crate) metadata_ref: LLVMMetadataRef,
1454    _marker: PhantomData<&'ctx Context>,
1455}
1456
1457impl<'ctx> DIEnumerator<'ctx> {
1458    /// Acquires the underlying raw pointer belonging to this `DIEnumerator` type.
1459    pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1460        self.metadata_ref
1461    }
1462
1463    pub fn as_type(&self) -> DIType<'ctx> {
1464        DIType {
1465            metadata_ref: self.metadata_ref,
1466            _marker: PhantomData,
1467        }
1468    }
1469}
1470
1471pub use flags::*;
1472mod flags {
1473    pub use llvm_sys::debuginfo::LLVMDIFlags as DIFlags;
1474    use llvm_sys::debuginfo::{LLVMDWARFEmissionKind, LLVMDWARFSourceLanguage};
1475
1476    pub trait DIFlagsConstants {
1477        const ZERO: Self;
1478        const PRIVATE: Self;
1479        const PROTECTED: Self;
1480        const PUBLIC: Self;
1481        const FWD_DECL: Self;
1482        const APPLE_BLOCK: Self;
1483        const VIRTUAL: Self;
1484        const ARTIFICIAL: Self;
1485        const EXPLICIT: Self;
1486        const PROTOTYPED: Self;
1487        const OBJC_CLASS_COMPLETE: Self;
1488        const OBJECT_POINTER: Self;
1489        const VECTOR: Self;
1490        const STATIC_MEMBER: Self;
1491        const LVALUE_REFERENCE: Self;
1492        const RVALUE_REFERENCE: Self;
1493        const RESERVED: Self;
1494        const SINGLE_INHERITANCE: Self;
1495        const MULTIPLE_INHERITANCE: Self;
1496        const VIRTUAL_INHERITANCE: Self;
1497        const INTRODUCED_VIRTUAL: Self;
1498        const BIT_FIELD: Self;
1499        const NO_RETURN: Self;
1500        const TYPE_PASS_BY_VALUE: Self;
1501        const TYPE_PASS_BY_REFERENCE: Self;
1502        //
1503        //const ENUM_CLASS: Self;
1504        const THUNK: Self;
1505        //const RESERVED_BIT4: Self;
1506        //
1507        //const BIGE_NDIAN: Self;
1508        //
1509        //const LITTLE_ENDIAN: Self;
1510        const INDIRECT_VIRTUAL_BASE: Self;
1511    }
1512    impl DIFlagsConstants for DIFlags {
1513        const ZERO: DIFlags = llvm_sys::debuginfo::LLVMDIFlagZero;
1514        const PRIVATE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagPrivate;
1515        const PROTECTED: DIFlags = llvm_sys::debuginfo::LLVMDIFlagProtected;
1516        const PUBLIC: DIFlags = llvm_sys::debuginfo::LLVMDIFlagPublic;
1517        const FWD_DECL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagFwdDecl;
1518        const APPLE_BLOCK: DIFlags = llvm_sys::debuginfo::LLVMDIFlagAppleBlock;
1519        const VIRTUAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagVirtual;
1520        const ARTIFICIAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagArtificial;
1521        const EXPLICIT: DIFlags = llvm_sys::debuginfo::LLVMDIFlagExplicit;
1522        const PROTOTYPED: DIFlags = llvm_sys::debuginfo::LLVMDIFlagPrototyped;
1523        const OBJC_CLASS_COMPLETE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagObjcClassComplete;
1524        const OBJECT_POINTER: DIFlags = llvm_sys::debuginfo::LLVMDIFlagObjectPointer;
1525        const VECTOR: DIFlags = llvm_sys::debuginfo::LLVMDIFlagVector;
1526        const STATIC_MEMBER: DIFlags = llvm_sys::debuginfo::LLVMDIFlagStaticMember;
1527        const LVALUE_REFERENCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagLValueReference;
1528        const RVALUE_REFERENCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagRValueReference;
1529        const RESERVED: DIFlags = llvm_sys::debuginfo::LLVMDIFlagReserved;
1530        const SINGLE_INHERITANCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagSingleInheritance;
1531        const MULTIPLE_INHERITANCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagMultipleInheritance;
1532        const VIRTUAL_INHERITANCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagVirtualInheritance;
1533        const INTRODUCED_VIRTUAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagIntroducedVirtual;
1534        const BIT_FIELD: DIFlags = llvm_sys::debuginfo::LLVMDIFlagBitField;
1535        const NO_RETURN: DIFlags = llvm_sys::debuginfo::LLVMDIFlagNoReturn;
1536        const TYPE_PASS_BY_VALUE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagTypePassByValue;
1537        const TYPE_PASS_BY_REFERENCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagTypePassByReference;
1538        //
1539        //const ENUM_CLASS: DIFlags = llvm_sys::debuginfo::LLVMDIFlagEnumClass;
1540        const THUNK: DIFlags = llvm_sys::debuginfo::LLVMDIFlagThunk;
1541        //const BIG_ENDIAN: DIFlags = llvm_sys::debuginfo::LLVMDIFlagBigEndian;
1542        //
1543        //const LITTLE_ENDIAN: DIFlags = llvm_sys::debuginfo::LLVMDIFlagLittleEndian;
1544        const INDIRECT_VIRTUAL_BASE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagIndirectVirtualBase;
1545    }
1546
1547    /// The amount of debug information to emit. Corresponds to `LLVMDWARFEmissionKind` enum from LLVM.
1548    #[llvm_enum(LLVMDWARFEmissionKind)]
1549    #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1550    pub enum DWARFEmissionKind {
1551        #[llvm_variant(LLVMDWARFEmissionKindNone)]
1552        None,
1553        #[llvm_variant(LLVMDWARFEmissionKindFull)]
1554        Full,
1555        #[llvm_variant(LLVMDWARFEmissionKindLineTablesOnly)]
1556        LineTablesOnly,
1557    }
1558
1559    /// Source languages known by DWARF. Corresponds to `LLVMDWARFSourceLanguage` enum from LLVM.
1560    #[llvm_enum(LLVMDWARFSourceLanguage)]
1561    #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1562    pub enum DWARFSourceLanguage {
1563        #[llvm_variant(LLVMDWARFSourceLanguageC89)]
1564        C89,
1565        #[llvm_variant(LLVMDWARFSourceLanguageC)]
1566        C,
1567        #[llvm_variant(LLVMDWARFSourceLanguageAda83)]
1568        Ada83,
1569        #[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus)]
1570        CPlusPlus,
1571        #[llvm_variant(LLVMDWARFSourceLanguageCobol74)]
1572        Cobol74,
1573        #[llvm_variant(LLVMDWARFSourceLanguageCobol85)]
1574        Cobol85,
1575        #[llvm_variant(LLVMDWARFSourceLanguageFortran77)]
1576        Fortran77,
1577        #[llvm_variant(LLVMDWARFSourceLanguageFortran90)]
1578        Fortran90,
1579        #[llvm_variant(LLVMDWARFSourceLanguagePascal83)]
1580        Pascal83,
1581        #[llvm_variant(LLVMDWARFSourceLanguageModula2)]
1582        Modula2,
1583        #[llvm_variant(LLVMDWARFSourceLanguageJava)]
1584        Java,
1585        #[llvm_variant(LLVMDWARFSourceLanguageC99)]
1586        C99,
1587        #[llvm_variant(LLVMDWARFSourceLanguageAda95)]
1588        Ada95,
1589        #[llvm_variant(LLVMDWARFSourceLanguageFortran95)]
1590        Fortran95,
1591        #[llvm_variant(LLVMDWARFSourceLanguagePLI)]
1592        PLI,
1593        #[llvm_variant(LLVMDWARFSourceLanguageObjC)]
1594        ObjC,
1595        #[llvm_variant(LLVMDWARFSourceLanguageObjC_plus_plus)]
1596        ObjCPlusPlus,
1597        #[llvm_variant(LLVMDWARFSourceLanguageUPC)]
1598        UPC,
1599        #[llvm_variant(LLVMDWARFSourceLanguageD)]
1600        D,
1601        #[llvm_variant(LLVMDWARFSourceLanguagePython)]
1602        Python,
1603        #[llvm_variant(LLVMDWARFSourceLanguageOpenCL)]
1604        OpenCL,
1605        #[llvm_variant(LLVMDWARFSourceLanguageGo)]
1606        Go,
1607        #[llvm_variant(LLVMDWARFSourceLanguageModula3)]
1608        Modula3,
1609        #[llvm_variant(LLVMDWARFSourceLanguageHaskell)]
1610        Haskell,
1611        #[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_03)]
1612        CPlusPlus03,
1613        #[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_11)]
1614        CPlusPlus11,
1615        #[llvm_variant(LLVMDWARFSourceLanguageOCaml)]
1616        OCaml,
1617        #[llvm_variant(LLVMDWARFSourceLanguageRust)]
1618        Rust,
1619        #[llvm_variant(LLVMDWARFSourceLanguageC11)]
1620        C11,
1621        #[llvm_variant(LLVMDWARFSourceLanguageSwift)]
1622        Swift,
1623        #[llvm_variant(LLVMDWARFSourceLanguageJulia)]
1624        Julia,
1625        #[llvm_variant(LLVMDWARFSourceLanguageDylan)]
1626        Dylan,
1627        #[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_14)]
1628        CPlusPlus14,
1629        #[llvm_variant(LLVMDWARFSourceLanguageFortran03)]
1630        Fortran03,
1631        #[llvm_variant(LLVMDWARFSourceLanguageFortran08)]
1632        Fortran08,
1633        #[llvm_variant(LLVMDWARFSourceLanguageRenderScript)]
1634        RenderScript,
1635        #[llvm_variant(LLVMDWARFSourceLanguageBLISS)]
1636        BLISS,
1637        #[llvm_variant(LLVMDWARFSourceLanguageMips_Assembler)]
1638        MipsAssembler,
1639        #[llvm_variant(LLVMDWARFSourceLanguageGOOGLE_RenderScript)]
1640        GOOGLERenderScript,
1641        #[llvm_variant(LLVMDWARFSourceLanguageBORLAND_Delphi)]
1642        BORLANDDelphi,
1643        #[llvm_versions(16..)]
1644        #[llvm_variant(LLVMDWARFSourceLanguageKotlin)]
1645        Kotlin,
1646        #[llvm_versions(16..)]
1647        #[llvm_variant(LLVMDWARFSourceLanguageZig)]
1648        Zig,
1649        #[llvm_versions(16..)]
1650        #[llvm_variant(LLVMDWARFSourceLanguageCrystal)]
1651        Crystal,
1652        #[llvm_versions(16..)]
1653        #[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_17)]
1654        CPlusPlus17,
1655        #[llvm_versions(16..)]
1656        #[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_20)]
1657        CPlusPlus20,
1658        #[llvm_versions(16..)]
1659        #[llvm_variant(LLVMDWARFSourceLanguageC17)]
1660        C17,
1661        #[llvm_versions(16..)]
1662        #[llvm_variant(LLVMDWARFSourceLanguageFortran18)]
1663        Fortran18,
1664        #[llvm_versions(16..)]
1665        #[llvm_variant(LLVMDWARFSourceLanguageAda2005)]
1666        Ada2005,
1667        #[llvm_versions(16..)]
1668        #[llvm_variant(LLVMDWARFSourceLanguageAda2012)]
1669        Ada2012,
1670        #[llvm_versions(17..)]
1671        #[llvm_variant(LLVMDWARFSourceLanguageMojo)]
1672        Mojo,
1673
1674        #[llvm_versions(19.1..)]
1675        #[llvm_variant(LLVMDWARFSourceLanguageHIP)]
1676        Hip,
1677
1678        #[llvm_versions(19.1..)]
1679        #[llvm_variant(LLVMDWARFSourceLanguageAssembly)]
1680        Assembly,
1681
1682        #[llvm_versions(19.1..)]
1683        #[llvm_variant(LLVMDWARFSourceLanguageC_sharp)]
1684        Csharp,
1685
1686        #[llvm_versions(19.1..)]
1687        #[llvm_variant(LLVMDWARFSourceLanguageGLSL)]
1688        Glsl,
1689
1690        #[llvm_versions(19.1..)]
1691        #[llvm_variant(LLVMDWARFSourceLanguageGLSL_ES)]
1692        GlslEs,
1693
1694        #[llvm_versions(19.1..)]
1695        #[llvm_variant(LLVMDWARFSourceLanguageHLSL)]
1696        Hlsl,
1697
1698        #[llvm_versions(19.1..)]
1699        #[llvm_variant(LLVMDWARFSourceLanguageOpenCL_CPP)]
1700        OpenClCpp,
1701
1702        #[llvm_versions(19.1..)]
1703        #[llvm_variant(LLVMDWARFSourceLanguageCPP_for_OpenCL)]
1704        CppForOpenCl,
1705
1706        #[llvm_versions(19.1..)]
1707        #[llvm_variant(LLVMDWARFSourceLanguageSYCL)]
1708        Sycl,
1709
1710        #[llvm_versions(19.1..)]
1711        #[llvm_variant(LLVMDWARFSourceLanguageRuby)]
1712        Ruby,
1713
1714        #[llvm_versions(19.1..)]
1715        #[llvm_variant(LLVMDWARFSourceLanguageMove)]
1716        Move,
1717
1718        #[llvm_versions(19.1..)]
1719        #[llvm_variant(LLVMDWARFSourceLanguageHylo)]
1720        Hylo,
1721
1722        #[llvm_versions(20..)]
1723        #[llvm_variant(LLVMDWARFSourceLanguageMetal)]
1724        Metal,
1725    }
1726}