llvm_lib/core/
context.rs

1//! LLVM `Context` functions and wrappers.
2
3use crate::core::types::TypeRef;
4use crate::{CInt, CStr, CString, CUint, GetRef, SizeT, UnsafeMutVoidPtr};
5use llvm_sys::prelude::{LLVMAttributeRef, LLVMContextRef, LLVMDiagnosticInfoRef};
6use llvm_sys::{core, LLVMDiagnosticHandler, LLVMDiagnosticSeverity, LLVMYieldCallback};
7use std::ops::Deref;
8
9/// Wrapper for `LLVMDiagnosticSeverity`, representing the severity levels of diagnostics in LLVM.
10///
11/// The `DiagnosticSeverity` enum maps to the `LLVMDiagnosticSeverity` in the LLVM core library. It categorizes
12/// the severity levels of diagnostic messages that can be generated by LLVM during compilation or other processing.
13/// This enum helps identify the nature of the diagnostic messages, such as errors, warnings, remarks, and notes.
14#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15pub enum DiagnosticSeverity {
16    /// Represents an error diagnostic. Errors indicate critical issues that typically prevent the code from compiling successfully.
17    DSError,
18    /// Represents a warning diagnostic. Warnings indicate potential issues that do not stop compilation but could lead to problems.
19    DSWarning,
20    /// Represents a remark diagnostic. Remarks provide additional information that might be useful but is not necessarily problematic.
21    DSRemark,
22    /// Represents a note diagnostic. Notes usually provide supplementary information related to warnings or errors.
23    DSNote,
24}
25
26impl From<LLVMDiagnosticSeverity> for DiagnosticSeverity {
27    fn from(severity: LLVMDiagnosticSeverity) -> Self {
28        match severity {
29            LLVMDiagnosticSeverity::LLVMDSError => Self::DSError,
30            LLVMDiagnosticSeverity::LLVMDSWarning => Self::DSWarning,
31            LLVMDiagnosticSeverity::LLVMDSRemark => Self::DSRemark,
32            LLVMDiagnosticSeverity::LLVMDSNote => Self::DSNote,
33        }
34    }
35}
36
37/// LLVM Context wrapper
38#[derive(Debug)]
39pub struct ContextRef(LLVMContextRef);
40
41impl From<LLVMContextRef> for ContextRef {
42    fn from(value: LLVMContextRef) -> Self {
43        Self(value)
44    }
45}
46
47impl ContextRef {
48    /// Create new LLVM Context
49    #[must_use]
50    pub fn new() -> Self {
51        Self::context_create()
52    }
53}
54
55/// LLVM specific implementations
56impl ContextRef {
57    /// Create a new context.
58    ///
59    /// ## Safety
60    /// Every call to this function should be paired with a call to
61    /// `Self::context_dispose` or the context will leak memory.
62    #[must_use]
63    pub fn context_create() -> Self {
64        unsafe { Self(core::LLVMContextCreate()) }
65    }
66
67    /// Retrieves the global context instance.
68    ///
69    /// The global context is particularly convenient instance managed by LLVM
70    /// itself. It is the default context provided for any operations that
71    /// require it.
72    ///
73    /// ### Safety
74    /// Failure to specify the correct context in concurrent
75    /// environments can lead to data corruption.  In general, it is always
76    /// recommended that each thread of execution attempting to access the LLVM
77    /// API have its own `Context` instance, rather than rely on this global
78    /// context.
79    ///
80    /// # Details
81    ///
82    /// This function wraps the `LLVMContextSetDiagnosticHandler` function from the LLVM core library. It allows you to set
83    /// a custom diagnostic handler function (`LLVMDiagnosticHandler`) that will be invoked when diagnostic messages
84    /// (such as errors, warnings, or remarks) are generated within the context represented by `self`. Additionally,
85    /// an optional diagnostic context (`UnsafeMutVoidPtr`) can be passed, which can hold user-defined data to be used
86    /// by the diagnostic handler.
87    ///
88    /// # Parameters
89    ///
90    /// - `handler`: The diagnostic handler function (`LLVMDiagnosticHandler`) to be set for the context.
91    /// - `diagnostic_context`: An opaque pointer (`UnsafeMutVoidPtr`) that can be passed to the diagnostic handler. This
92    ///   context is typically used to store additional data that the handler might need when processing diagnostics.
93    #[must_use]
94    pub fn get_global_context() -> Self {
95        unsafe { Self(core::LLVMGetGlobalContext()) }
96    }
97
98    /// Set debug diagnostic handler for this context.
99    ///
100    /// ## Safety
101    /// To provide safe operations wi with diagnostic context should be set:
102    /// - `handler` - LLVM diagnostic function (handler)
103    /// - `diagnostic_context` - raw pointer for diagnostic
104    /// NOTE: it's much safer to use raw pointer in that case than `std::ptr::NonNull` structs.
105    pub fn set_diagnostic_handler(
106        &self,
107        handler: LLVMDiagnosticHandler,
108        diagnostic_context: UnsafeMutVoidPtr,
109    ) {
110        unsafe {
111            core::LLVMContextSetDiagnosticHandler(self.0, handler, *diagnostic_context);
112        }
113    }
114
115    /// Get the diagnostic handler of this context.
116    ///
117    /// # Details
118    ///
119    /// Retrieves the diagnostic handler associated with the current LLVM context.
120    ///
121    /// This function wraps the `LLVMContextGetDiagnosticHandler` function from the LLVM core library. It returns the
122    /// diagnostic handler (`LLVMDiagnosticHandler`) associated with the context represented by `self`. The diagnostic handler
123    /// is a function or callback that is invoked when a diagnostic message (such as an error or warning) is generated during
124    /// compilation or other LLVM operations.
125    ///
126    /// # Returns
127    ///
128    /// Returns an `LLVMDiagnosticHandler` representing the diagnostic handler associated with the current LLVM context.
129    #[must_use]
130    pub fn get_diagnostic_handler(&self) -> LLVMDiagnosticHandler {
131        unsafe { core::LLVMContextGetDiagnosticHandler(self.0) }
132    }
133
134    /// Get the diagnostic context of this context.
135    ///
136    /// # Details
137    ///
138    /// Retrieves the diagnostic context associated with the current LLVM context.
139    ///
140    /// This function wraps the `LLVMContextGetDiagnosticContext` function from the LLVM core library. It returns a raw
141    /// pointer wrapped in `UnsafeMutVoidPtr` that represents the diagnostic context associated with the context represented
142    /// by `self`. The diagnostic context can be used to store and retrieve additional information related to diagnostics
143    /// generated during compilation or other operations.
144    ///
145    /// # Returns
146    ///
147    /// Returns an `UnsafeMutVoidPtr` representing the diagnostic context associated with the current LLVM context.
148    ///
149    /// # Safety
150    ///
151    /// The returned pointer is unsafe and must be handled with care. Ensure that the pointer is used correctly and that any
152    /// operations involving the pointer respect the rules of memory safety.
153    #[must_use]
154    pub fn get_diagnostic_context(&self) -> UnsafeMutVoidPtr {
155        unsafe {
156            let raw_ptr = core::LLVMContextGetDiagnosticContext(self.0);
157            UnsafeMutVoidPtr(raw_ptr)
158        }
159    }
160
161    /// Set the yield callback function for this context.
162    ///
163    /// #Details
164    ///
165    /// Sets a yield callback for the current LLVM context.
166    ///
167    /// This function wraps the `LLVMContextSetYieldCallback` function from the LLVM core library. It allows you to set
168    /// a yield callback function that will be invoked periodically during long-running operations in the context represented
169    /// by `self`. Yield callbacks can be used to implement cooperative multitasking, allowing other tasks to run or perform
170    /// actions such as checking for user interruptions.
171    ///
172    /// # Parameters
173    ///
174    /// - `callback`: The callback function (`LLVMYieldCallback`) to be invoked periodically during long-running operations.
175    /// - `opaque_handle`: An opaque pointer (`UnsafeMutVoidPtr`) that can be passed to the callback function. This handle
176    ///   is typically used to maintain state or pass additional data to the callback.
177    pub fn set_yield_callback(&self, callback: LLVMYieldCallback, opaque_handle: UnsafeMutVoidPtr) {
178        unsafe { core::LLVMContextSetYieldCallback(self.0, callback, *opaque_handle) }
179    }
180
181    /// Retrieve whether the given context is set to discard all value names.
182    ///
183    /// # Details
184    ///
185    /// Checks whether value names should be discarded in the current LLVM context.
186    ///
187    /// This function wraps the `LLVMContextShouldDiscardValueNames` function from the LLVM core library. It determines
188    /// whether the context represented by `self` is currently set to discard value names. Discarding value names can reduce
189    /// memory usage and improve performance, but it removes human-readable names for values, which may impact debugging
190    /// and analysis.
191    ///
192    /// # Returns
193    ///
194    /// Returns `true` if the context is set to discard value names, otherwise returns `false`.
195    #[must_use]
196    pub fn should_discard_value_names(&self) -> bool {
197        unsafe { core::LLVMContextShouldDiscardValueNames(self.0) != 0 }
198    }
199
200    /// Set whether the given context discards all value names.
201    ///
202    /// If true, only the names of `GlobalValue` objects will be available in the IR.
203    /// This can be used to save memory and runtime, especially in release mode.
204    ///
205    /// # Details
206    ///
207    /// Configures whether value names should be discarded in the current LLVM context.
208    ///
209    /// This function wraps the `LLVMContextSetDiscardValueNames` function from the LLVM core library. It allows you to
210    /// enable or disable the discarding of value names within the context represented by `self`. Discarding value names
211    /// can reduce memory usage and improve performance, but at the cost of losing human-readable names for values.
212    ///
213    /// # Parameters
214    ///
215    /// - `discard`: A boolean indicating whether to discard value names (`true` to discard, `false` to keep them).
216    ///
217    /// # Note
218    ///
219    /// Disabling value name retention can make debugging and analysis more difficult since values will lose their human-readable names.
220    pub fn set_discard_value_names(&self, discard: bool) {
221        unsafe {
222            core::LLVMContextSetDiscardValueNames(self.0, *CInt::from(discard));
223        }
224    }
225
226    /// Deinitialize this value and dispose of its resources.
227    ///
228    /// Destroy a context instance.
229    /// This should be called for every call to `self::context_create` (`LLVMContextCreate()`) or memory
230    /// will be leaked.
231    ///
232    /// # Details
233    ///
234    /// Disposes of the current LLVM context, freeing associated resources.
235    ///
236    /// This function wraps the `LLVMContextDispose` function from the LLVM core library. It releases the resources
237    /// associated with the LLVM context represented by `self`. After calling this function, the context should no longer
238    /// be used, as it will be in an invalid state.
239    ///
240    /// # Safety
241    ///
242    /// This function should be called when you are done using the context to ensure that all resources are properly freed.
243    pub fn context_dispose(&self) {
244        unsafe { core::LLVMContextDispose(self.get_ref()) }
245    }
246
247    /// Get  Metadata `KindId` by name in current Context.
248    /// Useful for working with Metadata.
249    ///
250    /// # Details
251    ///
252    /// Retrieves the metadata kind ID by name within the current context.
253    ///
254    /// This function simplifies the retrieval of a metadata kind ID by wrapping the `get_md_kind_id_in_context`
255    /// method from `MetadataKindId`. It returns the metadata kind ID corresponding to the provided name within
256    /// the context represented by `self`. This is useful for working with metadata in LLVM IR.
257    ///
258    /// # Parameters
259    ///
260    /// - `name`: A string slice (`&str`) representing the name of the metadata kind.
261    ///
262    /// # Returns
263    ///
264    /// Returns a `MetadataKindId` representing the ID associated with the provided metadata kind name in the current context.
265    #[must_use]
266    pub fn get_md_kind_id_in_context(&self, name: &str) -> MetadataKindId {
267        MetadataKindId::get_md_kind_id_in_context(self, name)
268    }
269
270    /// Create an enum attribute.
271    ///
272    /// # Details
273    ///
274    /// Creates an enum attribute within the current LLVM context or module.
275    ///
276    /// This function simplifies the creation of an enum attribute by wrapping the `create_enum_attribute` method
277    /// from `AttributeRef`. It creates an enum attribute with the specified kind ID and value within the context or module
278    /// represented by `self`.
279    ///
280    /// # Parameters
281    ///
282    /// - `kind_id`: A `u32` representing the kind ID of the enum attribute. This ID specifies the kind of the attribute.
283    /// - `val`: A `u64` representing the value of the enum attribute.
284    ///
285    /// # Returns
286    ///
287    /// Returns an `AttributeRef` representing the created enum attribute.
288    #[must_use]
289    pub fn create_enum_attribute(&self, kind_id: u32, val: u64) -> AttributeRef {
290        AttributeRef::create_enum_attribute(self, kind_id, val)
291    }
292
293    /// Create a type attribute in context
294    ///
295    /// # Details
296    ///
297    /// Creates a string attribute within the current LLVM context or module.
298    ///
299    /// This function simplifies the creation of a string attribute by wrapping the `create_string_attribute` method
300    /// from `AttributeRef`. It creates a string attribute with the specified key and value within the context or module
301    /// represented by `self`.
302    ///
303    /// # Parameters
304    ///
305    /// - `key`: A string slice (`&str`) representing the key (kind) of the attribute.
306    /// - `value`: A string slice (`&str`) representing the value of the attribute.
307    ///
308    /// # Returns
309    ///
310    /// Returns an `AttributeRef` representing the created string attribute.
311    #[must_use]
312    pub fn create_type_attribute(&self, kind_id: u32, type_ref: &TypeRef) -> AttributeRef {
313        AttributeRef::create_type_attribute(self, kind_id, type_ref)
314    }
315
316    /// Create a string attribute in context
317    #[must_use]
318    pub fn create_string_attribute(&self, key: &str, value: &str) -> AttributeRef {
319        AttributeRef::create_string_attribute(self, key, value)
320    }
321
322    /// Obtain a Type from a context by its registered name.
323    ///
324    /// # Details
325    ///
326    /// Retrieves a type by its name within the current LLVM module or context.
327    ///
328    /// This function wraps the `LLVMGetTypeByName2` function from the LLVM core library. It searches for a type
329    /// with the specified name within the context or module represented by `self`. If a type with the given name
330    /// is found, it returns a `TypeRef` representing the type. Otherwise, it returns `None`.
331    ///
332    /// # Parameters
333    ///
334    /// - `name`: A string slice (`&str`) representing the name of the type to search for.
335    ///
336    /// # Returns
337    ///
338    /// Returns an `Option<TypeRef>`:
339    /// - `Some(TypeRef)` if the type with the specified name is found.
340    /// - `None` if the type is not found.
341    #[must_use]
342    pub fn get_type_by_name2(&self, name: &str) -> Option<TypeRef> {
343        let c_name = CString::from(name);
344        let type_ref = unsafe { core::LLVMGetTypeByName2(self.0, c_name.as_ptr()) };
345        if type_ref.is_null() {
346            None
347        } else {
348            Some(TypeRef::from(type_ref))
349        }
350    }
351}
352
353impl Drop for ContextRef {
354    /// Dispose  context
355    fn drop(&mut self) {
356        self.context_dispose();
357    }
358}
359
360impl Deref for ContextRef {
361    type Target = LLVMContextRef;
362    fn deref(&self) -> &Self::Target {
363        &self.0
364    }
365}
366
367impl GetRef for ContextRef {
368    type RawRef = LLVMContextRef;
369    fn get_ref(&self) -> Self::RawRef {
370        self.0
371    }
372}
373
374/// Wrapper for `MetadataKindId`
375pub struct MetadataKindId(pub u32);
376
377impl MetadataKindId {
378    /// Get `MetadataKindId` by name in current `Context`.
379    /// Useful for working with Metadata.
380    ///
381    /// # Details
382    ///
383    /// Retrieves the metadata kind ID associated with a given name within a specific LLVM context.
384    ///
385    /// This function wraps the `LLVMGetMDKindIDInContext` function from the LLVM core library. It returns the metadata kind ID
386    /// corresponding to the provided name within the specified LLVM context. Metadata kinds in LLVM IR are used to attach
387    /// additional information to various IR constructs, such as instructions or functions. Using this function allows for
388    /// context-specific retrieval of metadata kind IDs.
389    ///
390    /// # Parameters
391    ///
392    /// - `context`: A reference to the `ContextRef` in which the metadata kind ID will be retrieved.
393    /// - `name`: A string slice (`&str`) representing the name of the metadata kind.
394    ///
395    /// # Returns
396    ///
397    /// Returns a `MetadataKindId` representing the ID associated with the provided metadata kind name within the specified context.
398    #[must_use]
399    pub fn get_md_kind_id_in_context(context: &ContextRef, name: &str) -> Self {
400        let c_name = CString::from(name);
401        let id = unsafe {
402            core::LLVMGetMDKindIDInContext(
403                context.get_ref(),
404                c_name.as_ptr(),
405                *CUint::from(c_name.count_bytes()),
406            )
407        };
408        Self(id)
409    }
410
411    /// Get  Metadata `KindId` by name.
412    /// Useful for working with Metadata.
413    ///
414    /// # Details
415    ///
416    /// Retrieves the metadata kind ID associated with a given name.
417    ///
418    /// This function wraps the `LLVMGetMDKindID` function from the LLVM core library. It returns the metadata kind ID
419    /// corresponding to the provided name. Metadata kinds in LLVM IR are used to attach additional information to
420    /// various IR constructs, such as instructions or functions.
421    ///
422    /// # Parameters
423    ///
424    /// - `name`: A string slice (`&str`) representing the name of the metadata kind.
425    ///
426    /// # Returns
427    ///
428    /// Returns a `MetadataKindId` representing the ID associated with the provided metadata kind name.
429    #[must_use]
430    pub fn get_md_kind_id(name: &str) -> Self {
431        let c_name = CString::from(name);
432        let id =
433            unsafe { core::LLVMGetMDKindID(c_name.as_ptr(), *CUint::from(c_name.count_bytes())) };
434        Self(id)
435    }
436}
437
438/// LLVM Attributes structure wrapper
439pub struct AttributeRef(LLVMAttributeRef);
440
441impl From<LLVMAttributeRef> for AttributeRef {
442    fn from(value: LLVMAttributeRef) -> Self {
443        Self(value)
444    }
445}
446
447impl GetRef for AttributeRef {
448    type RawRef = LLVMAttributeRef;
449    fn get_ref(&self) -> Self::RawRef {
450        self.0
451    }
452}
453
454impl AttributeRef {
455    /// Return the unique id given the name of the enum attribute,
456    /// or 0 if no attribute by that name exists.
457    ///
458    /// See <http://llvm.org/docs/LangRef.html#parameter-attributes>
459    /// and <http://llvm.org/docs/LangRef.html#function-attributes>
460    /// for the list of available attributes.
461    ///
462    /// # Note
463    ///
464    /// Attribute names and/or id are subject to change without
465    /// going through the C API deprecation cycle.
466    ///
467    /// # Details
468    ///
469    /// Retrieves the enum attribute kind ID associated with a given name.
470    ///
471    /// This function wraps the `LLVMGetEnumAttributeKindForName` function from the LLVM core library. It returns the
472    /// kind ID of the enum attribute that corresponds to the provided name. This is useful for looking up the kind ID
473    /// of an enum attribute by its name, allowing you to work with attributes in a more human-readable way.
474    ///
475    /// # Parameters
476    ///
477    /// - `name`: A string slice (`&str`) representing the name of the enum attribute.
478    ///
479    /// # Returns
480    ///
481    /// Returns a `u32` representing the kind ID associated with the provided attribute name.
482    #[must_use]
483    pub fn get_enum_attribute_kind_for_name(name: &str) -> u32 {
484        let c_name = CString::from(name);
485        unsafe {
486            core::LLVMGetEnumAttributeKindForName(c_name.as_ptr(), *SizeT(c_name.count_bytes()))
487        }
488    }
489
490    /// Get last enum attribute
491    ///
492    /// # Details
493    ///
494    /// Retrieves the highest (last) enum attribute kind ID used in LLVM.
495    ///
496    /// This function wraps the `LLVMGetLastEnumAttributeKind` function from the LLVM core library. It returns the
497    /// highest (last) enum attribute kind ID that is currently defined in LLVM. This can be useful for determining
498    /// the range of valid enum attribute kinds or for iterating over all possible enum attributes.
499    ///
500    /// # Returns
501    ///
502    /// Returns a `u32` representing the highest (last) enum attribute kind ID.
503    #[must_use]
504    pub fn get_last_enum_attribute_kind() -> u32 {
505        unsafe { core::LLVMGetLastEnumAttributeKind() }
506    }
507
508    /// Create an enum attribute.
509    ///
510    /// # Details
511    ///
512    /// Creates an enum attribute in the specified LLVM context.
513    ///
514    /// This function wraps the `LLVMCreateEnumAttribute` function from the LLVM core library. It creates and returns
515    /// an enum attribute with the specified kind ID and value within the given LLVM context. Enum attributes in LLVM IR
516    /// represent attributes that have a fixed set of possible values, and this function allows you to create such attributes
517    /// with a specific value.
518    ///
519    /// # Parameters
520    ///
521    /// - `context`: A reference to the `ContextRef` in which the enum attribute will be created.
522    /// - `kind_id`: A `u32` representing the kind ID of the enum attribute. This ID specifies the kind of the attribute.
523    /// - `val`: A `u64` representing the value of the enum attribute.
524    ///
525    /// # Returns
526    ///
527    /// Returns an instance of `AttributeRef` representing the created enum attribute.
528    #[must_use]
529    pub fn create_enum_attribute(context: &ContextRef, kind_id: u32, val: u64) -> Self {
530        let attr =
531            unsafe { core::LLVMCreateEnumAttribute(context.get_ref(), *CUint::from(kind_id), val) };
532        Self(attr)
533    }
534
535    /// Get the unique id corresponding to the enum attribute passed as argument.
536    ///
537    /// # Details
538    ///
539    /// Retrieves the kind (ID) of an enum attribute as a `u32`.
540    ///
541    /// This function wraps the `LLVMGetEnumAttributeKind` function from the LLVM core library. It returns the
542    /// kind or ID associated with the enum attribute represented by `self`. The kind ID identifies the specific
543    /// attribute within the set of possible enum attributes in LLVM IR.
544    ///
545    /// # Returns
546    ///
547    /// Returns a `u32` representing the kind (ID) of the enum attribute.
548    #[must_use]
549    pub fn get_enum_attribute_kind(&self) -> u32 {
550        unsafe { core::LLVMGetEnumAttributeKind(self.0) }
551    }
552
553    /// Get the enum attribute's value. 0 is returned if none exists.
554    ///
555    /// # Details
556    ///
557    /// Retrieves the value of an enum attribute as a `u64`.
558    ///
559    /// This function wraps the `LLVMGetEnumAttributeValue` function from the LLVM core library. It returns the
560    /// numeric value associated with the enum attribute represented by `self`. Enum attributes in LLVM IR typically
561    /// represent attributes that have a fixed set of possible values, and this function allows you to access the value
562    /// of such attributes.
563    ///
564    /// # Returns
565    ///
566    /// Returns a `u64` representing the value of the enum attribute.
567    #[must_use]
568    pub fn get_enum_attribute_value(&self) -> u64 {
569        unsafe { core::LLVMGetEnumAttributeValue(self.0) }
570    }
571
572    /// Create a type attribute
573    ///
574    /// # Details
575    ///
576    /// Creates a type attribute in the specified LLVM context.
577    ///
578    /// This function wraps the `LLVMCreateTypeAttribute` function from the LLVM core library. It creates and returns
579    /// a type attribute with the specified kind ID and associated type within the given LLVM context. Type attributes
580    /// are used to annotate functions, instructions, or other entities with additional type information in LLVM IR.
581    ///
582    /// # Parameters
583    ///
584    /// - `context`: A reference to the `ContextRef` in which the type attribute will be created.
585    /// - `kind_id`: A `u32` representing the kind ID of the type attribute. This ID specifies the kind of the attribute.
586    /// - `type_ref`: A reference to the `TypeRef` representing the type associated with the attribute.
587    ///
588    /// # Returns
589    ///
590    /// Returns an instance of `AttributeRef` representing the created type attribute.
591    #[must_use]
592    pub fn create_type_attribute(context: &ContextRef, kind_id: u32, type_ref: &TypeRef) -> Self {
593        let attr = unsafe {
594            core::LLVMCreateTypeAttribute(context.get_ref(), kind_id, type_ref.get_ref())
595        };
596        Self(attr)
597    }
598
599    /// Get the type attribute's value.
600    ///
601    /// # Details
602    ///
603    /// Retrieves the type value of a type attribute.
604    ///
605    /// This function wraps the `LLVMGetTypeAttributeValue` function from the LLVM core library. It returns the type
606    /// associated with the type attribute represented by `self`. This function is useful for accessing the type information
607    /// stored within a type attribute in LLVM IR.
608    ///
609    /// # Returns
610    ///
611    /// Returns a `TypeRef` representing the type value associated with the type attribute.
612    #[must_use]
613    pub fn get_type_attribute_value(&self) -> TypeRef {
614        let type_ref = unsafe { core::LLVMGetTypeAttributeValue(self.0) };
615        type_ref.into()
616    }
617
618    /// Create a string attribute.
619    ///
620    /// # Details
621    ///
622    /// Creates a string attribute in the specified LLVM context.
623    ///
624    /// This function wraps the `LLVMCreateStringAttribute` function from the LLVM core library. It creates and returns
625    /// a string attribute with the specified key and value within the given LLVM context. String attributes in LLVM IR
626    /// are typically used to annotate functions, instructions, or other entities with additional metadata in the form of key-value pairs.
627    ///
628    /// # Parameters
629    ///
630    /// - `context`: A reference to the `ContextRef` in which the string attribute will be created.
631    /// - `key`: A string slice (`&str`) representing the key (kind) of the attribute.
632    /// - `value`: A string slice (`&str`) representing the value of the attribute.
633    ///
634    /// # Returns
635    ///
636    /// Returns an instance of `AttributeRef` representing the created string attribute.
637    #[must_use]
638    pub fn create_string_attribute(context: &ContextRef, key: &str, value: &str) -> Self {
639        let c_key = CString::from(key);
640        let c_value = CString::from(value);
641        let attr = unsafe {
642            core::LLVMCreateStringAttribute(
643                context.get_ref(),
644                c_key.as_ptr(),
645                *CUint::from(c_key.count_bytes()),
646                c_value.as_ptr(),
647                *CUint::from(c_value.count_bytes()),
648            )
649        };
650        Self(attr)
651    }
652
653    /// Get the string attribute's kind.
654    ///
655    /// # Details
656    ///
657    /// Retrieves the kind (key) of a string attribute as a `String`.
658    ///
659    /// This function wraps the `LLVMGetStringAttributeKind` function from the LLVM core library. It returns the kind
660    /// or key associated with a string attribute represented by `self`. The kind is returned as a `String` if it exists;
661    /// otherwise, `None` is returned. This function is useful for extracting the key part of key-value pair attributes in LLVM IR.
662    ///
663    /// # Returns
664    ///
665    /// Returns an `Option<String>`:
666    /// - `Some(String)` containing the attribute kind (key) if it exists.
667    /// - `None` if the attribute has no kind or the kind could not be retrieved.
668    #[must_use]
669    pub fn get_string_attribute_kind(&self) -> Option<String> {
670        let mut length = *CUint::from(0_usize);
671        unsafe {
672            let c_str = core::LLVMGetStringAttributeKind(self.0, &mut length);
673            if c_str.is_null() {
674                return None;
675            }
676            Some(CStr::new(c_str).to_string())
677        }
678    }
679
680    /// Get the string attribute's value.
681    ///
682    /// # Details
683    ///
684    /// Retrieves the value of a string attribute as a `String`.
685    ///
686    /// This function wraps the `LLVMGetStringAttributeValue` function from the LLVM core library. It returns the value
687    /// associated with a string attribute represented by `self`. The value is returned as a `String` if the attribute has
688    /// a value; otherwise, `None` is returned. This function is useful for extracting the value part of key-value pair
689    /// attributes in LLVM IR.
690    ///
691    /// # Returns
692    ///
693    /// Returns an `Option<String>`:
694    /// - `Some(String)` containing the attribute value if it exists.
695    /// - `None` if the attribute has no value or the value could not be retrieved.
696    #[must_use]
697    pub fn get_string_attribute_value(&self) -> Option<String> {
698        let mut length = *CUint::from(0_usize);
699        unsafe {
700            let c_str = core::LLVMGetStringAttributeValue(self.get_ref(), &mut length);
701            if c_str.is_null() {
702                return None;
703            }
704            Some(CStr::new(c_str).to_string())
705        }
706    }
707
708    /// Check for the  types of attributes.
709    ///
710    /// # Details
711    ///
712    /// Checks whether the attribute is a string attribute.
713    ///
714    /// This function wraps the `LLVMIsStringAttribute` function from the LLVM core library. It determines whether
715    /// the attribute represented by `self` is a string attribute. String attributes are typically key-value pairs
716    /// where the key is a string and the value may also be a string or other data.
717    ///
718    /// # Returns
719    ///
720    /// Returns `true` if the attribute is a string attribute, otherwise returns `false`.
721    #[must_use]
722    pub fn is_enum(&self) -> bool {
723        unsafe { core::LLVMIsEnumAttribute(self.get_ref()) != 0 }
724    }
725
726    /// Check for the  types of attributes.
727    #[must_use]
728    pub fn is_string_attribute(&self) -> bool {
729        unsafe { core::LLVMIsStringAttribute(self.get_ref()) != 0 }
730    }
731
732    /// Check for the  types of attributes.
733    ///
734    /// # Details
735    ///
736    /// Checks whether the attribute is a type attribute.
737    ///
738    /// This function wraps the `LLVMIsTypeAttribute` function from the LLVM core library. It determines whether
739    /// the attribute represented by `self` is a type attribute. Type attributes are associated with types rather than
740    /// with functions or parameters.
741    ///
742    /// # Returns
743    ///
744    /// Returns `true` if the attribute is a type attribute, otherwise returns `false`.
745    #[must_use]
746    pub fn is_type_attribute(&self) -> bool {
747        unsafe { core::LLVMIsTypeAttribute(self.get_ref()) != 0 }
748    }
749}
750
751/// LLVM Diagnostic Info structure wrapper
752pub struct DiagnosticInfoRef(LLVMDiagnosticInfoRef);
753
754impl From<LLVMDiagnosticInfoRef> for DiagnosticInfoRef {
755    fn from(value: LLVMDiagnosticInfoRef) -> Self {
756        Self(value)
757    }
758}
759
760impl GetRef for DiagnosticInfoRef {
761    type RawRef = LLVMDiagnosticInfoRef;
762    fn get_ref(&self) -> Self::RawRef {
763        self.0
764    }
765}
766
767impl DiagnosticInfoRef {
768    /// Return a string representation of the `DiagnosticInfo`.
769    ///
770    /// # Details
771    ///
772    /// This function wraps the `LLVMGetDiagInfoDescription` function from the LLVM core library. It retrieves a description
773    /// of the diagnostic information represented by `self` as a `String`. The description provides a human-readable explanation
774    /// of the diagnostic. After obtaining the string, the memory is freed using `LLVMDisposeMessage`.
775    ///
776    /// # Returns
777    ///
778    /// Returns an `Option<String>`:
779    /// - `Some(String)` containing the description of the diagnostic if successful.
780    /// - `None` if the description could not be retrieved.
781    ///
782    /// # Safety
783    ///
784    /// This function allocates memory for the string, which is freed using `LLVMDisposeMessage`.
785    #[must_use]
786    pub fn get_description(&self) -> Option<String> {
787        unsafe {
788            let c_str = core::LLVMGetDiagInfoDescription(self.get_ref());
789            if c_str.is_null() {
790                return None;
791            }
792            let value = CStr::new(c_str).to_string();
793            // Dispose message
794            core::LLVMDisposeMessage(c_str);
795            Some(value)
796        }
797    }
798
799    /// Return an enum `DiagnosticSeverity` type
800    ///
801    /// # Details
802    ///
803    /// Retrieves the severity level of the diagnostic information.
804    ///
805    /// This function wraps the `LLVMGetDiagInfoSeverity` function from the LLVM core library. It returns the severity
806    /// level of the diagnostic information represented by `self`. The severity level indicates the nature of the diagnostic,
807    /// such as whether it is an error, warning, remark, or note.
808    ///
809    /// # Returns
810    ///
811    /// Returns a `DiagnosticSeverity` enum variant representing the severity level of the diagnostic.
812    #[must_use]
813    pub fn get_severity(&self) -> DiagnosticSeverity {
814        unsafe {
815            let severity = core::LLVMGetDiagInfoSeverity(self.get_ref());
816            DiagnosticSeverity::from(severity)
817        }
818    }
819}