Skip to content

Commit b9c5327

Browse files
abrooooTheDan64
andauthored
add support for enumeration type and enumerators (#623)
* add support for enumeration debug types * add doc * guard enumeration debug info for LLVM 9+ LLVMDIBuilderCreateEnumerator was added in LLVM 9.0 => guard create_enumerator, create_enumeration_type, and test. * add llvm21-1 to the tests --------- Co-authored-by: Dan Kolsoi <ThaDan64@gmail.com>
1 parent 6354acb commit b9c5327

2 files changed

Lines changed: 156 additions & 0 deletions

File tree

src/debug_info.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ use llvm_sys::debuginfo::{
127127
LLVMDITypeGetAlignInBits, LLVMDITypeGetOffsetInBits, LLVMDITypeGetSizeInBits,
128128
};
129129

130+
#[llvm_versions(9..)]
131+
use llvm_sys::debuginfo::{LLVMDIBuilderCreateEnumerationType, LLVMDIBuilderCreateEnumerator};
132+
130133
#[llvm_versions(..19.1)]
131134
use llvm_sys::debuginfo::{
132135
LLVMDIBuilderInsertDbgValueBefore, LLVMDIBuilderInsertDeclareAtEnd, LLVMDIBuilderInsertDeclareBefore,
@@ -815,6 +818,55 @@ impl<'ctx> DebugInfoBuilder<'ctx> {
815818
}
816819
}
817820

821+
/// Create an enumeration type
822+
#[llvm_versions(9..)]
823+
pub fn create_enumeration_type(
824+
&self,
825+
scope: DIScope<'ctx>,
826+
name: &str,
827+
file: DIFile<'ctx>,
828+
line_no: u32,
829+
size_in_bits: u64,
830+
align_in_bits: u32,
831+
elements: &[DIEnumerator<'ctx>],
832+
inner_type: DIType<'ctx>,
833+
) -> DICompositeType<'ctx> {
834+
let mut elements: Vec<LLVMMetadataRef> = elements.iter().map(|dt| dt.metadata_ref).collect();
835+
let metadata_ref = unsafe {
836+
LLVMDIBuilderCreateEnumerationType(
837+
self.builder,
838+
scope.metadata_ref,
839+
name.as_ptr() as _,
840+
name.len(),
841+
file.metadata_ref,
842+
line_no,
843+
size_in_bits,
844+
align_in_bits,
845+
elements.as_mut_ptr(),
846+
elements.len().try_into().unwrap(),
847+
inner_type.metadata_ref,
848+
)
849+
};
850+
851+
DICompositeType {
852+
metadata_ref,
853+
_marker: PhantomData,
854+
}
855+
}
856+
857+
/// Create an enumerator
858+
#[llvm_versions(9..)]
859+
pub fn create_enumerator(&self, name: &str, value: i64, is_unsigned: bool) -> DIEnumerator<'ctx> {
860+
let metadata_ref = unsafe {
861+
LLVMDIBuilderCreateEnumerator(self.builder, name.as_ptr() as _, name.len(), value, is_unsigned as i32)
862+
};
863+
864+
DIEnumerator {
865+
metadata_ref,
866+
_marker: PhantomData,
867+
}
868+
}
869+
818870
pub fn create_global_variable_expression(
819871
&self,
820872
scope: DIScope<'ctx>,
@@ -1436,6 +1488,26 @@ impl DIExpression<'_> {
14361488
}
14371489
}
14381490

1491+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1492+
pub struct DIEnumerator<'ctx> {
1493+
pub(crate) metadata_ref: LLVMMetadataRef,
1494+
_marker: PhantomData<&'ctx Context>,
1495+
}
1496+
1497+
impl<'ctx> DIEnumerator<'ctx> {
1498+
/// Acquires the underlying raw pointer belonging to this `DIEnumerator` type.
1499+
pub fn as_mut_ptr(&self) -> LLVMMetadataRef {
1500+
self.metadata_ref
1501+
}
1502+
1503+
pub fn as_type(&self) -> DIType<'ctx> {
1504+
DIType {
1505+
metadata_ref: self.metadata_ref,
1506+
_marker: PhantomData,
1507+
}
1508+
}
1509+
}
1510+
14391511
pub use flags::*;
14401512
mod flags {
14411513
pub use llvm_sys::debuginfo::LLVMDIFlags as DIFlags;

tests/all/test_debug_info.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,3 +636,87 @@ fn test_array_type() {
636636

637637
dibuilder.create_array_type(di_type, 160, 64, &[(0..20), (-1..30), (20..55)]);
638638
}
639+
640+
#[llvm_versions(9..)]
641+
#[test]
642+
fn test_enumeration_types() {
643+
let context = Context::create();
644+
let module = context.create_module("bin");
645+
646+
let (dibuilder, compile_unit) = module.create_debug_info_builder(
647+
true,
648+
DWARFSourceLanguage::C,
649+
"source_file",
650+
".",
651+
"my llvm compiler frontend",
652+
false,
653+
"",
654+
0,
655+
"",
656+
DWARFEmissionKind::Full,
657+
0,
658+
false,
659+
false,
660+
#[cfg(any(
661+
feature = "llvm11-0",
662+
feature = "llvm12-0",
663+
feature = "llvm13-0",
664+
feature = "llvm14-0",
665+
feature = "llvm15-0",
666+
feature = "llvm16-0",
667+
feature = "llvm17-0",
668+
feature = "llvm18-1",
669+
feature = "llvm19-1",
670+
feature = "llvm20-1",
671+
feature = "llvm21-1"
672+
))]
673+
"",
674+
#[cfg(any(
675+
feature = "llvm11-0",
676+
feature = "llvm12-0",
677+
feature = "llvm13-0",
678+
feature = "llvm14-0",
679+
feature = "llvm15-0",
680+
feature = "llvm16-0",
681+
feature = "llvm17-0",
682+
feature = "llvm18-1",
683+
feature = "llvm19-1",
684+
feature = "llvm20-1",
685+
feature = "llvm21-1"
686+
))]
687+
"",
688+
);
689+
690+
let di_type = dibuilder
691+
.create_basic_type("type_name", 8_u64, 0x00, DIFlags::ZERO)
692+
.unwrap()
693+
.as_type();
694+
695+
// Smoke test that the enums get created
696+
let enum_red = dibuilder.create_enumerator("RED", 0, false);
697+
let enum_green = dibuilder.create_enumerator("GREEN", 1, false);
698+
let enum_blue = dibuilder.create_enumerator("BLUE", 2, false);
699+
700+
// Smoke test that the enumeration type gets created
701+
dibuilder.create_enumeration_type(
702+
compile_unit.as_debug_info_scope(),
703+
"Color",
704+
compile_unit.get_file(),
705+
1,
706+
32,
707+
32,
708+
&[enum_red, enum_green, enum_blue],
709+
di_type,
710+
);
711+
712+
// Smoke test that we can get the pointer and type back from the enumerator
713+
assert!(!enum_red.as_mut_ptr().is_null());
714+
715+
let _enum_red_as_type = enum_red.as_type();
716+
717+
// check that finalize works without errors
718+
dibuilder.finalize();
719+
720+
// check that module is still valid
721+
assert!(module.verify().is_ok());
722+
}

0 commit comments

Comments
 (0)