use crate::AddressSpace;
use crate::basic_block::BasicBlock;
use crate::context::{AsContextRef, Context};
pub use crate::debug_info::flags::{DIFlags, DIFlagsConstants};
use crate::module::Module;
use crate::support::assert_niche;
use crate::values::{AsValueRef, BasicValueEnum, InstructionValue, MetadataValue, PointerValue};
use llvm_sys::core::LLVMMetadataAsValue;
use llvm_sys::{LLVMOpaqueDIBuilder, LLVMOpaqueMetadata};
use llvm_sys::debuginfo::LLVMDIBuilderCreateTypedef;
pub use llvm_sys::debuginfo::LLVMDWARFTypeEncoding;
use llvm_sys::debuginfo::LLVMDebugMetadataVersion;
use llvm_sys::debuginfo::LLVMDisposeDIBuilder;
use llvm_sys::debuginfo::LLVMMetadataReplaceAllUsesWith;
use llvm_sys::debuginfo::LLVMTemporaryMDNode;
use llvm_sys::debuginfo::{LLVMCreateDIBuilder, LLVMCreateDIBuilderDisallowUnresolved};
use llvm_sys::debuginfo::{
LLVMDIBuilderCreateArrayType, LLVMDIBuilderCreateAutoVariable, LLVMDIBuilderCreateBasicType,
LLVMDIBuilderCreateCompileUnit, LLVMDIBuilderCreateDebugLocation, LLVMDIBuilderCreateExpression,
LLVMDIBuilderCreateFile, LLVMDIBuilderCreateFunction, LLVMDIBuilderCreateLexicalBlock,
LLVMDIBuilderCreateMemberType, LLVMDIBuilderCreateNameSpace, LLVMDIBuilderCreateParameterVariable,
LLVMDIBuilderCreatePointerType, LLVMDIBuilderCreateReferenceType, LLVMDIBuilderCreateStructType,
LLVMDIBuilderCreateSubroutineType, LLVMDIBuilderCreateUnionType, LLVMDIBuilderFinalize,
LLVMDIBuilderGetOrCreateSubrange, LLVMDILocationGetColumn, LLVMDILocationGetLine, LLVMDILocationGetScope,
LLVMDITypeGetAlignInBits, LLVMDITypeGetOffsetInBits, LLVMDITypeGetSizeInBits,
};
use llvm_sys::debuginfo::{LLVMDIBuilderCreateEnumerationType, LLVMDIBuilderCreateEnumerator};
#[llvm_versions(..19.1)]
use llvm_sys::debuginfo::{
LLVMDIBuilderInsertDbgValueBefore, LLVMDIBuilderInsertDeclareAtEnd, LLVMDIBuilderInsertDeclareBefore,
};
#[llvm_versions(19.1..)]
use llvm_sys::debuginfo::{
LLVMDIBuilderInsertDbgValueRecordBefore as LLVMDIBuilderInsertDbgValueBefore,
LLVMDIBuilderInsertDeclareRecordAtEnd as LLVMDIBuilderInsertDeclareAtEnd,
LLVMDIBuilderInsertDeclareRecordBefore as LLVMDIBuilderInsertDeclareBefore,
};
#[llvm_versions(19.1..)]
use llvm_sys::prelude::LLVMValueRef;
use llvm_sys::debuginfo::{LLVMDIBuilderCreateConstantValueExpression, LLVMDIBuilderCreateGlobalVariableExpression};
use llvm_sys::prelude::{LLVMDIBuilderRef, LLVMMetadataRef};
use std::convert::TryInto;
use std::marker::PhantomData;
use std::ops::Range;
use std::ptr::NonNull;
pub fn debug_metadata_version() -> libc::c_uint {
unsafe { LLVMDebugMetadataVersion() }
}
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq)]
pub struct DebugInfoBuilder<'ctx> {
pub(crate) builder: NonNull<LLVMOpaqueDIBuilder>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DebugInfoBuilder>();
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DIScope<'ctx> {
metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DIScope>();
impl DIScope<'_> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
pub trait AsDIScope<'ctx> {
#[allow(clippy::wrong_self_convention)]
fn as_debug_info_scope(self) -> DIScope<'ctx>;
}
impl<'ctx> DebugInfoBuilder<'ctx> {
pub(crate) fn new(
module: &Module,
allow_unresolved: bool,
language: DWARFSourceLanguage,
filename: &str,
directory: &str,
producer: &str,
is_optimized: bool,
flags: &str,
runtime_ver: libc::c_uint,
split_name: &str,
kind: DWARFEmissionKind,
dwo_id: libc::c_uint,
split_debug_inlining: bool,
debug_info_for_profiling: bool,
sysroot: &str,
sdk: &str,
) -> (Self, DICompileUnit<'ctx>) {
let builder = unsafe {
if allow_unresolved {
LLVMCreateDIBuilder(module.as_mut_ptr())
} else {
LLVMCreateDIBuilderDisallowUnresolved(module.as_mut_ptr())
}
};
let builder = DebugInfoBuilder {
builder: unsafe { NonNull::new_unchecked(builder) },
_marker: PhantomData,
};
let file = builder.create_file(filename, directory);
let cu = builder.create_compile_unit(
language,
file,
producer,
is_optimized,
flags,
runtime_ver,
split_name,
kind,
dwo_id,
split_debug_inlining,
debug_info_for_profiling,
sysroot,
sdk,
);
(builder, cu)
}
pub fn as_mut_ptr(&self) -> LLVMDIBuilderRef {
self.builder.as_ptr()
}
fn create_compile_unit(
&self,
language: DWARFSourceLanguage,
file: DIFile<'ctx>,
producer: &str,
is_optimized: bool,
flags: &str,
runtime_ver: libc::c_uint,
split_name: &str,
kind: DWARFEmissionKind,
dwo_id: libc::c_uint,
split_debug_inlining: bool,
debug_info_for_profiling: bool,
sysroot: &str,
sdk: &str,
) -> DICompileUnit<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateCompileUnit(
self.as_mut_ptr(),
language.into(),
file.as_mut_ptr(),
producer.as_ptr() as _,
producer.len(),
is_optimized as _,
flags.as_ptr() as _,
flags.len(),
runtime_ver,
split_name.as_ptr() as _,
split_name.len(),
kind.into(),
dwo_id,
split_debug_inlining as _,
debug_info_for_profiling as _,
sysroot.as_ptr() as _,
sysroot.len(),
sdk.as_ptr() as _,
sdk.len(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DICompileUnit {
file,
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_function(
&self,
scope: DIScope<'ctx>,
name: &str,
linkage_name: Option<&str>,
file: DIFile<'ctx>,
line_no: u32,
ditype: DISubroutineType<'ctx>,
is_local_to_unit: bool,
is_definition: bool,
scope_line: u32,
flags: DIFlags,
is_optimized: bool,
) -> DISubprogram<'ctx> {
let linkage_name = linkage_name.unwrap_or(name);
let metadata_ref = unsafe {
LLVMDIBuilderCreateFunction(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
linkage_name.as_ptr() as _,
linkage_name.len(),
file.as_mut_ptr(),
line_no,
ditype.as_mut_ptr(),
is_local_to_unit as _,
is_definition as _,
scope_line as libc::c_uint,
flags,
is_optimized as _,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DISubprogram {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_lexical_block(
&self,
parent_scope: DIScope<'ctx>,
file: DIFile<'ctx>,
line: u32,
column: u32,
) -> DILexicalBlock<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateLexicalBlock(
self.as_mut_ptr(),
parent_scope.as_mut_ptr(),
file.as_mut_ptr(),
line as libc::c_uint,
column as libc::c_uint,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DILexicalBlock {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_file(&self, filename: &str, directory: &str) -> DIFile<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateFile(
self.as_mut_ptr(),
filename.as_ptr() as _,
filename.len(),
directory.as_ptr() as _,
directory.len(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIFile {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_debug_location(
&self,
context: impl AsContextRef<'ctx>,
line: u32,
column: u32,
scope: DIScope<'ctx>,
inlined_at: Option<DILocation<'ctx>>,
) -> DILocation<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateDebugLocation(
context.as_ctx_ref(),
line,
column,
scope.as_mut_ptr(),
inlined_at.map(|l| l.as_mut_ptr()).unwrap_or(std::ptr::null_mut()),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DILocation {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_basic_type(
&self,
name: &str,
size_in_bits: u64,
encoding: LLVMDWARFTypeEncoding,
flags: DIFlags,
) -> Result<DIBasicType<'ctx>, crate::error::Error> {
if name.is_empty() {
return Err(crate::error::Error::EmptyNameError);
}
let metadata_ref = unsafe {
LLVMDIBuilderCreateBasicType(
self.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
size_in_bits,
encoding,
flags,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
Ok(DIBasicType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
})
}
pub fn create_typedef(
&self,
ditype: DIType<'ctx>,
name: &str,
file: DIFile<'ctx>,
line_no: u32,
scope: DIScope<'ctx>,
align_in_bits: u32,
) -> DIDerivedType<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateTypedef(
self.as_mut_ptr(),
ditype.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
file.as_mut_ptr(),
line_no,
scope.as_mut_ptr(),
align_in_bits,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIDerivedType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_union_type(
&self,
scope: DIScope<'ctx>,
name: &str,
file: DIFile<'ctx>,
line_no: u32,
size_in_bits: u64,
align_in_bits: u32,
flags: DIFlags,
elements: &[DIType<'ctx>],
runtime_language: u32,
unique_id: &str,
) -> DICompositeType<'ctx> {
let mut elements: Vec<LLVMMetadataRef> = elements.iter().map(|dt| dt.as_mut_ptr()).collect();
let metadata_ref = unsafe {
LLVMDIBuilderCreateUnionType(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
file.as_mut_ptr(),
line_no,
size_in_bits,
align_in_bits,
flags,
elements.as_mut_ptr(),
elements.len().try_into().unwrap(),
runtime_language,
unique_id.as_ptr() as _,
unique_id.len(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DICompositeType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_member_type(
&self,
scope: DIScope<'ctx>,
name: &str,
file: DIFile<'ctx>,
line_no: libc::c_uint,
size_in_bits: u64,
align_in_bits: u32,
offset_in_bits: u64,
flags: DIFlags,
ty: DIType<'ctx>,
) -> DIDerivedType<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateMemberType(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
file.as_mut_ptr(),
line_no,
size_in_bits,
align_in_bits,
offset_in_bits,
flags,
ty.as_mut_ptr(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIDerivedType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_struct_type(
&self,
scope: DIScope<'ctx>,
name: &str,
file: DIFile<'ctx>,
line_no: libc::c_uint,
size_in_bits: u64,
align_in_bits: u32,
flags: DIFlags,
derived_from: Option<DIType<'ctx>>,
elements: &[DIType<'ctx>],
runtime_language: libc::c_uint,
vtable_holder: Option<DIType<'ctx>>,
unique_id: &str,
) -> DICompositeType<'ctx> {
let mut elements: Vec<LLVMMetadataRef> = elements.iter().map(|dt| dt.as_mut_ptr()).collect();
let derived_from = derived_from.map_or(std::ptr::null_mut(), |dt| dt.as_mut_ptr());
let vtable_holder = vtable_holder.map_or(std::ptr::null_mut(), |dt| dt.as_mut_ptr());
let metadata_ref = unsafe {
LLVMDIBuilderCreateStructType(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
file.as_mut_ptr(),
line_no,
size_in_bits,
align_in_bits,
flags,
derived_from,
elements.as_mut_ptr(),
elements.len().try_into().unwrap(),
runtime_language,
vtable_holder,
unique_id.as_ptr() as _,
unique_id.len(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DICompositeType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_subroutine_type(
&self,
file: DIFile<'ctx>,
return_type: Option<DIType<'ctx>>,
parameter_types: &[DIType<'ctx>],
flags: DIFlags,
) -> DISubroutineType<'ctx> {
let mut p = vec![return_type.map_or(std::ptr::null_mut(), |t| t.as_mut_ptr())];
p.append(
&mut parameter_types
.iter()
.map(|t| t.as_mut_ptr())
.collect::<Vec<LLVMMetadataRef>>(),
);
let metadata_ref = unsafe {
LLVMDIBuilderCreateSubroutineType(
self.as_mut_ptr(),
file.as_mut_ptr(),
p.as_mut_ptr(),
p.len().try_into().unwrap(),
flags,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DISubroutineType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_pointer_type(
&self,
name: &str,
pointee: DIType<'ctx>,
size_in_bits: u64,
align_in_bits: u32,
address_space: AddressSpace,
) -> DIDerivedType<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreatePointerType(
self.as_mut_ptr(),
pointee.as_mut_ptr(),
size_in_bits,
align_in_bits,
address_space.0,
name.as_ptr() as _,
name.len(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null");
DIDerivedType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_reference_type(&self, pointee: DIType<'ctx>, tag: u32) -> DIDerivedType<'ctx> {
let metadata_ref = unsafe { LLVMDIBuilderCreateReferenceType(self.as_mut_ptr(), tag, pointee.as_mut_ptr()) };
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIDerivedType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_array_type(
&self,
inner_type: DIType<'ctx>,
size_in_bits: u64,
align_in_bits: u32,
subscripts: &[Range<i64>],
) -> DICompositeType<'ctx> {
let mut subscripts = subscripts
.iter()
.map(|range| {
let lower = range.start;
let upper = range.end;
let subscript_size = upper - lower;
unsafe { LLVMDIBuilderGetOrCreateSubrange(self.as_mut_ptr(), lower, subscript_size) }
})
.collect::<Vec<_>>();
let metadata_ref = unsafe {
LLVMDIBuilderCreateArrayType(
self.as_mut_ptr(),
size_in_bits,
align_in_bits,
inner_type.as_mut_ptr(),
subscripts.as_mut_ptr(),
subscripts.len().try_into().unwrap(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DICompositeType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_enumeration_type(
&self,
scope: DIScope<'ctx>,
name: &str,
file: DIFile<'ctx>,
line_no: u32,
size_in_bits: u64,
align_in_bits: u32,
elements: &[DIEnumerator<'ctx>],
inner_type: DIType<'ctx>,
) -> DICompositeType<'ctx> {
let mut elements: Vec<LLVMMetadataRef> = elements.iter().map(|dt| dt.as_mut_ptr()).collect();
let metadata_ref = unsafe {
LLVMDIBuilderCreateEnumerationType(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
file.as_mut_ptr(),
line_no,
size_in_bits,
align_in_bits,
elements.as_mut_ptr(),
elements.len().try_into().unwrap(),
inner_type.as_mut_ptr(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DICompositeType {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_enumerator(&self, name: &str, value: i64, is_unsigned: bool) -> DIEnumerator<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateEnumerator(
self.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
value,
is_unsigned as i32,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIEnumerator {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_global_variable_expression(
&self,
scope: DIScope<'ctx>,
name: &str,
linkage: &str,
file: DIFile<'ctx>,
line_no: u32,
ty: DIType<'ctx>,
local_to_unit: bool,
expression: Option<DIExpression>,
declaration: Option<DIScope>,
align_in_bits: u32,
) -> DIGlobalVariableExpression<'ctx> {
let expression_ptr = expression.map_or(std::ptr::null_mut(), |dt| dt.as_mut_ptr());
let decl_ptr = declaration.map_or(std::ptr::null_mut(), |dt| dt.as_mut_ptr());
let metadata_ref = unsafe {
LLVMDIBuilderCreateGlobalVariableExpression(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
linkage.as_ptr() as _,
linkage.len(),
file.as_mut_ptr(),
line_no,
ty.as_mut_ptr(),
local_to_unit as _,
expression_ptr,
decl_ptr,
align_in_bits,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIGlobalVariableExpression {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_constant_expression(&self, value: i64) -> DIExpression<'ctx> {
let metadata_ref = unsafe { LLVMDIBuilderCreateConstantValueExpression(self.as_mut_ptr(), value as _) };
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIExpression {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_parameter_variable(
&self,
scope: DIScope<'ctx>,
name: &str,
arg_no: u32,
file: DIFile<'ctx>,
line_no: u32,
ty: DIType<'ctx>,
always_preserve: bool,
flags: DIFlags,
) -> DILocalVariable<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateParameterVariable(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
arg_no,
file.as_mut_ptr(),
line_no,
ty.as_mut_ptr(),
always_preserve as _,
flags,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DILocalVariable {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_auto_variable(
&self,
scope: DIScope<'ctx>,
name: &str,
file: DIFile<'ctx>,
line_no: u32,
ty: DIType<'ctx>,
always_preserve: bool,
flags: DIFlags,
align_in_bits: u32,
) -> DILocalVariable<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateAutoVariable(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
file.as_mut_ptr(),
line_no,
ty.as_mut_ptr(),
always_preserve as _,
flags,
align_in_bits,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DILocalVariable {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn create_namespace(&self, scope: DIScope<'ctx>, name: &str, export_symbols: bool) -> DINamespace<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateNameSpace(
self.as_mut_ptr(),
scope.as_mut_ptr(),
name.as_ptr() as _,
name.len(),
export_symbols as _,
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DINamespace {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn insert_declare_before_instruction(
&self,
storage: PointerValue<'ctx>,
var_info: Option<DILocalVariable<'ctx>>,
expr: Option<DIExpression<'ctx>>,
debug_loc: DILocation<'ctx>,
instruction: InstructionValue<'ctx>,
) -> InstructionValue<'ctx> {
let value_ref = unsafe {
LLVMDIBuilderInsertDeclareBefore(
self.as_mut_ptr(),
storage.as_value_ref(),
var_info.map(|v| v.as_mut_ptr()).unwrap_or(std::ptr::null_mut()),
expr.unwrap_or_else(|| self.create_expression(vec![])).as_mut_ptr(),
debug_loc.as_mut_ptr(),
instruction.as_value_ref(),
)
};
#[cfg(any(
feature = "llvm19-1",
feature = "llvm20-1",
feature = "llvm21-1",
feature = "llvm22-1"
))]
{
unsafe { InstructionValue::new(value_ref as LLVMValueRef) }
}
#[cfg(not(any(
feature = "llvm19-1",
feature = "llvm20-1",
feature = "llvm21-1",
feature = "llvm22-1"
)))]
{
unsafe { InstructionValue::new(value_ref) }
}
}
pub fn insert_declare_at_end(
&self,
storage: PointerValue<'ctx>,
var_info: Option<DILocalVariable<'ctx>>,
expr: Option<DIExpression<'ctx>>,
debug_loc: DILocation<'ctx>,
block: BasicBlock<'ctx>,
) -> InstructionValue<'ctx> {
let value_ref = unsafe {
LLVMDIBuilderInsertDeclareAtEnd(
self.as_mut_ptr(),
storage.as_value_ref(),
var_info.map(|v| v.as_mut_ptr()).unwrap_or(std::ptr::null_mut()),
expr.unwrap_or_else(|| self.create_expression(vec![])).as_mut_ptr(),
debug_loc.as_mut_ptr(),
block.as_mut_ptr(),
)
};
#[cfg(any(
feature = "llvm19-1",
feature = "llvm20-1",
feature = "llvm21-1",
feature = "llvm22-1"
))]
{
unsafe { InstructionValue::new(value_ref as LLVMValueRef) }
}
#[cfg(not(any(
feature = "llvm19-1",
feature = "llvm20-1",
feature = "llvm21-1",
feature = "llvm22-1"
)))]
{
unsafe { InstructionValue::new(value_ref) }
}
}
pub fn create_expression(&self, mut address_operations: Vec<i64>) -> DIExpression<'ctx> {
let metadata_ref = unsafe {
LLVMDIBuilderCreateExpression(
self.as_mut_ptr(),
address_operations.as_mut_ptr() as *mut _,
address_operations.len(),
)
};
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIExpression {
metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) },
_marker: PhantomData,
}
}
pub fn insert_dbg_value_before(
&self,
value: BasicValueEnum<'ctx>,
var_info: DILocalVariable<'ctx>,
expr: Option<DIExpression<'ctx>>,
debug_loc: DILocation<'ctx>,
instruction: InstructionValue<'ctx>,
) -> InstructionValue<'ctx> {
let value_ref = unsafe {
LLVMDIBuilderInsertDbgValueBefore(
self.as_mut_ptr(),
value.as_value_ref(),
var_info.as_mut_ptr(),
expr.unwrap_or_else(|| self.create_expression(vec![])).as_mut_ptr(),
debug_loc.as_mut_ptr(),
instruction.as_value_ref(),
)
};
#[cfg(any(
feature = "llvm19-1",
feature = "llvm20-1",
feature = "llvm21-1",
feature = "llvm22-1"
))]
{
unsafe { InstructionValue::new(value_ref as LLVMValueRef) }
}
#[cfg(not(any(
feature = "llvm19-1",
feature = "llvm20-1",
feature = "llvm21-1",
feature = "llvm22-1"
)))]
{
unsafe { InstructionValue::new(value_ref) }
}
}
pub unsafe fn create_placeholder_derived_type(&self, context: impl AsContextRef<'ctx>) -> DIDerivedType<'ctx> {
unsafe {
let metadata_ref = LLVMTemporaryMDNode(context.as_ctx_ref(), std::ptr::null_mut(), 0);
debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null.");
DIDerivedType {
metadata_ref: NonNull::new_unchecked(metadata_ref),
_marker: PhantomData,
}
}
}
pub unsafe fn replace_placeholder_derived_type(
&self,
placeholder: DIDerivedType<'ctx>,
other: DIDerivedType<'ctx>,
) {
unsafe {
LLVMMetadataReplaceAllUsesWith(placeholder.as_mut_ptr(), other.as_mut_ptr());
}
}
pub fn finalize(&self) {
unsafe { LLVMDIBuilderFinalize(self.as_mut_ptr()) };
}
}
impl Drop for DebugInfoBuilder<'_> {
fn drop(&mut self) {
self.finalize();
unsafe { LLVMDisposeDIBuilder(self.as_mut_ptr()) }
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DIFile<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DIFile>();
impl<'ctx> AsDIScope<'ctx> for DIFile<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
impl DIFile<'_> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DICompileUnit<'ctx> {
file: DIFile<'ctx>,
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DICompileUnit>();
impl<'ctx> DICompileUnit<'ctx> {
pub fn get_file(&self) -> DIFile<'ctx> {
self.file
}
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
impl<'ctx> AsDIScope<'ctx> for DICompileUnit<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DINamespace<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DINamespace>();
impl DINamespace<'_> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
impl<'ctx> AsDIScope<'ctx> for DINamespace<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DISubprogram<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
pub(crate) _marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DISubprogram>();
impl<'ctx> AsDIScope<'ctx> for DISubprogram<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
impl DISubprogram<'_> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DIType<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DIType>();
impl DIType<'_> {
pub fn get_size_in_bits(&self) -> u64 {
unsafe { LLVMDITypeGetSizeInBits(self.as_mut_ptr()) }
}
pub fn get_align_in_bits(&self) -> u32 {
unsafe { LLVMDITypeGetAlignInBits(self.as_mut_ptr()) }
}
pub fn get_offset_in_bits(&self) -> u64 {
unsafe { LLVMDITypeGetOffsetInBits(self.as_mut_ptr()) }
}
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
impl<'ctx> AsDIScope<'ctx> for DIType<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DIDerivedType<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DIDerivedType>();
impl<'ctx> DIDerivedType<'ctx> {
pub fn as_type(&self) -> DIType<'ctx> {
DIType {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
impl DIDerivedType<'_> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
impl<'ctx> AsDIScope<'ctx> for DIDerivedType<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DIBasicType<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DIBasicType>();
impl<'ctx> DIBasicType<'ctx> {
pub fn as_type(&self) -> DIType<'ctx> {
DIType {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
impl<'ctx> AsDIScope<'ctx> for DIBasicType<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DICompositeType<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DICompositeType>();
impl<'ctx> DICompositeType<'ctx> {
pub fn as_type(&self) -> DIType<'ctx> {
DIType {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
impl<'ctx> AsDIScope<'ctx> for DICompositeType<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DISubroutineType<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DISubroutineType>();
impl<'ctx> DISubroutineType<'ctx> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DILexicalBlock<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DILexicalBlock>();
impl<'ctx> AsDIScope<'ctx> for DILexicalBlock<'ctx> {
fn as_debug_info_scope(self) -> DIScope<'ctx> {
DIScope {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
impl DILexicalBlock<'_> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DILocation<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
pub(crate) _marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DILocation>();
impl<'ctx> DILocation<'ctx> {
pub fn get_line(&self) -> u32 {
unsafe { LLVMDILocationGetLine(self.as_mut_ptr()) }
}
pub fn get_column(&self) -> u32 {
unsafe { LLVMDILocationGetColumn(self.as_mut_ptr()) }
}
pub fn get_scope(&self) -> DIScope<'ctx> {
DIScope {
metadata_ref: unsafe { NonNull::new_unchecked(LLVMDILocationGetScope(self.as_mut_ptr())) },
_marker: PhantomData,
}
}
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DILocalVariable<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DILocalVariable>();
impl DILocalVariable<'_> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DIGlobalVariableExpression<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DIGlobalVariableExpression>();
impl<'ctx> DIGlobalVariableExpression<'ctx> {
pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> {
unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.as_mut_ptr())) }
}
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DIExpression<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DIExpression>();
impl DIExpression<'_> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
}
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct DIEnumerator<'ctx> {
pub(crate) metadata_ref: NonNull<LLVMOpaqueMetadata>,
_marker: PhantomData<&'ctx Context>,
}
const _: () = assert_niche::<DIEnumerator>();
impl<'ctx> DIEnumerator<'ctx> {
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
self.metadata_ref.as_ptr()
}
pub fn as_type(&self) -> DIType<'ctx> {
DIType {
metadata_ref: self.metadata_ref,
_marker: PhantomData,
}
}
}
pub use flags::*;
mod flags {
pub use llvm_sys::debuginfo::LLVMDIFlags as DIFlags;
use llvm_sys::debuginfo::{LLVMDWARFEmissionKind, LLVMDWARFSourceLanguage};
pub trait DIFlagsConstants {
const ZERO: Self;
const PRIVATE: Self;
const PROTECTED: Self;
const PUBLIC: Self;
const FWD_DECL: Self;
const APPLE_BLOCK: Self;
const VIRTUAL: Self;
const ARTIFICIAL: Self;
const EXPLICIT: Self;
const PROTOTYPED: Self;
const OBJC_CLASS_COMPLETE: Self;
const OBJECT_POINTER: Self;
const VECTOR: Self;
const STATIC_MEMBER: Self;
const LVALUE_REFERENCE: Self;
const RVALUE_REFERENCE: Self;
const RESERVED: Self;
const SINGLE_INHERITANCE: Self;
const MULTIPLE_INHERITANCE: Self;
const VIRTUAL_INHERITANCE: Self;
const INTRODUCED_VIRTUAL: Self;
const BIT_FIELD: Self;
const NO_RETURN: Self;
const TYPE_PASS_BY_VALUE: Self;
const TYPE_PASS_BY_REFERENCE: Self;
const THUNK: Self;
const INDIRECT_VIRTUAL_BASE: Self;
}
impl DIFlagsConstants for DIFlags {
const ZERO: DIFlags = llvm_sys::debuginfo::LLVMDIFlagZero;
const PRIVATE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagPrivate;
const PROTECTED: DIFlags = llvm_sys::debuginfo::LLVMDIFlagProtected;
const PUBLIC: DIFlags = llvm_sys::debuginfo::LLVMDIFlagPublic;
const FWD_DECL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagFwdDecl;
const APPLE_BLOCK: DIFlags = llvm_sys::debuginfo::LLVMDIFlagAppleBlock;
const VIRTUAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagVirtual;
const ARTIFICIAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagArtificial;
const EXPLICIT: DIFlags = llvm_sys::debuginfo::LLVMDIFlagExplicit;
const PROTOTYPED: DIFlags = llvm_sys::debuginfo::LLVMDIFlagPrototyped;
const OBJC_CLASS_COMPLETE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagObjcClassComplete;
const OBJECT_POINTER: DIFlags = llvm_sys::debuginfo::LLVMDIFlagObjectPointer;
const VECTOR: DIFlags = llvm_sys::debuginfo::LLVMDIFlagVector;
const STATIC_MEMBER: DIFlags = llvm_sys::debuginfo::LLVMDIFlagStaticMember;
const LVALUE_REFERENCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagLValueReference;
const RVALUE_REFERENCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagRValueReference;
const RESERVED: DIFlags = llvm_sys::debuginfo::LLVMDIFlagReserved;
const SINGLE_INHERITANCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagSingleInheritance;
const MULTIPLE_INHERITANCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagMultipleInheritance;
const VIRTUAL_INHERITANCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagVirtualInheritance;
const INTRODUCED_VIRTUAL: DIFlags = llvm_sys::debuginfo::LLVMDIFlagIntroducedVirtual;
const BIT_FIELD: DIFlags = llvm_sys::debuginfo::LLVMDIFlagBitField;
const NO_RETURN: DIFlags = llvm_sys::debuginfo::LLVMDIFlagNoReturn;
const TYPE_PASS_BY_VALUE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagTypePassByValue;
const TYPE_PASS_BY_REFERENCE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagTypePassByReference;
const THUNK: DIFlags = llvm_sys::debuginfo::LLVMDIFlagThunk;
const INDIRECT_VIRTUAL_BASE: DIFlags = llvm_sys::debuginfo::LLVMDIFlagIndirectVirtualBase;
}
#[llvm_enum(LLVMDWARFEmissionKind)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum DWARFEmissionKind {
#[llvm_variant(LLVMDWARFEmissionKindNone)]
None,
#[llvm_variant(LLVMDWARFEmissionKindFull)]
Full,
#[llvm_variant(LLVMDWARFEmissionKindLineTablesOnly)]
LineTablesOnly,
}
#[llvm_enum(LLVMDWARFSourceLanguage)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum DWARFSourceLanguage {
#[llvm_variant(LLVMDWARFSourceLanguageC89)]
C89,
#[llvm_variant(LLVMDWARFSourceLanguageC)]
C,
#[llvm_variant(LLVMDWARFSourceLanguageAda83)]
Ada83,
#[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus)]
CPlusPlus,
#[llvm_variant(LLVMDWARFSourceLanguageCobol74)]
Cobol74,
#[llvm_variant(LLVMDWARFSourceLanguageCobol85)]
Cobol85,
#[llvm_variant(LLVMDWARFSourceLanguageFortran77)]
Fortran77,
#[llvm_variant(LLVMDWARFSourceLanguageFortran90)]
Fortran90,
#[llvm_variant(LLVMDWARFSourceLanguagePascal83)]
Pascal83,
#[llvm_variant(LLVMDWARFSourceLanguageModula2)]
Modula2,
#[llvm_variant(LLVMDWARFSourceLanguageJava)]
Java,
#[llvm_variant(LLVMDWARFSourceLanguageC99)]
C99,
#[llvm_variant(LLVMDWARFSourceLanguageAda95)]
Ada95,
#[llvm_variant(LLVMDWARFSourceLanguageFortran95)]
Fortran95,
#[llvm_variant(LLVMDWARFSourceLanguagePLI)]
PLI,
#[llvm_variant(LLVMDWARFSourceLanguageObjC)]
ObjC,
#[llvm_variant(LLVMDWARFSourceLanguageObjC_plus_plus)]
ObjCPlusPlus,
#[llvm_variant(LLVMDWARFSourceLanguageUPC)]
UPC,
#[llvm_variant(LLVMDWARFSourceLanguageD)]
D,
#[llvm_variant(LLVMDWARFSourceLanguagePython)]
Python,
#[llvm_variant(LLVMDWARFSourceLanguageOpenCL)]
OpenCL,
#[llvm_variant(LLVMDWARFSourceLanguageGo)]
Go,
#[llvm_variant(LLVMDWARFSourceLanguageModula3)]
Modula3,
#[llvm_variant(LLVMDWARFSourceLanguageHaskell)]
Haskell,
#[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_03)]
CPlusPlus03,
#[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_11)]
CPlusPlus11,
#[llvm_variant(LLVMDWARFSourceLanguageOCaml)]
OCaml,
#[llvm_variant(LLVMDWARFSourceLanguageRust)]
Rust,
#[llvm_variant(LLVMDWARFSourceLanguageC11)]
C11,
#[llvm_variant(LLVMDWARFSourceLanguageSwift)]
Swift,
#[llvm_variant(LLVMDWARFSourceLanguageJulia)]
Julia,
#[llvm_variant(LLVMDWARFSourceLanguageDylan)]
Dylan,
#[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_14)]
CPlusPlus14,
#[llvm_variant(LLVMDWARFSourceLanguageFortran03)]
Fortran03,
#[llvm_variant(LLVMDWARFSourceLanguageFortran08)]
Fortran08,
#[llvm_variant(LLVMDWARFSourceLanguageRenderScript)]
RenderScript,
#[llvm_variant(LLVMDWARFSourceLanguageBLISS)]
BLISS,
#[llvm_variant(LLVMDWARFSourceLanguageMips_Assembler)]
MipsAssembler,
#[llvm_variant(LLVMDWARFSourceLanguageGOOGLE_RenderScript)]
GOOGLERenderScript,
#[llvm_variant(LLVMDWARFSourceLanguageBORLAND_Delphi)]
BORLANDDelphi,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageKotlin)]
Kotlin,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageZig)]
Zig,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageCrystal)]
Crystal,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_17)]
CPlusPlus17,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageC_plus_plus_20)]
CPlusPlus20,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageC17)]
C17,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageFortran18)]
Fortran18,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageAda2005)]
Ada2005,
#[llvm_versions(16..)]
#[llvm_variant(LLVMDWARFSourceLanguageAda2012)]
Ada2012,
#[llvm_versions(17..)]
#[llvm_variant(LLVMDWARFSourceLanguageMojo)]
Mojo,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageHIP)]
Hip,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageAssembly)]
Assembly,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageC_sharp)]
Csharp,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageGLSL)]
Glsl,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageGLSL_ES)]
GlslEs,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageHLSL)]
Hlsl,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageOpenCL_CPP)]
OpenClCpp,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageCPP_for_OpenCL)]
CppForOpenCl,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageSYCL)]
Sycl,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageRuby)]
Ruby,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageMove)]
Move,
#[llvm_versions(19.1..)]
#[llvm_variant(LLVMDWARFSourceLanguageHylo)]
Hylo,
#[llvm_versions(20..)]
#[llvm_variant(LLVMDWARFSourceLanguageMetal)]
Metal,
}
}