Skip to main content

inkwell/
comdat.rs

1//! A `Comdat` helps resolve linker errors for duplicate sections.
2// https://llvm.org/doxygen/IR_2Comdat_8h_source.html
3// https://stackoverflow.com/questions/1834597/what-is-the-comdat-section-used-for
4
5use std::ptr::NonNull;
6
7use llvm_sys::LLVMComdat;
8use llvm_sys::comdat::{LLVMComdatSelectionKind, LLVMGetComdatSelectionKind, LLVMSetComdatSelectionKind};
9use llvm_sys::prelude::LLVMComdatRef;
10
11use crate::support::assert_niche;
12
13#[llvm_enum(LLVMComdatSelectionKind)]
14#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
15/// Determines how linker conflicts are to be resolved.
16pub enum ComdatSelectionKind {
17    /// The linker may choose any COMDAT.
18    #[llvm_variant(LLVMAnyComdatSelectionKind)]
19    Any,
20    /// The data referenced by the COMDAT must be the same.
21    #[llvm_variant(LLVMExactMatchComdatSelectionKind)]
22    ExactMatch,
23    /// The linker will choose the largest COMDAT.
24    #[llvm_variant(LLVMLargestComdatSelectionKind)]
25    Largest,
26    /// No other Module may specify this COMDAT.
27    #[llvm_variant(LLVMNoDuplicatesComdatSelectionKind)]
28    NoDuplicates,
29    /// The data referenced by the COMDAT must be the same size.
30    #[llvm_variant(LLVMSameSizeComdatSelectionKind)]
31    SameSize,
32}
33
34/// A `Comdat` determines how to resolve duplicate sections when linking.
35#[repr(transparent)]
36#[derive(Debug, PartialEq, Eq, Copy, Clone)]
37pub struct Comdat(pub(crate) NonNull<LLVMComdat>);
38const _: () = assert_niche::<Comdat>();
39
40impl Comdat {
41    /// Creates a new [Comdat] type from an [LLVMComdatRef].
42    ///
43    /// # Safety
44    ///
45    /// `comdat` must be non-null and point to a valid value.
46    pub unsafe fn new(comdat: LLVMComdatRef) -> Self {
47        debug_assert!(!comdat.is_null());
48
49        Comdat(unsafe { NonNull::new_unchecked(comdat) })
50    }
51
52    /// Acquires the underlying raw pointer belonging to this `Comdat` type.
53    pub fn as_mut_ptr(&self) -> LLVMComdatRef {
54        self.0.as_ptr()
55    }
56
57    /// Gets what kind of `Comdat` this is.
58    pub fn get_selection_kind(self) -> ComdatSelectionKind {
59        let kind_ptr = unsafe { LLVMGetComdatSelectionKind(self.as_mut_ptr()) };
60
61        ComdatSelectionKind::new(kind_ptr)
62    }
63
64    /// Sets what kind of `Comdat` this should be.
65    pub fn set_selection_kind(self, kind: ComdatSelectionKind) {
66        unsafe { LLVMSetComdatSelectionKind(self.as_mut_ptr(), kind.into()) }
67    }
68}