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}