Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

di: add safe wrapper around LLVMGlobalCopyAllMetadata #170

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 38 additions & 19 deletions src/llvm/di.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,8 @@ impl DISanitizer {
);
}

if can_get_all_metadata(value) {
for (index, (kind, metadata)) in iter_metadata_copy(value).enumerate() {
if let Some(entries) = MetadataEntries::new(value) {
for (index, (metadata, kind)) in entries.iter().enumerate() {
let metadata_value = LLVMMetadataAsValue(self.context, metadata);
trace!("{one:depth$}all_metadata entry: index:{}", index);
self.discover(metadata_value, depth + 1);
Expand Down Expand Up @@ -348,15 +348,42 @@ unsafe fn iter_operands(v: LLVMValueRef) -> impl Iterator<Item = LLVMValueRef> {
(0..LLVMGetNumOperands(v)).map(move |i| LLVMGetOperand(v, i as u32))
}

unsafe fn iter_metadata_copy(v: LLVMValueRef) -> impl Iterator<Item = (u32, LLVMMetadataRef)> {
let mut count = 0;
let entries = LLVMGlobalCopyAllMetadata(v, &mut count);
(0..count).map(move |index| {
(
LLVMValueMetadataEntriesGetKind(entries, index as u32),
LLVMValueMetadataEntriesGetMetadata(entries, index as u32),
)
})
struct MetadataEntries {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move it to src/llvm/types/di.rs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all metadata is DI?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. I see that the LLVMGlobalCopyAllMetadata belongs to llvm/lib/IR/Core.cpp. I would then keep it in src/llvm/types/ir.rs (or, eventually, but probably too muc effort - split ir.rs into a subdir with mod.rs and core.rs, where eventual wrappers for other IR/* files could have their own files).

My main point is that I would prefer to not mix wrappers (which are currently in the types subdir) and DI sanitization logic in the same module.

entries: *mut LLVMValueMetadataEntry,
count: usize,
}

impl MetadataEntries {
fn new(v: LLVMValueRef) -> Option<Self> {
if unsafe { LLVMIsAGlobalObject(v).is_null() && LLVMIsAInstruction(v).is_null() } {
return None;
}

let mut count = 0;
let entries = unsafe { LLVMGlobalCopyAllMetadata(v, &mut count) };
if entries.is_null() {
return None;
}

Some(MetadataEntries { entries, count })
}

fn iter(&self) -> impl Iterator<Item = (LLVMMetadataRef, u32)> + '_ {
(0..self.count).map(move |index| unsafe {
(
LLVMValueMetadataEntriesGetMetadata(self.entries, index as u32),
LLVMValueMetadataEntriesGetKind(self.entries, index as u32),
)
})
}
}

impl Drop for MetadataEntries {
fn drop(&mut self) {
unsafe {
LLVMDisposeValueMetadataEntries(self.entries);
}
}
}

unsafe fn is_instruction(v: LLVMValueRef) -> bool {
Expand All @@ -371,14 +398,6 @@ unsafe fn is_user(v: LLVMValueRef) -> bool {
!LLVMIsAUser(v).is_null()
}

unsafe fn is_globalobject(v: LLVMValueRef) -> bool {
!LLVMIsAGlobalObject(v).is_null()
}

unsafe fn can_get_all_metadata(v: LLVMValueRef) -> bool {
is_globalobject(v) || is_instruction(v)
}

unsafe fn can_get_operands(v: LLVMValueRef) -> bool {
is_mdnode(v) || is_user(v)
}
Expand Down