Skip to main content

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