inkwell/
lib.rs

1//! Inkwell documentation is a work in progress.
2//!
3//! If you have any LLVM knowledge that could be used to improve these docs, we would greatly appreciate you opening an issue and/or a pull request on our [GitHub page](https://github.com/TheDan64/inkwell).
4//!
5//! Due to a rustdoc issue, this documentation represents only the latest supported LLVM version. We hope that this issue will be resolved in the future so that multiple versions can be documented side by side.
6//!
7//! # Library Wide Notes
8//!
9//! * Most functions which take a string slice as input may possibly panic in the unlikely event that a c style string cannot be created based on it. (IE if your slice already has a null byte in it)
10
11#![deny(missing_debug_implementations)]
12#![allow(clippy::missing_safety_doc, clippy::too_many_arguments, clippy::result_unit_err)]
13#![cfg_attr(feature = "nightly", feature(doc_cfg))]
14
15#[macro_use]
16extern crate inkwell_internals;
17
18#[macro_use]
19pub mod support;
20#[deny(missing_docs)]
21pub mod attributes;
22#[deny(missing_docs)]
23pub mod basic_block;
24pub mod builder;
25#[deny(missing_docs)]
26#[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
27pub mod comdat;
28#[deny(missing_docs)]
29pub mod context;
30pub mod data_layout;
31#[cfg(not(any(feature = "llvm4-0", feature = "llvm5-0", feature = "llvm6-0")))]
32pub mod debug_info;
33pub mod execution_engine;
34pub mod intrinsics;
35pub mod memory_buffer;
36pub mod memory_manager;
37#[deny(missing_docs)]
38pub mod module;
39pub mod object_file;
40pub mod passes;
41pub mod targets;
42pub mod types;
43pub mod values;
44
45// Boilerplate to select a desired llvm_sys version at compile & link time.
46#[cfg(feature = "llvm10-0")]
47pub extern crate llvm_sys_100 as llvm_sys;
48#[cfg(feature = "llvm11-0")]
49pub extern crate llvm_sys_110 as llvm_sys;
50#[cfg(feature = "llvm12-0")]
51pub extern crate llvm_sys_120 as llvm_sys;
52#[cfg(feature = "llvm13-0")]
53pub extern crate llvm_sys_130 as llvm_sys;
54#[cfg(feature = "llvm14-0")]
55pub extern crate llvm_sys_140 as llvm_sys;
56#[cfg(feature = "llvm15-0")]
57pub extern crate llvm_sys_150 as llvm_sys;
58#[cfg(feature = "llvm16-0")]
59pub extern crate llvm_sys_160 as llvm_sys;
60#[cfg(feature = "llvm17-0")]
61pub extern crate llvm_sys_170 as llvm_sys;
62#[cfg(feature = "llvm18-0")]
63pub extern crate llvm_sys_180 as llvm_sys;
64#[cfg(feature = "llvm4-0")]
65pub extern crate llvm_sys_40 as llvm_sys;
66#[cfg(feature = "llvm5-0")]
67pub extern crate llvm_sys_50 as llvm_sys;
68#[cfg(feature = "llvm6-0")]
69pub extern crate llvm_sys_60 as llvm_sys;
70#[cfg(feature = "llvm7-0")]
71pub extern crate llvm_sys_70 as llvm_sys;
72#[cfg(feature = "llvm8-0")]
73pub extern crate llvm_sys_80 as llvm_sys;
74#[cfg(feature = "llvm9-0")]
75pub extern crate llvm_sys_90 as llvm_sys;
76
77use llvm_sys::target_machine::LLVMCodeGenOptLevel;
78use llvm_sys::{
79    LLVMAtomicOrdering, LLVMAtomicRMWBinOp, LLVMDLLStorageClass, LLVMIntPredicate, LLVMRealPredicate,
80    LLVMThreadLocalMode, LLVMVisibility,
81};
82
83#[llvm_versions(7..)]
84use llvm_sys::LLVMInlineAsmDialect;
85
86#[cfg(feature = "serde")]
87use serde::{Deserialize, Serialize};
88use std::convert::TryFrom;
89
90// Thanks to kennytm for coming up with assert_unique_features!
91// which ensures that the LLVM feature flags are mutually exclusive
92macro_rules! assert_unique_features {
93    () => {};
94    ($first:tt $(,$rest:tt)*) => {
95        $(
96            #[cfg(all(feature = $first, feature = $rest))]
97            compile_error!(concat!("features \"", $first, "\" and \"", $rest, "\" cannot be used together"));
98        )*
99        assert_unique_features!($($rest),*);
100    }
101}
102
103// This macro ensures that at least one of the LLVM feature
104// flags are provided and prints them out if none are provided
105macro_rules! assert_used_features {
106    ($($all:tt),*) => {
107        #[cfg(not(any($(feature = $all),*)))]
108        compile_error!(concat!("One of the LLVM feature flags must be provided: ", $($all, " "),*));
109    }
110}
111
112macro_rules! assert_unique_used_features {
113    ($($all:tt),*) => {
114        assert_unique_features!($($all),*);
115        assert_used_features!($($all),*);
116    }
117}
118
119assert_unique_used_features! {
120    "llvm4-0",
121    "llvm5-0",
122    "llvm6-0",
123    "llvm7-0",
124    "llvm8-0",
125    "llvm9-0",
126    "llvm10-0",
127    "llvm11-0",
128    "llvm12-0",
129    "llvm13-0",
130    "llvm14-0",
131    "llvm15-0",
132    "llvm16-0",
133    "llvm17-0",
134    "llvm18-0"
135}
136
137#[cfg(all(
138    any(
139        feature = "llvm4-0",
140        feature = "llvm5-0",
141        feature = "llvm6-0",
142        feature = "llvm7-0",
143        feature = "llvm8-0",
144        feature = "llvm9-0",
145        feature = "llvm10-0",
146        feature = "llvm11-0",
147        feature = "llvm12-0",
148        feature = "llvm13-0",
149        feature = "llvm14-0"
150    ),
151    not(feature = "typed-pointers")
152))]
153compile_error!("Opaque pointers are not supported prior to LLVM version 15.0.");
154
155#[cfg(all(any(feature = "llvm17-0", feature = "llvm18-0"), feature = "typed-pointers"))]
156compile_error!("Typed pointers are not supported starting from LLVM version 17.0.");
157
158/// Defines the address space in which a global will be inserted.
159///
160/// The default address space is number zero. An address space can always be created from a [`u16`]:
161/// ```no_run
162/// inkwell::AddressSpace::from(1u16);
163/// ```
164///
165/// An address space is a 24-bit number. To convert from a [`u32`], use the [`TryFrom`] implementation:
166///
167/// ```no_run
168/// inkwell::AddressSpace::try_from(42u32).expect("fits in 24-bit unsigned int");
169/// ```
170///
171/// # Remarks
172/// See also: <https://llvm-swift.github.io/LLVMSwift/Structs/AddressSpace.html>
173#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
174pub struct AddressSpace(u32);
175
176impl From<u16> for AddressSpace {
177    fn from(val: u16) -> Self {
178        AddressSpace(val as u32)
179    }
180}
181
182impl TryFrom<u32> for AddressSpace {
183    type Error = ();
184
185    fn try_from(val: u32) -> Result<Self, Self::Error> {
186        // address space is a 24-bit integer
187        if val < 1 << 24 {
188            Ok(AddressSpace(val))
189        } else {
190            Err(())
191        }
192    }
193}
194
195// REVIEW: Maybe this belongs in some sort of prelude?
196/// This enum defines how to compare a `left` and `right` `IntValue`.
197#[llvm_enum(LLVMIntPredicate)]
198#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
199pub enum IntPredicate {
200    /// Equal
201    #[llvm_variant(LLVMIntEQ)]
202    EQ,
203
204    /// Not Equal
205    #[llvm_variant(LLVMIntNE)]
206    NE,
207
208    /// Unsigned Greater Than
209    #[llvm_variant(LLVMIntUGT)]
210    UGT,
211
212    /// Unsigned Greater Than or Equal
213    #[llvm_variant(LLVMIntUGE)]
214    UGE,
215
216    /// Unsigned Less Than
217    #[llvm_variant(LLVMIntULT)]
218    ULT,
219
220    /// Unsigned Less Than or Equal
221    #[llvm_variant(LLVMIntULE)]
222    ULE,
223
224    /// Signed Greater Than
225    #[llvm_variant(LLVMIntSGT)]
226    SGT,
227
228    /// Signed Greater Than or Equal
229    #[llvm_variant(LLVMIntSGE)]
230    SGE,
231
232    /// Signed Less Than
233    #[llvm_variant(LLVMIntSLT)]
234    SLT,
235
236    /// Signed Less Than or Equal
237    #[llvm_variant(LLVMIntSLE)]
238    SLE,
239}
240
241// REVIEW: Maybe this belongs in some sort of prelude?
242/// Defines how to compare a `left` and `right` `FloatValue`.
243#[llvm_enum(LLVMRealPredicate)]
244#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
245pub enum FloatPredicate {
246    /// Returns true if `left` == `right` and neither are NaN
247    #[llvm_variant(LLVMRealOEQ)]
248    OEQ,
249
250    /// Returns true if `left` >= `right` and neither are NaN
251    #[llvm_variant(LLVMRealOGE)]
252    OGE,
253
254    /// Returns true if `left` > `right` and neither are NaN
255    #[llvm_variant(LLVMRealOGT)]
256    OGT,
257
258    /// Returns true if `left` <= `right` and neither are NaN
259    #[llvm_variant(LLVMRealOLE)]
260    OLE,
261
262    /// Returns true if `left` < `right` and neither are NaN
263    #[llvm_variant(LLVMRealOLT)]
264    OLT,
265
266    /// Returns true if `left` != `right` and neither are NaN
267    #[llvm_variant(LLVMRealONE)]
268    ONE,
269
270    /// Returns true if neither value is NaN
271    #[llvm_variant(LLVMRealORD)]
272    ORD,
273
274    /// Always returns false
275    #[llvm_variant(LLVMRealPredicateFalse)]
276    PredicateFalse,
277
278    /// Always returns true
279    #[llvm_variant(LLVMRealPredicateTrue)]
280    PredicateTrue,
281
282    /// Returns true if `left` == `right` or either is NaN
283    #[llvm_variant(LLVMRealUEQ)]
284    UEQ,
285
286    /// Returns true if `left` >= `right` or either is NaN
287    #[llvm_variant(LLVMRealUGE)]
288    UGE,
289
290    /// Returns true if `left` > `right` or either is NaN
291    #[llvm_variant(LLVMRealUGT)]
292    UGT,
293
294    /// Returns true if `left` <= `right` or either is NaN
295    #[llvm_variant(LLVMRealULE)]
296    ULE,
297
298    /// Returns true if `left` < `right` or either is NaN
299    #[llvm_variant(LLVMRealULT)]
300    ULT,
301
302    /// Returns true if `left` != `right` or either is NaN
303    #[llvm_variant(LLVMRealUNE)]
304    UNE,
305
306    /// Returns true if either value is NaN
307    #[llvm_variant(LLVMRealUNO)]
308    UNO,
309}
310
311// REVIEW: Maybe this belongs in some sort of prelude?
312#[llvm_enum(LLVMAtomicOrdering)]
313#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
314pub enum AtomicOrdering {
315    #[llvm_variant(LLVMAtomicOrderingNotAtomic)]
316    NotAtomic,
317    #[llvm_variant(LLVMAtomicOrderingUnordered)]
318    Unordered,
319    #[llvm_variant(LLVMAtomicOrderingMonotonic)]
320    Monotonic,
321    #[llvm_variant(LLVMAtomicOrderingAcquire)]
322    Acquire,
323    #[llvm_variant(LLVMAtomicOrderingRelease)]
324    Release,
325    #[llvm_variant(LLVMAtomicOrderingAcquireRelease)]
326    AcquireRelease,
327    #[llvm_variant(LLVMAtomicOrderingSequentiallyConsistent)]
328    SequentiallyConsistent,
329}
330
331#[llvm_enum(LLVMAtomicRMWBinOp)]
332#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
333pub enum AtomicRMWBinOp {
334    /// Stores to memory and returns the prior value.
335    #[llvm_variant(LLVMAtomicRMWBinOpXchg)]
336    Xchg,
337
338    /// Adds to the value in memory and returns the prior value.
339    #[llvm_variant(LLVMAtomicRMWBinOpAdd)]
340    Add,
341
342    /// Subtract a value off the value in memory and returns the prior value.
343    #[llvm_variant(LLVMAtomicRMWBinOpSub)]
344    Sub,
345
346    /// Bitwise and into memory and returns the prior value.
347    #[llvm_variant(LLVMAtomicRMWBinOpAnd)]
348    And,
349
350    /// Bitwise nands into memory and returns the prior value.
351    #[llvm_variant(LLVMAtomicRMWBinOpNand)]
352    Nand,
353
354    /// Bitwise ors into memory and returns the prior value.
355    #[llvm_variant(LLVMAtomicRMWBinOpOr)]
356    Or,
357
358    /// Bitwise xors into memory and returns the prior value.
359    #[llvm_variant(LLVMAtomicRMWBinOpXor)]
360    Xor,
361
362    /// Sets memory to the signed-greater of the value provided and the value in memory. Returns the value that was in memory.
363    #[llvm_variant(LLVMAtomicRMWBinOpMax)]
364    Max,
365
366    /// Sets memory to the signed-lesser of the value provided and the value in memory. Returns the value that was in memory.
367    #[llvm_variant(LLVMAtomicRMWBinOpMin)]
368    Min,
369
370    /// Sets memory to the unsigned-greater of the value provided and the value in memory. Returns the value that was in memory.
371    #[llvm_variant(LLVMAtomicRMWBinOpUMax)]
372    UMax,
373
374    /// Sets memory to the unsigned-lesser of the value provided and the value in memory. Returns the value that was in memory.
375    #[llvm_variant(LLVMAtomicRMWBinOpUMin)]
376    UMin,
377
378    /// Adds to the float-typed value in memory and returns the prior value.
379    // Although this was added in LLVM 9, it wasn't exposed to the C API
380    // until 10.0.
381    #[llvm_versions(10..)]
382    #[llvm_variant(LLVMAtomicRMWBinOpFAdd)]
383    FAdd,
384
385    /// Subtract a float-typed value off the value in memory and returns the prior value.
386    // Although this was added in LLVM 9, it wasn't exposed to the C API
387    // until 10.0.
388    #[llvm_versions(10..)]
389    #[llvm_variant(LLVMAtomicRMWBinOpFSub)]
390    FSub,
391
392    /// Sets memory to the greater of the two float-typed values, one provided and one from memory. Returns the value that was in memory.
393    #[llvm_versions(15..)]
394    #[llvm_variant(LLVMAtomicRMWBinOpFMax)]
395    FMax,
396
397    /// Sets memory to the lesser of the two float-typed values, one provided and one from memory. Returns the value that was in memory.
398    #[llvm_versions(15..)]
399    #[llvm_variant(LLVMAtomicRMWBinOpFMin)]
400    FMin,
401}
402
403/// Defines the optimization level used to compile a [`Module`](crate::module::Module).
404///
405/// # Remarks
406///
407/// See the C++ API documentation: [`llvm::CodeGenOpt`](https://llvm.org/doxygen/namespacellvm_1_1CodeGenOpt.html).
408#[repr(u32)]
409#[derive(Debug, PartialEq, Eq, Copy, Clone)]
410#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
411pub enum OptimizationLevel {
412    None = 0,
413    Less = 1,
414    Default = 2,
415    Aggressive = 3,
416}
417
418impl Default for OptimizationLevel {
419    /// Returns the default value for `OptimizationLevel`, namely `OptimizationLevel::Default`.
420    fn default() -> Self {
421        OptimizationLevel::Default
422    }
423}
424
425impl From<OptimizationLevel> for LLVMCodeGenOptLevel {
426    fn from(value: OptimizationLevel) -> Self {
427        match value {
428            OptimizationLevel::None => LLVMCodeGenOptLevel::LLVMCodeGenLevelNone,
429            OptimizationLevel::Less => LLVMCodeGenOptLevel::LLVMCodeGenLevelLess,
430            OptimizationLevel::Default => LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault,
431            OptimizationLevel::Aggressive => LLVMCodeGenOptLevel::LLVMCodeGenLevelAggressive,
432        }
433    }
434}
435
436#[llvm_enum(LLVMVisibility)]
437#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
439pub enum GlobalVisibility {
440    #[llvm_variant(LLVMDefaultVisibility)]
441    Default,
442    #[llvm_variant(LLVMHiddenVisibility)]
443    Hidden,
444    #[llvm_variant(LLVMProtectedVisibility)]
445    Protected,
446}
447
448impl Default for GlobalVisibility {
449    /// Returns the default value for `GlobalVisibility`, namely `GlobalVisibility::Default`.
450    fn default() -> Self {
451        GlobalVisibility::Default
452    }
453}
454
455#[derive(Clone, Copy, Debug, Eq, PartialEq)]
456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
457pub enum ThreadLocalMode {
458    GeneralDynamicTLSModel,
459    LocalDynamicTLSModel,
460    InitialExecTLSModel,
461    LocalExecTLSModel,
462}
463
464impl ThreadLocalMode {
465    pub(crate) fn new(thread_local_mode: LLVMThreadLocalMode) -> Option<Self> {
466        match thread_local_mode {
467            LLVMThreadLocalMode::LLVMGeneralDynamicTLSModel => Some(ThreadLocalMode::GeneralDynamicTLSModel),
468            LLVMThreadLocalMode::LLVMLocalDynamicTLSModel => Some(ThreadLocalMode::LocalDynamicTLSModel),
469            LLVMThreadLocalMode::LLVMInitialExecTLSModel => Some(ThreadLocalMode::InitialExecTLSModel),
470            LLVMThreadLocalMode::LLVMLocalExecTLSModel => Some(ThreadLocalMode::LocalExecTLSModel),
471            LLVMThreadLocalMode::LLVMNotThreadLocal => None,
472        }
473    }
474
475    pub(crate) fn as_llvm_mode(self) -> LLVMThreadLocalMode {
476        match self {
477            ThreadLocalMode::GeneralDynamicTLSModel => LLVMThreadLocalMode::LLVMGeneralDynamicTLSModel,
478            ThreadLocalMode::LocalDynamicTLSModel => LLVMThreadLocalMode::LLVMLocalDynamicTLSModel,
479            ThreadLocalMode::InitialExecTLSModel => LLVMThreadLocalMode::LLVMInitialExecTLSModel,
480            ThreadLocalMode::LocalExecTLSModel => LLVMThreadLocalMode::LLVMLocalExecTLSModel,
481            // None => LLVMThreadLocalMode::LLVMNotThreadLocal,
482        }
483    }
484}
485
486#[llvm_enum(LLVMDLLStorageClass)]
487#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
489pub enum DLLStorageClass {
490    #[llvm_variant(LLVMDefaultStorageClass)]
491    Default,
492    #[llvm_variant(LLVMDLLImportStorageClass)]
493    Import,
494    #[llvm_variant(LLVMDLLExportStorageClass)]
495    Export,
496}
497
498impl Default for DLLStorageClass {
499    /// Returns the default value for `DLLStorageClass`, namely `DLLStorageClass::Default`.
500    fn default() -> Self {
501        DLLStorageClass::Default
502    }
503}
504
505#[llvm_versions(7..)]
506#[llvm_enum(LLVMInlineAsmDialect)]
507#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
509pub enum InlineAsmDialect {
510    #[llvm_variant(LLVMInlineAsmDialectATT)]
511    ATT,
512    #[llvm_variant(LLVMInlineAsmDialectIntel)]
513    Intel,
514}